Skip to content
Permalink
Browse files
Don't expose an outline subsymbol for SVG fill symbol layers
This is inconsistent with all other fill types, which don't
have a special outline subsymbol. Users should be creating
outline layers when they want an outline instead.

When reading an SVG fill symbol layer from XML, automatically
upgrade any outline subsymbol which is used by the fill to
be separate symbol layers for the parent fill symbol so
that existing symbols will appear as designed in older QGIS
versions.

Fixes #14103
  • Loading branch information
nyalldawson committed Oct 23, 2021
1 parent 853f218 commit ec41cb59b44b1b4190b7e7ae516d429e55611e84
@@ -818,11 +818,6 @@ Base class for polygon renderers generating texture images
virtual void renderPolygon( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context );


virtual QgsSymbol *subSymbol();

virtual bool setSubSymbol( QgsSymbol *symbol /Transfer/ );


void setStrokeWidthUnit( QgsUnitTypes::RenderUnit unit );
%Docstring
Sets the ``units`` fo the symbol's stroke width.
@@ -893,28 +888,19 @@ fill is positioned relative to the feature.

virtual QgsMapUnitScale mapUnitScale() const;

virtual double estimateMaxBleed( const QgsRenderContext &context ) const;

virtual double dxfWidth( const QgsDxfExport &e, QgsSymbolRenderContext &context ) const;

virtual QColor dxfColor( QgsSymbolRenderContext &context ) const;

virtual Qt::PenStyle dxfPenStyle() const;

virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;

virtual QVariantMap properties() const;

virtual bool hasDataDefinedProperties() const;


protected:



virtual void applyDataDefinedSettings( QgsSymbolRenderContext &context );
%Docstring
Custom stroke
Applies data defined settings prior to generating the fill symbol brush.
%End

virtual bool applyBrushTransformFromContext( QgsSymbolRenderContext *context = 0 ) const;
@@ -1256,6 +1242,8 @@ Used internally when reading/writing symbols.

virtual void stopRender( QgsSymbolRenderContext &context );

virtual void renderPolygon( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context );

virtual QVariantMap properties() const;

virtual QgsSVGFillSymbolLayer *clone() const /Factory/;
@@ -1264,6 +1252,18 @@ Used internally when reading/writing symbols.

virtual bool usesMapUnits() const;

virtual QgsSymbol *subSymbol();

virtual bool setSubSymbol( QgsSymbol *symbol /Transfer/ );

virtual double estimateMaxBleed( const QgsRenderContext &context ) const;

virtual QColor dxfColor( QgsSymbolRenderContext &context ) const;

virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;

virtual bool hasDataDefinedProperties() const;


void setSvgFilePath( const QString &svgPath );
%Docstring
@@ -1702,7 +1702,6 @@ QgsMapUnitScale QgsShapeburstFillSymbolLayer::mapUnitScale() const

QgsImageFillSymbolLayer::QgsImageFillSymbolLayer()
{
setSubSymbol( new QgsLineSymbol() );
}

QgsImageFillSymbolLayer::~QgsImageFillSymbolLayer() = default;
@@ -1750,51 +1749,10 @@ void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF &points, const QVec
}
p->setBrush( mBrush );
_renderPolygon( p, points, rings, context );
if ( mStroke )
{
mStroke->renderPolyline( points, context.feature(), context.renderContext(), -1, SELECT_FILL_BORDER && context.selected() );
if ( rings )
{
for ( auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
{
mStroke->renderPolyline( *ringIt, context.feature(), context.renderContext(), -1, SELECT_FILL_BORDER && context.selected() );
}
}
}

mBrush.setTransform( bkTransform );
}

QgsSymbol *QgsImageFillSymbolLayer::subSymbol()
{
return mStroke.get();
}

bool QgsImageFillSymbolLayer::setSubSymbol( QgsSymbol *symbol )
{
if ( !symbol ) //unset current stroke
{
mStroke.reset( nullptr );
return true;
}

if ( symbol->type() != Qgis::SymbolType::Line )
{
delete symbol;
return false;
}

QgsLineSymbol *lineSymbol = dynamic_cast<QgsLineSymbol *>( symbol );
if ( lineSymbol )
{
mStroke.reset( lineSymbol );
return true;
}

delete symbol;
return false;
}

void QgsImageFillSymbolLayer::setOutputUnit( QgsUnitTypes::RenderUnit unit )
{
mStrokeWidthUnit = unit;
@@ -1815,16 +1773,6 @@ QgsMapUnitScale QgsImageFillSymbolLayer::mapUnitScale() const
return mStrokeWidthMapUnitScale;
}

double QgsImageFillSymbolLayer::estimateMaxBleed( const QgsRenderContext &context ) const
{
if ( mStroke && mStroke->symbolLayer( 0 ) )
{
double subLayerBleed = mStroke->symbolLayer( 0 )->estimateMaxBleed( context );
return subLayerBleed;
}
return 0;
}

double QgsImageFillSymbolLayer::dxfWidth( const QgsDxfExport &e, QgsSymbolRenderContext &context ) const
{
double width = mStrokeWidth;
@@ -1836,16 +1784,6 @@ double QgsImageFillSymbolLayer::dxfWidth( const QgsDxfExport &e, QgsSymbolRender
return width * e.mapUnitScaleFactor( e.symbologyScale(), mStrokeWidthUnit, e.mapUnits(), context.renderContext().mapToPixel().mapUnitsPerPixel() );
}

QColor QgsImageFillSymbolLayer::dxfColor( QgsSymbolRenderContext &context ) const
{
Q_UNUSED( context )
if ( !mStroke )
{
return QColor( Qt::black );
}
return mStroke->color();
}

Qt::PenStyle QgsImageFillSymbolLayer::dxfPenStyle() const
{
return Qt::SolidLine;
@@ -1868,23 +1806,6 @@ QVariantMap QgsImageFillSymbolLayer::properties() const
return map;
}

QSet<QString> QgsImageFillSymbolLayer::usedAttributes( const QgsRenderContext &context ) const
{
QSet<QString> attr = QgsFillSymbolLayer::usedAttributes( context );
if ( mStroke )
attr.unite( mStroke->usedAttributes( context ) );
return attr;
}

bool QgsImageFillSymbolLayer::hasDataDefinedProperties() const
{
if ( QgsSymbolLayer::hasDataDefinedProperties() )
return true;
if ( mStroke && mStroke->hasDataDefinedProperties() )
return true;
return false;
}

bool QgsImageFillSymbolLayer::applyBrushTransformFromContext( QgsSymbolRenderContext *context ) const
{
//coordinate reference
@@ -1926,7 +1847,6 @@ QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray &svgData, double
mStrokeWidth = 0.3;
mAngle = angle;
mColor = QColor( 255, 255, 255 );
setSubSymbol( new QgsLineSymbol() );
setDefaultSvgParams();
}

@@ -1938,7 +1858,8 @@ void QgsSVGFillSymbolLayer::setOutputUnit( QgsUnitTypes::RenderUnit unit )
mPatternWidthUnit = unit;
mSvgStrokeWidthUnit = unit;
mStrokeWidthUnit = unit;
mStroke->setOutputUnit( unit );
if ( mStroke )
mStroke->setOutputUnit( unit );
}

QgsUnitTypes::RenderUnit QgsSVGFillSymbolLayer::outputUnit() const
@@ -2177,6 +2098,23 @@ void QgsSVGFillSymbolLayer::stopRender( QgsSymbolRenderContext &context )
}
}

void QgsSVGFillSymbolLayer::renderPolygon( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context )
{
QgsImageFillSymbolLayer::renderPolygon( points, rings, context );

if ( mStroke )
{
mStroke->renderPolyline( points, context.feature(), context.renderContext(), -1, SELECT_FILL_BORDER && context.selected() );
if ( rings )
{
for ( auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
{
mStroke->renderPolyline( *ringIt, context.feature(), context.renderContext(), -1, SELECT_FILL_BORDER && context.selected() );
}
}
}
}

QVariantMap QgsSVGFillSymbolLayer::properties() const
{
QVariantMap map;
@@ -2304,6 +2242,73 @@ bool QgsSVGFillSymbolLayer::usesMapUnits() const
|| mSvgStrokeWidthUnit == QgsUnitTypes::RenderMapUnits || mSvgStrokeWidthUnit == QgsUnitTypes::RenderMetersInMapUnits;
}

QgsSymbol *QgsSVGFillSymbolLayer::subSymbol()
{
return mStroke.get();
}

bool QgsSVGFillSymbolLayer::setSubSymbol( QgsSymbol *symbol )
{
if ( !symbol ) //unset current stroke
{
mStroke.reset( nullptr );
return true;
}

if ( symbol->type() != Qgis::SymbolType::Line )
{
delete symbol;
return false;
}

QgsLineSymbol *lineSymbol = dynamic_cast<QgsLineSymbol *>( symbol );
if ( lineSymbol )
{
mStroke.reset( lineSymbol );
return true;
}

delete symbol;
return false;
}

double QgsSVGFillSymbolLayer::estimateMaxBleed( const QgsRenderContext &context ) const
{
if ( mStroke && mStroke->symbolLayer( 0 ) )
{
double subLayerBleed = mStroke->symbolLayer( 0 )->estimateMaxBleed( context );
return subLayerBleed;
}
return 0;
}

QColor QgsSVGFillSymbolLayer::dxfColor( QgsSymbolRenderContext &context ) const
{
Q_UNUSED( context )
if ( !mStroke )
{
return QColor( Qt::black );
}
return mStroke->color();
}

QSet<QString> QgsSVGFillSymbolLayer::usedAttributes( const QgsRenderContext &context ) const
{
QSet<QString> attr = QgsImageFillSymbolLayer::usedAttributes( context );
if ( mStroke )
attr.unite( mStroke->usedAttributes( context ) );
return attr;
}

bool QgsSVGFillSymbolLayer::hasDataDefinedProperties() const
{
if ( QgsImageFillSymbolLayer::hasDataDefinedProperties() )
return true;
if ( mStroke && mStroke->hasDataDefinedProperties() )
return true;
return false;
}

QgsSymbolLayer *QgsSVGFillSymbolLayer::createFromSld( QDomElement &element )
{
QString path, mimeType;
@@ -3561,11 +3566,6 @@ void QgsPointPatternFillSymbolLayer::startRender( QgsSymbolRenderContext &contex
// optimised render for screen only, use image based brush
applyPattern( context, mBrush, mDistanceX, mDistanceY, mDisplacementX, mDisplacementY, mOffsetX, mOffsetY );
}

if ( mStroke )
{
mStroke->startRender( context.renderContext(), context.fields() );
}
}

void QgsPointPatternFillSymbolLayer::stopRender( QgsSymbolRenderContext &context )
@@ -3574,11 +3574,6 @@ void QgsPointPatternFillSymbolLayer::stopRender( QgsSymbolRenderContext &context
{
mMarkerSymbol->stopRender( context.renderContext() );
}

if ( mStroke )
{
mStroke->stopRender( context.renderContext() );
}
}

void QgsPointPatternFillSymbolLayer::renderPolygon( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context )
@@ -3833,18 +3828,6 @@ void QgsPointPatternFillSymbolLayer::renderPolygon( const QPolygonF &points, con

p->restore();

if ( mStroke )
{
mStroke->renderPolyline( points, context.feature(), context.renderContext(), -1, SELECT_FILL_BORDER && context.selected() );
if ( rings )
{
for ( auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
{
mStroke->renderPolyline( *ringIt, context.feature(), context.renderContext(), -1, SELECT_FILL_BORDER && context.selected() );
}
}
}

context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );
}

0 comments on commit ec41cb5

Please sign in to comment.