Skip to content

Commit 2f268d4

Browse files
aaimerldhont
authored andcommitted
Emit valid SLD when on screen mm are used
SLD does not have a notion of on screen mm, rescale them to pixels to get an equivalent, more valid and more widely usable, output
1 parent 5c4fd97 commit 2f268d4

File tree

8 files changed

+505
-33
lines changed

8 files changed

+505
-33
lines changed

src/core/qgsmaplayer.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1462,7 +1462,6 @@ void QgsMapLayer::exportSldStyle( QDomDocument &doc, QString &errorMsg )
14621462
// Create the root element
14631463
QDomElement root = myDocument.createElementNS( "http://www.opengis.net/sld", "StyledLayerDescriptor" );
14641464
root.setAttribute( "version", "1.1.0" );
1465-
root.setAttribute( "units", "mm" ); // default qgsmaprenderer is Millimeters
14661465
root.setAttribute( "xsi:schemaLocation", "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" );
14671466
root.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" );
14681467
root.setAttribute( "xmlns:se", "http://www.opengis.net/se" );

src/core/symbology-ng/qgsellipsesymbollayerv2.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,12 +409,9 @@ void QgsEllipseSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &el
409409
QDomElement graphicElem = doc.createElement( "se:Graphic" );
410410
element.appendChild( graphicElem );
411411

412-
QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, mSymbolName, mColor, mOutlineColor, mOutlineStyle, mOutlineWidth, mSymbolWidth );
413-
414-
// store w/h factor in a <VendorOption>
415-
double widthHeightFactor = mSymbolWidth / mSymbolHeight;
416-
QDomElement factorElem = QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "widthHeightFactor", QString::number( widthHeightFactor ) );
417-
graphicElem.appendChild( factorElem );
412+
double outlineWidth = QgsSymbolLayerV2Utils::rescaleUom( mOutlineWidth, mOutlineWidthUnit, props );
413+
double symbolWidth = QgsSymbolLayerV2Utils::rescaleUom( mSymbolWidth, mSymbolWidthUnit, props );
414+
QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, mSymbolName, mColor, mOutlineColor, mOutlineStyle, outlineWidth, symbolWidth );
418415

419416
// <Rotation>
420417
QgsDataDefined* ddRotation = getDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION );
@@ -452,6 +449,16 @@ void QgsEllipseSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &el
452449
}
453450
}
454451
QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
452+
QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
453+
454+
// <Displacement>
455+
QPointF offset = QgsSymbolLayerV2Utils::rescaleUom( mOffset, mOffsetUnit, props );
456+
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, offset );
457+
458+
// store w/h factor in a <VendorOption>
459+
double widthHeightFactor = mSymbolWidth / mSymbolHeight;
460+
QDomElement factorElem = QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "widthHeightFactor", QString::number( widthHeightFactor ) );
461+
graphicElem.appendChild( factorElem );
455462
}
456463

457464
QgsSymbolLayerV2* QgsEllipseSymbolLayerV2::createFromSld( QDomElement &element )

src/core/symbology-ng/qgsfillsymbollayerv2.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,13 @@ void QgsSimpleFillSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element,
352352
// <Stroke>
353353
QDomElement strokeElem = doc.createElement( "se:Stroke" );
354354
symbolizerElem.appendChild( strokeElem );
355-
QgsSymbolLayerV2Utils::lineToSld( doc, strokeElem, mBorderStyle, mBorderColor, mBorderWidth, &mPenJoinStyle );
355+
double borderWidth = QgsSymbolLayerV2Utils::rescaleUom( mBorderWidth, mBorderWidthUnit, props );
356+
QgsSymbolLayerV2Utils::lineToSld( doc, strokeElem, mBorderStyle, borderWidth, borderWidth, &mPenJoinStyle );
356357
}
357358

358359
// <se:Displacement>
359-
QgsSymbolLayerV2Utils::createDisplacementElement( doc, symbolizerElem, mOffset );
360+
QPointF offset = QgsSymbolLayerV2Utils::rescaleUom( mOffset, mOffsetUnit, props );
361+
QgsSymbolLayerV2Utils::createDisplacementElement( doc, symbolizerElem, offset );
360362
}
361363

362364
QString QgsSimpleFillSymbolLayerV2::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
@@ -1778,6 +1780,7 @@ void QgsSVGFillSymbolLayer::setOutputUnit( QgsSymbolV2::OutputUnit unit )
17781780
mPatternWidthUnit = unit;
17791781
mSvgOutlineWidthUnit = unit;
17801782
mOutlineWidthUnit = unit;
1783+
mOutline->setOutputUnit( unit );
17811784
}
17821785

17831786
QgsSymbolV2::OutputUnit QgsSVGFillSymbolLayer::outputUnit() const
@@ -2088,7 +2091,8 @@ void QgsSVGFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, cons
20882091

20892092
if ( !mSvgFilePath.isEmpty() )
20902093
{
2091-
QgsSymbolLayerV2Utils::externalGraphicToSld( doc, graphicElem, mSvgFilePath, "image/svg+xml", mColor, mPatternWidth );
2094+
double partternWidth = QgsSymbolLayerV2Utils::rescaleUom( mPatternWidth, mPatternWidthUnit, props );
2095+
QgsSymbolLayerV2Utils::externalGraphicToSld( doc, graphicElem, mSvgFilePath, "image/svg+xml", mColor, partternWidth );
20922096
}
20932097
else
20942098
{
@@ -2099,7 +2103,8 @@ void QgsSVGFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, cons
20992103

21002104
if ( mSvgOutlineColor.isValid() || mSvgOutlineWidth >= 0 )
21012105
{
2102-
QgsSymbolLayerV2Utils::lineToSld( doc, graphicElem, Qt::SolidLine, mSvgOutlineColor, mSvgOutlineWidth );
2106+
double svgOutlineWidth = QgsSymbolLayerV2Utils::rescaleUom( mSvgOutlineWidth, mSvgOutlineWidthUnit, props );
2107+
QgsSymbolLayerV2Utils::lineToSld( doc, graphicElem, Qt::SolidLine, mSvgOutlineColor, svgOutlineWidth );
21032108
}
21042109

21052110
// <Rotation>
@@ -2887,7 +2892,9 @@ void QgsLinePatternFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &eleme
28872892
//line properties must be inside the graphic definition
28882893
QColor lineColor = mFillLineSymbol ? mFillLineSymbol->color() : QColor();
28892894
double lineWidth = mFillLineSymbol ? mFillLineSymbol->width() : 0.0;
2890-
QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, "horline", QColor(), lineColor, Qt::SolidLine, lineWidth, mDistance );
2895+
lineWidth = QgsSymbolLayerV2Utils::rescaleUom( lineWidth, mLineWidthUnit, props );
2896+
double distance = QgsSymbolLayerV2Utils::rescaleUom( mDistance, mDistanceUnit, props );
2897+
QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, "horline", QColor(), lineColor, Qt::SolidLine, lineWidth, distance );
28912898

28922899
// <Rotation>
28932900
QString angleFunc;
@@ -2905,6 +2912,7 @@ void QgsLinePatternFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &eleme
29052912

29062913
// <se:Displacement>
29072914
QPointF lineOffset( sin( mLineAngle ) * mOffset, cos( mLineAngle ) * mOffset );
2915+
lineOffset = QgsSymbolLayerV2Utils::rescaleUom( lineOffset, mOffsetUnit, props );
29082916
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, lineOffset );
29092917
}
29102918

@@ -3064,6 +3072,11 @@ void QgsPointPatternFillSymbolLayer::setOutputUnit( QgsSymbolV2::OutputUnit unit
30643072
mDistanceYUnit = unit;
30653073
mDisplacementXUnit = unit;
30663074
mDisplacementYUnit = unit;
3075+
if ( mMarkerSymbol )
3076+
{
3077+
mMarkerSymbol->setOutputUnit( unit );
3078+
}
3079+
30673080
}
30683081

30693082
QgsSymbolV2::OutputUnit QgsPointPatternFillSymbolLayer::outputUnit() const
@@ -3306,7 +3319,9 @@ void QgsPointPatternFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &elem
33063319
fillElem.appendChild( graphicFillElem );
33073320

33083321
// store distanceX, distanceY, displacementX, displacementY in a <VendorOption>
3309-
QString dist = QgsSymbolLayerV2Utils::encodePoint( QPointF( mDistanceX, mDistanceY ) );
3322+
double dx = QgsSymbolLayerV2Utils::rescaleUom( mDistanceX, mDistanceXUnit, props );
3323+
double dy = QgsSymbolLayerV2Utils::rescaleUom( mDistanceY, mDistanceYUnit, props );
3324+
QString dist = QgsSymbolLayerV2Utils::encodePoint( QPointF( dx, dy ) );
33103325
QDomElement distanceElem = QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "distance", dist );
33113326
symbolizerElem.appendChild( distanceElem );
33123327

src/core/symbology-ng/qgslinesymbollayerv2.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -410,14 +410,17 @@ void QgsSimpleLineSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element,
410410
symbolizerElem.appendChild( strokeElem );
411411

412412
Qt::PenStyle penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
413-
QgsSymbolLayerV2Utils::lineToSld( doc, strokeElem, penStyle, mColor, mWidth,
414-
&mPenJoinStyle, &mPenCapStyle, &mCustomDashVector );
413+
double width = QgsSymbolLayerV2Utils::rescaleUom( mWidth, mWidthUnit, props );
414+
QVector<qreal> customDashVector = QgsSymbolLayerV2Utils::rescaleUom( mCustomDashVector, mCustomDashPatternUnit, props );
415+
QgsSymbolLayerV2Utils::lineToSld( doc, strokeElem, penStyle, mColor, width,
416+
&mPenJoinStyle, &mPenCapStyle, &customDashVector );
415417

416418
// <se:PerpendicularOffset>
417419
if ( !qgsDoubleNear( mOffset, 0.0 ) )
418420
{
419421
QDomElement perpOffsetElem = doc.createElement( "se:PerpendicularOffset" );
420-
perpOffsetElem.appendChild( doc.createTextNode( qgsDoubleToString( mOffset ) ) );
422+
double offset = QgsSymbolLayerV2Utils::rescaleUom( mOffset, mOffsetUnit, props );
423+
perpOffsetElem.appendChild( doc.createTextNode( qgsDoubleToString( offset ) ) );
421424
symbolizerElem.appendChild( perpOffsetElem );
422425
}
423426
}
@@ -1413,7 +1416,8 @@ void QgsMarkerLineSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element,
14131416
symbolizerElem.appendChild( QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "placement", "points" ) );
14141417
break;
14151418
default:
1416-
gap = qgsDoubleToString( mInterval );
1419+
double interval = QgsSymbolLayerV2Utils::rescaleUom( mInterval, mIntervalUnit, props );
1420+
gap = qgsDoubleToString( interval );
14171421
break;
14181422
}
14191423

@@ -1453,7 +1457,8 @@ void QgsMarkerLineSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element,
14531457
if ( !qgsDoubleNear( mOffset, 0.0 ) )
14541458
{
14551459
QDomElement perpOffsetElem = doc.createElement( "se:PerpendicularOffset" );
1456-
perpOffsetElem.appendChild( doc.createTextNode( qgsDoubleToString( mOffset ) ) );
1460+
double offset = QgsSymbolLayerV2Utils::rescaleUom( mOffset, mOffsetUnit, props );
1461+
perpOffsetElem.appendChild( doc.createTextNode( qgsDoubleToString( offset ) ) );
14571462
symbolizerElem.appendChild( perpOffsetElem );
14581463
}
14591464
}
@@ -1554,6 +1559,7 @@ double QgsMarkerLineSymbolLayerV2::width() const
15541559
void QgsMarkerLineSymbolLayerV2::setOutputUnit( QgsSymbolV2::OutputUnit unit )
15551560
{
15561561
QgsLineSymbolLayerV2::setOutputUnit( unit );
1562+
mMarker->setOutputUnit( unit );
15571563
mIntervalUnit = unit;
15581564
mOffsetUnit = unit;
15591565
mOffsetAlongLineUnit = unit;

src/core/symbology-ng/qgsmarkersymbollayerv2.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,9 @@ void QgsSimpleMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElemen
11231123
QDomElement graphicElem = doc.createElement( "se:Graphic" );
11241124
element.appendChild( graphicElem );
11251125

1126-
QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, encodeShape( mShape ), mColor, mBorderColor, mOutlineStyle, mOutlineWidth, mSize );
1126+
double outlineWidth = QgsSymbolLayerV2Utils::rescaleUom( mOutlineWidth, mOutlineWidthUnit, props );
1127+
double size = QgsSymbolLayerV2Utils::rescaleUom( mSize, mSizeUnit, props );
1128+
QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, encodeShape( mShape ), mColor, mBorderColor, mOutlineStyle, outlineWidth, size );
11271129

11281130
// <Rotation>
11291131
QString angleFunc;
@@ -1140,7 +1142,8 @@ void QgsSimpleMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElemen
11401142
QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
11411143

11421144
// <Displacement>
1143-
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, mOffset );
1145+
QPointF offset = QgsSymbolLayerV2Utils::rescaleUom( mOffset, mOffsetUnit, props );
1146+
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, offset );
11441147
}
11451148

11461149
QString QgsSimpleMarkerSymbolLayerV2::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
@@ -2225,7 +2228,8 @@ void QgsSvgMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &
22252228
QDomElement graphicElem = doc.createElement( "se:Graphic" );
22262229
element.appendChild( graphicElem );
22272230

2228-
QgsSymbolLayerV2Utils::externalGraphicToSld( doc, graphicElem, mPath, "image/svg+xml", mColor, mSize );
2231+
double size = QgsSymbolLayerV2Utils::rescaleUom( mSize, mSizeUnit, props );
2232+
QgsSymbolLayerV2Utils::externalGraphicToSld( doc, graphicElem, mPath, "image/svg+xml", mColor, size );
22292233

22302234
// <Rotation>
22312235
QString angleFunc;
@@ -2243,7 +2247,8 @@ void QgsSvgMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &
22432247
QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
22442248

22452249
// <Displacement>
2246-
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, mOffset );
2250+
QPointF offset = QgsSymbolLayerV2Utils::rescaleUom( mOffset, mOffsetUnit, props );
2251+
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, offset );
22472252
}
22482253

22492254
QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::createFromSld( QDomElement &element )
@@ -2848,6 +2853,8 @@ void QgsFontMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement
28482853
QString fontPath = QString( "ttf://%1" ).arg( mFontFamily );
28492854
int markIndex = mChr.unicode();
28502855
QgsSymbolLayerV2Utils::externalMarkerToSld( doc, graphicElem, fontPath, "ttf", &markIndex, mColor, mSize );
2856+
double size = QgsSymbolLayerV2Utils::rescaleUom( mSize, mSizeUnit, props );
2857+
QgsSymbolLayerV2Utils::externalMarkerToSld( doc, graphicElem, fontPath, "ttf", &markIndex, mColor, size );
28512858

28522859
// <Rotation>
28532860
QString angleFunc;
@@ -2864,7 +2871,8 @@ void QgsFontMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement
28642871
QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
28652872

28662873
// <Displacement>
2867-
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, mOffset );
2874+
QPointF offset = QgsSymbolLayerV2Utils::rescaleUom( mOffset, mOffsetUnit, props );
2875+
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, offset );
28682876
}
28692877

28702878
QRectF QgsFontMarkerSymbolLayerV2::bounds( QPointF point, QgsSymbolV2RenderContext& context )

src/core/symbology-ng/qgssymbollayerv2utils.cpp

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ QString QgsSymbolLayerV2Utils::encodeSldUom( QgsSymbolV2::OutputUnit unit, doubl
455455
// pixel is the SLD default uom. The "standardized rendering pixel
456456
// size" is defined to be 0.28mm × 0.28mm (millimeters).
457457
if ( scaleFactor )
458-
*scaleFactor = 0.28; // from millimeters to pixels
458+
*scaleFactor = 1 / 0.28; // from millimeters to pixels
459459

460460
// http://www.opengeospatial.org/sld/units/pixel
461461
return QString();
@@ -4081,3 +4081,80 @@ QList<double> QgsSymbolLayerV2Utils::prettyBreaks( double minimum, double maximu
40814081

40824082
return breaks;
40834083
}
4084+
4085+
double QgsSymbolLayerV2Utils::rescaleUom( double size, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props )
4086+
{
4087+
double scale = 1;
4088+
bool roundToUnit = false;
4089+
if ( unit == QgsUnitTypes::RenderUnknownUnit )
4090+
{
4091+
if ( props.contains( "uomScale" ) )
4092+
{
4093+
bool ok;
4094+
scale = props.value( "uomScale" ).toDouble( &ok );
4095+
if ( !ok )
4096+
{
4097+
return size;
4098+
}
4099+
}
4100+
}
4101+
else
4102+
{
4103+
if ( props.value( "uom" ) == "http://www.opengeospatial.org/se/units/metre" )
4104+
{
4105+
switch ( unit )
4106+
{
4107+
case QgsUnitTypes::RenderMillimeters:
4108+
scale = 0.001;
4109+
break;
4110+
case QgsUnitTypes::RenderPixels:
4111+
scale = 0.00028;
4112+
roundToUnit = true;
4113+
break;
4114+
default:
4115+
scale = 1;
4116+
}
4117+
}
4118+
else
4119+
{
4120+
// target is pixels
4121+
switch ( unit )
4122+
{
4123+
case QgsUnitTypes::RenderMillimeters:
4124+
scale = 1 / 0.28;
4125+
roundToUnit = true;
4126+
break;
4127+
// we don't have a good case for map units, as pixel values won't change based on zoom
4128+
default:
4129+
scale = 1;
4130+
}
4131+
}
4132+
4133+
}
4134+
double rescaled = size * scale;
4135+
// round to unit if the result is pixels to avoid a weird looking SLD (people often think
4136+
// of pixels as integers, even if SLD allows for float values in there
4137+
if ( roundToUnit )
4138+
{
4139+
rescaled = qRound( rescaled );
4140+
}
4141+
return rescaled;
4142+
}
4143+
4144+
QPointF QgsSymbolLayerV2Utils::rescaleUom( const QPointF& point, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props )
4145+
{
4146+
double x = rescaleUom( point.x(), unit, props );
4147+
double y = rescaleUom( point.y(), unit, props );
4148+
return QPointF( x, y );
4149+
}
4150+
4151+
QVector<qreal> QgsSymbolLayerV2Utils::rescaleUom( const QVector<qreal>& array, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props )
4152+
{
4153+
QVector<qreal> result;
4154+
QVector<qreal>::const_iterator it = array.constBegin();
4155+
for ( ; it != array.constEnd(); ++it )
4156+
{
4157+
result.append( rescaleUom( *it, unit, props ) );
4158+
}
4159+
return result;
4160+
}

src/core/symbology-ng/qgssymbollayerv2utils.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,28 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
479479
*/
480480
static QList<double> prettyBreaks( double minimum, double maximum, int classes );
481481

482+
/** Rescales the given size based on the uomScale found in the props, if any is found, otherwise
483+
* returns the value un-modified
484+
* @note added in 3.0
485+
* @note not available in Python bindings
486+
*/
487+
static double rescaleUom( double size, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props );
488+
489+
/** Rescales the given point based on the uomScale found in the props, if any is found, otherwise
490+
* returns a copy of the original point
491+
* @note added in 3.0
492+
* @note not available in Python bindings
493+
*/
494+
static QPointF rescaleUom( const QPointF& point, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props );
495+
496+
/** Rescales the given array based on the uomScale found in the props, if any is found, otherwise
497+
* returns a copy of the original point
498+
* @note added in 3.0
499+
* @note not available in Python bindings
500+
*/
501+
static QVector<qreal> rescaleUom( const QVector<qreal>& array, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props );
502+
503+
482504
};
483505

484506
class QPolygonF;

0 commit comments

Comments
 (0)