Skip to content
Permalink
Browse files

[feature][labeling] Use fill symbols to render rectangle,square,circl…

…e,ellipse background shields
  • Loading branch information
nirvn committed May 4, 2021
1 parent e66e305 commit 4fad4bac0fc6c4942492ece7d71866dd26dc8579
Showing with 295 additions and 101 deletions.
  1. +67 −0 python/core/auto_generated/textrenderer/qgstextbackgroundsettings.sip.in
  2. +93 −5 src/core/textrenderer/qgstextbackgroundsettings.cpp
  3. +37 −0 src/core/textrenderer/qgstextbackgroundsettings.h
  4. +24 −27 src/core/textrenderer/qgstextrenderer.cpp
  5. +2 −0 src/core/textrenderer/qgstextrenderer_p.h
  6. +2 −1 src/gui/labeling/qgslabelinggui.cpp
  7. +37 −42 src/gui/qgstextformatwidget.cpp
  8. +0 −1 src/gui/qgstextformatwidget.h
  9. +13 −24 src/ui/qgstextformatwidgetbase.ui
  10. +0 −1 tests/src/python/test_qgstextformatwidget.py
  11. +20 −0 tests/src/python/test_qgstextrenderer.py
  12. BIN ...ta/control_images/expected_pal_canvas/sp_background_rect_w_offset/sp_background_rect_w_offset.png
  13. BIN ...ntrol_images/expected_pal_canvas/sp_background_rect_w_offset/sp_background_rect_w_offset_mask.png
  14. BIN ..._images/expected_pal_composer/sp_img_background_rect_w_offset/sp_img_background_rect_w_offset.png
  15. BIN ..._images/expected_pal_composer/sp_pdf_background_rect_w_offset/sp_pdf_background_rect_w_offset.png
  16. BIN ...es/expected_pal_composer/sp_pdf_background_rect_w_offset/sp_pdf_background_rect_w_offset_mask.png
  17. BIN ..._images/expected_pal_composer/sp_svg_background_rect_w_offset/sp_svg_background_rect_w_offset.png
  18. BIN ...es/expected_pal_composer/sp_svg_background_rect_w_offset/sp_svg_background_rect_w_offset_mask.png
  19. BIN tests/testdata/control_images/text_renderer/background_ellipse_pixels/background_ellipse_pixels.png
  20. BIN ...estdata/control_images/text_renderer/background_ellipse_pixels/background_ellipse_pixels_mask.png
  21. BIN tests/testdata/control_images/text_renderer/background_fillsymbol/background_fillsymbol.png
  22. BIN tests/testdata/control_images/text_renderer/background_offset_mm/background_offset_mm.png
  23. BIN tests/testdata/control_images/text_renderer/background_offset_mm/background_offset_mm_mask.png
  24. BIN tests/testdata/control_images/text_renderer/background_opacity/background_opacity.png
  25. BIN tests/testdata/control_images/text_renderer/background_opacity/background_opacity_mask.png
  26. BIN ...ol_images/text_renderer/background_rect_multiline_mapunits/background_rect_multiline_mapunits.png
  27. BIN ...ages/text_renderer/background_rect_multiline_mapunits/background_rect_multiline_mapunits_mask.png
@@ -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;
@@ -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 );
@@ -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;
@@ -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 );
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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
@@ -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;
}

@@ -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;
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
}

@@ -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.