Skip to content

Commit

Permalink
[feature][labeling] Use fill symbols to render rectangle,square,circl…
Browse files Browse the repository at this point in the history
…e,ellipse background shields
  • Loading branch information
nirvn committed May 4, 2021
1 parent e66e305 commit 4fad4ba
Show file tree
Hide file tree
Showing 27 changed files with 295 additions and 101 deletions.
Expand Up @@ -141,6 +141,38 @@ to the background settings.
.. seealso:: :py:func:`markerSymbol`

.. versionadded:: 3.10
%End

QgsFillSymbol *fillSymbol() const;
%Docstring
Returns the fill symbol to be rendered in the background. Ownership remains with
the background settings.

.. note::

This is only used when the :py:func:`~QgsTextBackgroundSettings.type` is QgsTextBackgroundSettings.ShapeRectangle .
QgsTextBackgroundSettings.ShapeSquare, QgsTextBackgroundSettings.ShapeCircle or
QgsTextBackgroundSettings.ShapeEllipse

.. seealso:: :py:func:`setFillSymbol`

.. versionadded:: 3.20
%End

void setFillSymbol( QgsFillSymbol *symbol /Transfer/ );
%Docstring
Sets the current fill ``symbol`` for the background shape. Ownership is transferred
to the background settings.

.. note::

This is only used when the :py:func:`~QgsTextBackgroundSettings.type` is QgsTextBackgroundSettings.ShapeRectangle .
QgsTextBackgroundSettings.ShapeSquare, QgsTextBackgroundSettings.ShapeCircle or
QgsTextBackgroundSettings.ShapeEllipse

.. seealso:: :py:func:`fillSymbol`

.. versionadded:: 3.20
%End

SizeType sizeType() const;
Expand Down Expand Up @@ -447,6 +479,11 @@ Returns the color used for filing the background shape.
.. seealso:: :py:func:`setFillColor`

.. seealso:: :py:func:`strokeColor`

.. note::

As of QGIS 3.20, using this function is only recommended for SVG backgrounds, while
other background types should be configured through their symbols.
%End

void setFillColor( const QColor &color );
Expand All @@ -458,6 +495,11 @@ Sets the color used for filing the background shape.
.. seealso:: :py:func:`fillColor`

.. seealso:: :py:func:`setStrokeColor`

.. note::

As of QGIS 3.20, using this function is only recommended for SVG backgrounds, while
other background types should be configured through their symbols.
%End

QColor strokeColor() const;
Expand All @@ -467,6 +509,11 @@ Returns the color used for outlining the background shape.
.. seealso:: :py:func:`setStrokeColor`

.. seealso:: :py:func:`fillColor`

.. note::

As of QGIS 3.20, using this function is only recommended for SVG backgrounds, while
other background types should be configured through their symbols.
%End

void setStrokeColor( const QColor &color );
Expand Down Expand Up @@ -498,6 +545,11 @@ Sets the width of the shape's stroke (stroke). Units are specified through
.. seealso:: :py:func:`strokeWidth`

.. seealso:: :py:func:`setStrokeWidthUnit`

.. note::

As of QGIS 3.20, using this function is only recommended for SVG backgrounds, while
other background types should be configured through their symbols.
%End

QgsUnitTypes::RenderUnit strokeWidthUnit() const;
Expand All @@ -518,6 +570,11 @@ Sets the units used for the shape's stroke width.
.. seealso:: :py:func:`strokeWidthUnit`

.. seealso:: :py:func:`setStrokeWidth`

.. note::

As of QGIS 3.20, using this function is only recommended for SVG backgrounds, while
other background types should be configured through their symbols.
%End

QgsMapUnitScale strokeWidthMapUnitScale() const;
Expand All @@ -540,6 +597,11 @@ Sets the map unit scale object for the shape stroke width. This is only used if
.. seealso:: :py:func:`strokeWidthMapUnitScale`

.. seealso:: :py:func:`setStrokeWidthUnit`

.. note::

As of QGIS 3.20, using this function is only recommended for SVG backgrounds, while
other background types should be configured through their symbols.
%End

Qt::PenJoinStyle joinStyle() const;
Expand All @@ -556,6 +618,11 @@ Sets the join style used for drawing the background shape.
:param style: join style

.. seealso:: :py:func:`joinStyle`

.. note::

As of QGIS 3.20, using this function is only recommended for SVG backgrounds, while
other background types should be configured through their symbols.
%End

const QgsPaintEffect *paintEffect() const;
Expand Down
98 changes: 93 additions & 5 deletions src/core/textrenderer/qgstextbackgroundsettings.cpp
Expand Up @@ -18,13 +18,26 @@
#include "qgsvectorlayer.h"
#include "qgspallabeling.h"
#include "qgssymbollayerutils.h"
#include "qgsfillsymbollayer.h"
#include "qgspainting.h"
#include "qgstextrendererutils.h"
#include "qgspainteffectregistry.h"

QgsTextBackgroundSettings::QgsTextBackgroundSettings()
{
d = new QgsTextBackgroundSettingsPrivate();

// Create a default fill symbol to preserve API promise until QGIS 4.0
QgsSimpleFillSymbolLayer *fill = new QgsSimpleFillSymbolLayer( d->fillColor, Qt::SolidPattern, d->strokeColor );
fill->setStrokeWidth( d->strokeWidth );
fill->setStrokeWidthUnit( d->strokeWidthUnits );
fill->setStrokeWidthMapUnitScale( d->strokeWidthMapUnitScale );
fill->setStrokeStyle( !qgsDoubleNear( d->strokeWidth, 0.0 ) ? Qt::SolidLine : Qt::NoPen );
fill->setPenJoinStyle( d->joinStyle );

QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, fill );
setFillSymbol( fillSymbol );
}

QgsTextBackgroundSettings::QgsTextBackgroundSettings( const QgsTextBackgroundSettings &other ) //NOLINT
Expand Down Expand Up @@ -79,6 +92,10 @@ bool QgsTextBackgroundSettings::operator==( const QgsTextBackgroundSettings &oth
|| ( d->markerSymbol && QgsSymbolLayerUtils::symbolProperties( d->markerSymbol.get() ) != QgsSymbolLayerUtils::symbolProperties( other.markerSymbol() ) ) )
return false;

if ( static_cast< bool >( d->fillSymbol ) != static_cast< bool >( other.fillSymbol() )
|| ( d->fillSymbol && QgsSymbolLayerUtils::symbolProperties( d->fillSymbol.get() ) != QgsSymbolLayerUtils::symbolProperties( other.fillSymbol() ) ) )
return false;

return true;
}

Expand Down Expand Up @@ -127,6 +144,16 @@ void QgsTextBackgroundSettings::setMarkerSymbol( QgsMarkerSymbol *symbol )
d->markerSymbol.reset( symbol );
}

QgsFillSymbol *QgsTextBackgroundSettings::fillSymbol() const
{
return d->fillSymbol.get();
}

void QgsTextBackgroundSettings::setFillSymbol( QgsFillSymbol *symbol )
{
d->fillSymbol.reset( symbol );
}

QgsTextBackgroundSettings::SizeType QgsTextBackgroundSettings::sizeType() const
{
return d->sizeType;
Expand Down Expand Up @@ -275,6 +302,10 @@ QColor QgsTextBackgroundSettings::fillColor() const
void QgsTextBackgroundSettings::setFillColor( const QColor &color )
{
d->fillColor = color;
if ( d->fillSymbol )
{
d->fillSymbol->setColor( color );
}
}

QColor QgsTextBackgroundSettings::strokeColor() const
Expand All @@ -285,6 +316,10 @@ QColor QgsTextBackgroundSettings::strokeColor() const
void QgsTextBackgroundSettings::setStrokeColor( const QColor &color )
{
d->strokeColor = color;
if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QStringLiteral( "SimpleFill" ) )
{
static_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setStrokeColor( color );
}
}

double QgsTextBackgroundSettings::strokeWidth() const
Expand All @@ -295,6 +330,12 @@ double QgsTextBackgroundSettings::strokeWidth() const
void QgsTextBackgroundSettings::setStrokeWidth( double width )
{
d->strokeWidth = width;
if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QStringLiteral( "SimpleFill" ) )
{
QgsSimpleFillSymbolLayer *fill = static_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) );
fill->setStrokeWidth( width );
fill->setStrokeStyle( !qgsDoubleNear( width, 0.0 ) ? Qt::SolidLine : Qt::NoPen );
}
}

QgsUnitTypes::RenderUnit QgsTextBackgroundSettings::strokeWidthUnit() const
Expand All @@ -305,6 +346,10 @@ QgsUnitTypes::RenderUnit QgsTextBackgroundSettings::strokeWidthUnit() const
void QgsTextBackgroundSettings::setStrokeWidthUnit( QgsUnitTypes::RenderUnit units )
{
d->strokeWidthUnits = units;
if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QStringLiteral( "SimpleFill" ) )
{
static_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setStrokeWidthUnit( units );
}
}

QgsMapUnitScale QgsTextBackgroundSettings::strokeWidthMapUnitScale() const
Expand All @@ -315,6 +360,10 @@ QgsMapUnitScale QgsTextBackgroundSettings::strokeWidthMapUnitScale() const
void QgsTextBackgroundSettings::setStrokeWidthMapUnitScale( const QgsMapUnitScale &scale )
{
d->strokeWidthMapUnitScale = scale;
if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QStringLiteral( "SimpleFill" ) )
{
static_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setStrokeWidthMapUnitScale( scale );
}
}

Qt::PenJoinStyle QgsTextBackgroundSettings::joinStyle() const
Expand All @@ -325,6 +374,10 @@ Qt::PenJoinStyle QgsTextBackgroundSettings::joinStyle() const
void QgsTextBackgroundSettings::setJoinStyle( Qt::PenJoinStyle style )
{
d->joinStyle = style;
if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QStringLiteral( "SimpleFill" ) )
{
static_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setPenJoinStyle( style );
}
}

const QgsPaintEffect *QgsTextBackgroundSettings::paintEffect() const
Expand Down Expand Up @@ -589,11 +642,39 @@ void QgsTextBackgroundSettings::readXml( const QDomElement &elem, const QgsReadW
else
setPaintEffect( nullptr );

const QDomElement symbolElem = backgroundElem.firstChildElement( QStringLiteral( "symbol" ) );
if ( !symbolElem.isNull() )
setMarkerSymbol( QgsSymbolLayerUtils::loadSymbol< QgsMarkerSymbol >( symbolElem, context ) );
else
setMarkerSymbol( nullptr );
setMarkerSymbol( nullptr );
setFillSymbol( nullptr );
const QDomNodeList symbols = backgroundElem.elementsByTagName( QStringLiteral( "symbol" ) );
for ( int i = 0; i < symbols.size(); ++i )
{
if ( symbols.at( i ).isElement() )
{
const QDomElement symbolElement = symbols.at( i ).toElement();
const QString symbolElementName = symbolElement.attribute( QStringLiteral( "name" ) );
if ( symbolElementName == QStringLiteral( "markerSymbol" ) )
{
setMarkerSymbol( QgsSymbolLayerUtils::loadSymbol< QgsMarkerSymbol >( symbolElement, context ) );
}
else if ( symbolElementName == QStringLiteral( "fillSymbol" ) )
{
setFillSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( symbolElement, context ) );
}
}
}

if ( !d->fillSymbol )
{
QgsSimpleFillSymbolLayer *fill = new QgsSimpleFillSymbolLayer( d->fillColor, Qt::SolidPattern, d->strokeColor );
fill->setStrokeWidth( d->strokeWidth );
fill->setStrokeWidthUnit( d->strokeWidthUnits );
fill->setStrokeWidthMapUnitScale( d->strokeWidthMapUnitScale );
fill->setStrokeStyle( !qgsDoubleNear( d->strokeWidth, 0.0 ) ? Qt::SolidLine : Qt::NoPen );
fill->setPenJoinStyle( d->joinStyle );

QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, fill );
setFillSymbol( fillSymbol );
}
}

QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
Expand Down Expand Up @@ -631,6 +712,9 @@ QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument &doc, const QgsRea
if ( d->markerSymbol )
backgroundElem.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "markerSymbol" ), d->markerSymbol.get(), doc, context ) );

if ( d->fillSymbol )
backgroundElem.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "fillSymbol" ), d->fillSymbol.get(), doc, context ) );

return backgroundElem;
}

Expand Down Expand Up @@ -818,5 +902,9 @@ QSet<QString> QgsTextBackgroundSettings::referencedFields( const QgsRenderContex
{
fields.unite( d->markerSymbol->usedAttributes( context ) );
}
if ( d->fillSymbol )
{
fields.unite( d->fillSymbol->usedAttributes( context ) );
}
return fields;
}

0 comments on commit 4fad4ba

Please sign in to comment.