QGIS API Documentation  3.21.0-Master (5b68dc587e)
qgsmasksymbollayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmasksymbollayer.cpp
3  ---------------------
4  begin : July 2019
5  copyright : (C) 2019 by Hugo Mercier
6  email : hugo dot mercier at oslandia dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsmasksymbollayer.h"
17 #include "qgssymbollayerutils.h"
18 #include "qgsproject.h"
19 #include "qgsvectorlayer.h"
20 #include "qgspainteffect.h"
21 #include "qgspainterswapper.h"
22 #include "qgsmarkersymbol.h"
24 
26 {
27  mSymbol.reset( static_cast<QgsMarkerSymbol *>( QgsMarkerSymbol::createSimple( QVariantMap() ) ) );
28 }
29 
31 
33 {
34  return !mMaskedSymbolLayers.isEmpty();
35 }
36 
38 {
39  if ( symbol && symbol->type() == Qgis::SymbolType::Marker )
40  {
41  mSymbol.reset( static_cast<QgsMarkerSymbol *>( symbol ) );
42  return true;
43  }
44  delete symbol;
45  return false;
46 }
47 
49 {
51 
53 
54  if ( props.contains( QStringLiteral( "mask_symbollayers" ) ) )
55  {
56  l->setMasks( stringToSymbolLayerReferenceList( props[QStringLiteral( "mask_symbollayers" )].toString() ) );
57  }
58  return l;
59 }
60 
62 {
64  l->setSubSymbol( mSymbol->clone() );
65  l->setMasks( mMaskedSymbolLayers );
67  copyPaintEffect( l );
68  return l;
69 }
70 
72 {
73  return mSymbol.get();
74 }
75 
77 {
78  return QStringLiteral( "MaskMarker" );
79 }
80 
82 {
83  QVariantMap props;
84  props[QStringLiteral( "mask_symbollayers" )] = symbolLayerReferenceListToString( masks() );
85  return props;
86 }
87 
88 QSet<QString> QgsMaskMarkerSymbolLayer::usedAttributes( const QgsRenderContext &context ) const
89 {
90  QSet<QString> attributes = QgsMarkerSymbolLayer::usedAttributes( context );
91 
92  attributes.unite( mSymbol->usedAttributes( context ) );
93 
94  return attributes;
95 }
96 
98 {
100  return true;
101  if ( mSymbol && mSymbol->hasDataDefinedProperties() )
102  return true;
103  return false;
104 }
105 
107 {
108  // since we need to swap the regular painter with the mask painter during rendering,
109  // effects won't work. So we cheat by handling effects ourselves in renderPoint
110  if ( auto *lPaintEffect = paintEffect() )
111  {
112  mEffect.reset( lPaintEffect->clone() );
113  setPaintEffect( nullptr );
114  }
115  mSymbol->startRender( context.renderContext() );
116 }
117 
119 {
120  mSymbol->stopRender( context.renderContext() );
121  if ( mEffect )
122  {
123  setPaintEffect( mEffect.release() );
124  }
125 }
126 
128 {
130 }
131 
132 QList<QgsSymbolLayerReference> QgsMaskMarkerSymbolLayer::masks() const
133 {
134  return mMaskedSymbolLayers;
135 }
136 
137 void QgsMaskMarkerSymbolLayer::setMasks( const QList<QgsSymbolLayerReference> &maskedLayers )
138 {
139  mMaskedSymbolLayers = maskedLayers;
140 }
141 
143 {
144  return mSymbol->bounds( point, context.renderContext() );
145 }
146 
148 {
150  || ( mSymbol && mSymbol->usesMapUnits() );
151 }
152 
154 {
155  if ( !context.renderContext().painter() )
156  return;
157 
158  if ( context.renderContext().isGuiPreview() )
159  {
160  mSymbol->renderPoint( point, context.feature(), context.renderContext(), /* layer = */ -1, /* selected = */ false );
161  return;
162  }
163 
164  if ( ! context.renderContext().maskPainter() )
165  return;
166 
167  if ( mMaskedSymbolLayers.isEmpty() )
168  return;
169 
170  {
171  // Otherwise switch to the mask painter before rendering
172  const QgsPainterSwapper swapper( context.renderContext(), context.renderContext().maskPainter() );
173 
174  // Special case when an effect is defined on this mask symbol layer
175  // (effects defined on sub symbol's layers do not need special handling)
176  if ( mEffect && mEffect->enabled() )
177  {
178  QgsEffectPainter p( context.renderContext() );
179  // translate operates on the mask painter, which is what we want
180  p->translate( point );
181  p.setEffect( mEffect.get() );
182  mSymbol->renderPoint( QPointF( 0, 0 ), context.feature(), context.renderContext(), /* layer = */ -1, /* selected = */ false );
183  // the translation will be canceled at the end of scope here
184  }
185  else
186  {
187  mSymbol->renderPoint( point, context.feature(), context.renderContext(), /* layer = */ -1, /* selected = */ false );
188  }
189  }
190 }
191 
192 
@ Marker
Marker symbol.
A class to manager painter saving and restoring required for effect drawing.
void setEffect(QgsPaintEffect *effect)
Sets the effect to be painted.
void drawPreviewIcon(QgsSymbolRenderContext &context, QSize size) override
double size() const
Returns the symbol size.
QgsUnitTypes::RenderUnit mSizeUnit
Marker size unit.
A marker symbol type, for rendering Point and MultiPoint geometries.
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Special symbol layer that uses its sub symbol as a selective mask.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Create a new QgsMaskMarkerSymbolLayer.
void setMasks(const QList< QgsSymbolLayerReference > &maskedLayers)
Sets the symbol layers that will be masked by the sub symbol's shape.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QgsMaskMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
QString layerType() const override
Returns a string that represents this layer type.
bool enabled() const
Whether some masked symbol layers are defined.
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
~QgsMaskMarkerSymbolLayer() override
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
QList< QgsSymbolLayerReference > masks() const override
Returns a list of references to symbol layers that are masked by the sub symbol's shape.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsMaskMarkerSymbolLayer()
Simple constructor.
virtual void drawPreviewIcon(QgsSymbolRenderContext &context, QSize size) override
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
A class to manage painter saving and restoring required for drawing on a different painter (mask pain...
Contains information about the context of a rendering operation.
QPainter * maskPainter(int id=0)
Returns a mask QPainter for the render operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
bool isGuiPreview() const
Returns the Gui preview mode.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
const QgsFeature * feature() const
Returns the current feature being rendered.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:38
Qgis::SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:97
@ RenderMetersInMapUnits
Meters value as Map units.
Definition: qgsunittypes.h:176
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
QString symbolLayerReferenceListToString(const QgsSymbolLayerReferenceList &lst)
Utilitary function to turn a QgsSymbolLayerReferenceList into a string.
QgsSymbolLayerReferenceList stringToSymbolLayerReferenceList(const QString &str)
Utilitary function to parse a string originated from symbolLayerReferenceListToString into a QgsSymbo...