Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsmarkersymbollayer.h
3 : : ---------------------
4 : : begin : November 2009
5 : : copyright : (C) 2009 by Martin Dobias
6 : : email : wonder dot sk at gmail 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 : : #ifndef QGSMARKERSYMBOLLAYER_H
17 : : #define QGSMARKERSYMBOLLAYER_H
18 : :
19 : : #include "qgis_core.h"
20 : : #include "qgis_sip.h"
21 : : #include "qgssymbollayer.h"
22 : :
23 : : #define DEFAULT_SIMPLEMARKER_NAME "circle"
24 : : #define DEFAULT_SIMPLEMARKER_COLOR QColor(255,0,0)
25 : : #define DEFAULT_SIMPLEMARKER_BORDERCOLOR QColor( 35, 35, 35 )
26 : : #define DEFAULT_SIMPLEMARKER_JOINSTYLE Qt::BevelJoin
27 : : #define DEFAULT_SIMPLEMARKER_SIZE DEFAULT_POINT_SIZE
28 : : #define DEFAULT_SIMPLEMARKER_ANGLE 0
29 : :
30 : : #include <QPen>
31 : : #include <QBrush>
32 : : #include <QPicture>
33 : : #include <QPolygonF>
34 : : #include <QFont>
35 : :
36 : : /**
37 : : * \ingroup core
38 : : * \class QgsSimpleMarkerSymbolLayerBase
39 : : * \brief Abstract base class for simple marker symbol layers. Handles creation of the symbol shapes but
40 : : * leaves the actual drawing of the symbols to subclasses.
41 : : * \since QGIS 2.16
42 : : */
43 : 234 : class CORE_EXPORT QgsSimpleMarkerSymbolLayerBase : public QgsMarkerSymbolLayer
44 : : {
45 : :
46 : : public:
47 : :
48 : : //! Marker symbol shapes
49 : : enum Shape
50 : : {
51 : : Square, //!< Square
52 : : Diamond, //!< Diamond
53 : : Pentagon, //!< Pentagon
54 : : Hexagon, //!< Hexagon
55 : : Triangle, //!< Triangle
56 : : EquilateralTriangle, //!< Equilateral triangle
57 : : Star, //!< Star
58 : : Arrow, //!< Arrow
59 : : Circle, //!< Circle
60 : : Cross, //!< Cross (lines only)
61 : : CrossFill, //!< Solid filled cross
62 : : Cross2, //!< Rotated cross (lines only), "x" shape
63 : : Line, //!< Vertical line
64 : : ArrowHead, //!< Right facing arrow head (unfilled, lines only)
65 : : ArrowHeadFilled, //!< Right facing filled arrow head
66 : : SemiCircle, //!< Semi circle (top half)
67 : : ThirdCircle, //!< One third circle (top left third)
68 : : QuarterCircle, //!< Quarter circle (top left quarter)
69 : : QuarterSquare, //!< Quarter square (top left quarter)
70 : : HalfSquare, //!< Half square (left half)
71 : : DiagonalHalfSquare, //!< Diagonal half square (bottom left half)
72 : : RightHalfTriangle, //!< Right half of triangle
73 : : LeftHalfTriangle, //!< Left half of triangle
74 : : Octagon, //!< Octagon (since QGIS 3.18)
75 : : SquareWithCorners, //!< A square with diagonal corners (since QGIS 3.18)
76 : : AsteriskFill, //!< A filled asterisk shape (since QGIS 3.18)
77 : : HalfArc, //!< A line-only half arc (since QGIS 3.20)
78 : : ThirdArc, //!< A line-only one third arc (since QGIS 3.20)
79 : : QuarterArc, //!< A line-only one quarter arc (since QGIS 3.20)
80 : : };
81 : :
82 : : //! Returns a list of all available shape types.
83 : : static QList< QgsSimpleMarkerSymbolLayerBase::Shape > availableShapes();
84 : :
85 : : /**
86 : : * Returns TRUE if a symbol shape has a fill.
87 : : * \param shape shape to test
88 : : * \returns TRUE if shape uses a fill, or FALSE if shape uses lines only
89 : : */
90 : : static bool shapeIsFilled( QgsSimpleMarkerSymbolLayerBase::Shape shape );
91 : :
92 : : /**
93 : : * Constructor for QgsSimpleMarkerSymbolLayerBase.
94 : : * \param shape symbol shape for markers
95 : : * \param size symbol size (in mm)
96 : : * \param angle symbol rotation angle
97 : : * \param scaleMethod scaling method for data defined scaling
98 : : */
99 : : QgsSimpleMarkerSymbolLayerBase( QgsSimpleMarkerSymbolLayerBase::Shape shape = Circle,
100 : : double size = DEFAULT_SIMPLEMARKER_SIZE,
101 : : double angle = DEFAULT_SIMPLEMARKER_ANGLE,
102 : : QgsSymbol::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD );
103 : :
104 : : /**
105 : : * Returns the shape for the rendered marker symbol.
106 : : * \see setShape()
107 : : */
108 : : QgsSimpleMarkerSymbolLayerBase::Shape shape() const { return mShape; }
109 : :
110 : : /**
111 : : * Sets the rendered marker shape.
112 : : * \param shape new marker shape
113 : : * \see shape()
114 : : */
115 : 0 : void setShape( QgsSimpleMarkerSymbolLayerBase::Shape shape ) { mShape = shape; }
116 : :
117 : : /**
118 : : * Attempts to decode a string representation of a shape name to the corresponding
119 : : * shape.
120 : : * \param name encoded shape name
121 : : * \param ok if specified, will be set to TRUE if shape was successfully decoded
122 : : * \returns decoded name
123 : : * \see encodeShape()
124 : : */
125 : : static QgsSimpleMarkerSymbolLayerBase::Shape decodeShape( const QString &name, bool *ok = nullptr );
126 : :
127 : : /**
128 : : * Encodes a shape to its string representation.
129 : : * \param shape shape to encode
130 : : * \returns encoded string
131 : : * \see decodeShape()
132 : : */
133 : : static QString encodeShape( QgsSimpleMarkerSymbolLayerBase::Shape shape );
134 : :
135 : : void startRender( QgsSymbolRenderContext &context ) override;
136 : : void stopRender( QgsSymbolRenderContext &context ) override;
137 : : void renderPoint( QPointF point, QgsSymbolRenderContext &context ) override;
138 : : QRectF bounds( QPointF point, QgsSymbolRenderContext &context ) override;
139 : :
140 : : protected:
141 : :
142 : : /**
143 : : * Prepares the layer for drawing the specified shape (QPolygonF version)
144 : : */
145 : : bool prepareMarkerShape( Shape shape );
146 : :
147 : : /**
148 : : * Prepares the layer for drawing the specified shape (QPainterPath version)
149 : : */
150 : : bool prepareMarkerPath( Shape symbol );
151 : :
152 : : /**
153 : : * Creates a polygon representing the specified shape.
154 : : * \param shape shape to create
155 : : * \param polygon destination polygon for shape
156 : : * \returns TRUE if shape was successfully stored in polygon
157 : : */
158 : : bool shapeToPolygon( Shape shape, QPolygonF &polygon ) const;
159 : :
160 : : /**
161 : : * Calculates the desired size of the marker, considering data defined size overrides.
162 : : * \param context symbol render context
163 : : * \param hasDataDefinedSize will be set to TRUE if marker uses data defined sizes
164 : : * \returns marker size, in original size units
165 : : */
166 : : double calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const;
167 : :
168 : : /**
169 : : * Calculates the marker offset and rotation.
170 : : * \param context symbol render context
171 : : * \param scaledSize size of symbol to render
172 : : * \param hasDataDefinedRotation will be set to TRUE if marker has data defined rotation
173 : : * \param offset will be set to calculated marker offset (in painter units)
174 : : * \param angle will be set to calculated marker angle
175 : : */
176 : : void calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedRotation, QPointF &offset, double &angle ) const;
177 : :
178 : : //! Polygon of points in shape. If polygon is empty then shape is using mPath.
179 : : QPolygonF mPolygon;
180 : :
181 : : //! Painter path representing shape. If mPolygon is empty then the shape is stored in mPath.
182 : : QPainterPath mPath;
183 : :
184 : : //! Symbol shape
185 : : Shape mShape;
186 : :
187 : : private:
188 : :
189 : : /**
190 : : * Derived classes must implement draw() to handle drawing the generated shape onto the painter surface.
191 : : * \param context symbol render context
192 : : * \param shape shape to draw
193 : : * \param polygon polygon representing transformed marker shape. May be empty, in which case the shape will be specified
194 : : * in the path argument.
195 : : * \param path transformed painter path representing shape to draw
196 : : */
197 : : virtual void draw( QgsSymbolRenderContext &context, QgsSimpleMarkerSymbolLayerBase::Shape shape, const QPolygonF &polygon, const QPainterPath &path ) = 0 SIP_FORCE;
198 : : };
199 : :
200 : : /**
201 : : * \ingroup core
202 : : * \class QgsSimpleMarkerSymbolLayer
203 : : * \brief Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
204 : : */
205 : 468 : class CORE_EXPORT QgsSimpleMarkerSymbolLayer : public QgsSimpleMarkerSymbolLayerBase
206 : : {
207 : : public:
208 : :
209 : : /**
210 : : * Constructor for QgsSimpleMarkerSymbolLayer.
211 : : * \param shape symbol shape
212 : : * \param size symbol size (in mm)
213 : : * \param angle symbol rotation angle
214 : : * \param scaleMethod scaling method for data defined scaling
215 : : * \param color fill color for symbol
216 : : * \param strokeColor stroke color for symbol
217 : : * \param penJoinStyle join style for stroke pen
218 : : */
219 : : QgsSimpleMarkerSymbolLayer( QgsSimpleMarkerSymbolLayerBase::Shape shape = Circle,
220 : : double size = DEFAULT_SIMPLEMARKER_SIZE,
221 : : double angle = DEFAULT_SIMPLEMARKER_ANGLE,
222 : : QgsSymbol::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD,
223 : : const QColor &color = DEFAULT_SIMPLEMARKER_COLOR,
224 : : const QColor &strokeColor = DEFAULT_SIMPLEMARKER_BORDERCOLOR,
225 : : Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEMARKER_JOINSTYLE );
226 : :
227 : : // static methods
228 : :
229 : : /**
230 : : * Creates a new QgsSimpleMarkerSymbolLayer.
231 : : * \param properties a property map containing symbol properties (see properties())
232 : : * \returns new QgsSimpleMarkerSymbolLayer
233 : : */
234 : : static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY;
235 : :
236 : : /**
237 : : * Creates a new QgsSimpleMarkerSymbolLayer from an SLD XML element.
238 : : * \param element XML element containing SLD definition of symbol
239 : : * \returns new QgsSimpleMarkerSymbolLayer
240 : : */
241 : : static QgsSymbolLayer *createFromSld( QDomElement &element ) SIP_FACTORY;
242 : :
243 : : // reimplemented from base classes
244 : :
245 : : QString layerType() const override;
246 : : void startRender( QgsSymbolRenderContext &context ) override;
247 : : void renderPoint( QPointF point, QgsSymbolRenderContext &context ) override;
248 : : QVariantMap properties() const override;
249 : : QgsSimpleMarkerSymbolLayer *clone() const override SIP_FACTORY;
250 : : void writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const override;
251 : : QString ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const override;
252 : : bool writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift = QPointF( 0.0, 0.0 ) ) const override;
253 : : void setOutputUnit( QgsUnitTypes::RenderUnit unit ) override;
254 : : QgsUnitTypes::RenderUnit outputUnit() const override;
255 : : void setMapUnitScale( const QgsMapUnitScale &scale ) override;
256 : : QgsMapUnitScale mapUnitScale() const override;
257 : : bool usesMapUnits() const override;
258 : : QRectF bounds( QPointF point, QgsSymbolRenderContext &context ) override;
259 : 70 : QColor fillColor() const override { return mColor; }
260 : 22 : void setFillColor( const QColor &color ) override { mColor = color; }
261 : : void setColor( const QColor &color ) override;
262 : : QColor color() const override;
263 : :
264 : : // new methods
265 : :
266 : : /**
267 : : * Returns the marker's stroke color.
268 : : * \see setStrokeColor()
269 : : * \see strokeStyle()
270 : : * \see penJoinStyle()
271 : : */
272 : 10 : QColor strokeColor() const override { return mStrokeColor; }
273 : :
274 : : /**
275 : : * Sets the marker's stroke color.
276 : : * \param color stroke color
277 : : * \see strokeColor()
278 : : * \see setStrokeStyle()
279 : : * \see setPenJoinStyle()
280 : : */
281 : 0 : void setStrokeColor( const QColor &color ) override { mStrokeColor = color; }
282 : :
283 : : /**
284 : : * Returns the marker's stroke style (e.g., solid, dashed, etc)
285 : : * \see setStrokeStyle()
286 : : * \see strokeColor()
287 : : * \see penJoinStyle()
288 : : * \since QGIS 2.4
289 : : */
290 : : Qt::PenStyle strokeStyle() const { return mStrokeStyle; }
291 : :
292 : : /**
293 : : * Sets the marker's stroke style (e.g., solid, dashed, etc)
294 : : * \param strokeStyle style
295 : : * \see strokeStyle()
296 : : * \see setStrokeColor()
297 : : * \see setPenJoinStyle()
298 : : * \since QGIS 2.4
299 : : */
300 : 230 : void setStrokeStyle( Qt::PenStyle strokeStyle ) { mStrokeStyle = strokeStyle; }
301 : :
302 : : /**
303 : : * Returns the marker's stroke join style (e.g., miter, bevel, etc).
304 : : * \see setPenJoinStyle()
305 : : * \see penCapStyle()
306 : : * \see strokeColor()
307 : : * \see strokeStyle()
308 : : * \since QGIS 2.16
309 : : */
310 : : Qt::PenJoinStyle penJoinStyle() const { return mPenJoinStyle; }
311 : :
312 : : /**
313 : : * Sets the marker's stroke join style (e.g., miter, bevel, etc).
314 : : * \param style join style
315 : : * \see penJoinStyle()
316 : : * \see setPenCapStyle()
317 : : * \see setStrokeColor()
318 : : * \see setStrokeStyle()
319 : : * \since QGIS 2.16
320 : : */
321 : : void setPenJoinStyle( Qt::PenJoinStyle style ) { mPenJoinStyle = style; }
322 : :
323 : : /**
324 : : * Returns the marker's stroke cap style (e.g., flat, round, etc).
325 : : * \see setPenCapStyle()
326 : : * \see penJoinStyle()
327 : : * \see strokeColor()
328 : : * \see strokeStyle()
329 : : * \since QGIS 3.20
330 : : */
331 : : Qt::PenCapStyle penCapStyle() const { return mPenCapStyle; }
332 : :
333 : : /**
334 : : * Sets the marker's stroke cap \a style (e.g., flat, round, etc).
335 : : * \see penCapStyle()
336 : : * \see penJoinStyle()
337 : : * \see setStrokeColor()
338 : : * \see setStrokeStyle()
339 : : * \since QGIS 3.20
340 : : */
341 : 138 : void setPenCapStyle( Qt::PenCapStyle style ) { mPenCapStyle = style; }
342 : :
343 : : /**
344 : : * Returns the width of the marker's stroke.
345 : : * \see setStrokeWidth()
346 : : * \see strokeWidthUnit()
347 : : * \see strokeWidthMapUnitScale()
348 : : */
349 : : double strokeWidth() const { return mStrokeWidth; }
350 : :
351 : : /**
352 : : * Sets the width of the marker's stroke.
353 : : * \param w stroke width. See strokeWidthUnit() for units.
354 : : * \see strokeWidth()
355 : : * \see setStrokeWidthUnit()
356 : : * \see setStrokeWidthMapUnitScale()
357 : : */
358 : 235 : void setStrokeWidth( double w ) { mStrokeWidth = w; }
359 : :
360 : : /**
361 : : * Sets the unit for the width of the marker's stroke.
362 : : * \param u stroke width unit
363 : : * \see strokeWidthUnit()
364 : : * \see setStrokeWidth()
365 : : * \see setStrokeWidthMapUnitScale()
366 : : */
367 : 230 : void setStrokeWidthUnit( QgsUnitTypes::RenderUnit u ) { mStrokeWidthUnit = u; }
368 : :
369 : : /**
370 : : * Returns the unit for the width of the marker's stroke.
371 : : * \see setStrokeWidthUnit()
372 : : * \see strokeWidth()
373 : : * \see strokeWidthMapUnitScale()
374 : : */
375 : : QgsUnitTypes::RenderUnit strokeWidthUnit() const { return mStrokeWidthUnit; }
376 : :
377 : : /**
378 : : * Sets the map scale for the width of the marker's stroke.
379 : : * \param scale stroke width map unit scale
380 : : * \see strokeWidthMapUnitScale()
381 : : * \see setStrokeWidth()
382 : : * \see setStrokeWidthUnit()
383 : : */
384 : 230 : void setStrokeWidthMapUnitScale( const QgsMapUnitScale &scale ) { mStrokeWidthMapUnitScale = scale; }
385 : :
386 : : /**
387 : : * Returns the map scale for the width of the marker's stroke.
388 : : * \see setStrokeWidthMapUnitScale()
389 : : * \see strokeWidth()
390 : : * \see strokeWidthUnit()
391 : : */
392 : : const QgsMapUnitScale &strokeWidthMapUnitScale() const { return mStrokeWidthMapUnitScale; }
393 : :
394 : : protected:
395 : :
396 : : /**
397 : : * Draws the marker shape in the specified painter.
398 : : * \param p destination QPainter
399 : : * \param context symbol context
400 : : * \note this method does not handle setting the painter pen or brush to match the symbol's fill or stroke
401 : : */
402 : : void drawMarker( QPainter *p, QgsSymbolRenderContext &context );
403 : :
404 : : /**
405 : : * Prepares cache image
406 : : * \returns TRUE in case of success, FALSE if cache image size too large
407 : : */
408 : : bool prepareCache( QgsSymbolRenderContext &context );
409 : :
410 : : //! Stroke color
411 : : QColor mStrokeColor;
412 : : //! Stroke style
413 : : Qt::PenStyle mStrokeStyle = Qt::SolidLine;
414 : : //! Stroke width
415 : : double mStrokeWidth = 0;
416 : : //! Stroke width units
417 : : QgsUnitTypes::RenderUnit mStrokeWidthUnit = QgsUnitTypes::RenderMillimeters;
418 : : //! Stroke width map unit scale
419 : : QgsMapUnitScale mStrokeWidthMapUnitScale;
420 : : //! Stroke pen join style
421 : : Qt::PenJoinStyle mPenJoinStyle;
422 : : //! Stroke pen cap style
423 : : Qt::PenCapStyle mPenCapStyle = Qt::SquareCap;
424 : : //! QPen corresponding to marker's stroke style
425 : : QPen mPen;
426 : : //! QBrush corresponding to marker's fill style
427 : : QBrush mBrush;
428 : :
429 : : //! Cached image of marker, if using cached version
430 : : QImage mCache;
431 : : //! QPen to use as stroke of selected symbols
432 : : QPen mSelPen;
433 : : //! QBrush to use as fill of selected symbols
434 : : QBrush mSelBrush;
435 : : //! Cached image of selected marker, if using cached version
436 : : QImage mSelCache;
437 : :
438 : : /**
439 : : * TRUE if using cached images of markers for drawing. This is faster, but cannot
440 : : * be used when data defined properties are present
441 : : */
442 : : bool mUsingCache = false;
443 : :
444 : : //! Maximum width/height of cache image
445 : : static const int MAXIMUM_CACHE_WIDTH = 3000;
446 : :
447 : : private:
448 : : // cppcheck-suppress unusedPrivateFunction
449 : : void draw( QgsSymbolRenderContext &context, QgsSimpleMarkerSymbolLayerBase::Shape shape, const QPolygonF &polygon, const QPainterPath &path ) override SIP_FORCE;
450 : :
451 : : double mCachedOpacity = 1.0;
452 : :
453 : : };
454 : :
455 : : /**
456 : : * \ingroup core
457 : : * \class QgsFilledMarkerSymbolLayer
458 : : * \brief Filled marker symbol layer, consisting of a shape which is rendered using a QgsFillSymbol. This allows
459 : : * the symbol to support advanced styling of the interior and stroke of the shape.
460 : : * \since QGIS 2.16
461 : : */
462 : 0 : class CORE_EXPORT QgsFilledMarkerSymbolLayer : public QgsSimpleMarkerSymbolLayerBase
463 : : {
464 : : public:
465 : :
466 : : /**
467 : : * Constructor for QgsFilledMarkerSymbolLayer.
468 : : * \param shape symbol shape
469 : : * \param size symbol size (in mm)
470 : : * \param angle symbol rotation angle
471 : : * \param scaleMethod size scaling method
472 : : */
473 : : QgsFilledMarkerSymbolLayer( QgsSimpleMarkerSymbolLayerBase::Shape shape = Circle,
474 : : double size = DEFAULT_SIMPLEMARKER_SIZE,
475 : : double angle = DEFAULT_SIMPLEMARKER_ANGLE,
476 : : QgsSymbol::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD );
477 : :
478 : : /**
479 : : * Creates a new QgsFilledMarkerSymbolLayer.
480 : : * \param properties a property map containing symbol properties (see properties())
481 : : * \returns new QgsFilledMarkerSymbolLayer
482 : : */
483 : : static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY;
484 : :
485 : : QString layerType() const override;
486 : : void startRender( QgsSymbolRenderContext &context ) override;
487 : : void stopRender( QgsSymbolRenderContext &context ) override;
488 : : QVariantMap properties() const override;
489 : : QgsFilledMarkerSymbolLayer *clone() const override SIP_FACTORY;
490 : : QgsSymbol *subSymbol() override;
491 : : bool setSubSymbol( QgsSymbol *symbol SIP_TRANSFER ) override;
492 : : double estimateMaxBleed( const QgsRenderContext &context ) const override;
493 : : QSet<QString> usedAttributes( const QgsRenderContext &context ) const override;
494 : : bool hasDataDefinedProperties() const override;
495 : : void setColor( const QColor &c ) override;
496 : : QColor color() const override;
497 : : bool usesMapUnits() const override;
498 : :
499 : : private:
500 : : #ifdef SIP_RUN
501 : : QgsFilledMarkerSymbolLayer( const QgsFilledMarkerSymbolLayer & );
502 : : #endif
503 : :
504 : : // cppcheck-suppress unusedPrivateFunction
505 : : void draw( QgsSymbolRenderContext &context, QgsSimpleMarkerSymbolLayerBase::Shape shape, const QPolygonF &polygon, const QPainterPath &path ) override SIP_FORCE;
506 : :
507 : : //! Fill subsymbol
508 : : std::unique_ptr< QgsFillSymbol > mFill;
509 : : };
510 : :
511 : : //////////
512 : :
513 : : #define DEFAULT_SVGMARKER_SIZE 2*DEFAULT_POINT_SIZE
514 : : #define DEFAULT_SVGMARKER_ANGLE 0
515 : :
516 : : /**
517 : : * \ingroup core
518 : : * \class QgsSvgMarkerSymbolLayer
519 : : */
520 : 48 : class CORE_EXPORT QgsSvgMarkerSymbolLayer : public QgsMarkerSymbolLayer
521 : : {
522 : : public:
523 : : //! Constructs SVG marker symbol layer with picture from given absolute path to a SVG file
524 : : QgsSvgMarkerSymbolLayer( const QString &path,
525 : : double size = DEFAULT_SVGMARKER_SIZE,
526 : : double angle = DEFAULT_SVGMARKER_ANGLE,
527 : : QgsSymbol::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD );
528 : :
529 : : // static stuff
530 : :
531 : : //! Creates the symbol
532 : : static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY;
533 : : static QgsSymbolLayer *createFromSld( QDomElement &element ) SIP_FACTORY;
534 : :
535 : : /**
536 : : * Turns relative paths in properties map to absolute when reading and vice versa when writing.
537 : : * Used internally when reading/writing symbols.
538 : : * \since QGIS 3.0
539 : : */
540 : : static void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving );
541 : :
542 : : // implemented from base classes
543 : :
544 : : QString layerType() const override;
545 : :
546 : : void startRender( QgsSymbolRenderContext &context ) override;
547 : :
548 : : void stopRender( QgsSymbolRenderContext &context ) override;
549 : :
550 : : void renderPoint( QPointF point, QgsSymbolRenderContext &context ) override;
551 : :
552 : : QVariantMap properties() const override;
553 : : bool usesMapUnits() const override;
554 : :
555 : : QgsSvgMarkerSymbolLayer *clone() const override SIP_FACTORY;
556 : :
557 : : void writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const override;
558 : :
559 : : /**
560 : : * Returns the marker SVG path.
561 : : * \see setPath()
562 : : */
563 : : QString path() const { return mPath; }
564 : :
565 : : /**
566 : : * Set the marker SVG path.
567 : : * \param path SVG path
568 : : * \see path()
569 : : */
570 : : void setPath( const QString &path );
571 : :
572 : : /**
573 : : * Returns the default marker aspect ratio between width and height, 0 if not yet calculated.
574 : : * \see updateDefaultAspectRatio()
575 : : */
576 : : double defaultAspectRatio() const { return mDefaultAspectRatio; }
577 : :
578 : : /**
579 : : * Calculates the default marker aspect ratio between width and height.
580 : : * \returns the default aspect ratio value
581 : : * \see defaultAspectRatio()
582 : : */
583 : : double updateDefaultAspectRatio();
584 : :
585 : : /**
586 : : * Returns the preserved aspect ratio value, TRUE if fixed aspect ratio has been lower or equal to 0.
587 : : * \see setPreservedAspectRatio()
588 : : */
589 : 0 : bool preservedAspectRatio() const { return mFixedAspectRatio <= 0.0; }
590 : :
591 : : /**
592 : : * Set preserved the marker aspect ratio between width and height.
593 : : * \param par Preserved Aspect Ratio
594 : : * \returns the preserved aspect ratio value, TRUE if fixed aspect ratio has been lower or equal to 0
595 : : * \see preservedAspectRatio()
596 : : */
597 : : bool setPreservedAspectRatio( bool par );
598 : :
599 : : /**
600 : : * Returns the marker aspect ratio between width and height to be used in rendering,
601 : : * if the value set is lower or equal to 0 the aspect ratio will be preserved in rendering
602 : : * \see setFixedAspectRatio() QgsSvgCache
603 : : */
604 : : double fixedAspectRatio() const { return mFixedAspectRatio; }
605 : :
606 : : /**
607 : : * Set the marker aspect ratio between width and height to be used in rendering,
608 : : * if the value set is lower or equal to 0 the aspect ratio will be preserved in rendering
609 : : * \param ratio Fixed Aspect Ratio
610 : : * \see fixedAspectRatio() QgsSvgCache
611 : : */
612 : 40 : void setFixedAspectRatio( double ratio ) { mFixedAspectRatio = ratio; }
613 : :
614 : 0 : QColor fillColor() const override { return color(); }
615 : 40 : void setFillColor( const QColor &color ) override { setColor( color ); }
616 : :
617 : 0 : QColor strokeColor() const override { return mStrokeColor; }
618 : 40 : void setStrokeColor( const QColor &c ) override { mStrokeColor = c; }
619 : :
620 : : double strokeWidth() const { return mStrokeWidth; }
621 : 40 : void setStrokeWidth( double w ) { mStrokeWidth = w; }
622 : :
623 : : /**
624 : : * Returns the dynamic SVG parameters
625 : : * \since QGIS 3.18
626 : : */
627 : : QMap<QString, QgsProperty> parameters() const { return mParameters; }
628 : :
629 : : /**
630 : : * Sets the dynamic SVG parameters
631 : : * \since QGIS 3.18
632 : : */
633 : : void setParameters( const QMap<QString, QgsProperty> ¶meters );
634 : :
635 : : /**
636 : : * Sets the units for the stroke width.
637 : : * \param unit width units
638 : : * \see strokeWidthUnit()
639 : : */
640 : 40 : void setStrokeWidthUnit( QgsUnitTypes::RenderUnit unit ) { mStrokeWidthUnit = unit; }
641 : :
642 : : /**
643 : : * Returns the units for the stroke width.
644 : : * \see strokeWidthUnit()
645 : : */
646 : : QgsUnitTypes::RenderUnit strokeWidthUnit() const { return mStrokeWidthUnit; }
647 : :
648 : 40 : void setStrokeWidthMapUnitScale( const QgsMapUnitScale &scale ) { mStrokeWidthMapUnitScale = scale; }
649 : : const QgsMapUnitScale &strokeWidthMapUnitScale() const { return mStrokeWidthMapUnitScale; }
650 : :
651 : : void setOutputUnit( QgsUnitTypes::RenderUnit unit ) override;
652 : : QgsUnitTypes::RenderUnit outputUnit() const override;
653 : :
654 : : void setMapUnitScale( const QgsMapUnitScale &scale ) override;
655 : : QgsMapUnitScale mapUnitScale() const override;
656 : :
657 : : bool writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift = QPointF( 0.0, 0.0 ) ) const override;
658 : :
659 : : QRectF bounds( QPointF point, QgsSymbolRenderContext &context ) override;
660 : :
661 : : void prepareExpressions( const QgsSymbolRenderContext &context ) override;
662 : :
663 : : QSet<QString> usedAttributes( const QgsRenderContext &context ) const override;
664 : :
665 : : protected:
666 : :
667 : : /**
668 : : * Calculates the marker aspect ratio between width and height.
669 : : * \param context symbol render context
670 : : * \param scaledSize size of symbol to render
671 : : * \param hasDataDefinedAspectRatio will be set to TRUE if marker has data defined aspectRatio
672 : : */
673 : : double calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const;
674 : :
675 : : QString mPath;
676 : :
677 : : //! The marker default aspect ratio
678 : : double mDefaultAspectRatio = 0.0;
679 : : //! The marker fixed aspect ratio
680 : : double mFixedAspectRatio = 0.0;
681 : : //param(fill), param(stroke), param(stroke-width) are going
682 : : //to be replaced in memory
683 : : bool mHasFillParam = false;
684 : : QColor mStrokeColor;
685 : : double mStrokeWidth;
686 : : QMap<QString, QgsProperty> mParameters;
687 : :
688 : : QgsUnitTypes::RenderUnit mStrokeWidthUnit;
689 : : QgsMapUnitScale mStrokeWidthMapUnitScale;
690 : :
691 : : private:
692 : : double calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const;
693 : : void calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, QPointF &offset, double &angle ) const;
694 : :
695 : : };
696 : :
697 : :
698 : : //////////
699 : :
700 : : #define DEFAULT_RASTERMARKER_SIZE 2*DEFAULT_POINT_SIZE
701 : : #define DEFAULT_RASTERMARKER_ANGLE 0
702 : :
703 : : /**
704 : : * \ingroup core
705 : : * \class QgsRasterMarkerSymbolLayer
706 : : * \brief Raster marker symbol layer class.
707 : : * \since QGIS 3.6
708 : : */
709 : 0 : class CORE_EXPORT QgsRasterMarkerSymbolLayer : public QgsMarkerSymbolLayer
710 : : {
711 : : public:
712 : : //! Constructs raster marker symbol layer with picture from given absolute path to a raster image file
713 : : QgsRasterMarkerSymbolLayer( const QString &path = QString(),
714 : : double size = DEFAULT_SVGMARKER_SIZE,
715 : : double angle = DEFAULT_SVGMARKER_ANGLE,
716 : : QgsSymbol::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD );
717 : :
718 : : // static stuff
719 : :
720 : : /**
721 : : * Creates a raster marker symbol layer from a string map of properties.
722 : : * \param properties QVariantMap properties object
723 : : */
724 : : static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY;
725 : :
726 : : /**
727 : : * Turns relative paths in properties map to absolute when reading and vice versa when writing.
728 : : * Used internally when reading/writing symbols.
729 : : * \since QGIS 3.0
730 : : */
731 : : static void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving );
732 : :
733 : : // implemented from base classes
734 : :
735 : : QString layerType() const override;
736 : :
737 : : void renderPoint( QPointF point, QgsSymbolRenderContext &context ) override;
738 : :
739 : : QVariantMap properties() const override;
740 : :
741 : : QgsRasterMarkerSymbolLayer *clone() const override SIP_FACTORY;
742 : : bool usesMapUnits() const override;
743 : :
744 : : /**
745 : : * Calculates the marker aspect ratio between width and height.
746 : : * \param context symbol render context
747 : : * \param scaledSize size of symbol to render
748 : : * \param hasDataDefinedAspectRatio will be set to TRUE if marker has data defined aspectRatio
749 : : */
750 : : double calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const;
751 : :
752 : : /**
753 : : * Returns the marker raster image path.
754 : : * \see setPath()
755 : : */
756 : : QString path() const { return mPath; }
757 : :
758 : : /**
759 : : * Set the marker raster image path.
760 : : * \param path raster image path
761 : : * \see path()
762 : : */
763 : : void setPath( const QString &path );
764 : :
765 : : /**
766 : : * Returns the marker opacity.
767 : : * \returns opacity value between 0 (fully transparent) and 1 (fully opaque)
768 : : * \see setOpacity()
769 : : */
770 : : double opacity() const { return mOpacity; }
771 : :
772 : : /**
773 : : * Set the marker opacity.
774 : : * \param opacity opacity value between 0 (fully transparent) and 1 (fully opaque)
775 : : * \see opacity()
776 : : */
777 : 0 : void setOpacity( double opacity ) { mOpacity = opacity; }
778 : :
779 : : /**
780 : : * Returns the default marker aspect ratio between width and height, 0 if not yet calculated.
781 : : * \see updateDefaultAspectRatio()
782 : : */
783 : 0 : double defaultAspectRatio() const { return mDefaultAspectRatio; }
784 : :
785 : : /**
786 : : * Calculates the default marker aspect ratio between width and height.
787 : : * \returns the default aspect ratio value
788 : : * \see defaultAspectRatio()
789 : : */
790 : : double updateDefaultAspectRatio();
791 : :
792 : : /**
793 : : * Returns the preserved aspect ratio value, TRUE if fixed aspect ratio has been lower or equal to 0.
794 : : * \see setPreservedAspectRatio()
795 : : */
796 : 0 : bool preservedAspectRatio() const { return mFixedAspectRatio <= 0.0; }
797 : :
798 : : /**
799 : : * Set preserved the marker aspect ratio between width and height.
800 : : * \param par Preserved Aspect Ratio
801 : : * \returns the preserved aspect ratio value, TRUE if fixed aspect ratio has been lower or equal to 0
802 : : * \see preservedAspectRatio()
803 : : */
804 : : bool setPreservedAspectRatio( bool par );
805 : :
806 : : /**
807 : : * Returns the marker aspect ratio between width and height to be used in rendering,
808 : : * if the value set is lower or equal to 0 the aspect ratio will be preserved in rendering
809 : : * \see setFixedAspectRatio() QgsSvgCache
810 : : */
811 : : double fixedAspectRatio() const { return mFixedAspectRatio; }
812 : :
813 : : /**
814 : : * Set the marker aspect ratio between width and height to be used in rendering,
815 : : * if the value set is lower or equal to 0 the aspect ratio will be preserved in rendering
816 : : * \param ratio Fixed Aspect Ratio
817 : : * \see fixedAspectRatio() QgsSvgCache
818 : : */
819 : 0 : void setFixedAspectRatio( double ratio ) { mFixedAspectRatio = ratio; }
820 : :
821 : : void setMapUnitScale( const QgsMapUnitScale &scale ) override;
822 : : QgsMapUnitScale mapUnitScale() const override;
823 : :
824 : : QRectF bounds( QPointF point, QgsSymbolRenderContext &context ) override;
825 : :
826 : : protected:
827 : :
828 : : QString mPath;
829 : : //! The marker default opacity
830 : : double mOpacity = 1.0;
831 : : //! The marker default aspect ratio
832 : : double mDefaultAspectRatio = 0.0;
833 : : //! The marker fixed aspect ratio
834 : : double mFixedAspectRatio = 0.0;
835 : :
836 : : private:
837 : : double calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const;
838 : : void calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, QPointF &offset, double &angle ) const;
839 : :
840 : : };
841 : :
842 : :
843 : : //////////
844 : :
845 : : #define POINT2MM(x) ( (x) * 25.4 / 72 ) // point is 1/72 of inch
846 : : #define MM2POINT(x) ( (x) * 72 / 25.4 )
847 : :
848 : : #define DEFAULT_FONTMARKER_FONT "Dingbats"
849 : : #define DEFAULT_FONTMARKER_CHR QChar('A')
850 : : #define DEFAULT_FONTMARKER_SIZE POINT2MM(12)
851 : : #define DEFAULT_FONTMARKER_COLOR QColor( 35, 35, 35 )
852 : : #define DEFAULT_FONTMARKER_BORDERCOLOR QColor(Qt::white)
853 : : #define DEFAULT_FONTMARKER_JOINSTYLE Qt::MiterJoin
854 : : #define DEFAULT_FONTMARKER_ANGLE 0
855 : :
856 : : /**
857 : : * \ingroup core
858 : : * \class QgsFontMarkerSymbolLayer
859 : : */
860 : 0 : class CORE_EXPORT QgsFontMarkerSymbolLayer : public QgsMarkerSymbolLayer
861 : : {
862 : : public:
863 : :
864 : : //! Constructs a font marker symbol layer.
865 : : QgsFontMarkerSymbolLayer( const QString &fontFamily = DEFAULT_FONTMARKER_FONT,
866 : : QString chr = DEFAULT_FONTMARKER_CHR,
867 : : double pointSize = DEFAULT_FONTMARKER_SIZE,
868 : : const QColor &color = DEFAULT_FONTMARKER_COLOR,
869 : : double angle = DEFAULT_FONTMARKER_ANGLE );
870 : :
871 : : // static stuff
872 : :
873 : : /**
874 : : * Creates a new QgsFontMarkerSymbolLayer from a property map (see properties())
875 : : */
876 : : static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY;
877 : :
878 : : /**
879 : : * Creates a new QgsFontMarkerSymbolLayer from an SLD XML \a element.
880 : : */
881 : : static QgsSymbolLayer *createFromSld( QDomElement &element ) SIP_FACTORY;
882 : :
883 : : // implemented from base classes
884 : :
885 : : QString layerType() const override;
886 : :
887 : : void startRender( QgsSymbolRenderContext &context ) override;
888 : :
889 : : void stopRender( QgsSymbolRenderContext &context ) override;
890 : :
891 : : void renderPoint( QPointF point, QgsSymbolRenderContext &context ) override;
892 : :
893 : : QVariantMap properties() const override;
894 : :
895 : : QgsFontMarkerSymbolLayer *clone() const override SIP_FACTORY;
896 : :
897 : : void writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const override;
898 : : bool usesMapUnits() const override;
899 : :
900 : : // new methods
901 : :
902 : : /**
903 : : * Returns the font family name for the associated font which will be used to render the point.
904 : : *
905 : : * \see setFontFamily()
906 : : */
907 : : QString fontFamily() const { return mFontFamily; }
908 : :
909 : : /**
910 : : * Sets the font \a family for the font which will be used to render the point.
911 : : *
912 : : * \see fontFamily()
913 : : */
914 : 0 : void setFontFamily( const QString &family ) { mFontFamily = family; }
915 : :
916 : : /**
917 : : * Returns the font style for the associated font which will be used to render the point.
918 : : *
919 : : * \see setFontStyle()
920 : : * \since QGIS 3.14
921 : : */
922 : : QString fontStyle() const { return mFontStyle; }
923 : :
924 : : /**
925 : : * Sets the font \a style for the font which will be used to render the point.
926 : : *
927 : : * \see fontStyle()
928 : : * \since QGIS 3.14
929 : : */
930 : 0 : void setFontStyle( const QString &style ) { mFontStyle = style; }
931 : :
932 : : /**
933 : : * Returns the character(s) used when rendering points.
934 : : *
935 : : * \see setCharacter()
936 : : */
937 : : QString character() const { return mString; }
938 : :
939 : : /**
940 : : * Sets the character(s) used when rendering points.
941 : : *
942 : : * \see character()
943 : : */
944 : : void setCharacter( QString chr ) { mString = chr; }
945 : :
946 : 0 : QColor strokeColor() const override { return mStrokeColor; }
947 : 0 : void setStrokeColor( const QColor &color ) override { mStrokeColor = color; }
948 : :
949 : : /**
950 : : * Returns the marker's stroke width. Units are retrieved by strokeWidthUnit()
951 : : *
952 : : * \see setStrokeWidth()
953 : : * \see strokeWidthUnit()
954 : : * \see strokeWidthMapUnitScale()
955 : : *
956 : : * \since QGIS 2.16
957 : : */
958 : : double strokeWidth() const { return mStrokeWidth; }
959 : :
960 : : /**
961 : : * Set's the marker's stroke \a width. Units are set by setStrokeWidthUnit().
962 : : *
963 : : * \see strokeWidth()
964 : : * \see setStrokeWidthUnit()
965 : : * \see setStrokeWidthMapUnitScale()
966 : : *
967 : : * \since QGIS 2.16
968 : : */
969 : 0 : void setStrokeWidth( double width ) { mStrokeWidth = width; }
970 : :
971 : : /**
972 : : * Returns the stroke width unit.
973 : : *
974 : : * \see setStrokeWidthUnit()
975 : : * \see strokeWidth()
976 : : * \see strokeWidthMapUnitScale()
977 : : *
978 : : * \since QGIS 2.16
979 : : */
980 : : QgsUnitTypes::RenderUnit strokeWidthUnit() const { return mStrokeWidthUnit; }
981 : :
982 : : /**
983 : : * Sets the stroke width \a unit.
984 : : *
985 : : * \see strokeWidthUnit()
986 : : * \see setStrokeWidth()
987 : : * \see setStrokeWidthMapUnitScale()
988 : : * \since QGIS 2.16
989 : : */
990 : 0 : void setStrokeWidthUnit( QgsUnitTypes::RenderUnit unit ) { mStrokeWidthUnit = unit; }
991 : :
992 : : /**
993 : : * Returns the stroke width map unit scale.
994 : : *
995 : : * \see setStrokeWidthMapUnitScale()
996 : : * \see strokeWidth()
997 : : * \see strokeWidthUnit()
998 : : *
999 : : * \since QGIS 2.16
1000 : : */
1001 : : const QgsMapUnitScale &strokeWidthMapUnitScale() const { return mStrokeWidthMapUnitScale; }
1002 : :
1003 : : /**
1004 : : * Sets the stroke width map unit \a scale.
1005 : : *
1006 : : * \see strokeWidthMapUnitScale()
1007 : : * \see setStrokeWidth()
1008 : : * \see setStrokeWidthUnit()
1009 : : *
1010 : : * \since QGIS 2.16
1011 : : */
1012 : 0 : void setStrokeWidthMapUnitScale( const QgsMapUnitScale &scale ) { mStrokeWidthMapUnitScale = scale; }
1013 : :
1014 : : /**
1015 : : * Returns the stroke join style.
1016 : : *
1017 : : * \see setPenJoinStyle()
1018 : : *
1019 : : * \since QGIS 2.16
1020 : : */
1021 : : Qt::PenJoinStyle penJoinStyle() const { return mPenJoinStyle; }
1022 : :
1023 : : /**
1024 : : * Sets the stroke join \a style.
1025 : : *
1026 : : * \see penJoinStyle()
1027 : : *
1028 : : * \since QGIS 2.16
1029 : : */
1030 : 0 : void setPenJoinStyle( Qt::PenJoinStyle style ) { mPenJoinStyle = style; }
1031 : :
1032 : : QRectF bounds( QPointF point, QgsSymbolRenderContext &context ) override;
1033 : :
1034 : : private:
1035 : :
1036 : : QString mFontFamily;
1037 : : QString mFontStyle;
1038 : : QFont mFont;
1039 : : std::unique_ptr< QFontMetrics >mFontMetrics;
1040 : :
1041 : : QString mString;
1042 : :
1043 : : double mChrWidth = 0;
1044 : : QPointF mChrOffset;
1045 : : double mOrigSize;
1046 : :
1047 : : QColor mStrokeColor;
1048 : : double mStrokeWidth;
1049 : : QgsUnitTypes::RenderUnit mStrokeWidthUnit;
1050 : : QgsMapUnitScale mStrokeWidthMapUnitScale;
1051 : : Qt::PenJoinStyle mPenJoinStyle;
1052 : :
1053 : : QPen mPen;
1054 : : QBrush mBrush;
1055 : :
1056 : : bool mUseCachedPath = false;
1057 : : QPainterPath mCachedPath;
1058 : :
1059 : : // If font has a zero (or nearly zero) size, we skip rendering altogether..
1060 : : bool mNonZeroFontSize = true;
1061 : :
1062 : : QString characterToRender( QgsSymbolRenderContext &context, QPointF &charOffset, double &charWidth );
1063 : : void calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedRotation, QPointF &offset, double &angle ) const;
1064 : : double calculateSize( QgsSymbolRenderContext &context );
1065 : : };
1066 : :
1067 : : // clazy:excludeall=qstring-allocations
1068 : :
1069 : : #endif
1070 : :
1071 : :
|