Skip to content

Commit

Permalink
Fix svg outline widths are incorrectly scaled (fix #11522)
Browse files Browse the repository at this point in the history
SVG outline width sizes were not correctly calculated, and were
set to a constant value regardless of the rendered size of the svg
image. This meant that:
1. the rendered outline width was effectively randomly scaled
2. the width would change as the symbol size was modified

This change has some large flow on effects, eg:

- the large outline widths required to render an outline in <2.12
will now be drawn in their correct sizes, eg massive outlines. Projects
will need to be updated to reflect this.
- the default outline width set for the provided svg symbols (1 mm)
is much too large, so the symbols look bad with the default width.
This size needs to be modified in all the (~300 svg marker images)
- On the plus side, the long standing issue where most of the svg
symbols were rendered with white fill on white background and an
almost invisible black border is now fixed (refs #10908, #8538)
  • Loading branch information
nyalldawson committed Oct 10, 2015
1 parent a721752 commit 16f700a
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Expand Up @@ -1039,7 +1039,7 @@ QgsSvgMarkerSymbolLayerV2::QgsSvgMarkerSymbolLayerV2( const QString& name, doubl
mAngle = angle;
mOffset = QPointF( 0, 0 );
mScaleMethod = scaleMethod;
mOutlineWidth = 1.0;
mOutlineWidth = 0.2;
mOutlineWidthUnit = QgsSymbolV2::MM;
mColor = QColor( Qt::black );
mOutlineColor = QColor( Qt::black );
Expand Down
48 changes: 46 additions & 2 deletions src/core/symbology-ng/qgssvgcache.cpp
Expand Up @@ -229,7 +229,7 @@ void QgsSvgCache::containsParams( const QString& path, bool& hasFillParam, QColo
{
defaultFillColor = QColor( Qt::black );
defaultOutlineColor = QColor( Qt::black );
defaultOutlineWidth = 1.0;
defaultOutlineWidth = 0.2;

QDomDocument svgDoc;
if ( !svgDoc.setContent( getImageData( path ) ) )
Expand All @@ -256,12 +256,56 @@ void QgsSvgCache::replaceParamsAndCacheSvg( QgsSvgCacheEntry* entry )

//replace fill color, outline color, outline with in all nodes
QDomElement docElem = svgDoc.documentElement();
replaceElemParams( docElem, entry->fill, entry->outline, entry->outlineWidth );

double sizeScaleFactor = calcSizeScaleFactor( entry, docElem );
replaceElemParams( docElem, entry->fill, entry->outline, entry->outlineWidth * sizeScaleFactor );

entry->svgContent = svgDoc.toByteArray();
mTotalSize += entry->svgContent.size();
}

double QgsSvgCache::calcSizeScaleFactor( QgsSvgCacheEntry* entry, const QDomElement& docElem ) const
{
QString viewBox;

//bad size
if ( !entry || entry->size == 0 )
return 1.0;

//find svg viewbox attribute
//first check if docElem is svg element
if ( docElem.tagName() == "svg" )
{
viewBox = docElem.attribute( "viewBox", QString() );
}
else
{
QDomElement svgElem = docElem.firstChildElement( "svg" ) ;
if ( !svgElem.isNull() )
{
viewBox = svgElem.attribute( "viewBox", QString() );
}
}

//could not find valid viewbox attribute
if ( viewBox.isEmpty() )
return 1.0;

//width should be 3rd element in a 4 part space delimited string
QStringList parts = viewBox.split( " " );
if ( parts.count() != 4 )
return 1.0;

bool widthOk = false;
double width = parts.at( 2 ).toDouble( &widthOk );
if ( widthOk )
{
return width / entry->size ;
}

return 1.0;
}

QByteArray QgsSvgCache::getImageData( const QString &path ) const
{
// is it a path to local file?
Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology-ng/qgssvgcache.h
Expand Up @@ -178,6 +178,9 @@ class CORE_EXPORT QgsSvgCache : public QObject
void containsElemParams( const QDomElement& elem, bool& hasFillParam, QColor& defaultFill, bool& hasOutlineParam, QColor& defaultOutline,
bool& hasOutlineWidthParam, double& defaultOutlineWidth ) const;

/** Calculates scaling for rendered image sizes to SVG logical sizes*/
double calcSizeScaleFactor( QgsSvgCacheEntry* entry, const QDomElement& docElem ) const;

/** Release memory and remove cache entry from mEntryLookup*/
void removeCacheEntry( const QString& s, QgsSvgCacheEntry* entry );

Expand All @@ -189,6 +192,7 @@ class CORE_EXPORT QgsSvgCache : public QObject

//! Mutex to prevent concurrent access to the class from multiple threads at once (may corrupt the entries otherwise).
QMutex mMutex;

};

#endif // QGSSVGCACHE_H
3 changes: 3 additions & 0 deletions src/ui/symbollayer/widget_svgmarker.ui
Expand Up @@ -35,6 +35,9 @@
<property name="singleStep">
<double>0.200000000000000</double>
</property>
<property name="value">
<double>0.200000000000000</double>
</property>
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
Expand Down

0 comments on commit 16f700a

Please sign in to comment.