QGIS API Documentation  3.20.0-Odense (decaadbb31)
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  if ( symbol && symbol->type() == Qgis::SymbolType::Marker )
35  {
36  mSymbol.reset( static_cast<QgsMarkerSymbol *>( symbol ) );
37  return true;
38  }
39  delete symbol;
40  return false;
41 }
42 
44 {
46 
48 
49  if ( props.contains( QStringLiteral( "mask_symbollayers" ) ) )
50  {
51  l->setMasks( stringToSymbolLayerReferenceList( props[QStringLiteral( "mask_symbollayers" )].toString() ) );
52  }
53  return l;
54 }
55 
57 {
59  l->setSubSymbol( mSymbol->clone() );
60  l->setMasks( mMaskedSymbolLayers );
62  copyPaintEffect( l );
63  return l;
64 }
65 
67 {
68  return mSymbol.get();
69 }
70 
72 {
73  return QStringLiteral( "MaskMarker" );
74 }
75 
77 {
78  QVariantMap props;
79  props[QStringLiteral( "mask_symbollayers" )] = symbolLayerReferenceListToString( masks() );
80  return props;
81 }
82 
83 QSet<QString> QgsMaskMarkerSymbolLayer::usedAttributes( const QgsRenderContext &context ) const
84 {
85  QSet<QString> attributes = QgsMarkerSymbolLayer::usedAttributes( context );
86 
87  attributes.unite( mSymbol->usedAttributes( context ) );
88 
89  return attributes;
90 }
91 
93 {
95  return true;
96  if ( mSymbol && mSymbol->hasDataDefinedProperties() )
97  return true;
98  return false;
99 }
100 
102 {
103  // since we need to swap the regular painter with the mask painter during rendering,
104  // effects won't work. So we cheat by handling effects ourselves in renderPoint
105  if ( auto *lPaintEffect = paintEffect() )
106  {
107  mEffect.reset( lPaintEffect->clone() );
108  setPaintEffect( nullptr );
109  }
110  mSymbol->startRender( context.renderContext() );
111 }
112 
114 {
115  mSymbol->stopRender( context.renderContext() );
116  if ( mEffect )
117  {
118  setPaintEffect( mEffect.release() );
119  }
120 }
121 
123 {
125 }
126 
127 QList<QgsSymbolLayerReference> QgsMaskMarkerSymbolLayer::masks() const
128 {
129  return mMaskedSymbolLayers;
130 }
131 
132 void QgsMaskMarkerSymbolLayer::setMasks( const QList<QgsSymbolLayerReference> &maskedLayers )
133 {
134  mMaskedSymbolLayers = maskedLayers;
135 }
136 
138 {
139  return mSymbol->bounds( point, context.renderContext() );
140 }
141 
143 {
145  || ( mSymbol && mSymbol->usesMapUnits() );
146 }
147 
149 {
150  if ( !context.renderContext().painter() )
151  return;
152 
153  if ( context.renderContext().isGuiPreview() )
154  {
155  mSymbol->renderPoint( point, context.feature(), context.renderContext(), /* layer = */ -1, /* selected = */ false );
156  return;
157  }
158 
159  if ( ! context.renderContext().maskPainter() )
160  return;
161 
162  if ( mMaskedSymbolLayers.isEmpty() )
163  return;
164 
165  {
166  // Otherwise switch to the mask painter before rendering
167  QgsPainterSwapper swapper( context.renderContext(), context.renderContext().maskPainter() );
168 
169  // Special case when an effect is defined on this mask symbol layer
170  // (effects defined on sub symbol's layers do not need special handling)
171  if ( mEffect && mEffect->enabled() )
172  {
173  QgsEffectPainter p( context.renderContext() );
174  // translate operates on the mask painter, which is what we want
175  p->translate( point );
176  p.setEffect( mEffect.get() );
177  mSymbol->renderPoint( QPointF( 0, 0 ), context.feature(), context.renderContext(), /* layer = */ -1, /* selected = */ false );
178  // the translation will be canceled at the end of scope here
179  }
180  else
181  {
182  mSymbol->renderPoint( point, context.feature(), context.renderContext(), /* layer = */ -1, /* selected = */ false );
183  }
184  }
185 }
186 
187 
@ 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.
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...