1 /***************************************************************************
2 qgsrendercontext.h
3 ------------------
4 begin : March 16, 2008
5 copyright : (C) 2008 by Marco Hugentobler
6 email : marco dot hugentobler at karto dot baug dot ethz dot ch
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #ifndef QGSRENDERCONTEXT_H
19 #define QGSRENDERCONTEXT_H
20
21 #include "qgis_core.h"
22 #include "qgis_sip.h"
23 #include <QColor>
24 #include <QPainter>
25 #include <memory>
26
27 #include "qgscoordinatetransform.h"
28 #include "qgsexpressioncontext.h"
29 #include "qgsfeaturefilterprovider.h"
30 #include "qgsmaptopixel.h"
31 #include "qgsmapunitscale.h"
32 #include "qgsrectangle.h"
33 #include "qgsvectorsimplifymethod.h"
34 #include "qgsdistancearea.h"
35 #include "qgscoordinatetransformcontext.h"
36 #include "qgspathresolver.h"
37 #include "qgssymbollayerreference.h"
38 #include "qgstemporalrangeobject.h"
39
40 class QPainter;
41 class QgsAbstractGeometry;
42 class QgsLabelingEngine;
43 class QgsMapSettings;
44 class QgsRenderedFeatureHandlerInterface;
45 class QgsSymbolLayer;
46 class QgsMaskIdProvider;
47 class QgsMapClippingRegion;
48
49
50 /**
51 * \ingroup core
52 * \brief Contains information about the context of a rendering operation.
53 *
54 * The context of a rendering operation defines properties such as
55 * the conversion ratio between screen and map units, the extents
56 * to be rendered etc.
57 */
58 class CORE_EXPORT QgsRenderContext : public QgsTemporalRangeObject
59 {
60 public:
61 QgsRenderContext();
62 ~QgsRenderContext() override;
63
64 QgsRenderContext( const QgsRenderContext &rh );
65 QgsRenderContext &operator=( const QgsRenderContext &rh );
66
67 /**
68 * Enumeration of flags that affect rendering operations.
69 * \since QGIS 2.14
70 */
71 enum Flag
72 {
73 DrawEditingInfo = 0x01, //!< Enable drawing of vertex markers for layers in editing mode
74 ForceVectorOutput = 0x02, //!< Vector graphics should not be cached and drawn as raster images
75 UseAdvancedEffects = 0x04, //!< Enable layer opacity and blending effects
76 UseRenderingOptimization = 0x08, //!< Enable vector simplification and other rendering optimizations
77 DrawSelection = 0x10, //!< Whether vector selections should be shown in the rendered map
78 DrawSymbolBounds = 0x20, //!< Draw bounds of symbols (for debugging/testing)
79 RenderMapTile = 0x40, //!< Draw map such that there are no problems between adjacent tiles
80 Antialiasing = 0x80, //!< Use antialiasing while drawing
81 RenderPartialOutput = 0x100, //!< Whether to make extra effort to update map image with partially rendered layers (better for interactive map canvas). Added in QGIS 3.0
82 RenderPreviewJob = 0x200, //!< Render is a 'canvas preview' render, and shortcuts should be taken to ensure fast rendering
83 RenderBlocking = 0x400, //!< Render and load remote sources in the same thread to ensure rendering remote sources (svg and images). WARNING: this flag must NEVER be used from GUI based applications (like the main QGIS application) or crashes will result. Only for use in external scripts or QGIS server.
84 RenderSymbolPreview = 0x800, //!< The render is for a symbol preview only and map based properties may not be available, so care should be taken to handle map unit based sizes in an appropriate way.
85 LosslessImageRendering = 0x1000, //!< Render images losslessly whenever possible, instead of the default lossy jpeg rendering used for some destination devices (e.g. PDF). This flag only works with builds based on Qt 5.13 or later.
86 ApplyScalingWorkaroundForTextRendering = 0x2000, //!< Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters scaled out by a large amount) when rendering text. Generally this is recommended, but it may incur some performance cost.
87 Render3DMap = 0x4000, //!< Render is for a 3D map
88 ApplyClipAfterReprojection = 0x8000, //!< Feature geometry clipping to mapExtent() must be performed after the geometries are transformed using coordinateTransform(). Usually feature geometry clipping occurs using the extent() in the layer's CRS prior to geometry transformation, but in some cases when extent() could not be accurately calculated it is necessary to clip geometries to mapExtent() AFTER transforming them using coordinateTransform().
89 };
90 Q_DECLARE_FLAGS( Flags, Flag )
91
92 /**
93 * Options for rendering text.
94 * \since QGIS 3.4.3
95 */
96 enum TextRenderFormat
97 {
98 // refs for below dox: https://github.com/qgis/QGIS/pull/1286#issuecomment-39806854
99 // https://github.com/qgis/QGIS/pull/8573#issuecomment-445585826
100
101 /**
102 * Always render text using path objects (AKA outlines/curves).
103 *
104 * This setting guarantees the best quality rendering, even when using a raster paint surface
105 * (where sub-pixel path based text rendering is superior to sub-pixel text-based rendering).
106 * The downside is that text is converted to paths only, so users cannot open created vector
107 * outputs for post-processing in other applications and retain text editability.
108 *
109 * This setting also guarantees complete compatibility with the full range of formatting options available
110 * through QgsTextRenderer and QgsTextFormat, some of which may not be possible to reproduce when using
111 * a vector-based paint surface and TextFormatAlwaysText mode.
112 *
113 * A final benefit to this setting is that vector exports created using text as outlines do
114 * not require all users to have the original fonts installed in order to display the
115 * text in its original style.
116 */
117 TextFormatAlwaysOutlines,
118
119 /**
120 * Always render text as text objects.
121 *
122 * While this mode preserves text objects as text for post-processing in external vector editing applications,
123 * it can result in rendering artifacts or poor quality rendering, depending on the text format settings.
124 *
125 * Even with raster based paint devices, TextFormatAlwaysText can result in inferior rendering quality
126 * to TextFormatAlwaysOutlines.
127 *
128 * When rendering using TextFormatAlwaysText to a vector based device (e.g. PDF or SVG), care must be
129 * taken to ensure that the required fonts are available to users when opening the created files,
130 * or default fallback fonts will be used to display the output instead. (Although PDF exports MAY
131 * automatically embed some fonts when possible, depending on the user's platform).
132 */
133 TextFormatAlwaysText,
134 };
135
136 /**
137 * Set combination of flags that will be used for rendering.
138 * \since QGIS 2.14
139 */
140 void setFlags( QgsRenderContext::Flags flags );
141
142 /**
143 * Enable or disable a particular flag (other flags are not affected)
144 * \since QGIS 2.14
145 */
146 void setFlag( Flag flag, bool on = true );
147
148 /**
149 * Returns combination of flags used for rendering.
150 * \since QGIS 2.14
151 */
152 Flags flags() const;
153
154 /**
155 * Check whether a particular flag is enabled.
156 * \since QGIS 2.14
157 */
158 bool testFlag( Flag flag ) const;
159
160 /**
161 * create initialized QgsRenderContext instance from given QgsMapSettings
162 * \since QGIS 2.4
163 */
164 static QgsRenderContext fromMapSettings( const QgsMapSettings &mapSettings );
165
166 /**
167 * Creates a default render context given a pixel based QPainter destination.
168 * If no painter is specified or the painter has no device, then a default
169 * DPI of 88 will be assumed.
170 * \since QGIS 3.0
171 */
172 static QgsRenderContext fromQPainter( QPainter *painter );
173
174 //getters
175
176 /**
177 * Returns the destination QPainter for the render operation.
178 * \see setPainter()
179 */
painter()180 QPainter *painter() {return mPainter;}
181
182 #ifndef SIP_RUN
183
184 /**
185 * Returns the const destination QPainter for the render operation.
186 * \see setPainter()
187 * \since QGIS 3.12
188 */
painter()189 const QPainter *painter() const { return mPainter; }
190 #endif
191
192 /**
193 * Sets relevant flags on a destination \a painter, using the flags and settings
194 * currently defined for the render context.
195 *
196 * If no \a painter is specified, then the flags will be applied to the render
197 * context's painter().
198 *
199 * \since QGIS 3.16
200 */
201 void setPainterFlagsUsingContext( QPainter *painter = nullptr ) const;
202
203 /**
204 * Returns a mask QPainter for the render operation.
205 * Multiple mask painters can be defined, each with a unique identifier.
206 * nullptr is returned if a mask painter with the given identifier does not exist.
207 * This is currently used to implement selective masking.
208 * \see setMaskPainter()
209 * \see currentMaskId()
210 * \since QGIS 3.12
211 */
212 QPainter *maskPainter( int id = 0 ) { return mMaskPainter.value( id, nullptr ); }
213
214 /**
215 * When rendering a map layer in a second pass (for selective masking),
216 * some symbol layers may be disabled.
217 *
218 * Returns the list of disabled symbol layers.
219 * \see setDisabledSymbolLayers()
220 * \see isSymbolLayerEnabled()
221 * \since QGIS 3.12
222 */
disabledSymbolLayers()223 QSet<const QgsSymbolLayer *> disabledSymbolLayers() const { return mDisabledSymbolLayers; }
224
225 /**
226 * When rendering a map layer in a second pass (for selective masking),
227 * some symbol layers may be disabled.
228 *
229 * Checks whether a given symbol layer has been disabled for the current pass.
230 * \see setDisabledSymbolLayers()
231 * \see disabledSymbolLayers()
232 * \since QGIS 3.12
233 */
isSymbolLayerEnabled(const QgsSymbolLayer * layer)234 bool isSymbolLayerEnabled( const QgsSymbolLayer *layer ) const { return ! mDisabledSymbolLayers.contains( layer ); }
235
236 /**
237 * Returns the current coordinate transform for the context.
238 *
239 * This represents the coordinate transform required to transform a layer
240 * which is being rendered back to the CRS of the rendered map. If no coordinate
241 * transformation is required, or the render context is not associated with
242 * a map layer render, then an invalid coordinate transformation is returned.
243 *
244 * \see setCoordinateTransform()
245 */
coordinateTransform()246 QgsCoordinateTransform coordinateTransform() const {return mCoordTransform;}
247
248 /**
249 * A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
250 * \since QGIS 3.0
251 */
distanceArea()252 const QgsDistanceArea &distanceArea() const { return mDistanceArea; }
253
254 /**
255 * Returns the context's coordinate transform context, which stores various
256 * information regarding which datum transforms should be used when transforming points
257 * from a source to destination coordinate reference system.
258 *
259 * \see setTransformContext()
260 * \since QGIS 3.0
261 */
262 QgsCoordinateTransformContext transformContext() const;
263
264 /**
265 * Sets the context's coordinate transform \a context, which stores various
266 * information regarding which datum transforms should be used when transforming points
267 * from a source to destination coordinate reference system.
268 *
269 * \see transformContext()
270 * \since QGIS 3.0
271 */
272 void setTransformContext( const QgsCoordinateTransformContext &context );
273
274 /**
275 * Returns the path resolver for conversion between relative and absolute paths
276 * during rendering operations, e.g. for resolving relative symbol paths.
277 *
278 * \see setPathResolver()
279 * \since QGIS 3.0
280 */
pathResolver()281 const QgsPathResolver &pathResolver() const { return mPathResolver; }
282
283 /**
284 * Sets the path \a resolver for conversion between relative and absolute paths
285 * during rendering operations, e.g. for resolving relative symbol paths.
286 *
287 * \see pathResolver()
288 * \since QGIS 3.0
289 */
setPathResolver(const QgsPathResolver & resolver)290 void setPathResolver( const QgsPathResolver &resolver ) { mPathResolver = resolver; }
291
292 /**
293 * When rendering a map layer, calling this method returns the "clipping"
294 * extent for the layer (in the layer's CRS).
295 *
296 * This extent is a "worst-case" scenario, which is guaranteed to cover the complete
297 * visible portion of the layer when it is rendered to a map. It is often larger
298 * than the actual visible portion of that layer.
299 *
300 * \warning For some layers, depending on the visible extent and the coordinate
301 * transforms involved, this extent will represent the entire globe. This method
302 * should never be used to determine the actual visible extent of a map render.
303 *
304 * \see setExtent()
305 * \see mapExtent()
306 */
extent()307 const QgsRectangle &extent() const { return mExtent; }
308
309 /**
310 * Returns the original extent of the map being rendered.
311 *
312 * Unlike extent(), this extent is always in the final destination CRS for the map
313 * render and represents the exact bounds of the map being rendered.
314 *
315 * \see extent()
316 * \see setMapExtent()
317 * \since QGIS 3.4.8
318 */
mapExtent()319 QgsRectangle mapExtent() const { return mOriginalMapExtent; }
320
321 /**
322 * Returns the context's map to pixel transform, which transforms between map coordinates and device coordinates.
323 *
324 * \see setMapToPixel()
325 */
mapToPixel()326 const QgsMapToPixel &mapToPixel() const {return mMapToPixel;}
327
328 /**
329 * Returns the scaling factor for the render to convert painter units
330 * to physical sizes. This is usually equal to the number of pixels
331 * per millimeter.
332 * \see setScaleFactor()
333 */
scaleFactor()334 double scaleFactor() const {return mScaleFactor;}
335
336 /**
337 * Returns TRUE if the rendering operation has been stopped and any ongoing
338 * rendering should be canceled immediately.
339 *
340 * \see setRenderingStopped()
341 */
renderingStopped()342 bool renderingStopped() const {return mRenderingStopped;}
343
344 /**
345 * Returns TRUE if rendering operations should use vector operations instead
346 * of any faster raster shortcuts.
347 *
348 * \see setForceVectorOutput()
349 */
350 bool forceVectorOutput() const;
351
352 /**
353 * Returns TRUE if advanced effects such as blend modes such be used
354 *
355 * \see setUseAdvancedEffects()
356 */
357 bool useAdvancedEffects() const;
358
359 /**
360 * Used to enable or disable advanced effects such as blend modes
361 *
362 * \see useAdvancedEffects()
363 */
364 void setUseAdvancedEffects( bool enabled );
365
366 /**
367 * Returns TRUE if edit markers should be drawn during the render operation.
368 *
369 * \see setDrawEditingInformation()
370 */
371 bool drawEditingInformation() const;
372
373 /**
374 * Returns the renderer map scale. This will match the desired scale denominator
375 * for the rendered map, eg 1000.0 for a 1:1000 map render.
376 * \see setRendererScale()
377 */
rendererScale()378 double rendererScale() const {return mRendererScale;}
379
380 /**
381 * Gets access to new labeling engine (may be NULLPTR)
382 * \note not available in Python bindings
383 */
labelingEngine()384 QgsLabelingEngine *labelingEngine() const { return mLabelingEngine; } SIP_SKIP
385
386 /**
387 * Returns the color to use when rendering selected features.
388 *
389 * \see setSelectionColor()
390 */
selectionColor()391 QColor selectionColor() const { return mSelectionColor; }
392
393 /**
394 * Returns TRUE if vector selections should be shown in the rendered map
395 * \returns TRUE if selections should be shown
396 * \see setShowSelection
397 * \see selectionColor
398 * \since QGIS v2.4
399 */
400 bool showSelection() const;
401
402 //setters
403
404 /**
405 * Sets the current coordinate transform for the context.
406 *
407 * This represents the coordinate transform required to transform the layer
408 * which is being rendered back to the CRS of the rendered map.
409 *
410 * Set to an invalid QgsCoordinateTransform to indicate that no transformation is required.
411 *
412 * \see coordinateTransform()
413 */
414 void setCoordinateTransform( const QgsCoordinateTransform &t );
415
416 /**
417 * Sets the context's map to pixel transform, which transforms between map coordinates and device coordinates.
418 *
419 * \see mapToPixel()
420 */
setMapToPixel(const QgsMapToPixel & mtp)421 void setMapToPixel( const QgsMapToPixel &mtp ) {mMapToPixel = mtp;}
422
423 /**
424 * When rendering a map layer, calling this method sets the "clipping"
425 * extent for the layer (in the layer's CRS).
426 *
427 * This extent should be a "worst-case" scenario, which is guaranteed to
428 * completely cover the entire visible portion of the layer when it is rendered
429 * to the map. It may be larger than the actual visible area, but MUST contain at least the
430 * entire visible area.
431 *
432 * \see setExtent()
433 * \see setMapExtent()
434 */
setExtent(const QgsRectangle & extent)435 void setExtent( const QgsRectangle &extent ) {mExtent = extent;}
436
437 /**
438 * Sets the original \a extent of the map being rendered.
439 *
440 * Unlike setExtent(), this extent is always in the final destination CRS for the map
441 * render and represents the exact bounds of the map being rendered.
442 *
443 * \see mapExtent()
444 * \see setExtent()
445 * \since QGIS 3.4.8
446 */
setMapExtent(const QgsRectangle & extent)447 void setMapExtent( const QgsRectangle &extent ) { mOriginalMapExtent = extent; }
448
449 /**
450 * Sets whether edit markers should be drawn during the render operation.
451 *
452 * \see drawEditingInformation()
453 */
454 void setDrawEditingInformation( bool b );
455
456 /**
457 * Sets whether the rendering operation has been \a stopped and any ongoing
458 * rendering should be canceled immediately.
459 *
460 * \see renderingStopped()
461 */
setRenderingStopped(bool stopped)462 void setRenderingStopped( bool stopped ) {mRenderingStopped = stopped;}
463
464 /**
465 * A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
466 * Will be used to convert meter distances to active MapUnit values for QgsUnitTypes::RenderMetersInMapUnits
467 * \since QGIS 3.0
468 */
setDistanceArea(const QgsDistanceArea & distanceArea)469 void setDistanceArea( const QgsDistanceArea &distanceArea ) {mDistanceArea = distanceArea ;}
470
471 /**
472 * Sets the scaling factor for the render to convert painter units
473 * to physical sizes. This should usually be equal to the number of pixels
474 * per millimeter.
475 * \see scaleFactor()
476 */
setScaleFactor(double factor)477 void setScaleFactor( double factor ) {mScaleFactor = factor;}
478
479 /**
480 * Sets the renderer map scale. This should match the desired scale denominator
481 * for the rendered map, eg 1000.0 for a 1:1000 map render.
482 * \see rendererScale()
483 */
setRendererScale(double scale)484 void setRendererScale( double scale ) {mRendererScale = scale;}
485
486 /**
487 * Sets the destination QPainter for the render operation. Ownership of the painter
488 * is not transferred and the QPainter destination must stay alive for the duration
489 * of any rendering operations.
490 * \see painter()
491 */
setPainter(QPainter * p)492 void setPainter( QPainter *p ) {mPainter = p;}
493
494 /**
495 * Sets a mask QPainter for the render operation. Ownership of the painter
496 * is not transferred and the QPainter must stay alive for the duration
497 * of any rendering operations.
498 * Multiple mask painters can be defined and the second parameter gives a unique identifier to each one.
499 * \see maskPainter()
500 */
501 void setMaskPainter( QPainter *p, int id = 0 ) { mMaskPainter[id] = p; }
502
503 /**
504 * When rendering a map layer in a second pass (for selective masking),
505 * some symbol layers may be disabled.
506 *
507 * Sets the list of disabled symbol layers.
508 * \see disabledSymbolLayers()
509 * \see isSymbolLayerEnabled()
510 * \since QGIS 3.12
511 */
setDisabledSymbolLayers(const QSet<const QgsSymbolLayer * > & symbolLayers)512 void setDisabledSymbolLayers( const QSet<const QgsSymbolLayer *> &symbolLayers ) { mDisabledSymbolLayers = symbolLayers; }
513
514 /**
515 * Sets whether rendering operations should use vector operations instead
516 * of any faster raster shortcuts.
517 *
518 * \see forceVectorOutput()
519 */
520 void setForceVectorOutput( bool force );
521
522 /**
523 * Assign new labeling engine
524 * \note not available in Python bindings
525 */
setLabelingEngine(QgsLabelingEngine * engine)526 void setLabelingEngine( QgsLabelingEngine *engine ) { mLabelingEngine = engine; } SIP_SKIP
527
528 /**
529 * Sets the \a color to use when rendering selected features.
530 *
531 * \see selectionColor()
532 */
setSelectionColor(const QColor & color)533 void setSelectionColor( const QColor &color ) { mSelectionColor = color; }
534
535 /**
536 * Sets whether vector selections should be shown in the rendered map
537 * \param showSelection set to TRUE if selections should be shown
538 * \see showSelection
539 * \see setSelectionColor
540 * \since QGIS v2.4
541 */
542 void setShowSelection( bool showSelection );
543
544 /**
545 * Returns TRUE if the rendering optimization (geometry simplification) can be executed
546 *
547 * \see setUseRenderingOptimization()
548 */
549 bool useRenderingOptimization() const;
550
551 /**
552 * Sets whether the rendering optimization (geometry simplification) should be executed
553 *
554 * \see useRenderingOptimization()
555 */
556 void setUseRenderingOptimization( bool enabled );
557
558 /**
559 * Returns the simplification settings to use when rendering vector layers.
560 *
561 * The default is to use no simplification.
562 *
563 * \see setVectorSimplifyMethod()
564 * \since QGIS 2.4
565 */
vectorSimplifyMethod()566 const QgsVectorSimplifyMethod &vectorSimplifyMethod() const { return mVectorSimplifyMethod; }
567
568 /**
569 * Sets the simplification setting to use when rendering vector layers.
570 *
571 * This can be used to specify simplification methods to apply during map exports and renders,
572 * e.g. to allow vector layers to be simplified to an appropriate maximum level of detail
573 * during PDF exports or to speed up layer rendering
574 *
575 * The default is to use no simplification.
576 *
577 * \see vectorSimplifyMethod()
578 *
579 * \since QGIS 2.4
580 */
setVectorSimplifyMethod(const QgsVectorSimplifyMethod & simplifyMethod)581 void setVectorSimplifyMethod( const QgsVectorSimplifyMethod &simplifyMethod ) { mVectorSimplifyMethod = simplifyMethod; }
582
583 /**
584 * Sets the expression context. This context is used for all expression evaluation
585 * associated with this render context.
586 * \see expressionContext()
587 * \since QGIS 2.12
588 */
setExpressionContext(const QgsExpressionContext & context)589 void setExpressionContext( const QgsExpressionContext &context ) { mExpressionContext = context; }
590
591 /**
592 * Gets the expression context. This context should be used for all expression evaluation
593 * associated with this render context.
594 * \see setExpressionContext()
595 * \since QGIS 2.12
596 */
expressionContext()597 QgsExpressionContext &expressionContext() { return mExpressionContext; }
598
599 /**
600 * Gets the expression context (const version). This context should be used for all expression evaluation
601 * associated with this render context.
602 * \see setExpressionContext()
603 * \note not available in Python bindings
604 * \since QGIS 2.12
605 */
expressionContext()606 const QgsExpressionContext &expressionContext() const { return mExpressionContext; } SIP_SKIP
607
608 //! Returns pointer to the unsegmentized geometry
geometry()609 const QgsAbstractGeometry *geometry() const { return mGeometry; }
610 //! Sets pointer to original (unsegmentized) geometry
setGeometry(const QgsAbstractGeometry * geometry)611 void setGeometry( const QgsAbstractGeometry *geometry ) { mGeometry = geometry; }
612
613 /**
614 * Set a filter feature provider used for additional filtering of rendered features.
615 * \param ffp the filter feature provider
616 * \see featureFilterProvider()
617 * \since QGIS 2.14
618 */
619 void setFeatureFilterProvider( const QgsFeatureFilterProvider *ffp );
620
621 /**
622 * Gets the filter feature provider used for additional filtering of rendered features.
623 * \returns the filter feature provider
624 * \see setFeatureFilterProvider()
625 * \since QGIS 2.14
626 */
627 const QgsFeatureFilterProvider *featureFilterProvider() const;
628
629 /**
630 * Sets the segmentation tolerance applied when rendering curved geometries
631 * \param tolerance the segmentation tolerance
632 * \see segmentationTolerance()
633 * \see segmentationToleranceType()
634 */
setSegmentationTolerance(double tolerance)635 void setSegmentationTolerance( double tolerance ) { mSegmentationTolerance = tolerance; }
636
637 /**
638 * Gets the segmentation tolerance applied when rendering curved geometries
639 * \see setSegmentationTolerance()
640 */
segmentationTolerance()641 double segmentationTolerance() const { return mSegmentationTolerance; }
642
643 /**
644 * Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
645 * \param type the segmentation tolerance typename
646 * \see segmentationToleranceType()
647 * \see segmentationTolerance()
648 */
setSegmentationToleranceType(QgsAbstractGeometry::SegmentationToleranceType type)649 void setSegmentationToleranceType( QgsAbstractGeometry::SegmentationToleranceType type ) { mSegmentationToleranceType = type; }
650
651 /**
652 * Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
653 * \see setSegmentationToleranceType()
654 */
segmentationToleranceType()655 QgsAbstractGeometry::SegmentationToleranceType segmentationToleranceType() const { return mSegmentationToleranceType; }
656
657 // Conversions
658
659 /**
660 * Converts a size from the specified units to painter units (pixels). The conversion respects the limits
661 * specified by the optional scale parameter.
662 * \see convertToMapUnits()
663 * \since QGIS 3.0
664 */
665 double convertToPainterUnits( double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale = QgsMapUnitScale() ) const;
666
667 /**
668 * Converts a size from the specified units to map units. The conversion respects the limits
669 * specified by the optional scale parameter.
670 * \see convertToPainterUnits()
671 * \since QGIS 3.0
672 */
673 double convertToMapUnits( double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale = QgsMapUnitScale() ) const;
674
675 /**
676 * Converts a size from map units to the specified units.
677 * \see convertToMapUnits()
678 * \since QGIS 3.0
679 */
680 double convertFromMapUnits( double sizeInMapUnits, QgsUnitTypes::RenderUnit outputUnit ) const;
681
682 /**
683 * Convert meter distances to active MapUnit values for QgsUnitTypes::RenderMetersInMapUnits
684 * \note
685 * When the sourceCrs() is geographic, the center of the Extent will be used
686 * \since QGIS 3.0
687 */
688 double convertMetersToMapUnits( double meters ) const;
689
690 /**
691 * Returns the text render format, which dictates how text is rendered (e.g. as paths or real text objects).
692 *
693 * \see setTextRenderFormat()
694 * \since QGIS 3.4.3
695 */
textRenderFormat()696 TextRenderFormat textRenderFormat() const
697 {
698 return mTextRenderFormat;
699 }
700
701 /**
702 * Sets the text render \a format, which dictates how text is rendered (e.g. as paths or real text objects).
703 *
704 * \see textRenderFormat()
705 * \since QGIS 3.4.3
706 */
setTextRenderFormat(TextRenderFormat format)707 void setTextRenderFormat( TextRenderFormat format )
708 {
709 mTextRenderFormat = format;
710 }
711
712 /**
713 * Returns the list of rendered feature handlers to use while rendering map layers.
714 * \see hasRenderedFeatureHandlers()
715 * \since QGIS 3.10
716 */
717 QList<QgsRenderedFeatureHandlerInterface *> renderedFeatureHandlers() const;
718
719 /**
720 * Returns TRUE if the context has any rendered feature handlers.
721 * \see renderedFeatureHandlers()
722 * \since QGIS 3.10
723 */
hasRenderedFeatureHandlers()724 bool hasRenderedFeatureHandlers() const { return mHasRenderedFeatureHandlers; }
725
726 /**
727 * Attaches a mask id provider to the context. It will allow some rendering operations to set the current mask id
728 * based on the context (label layer names and label rules for instance).
729 * \see QgsMaskIdProvider
730 * \see setCurrentMaskId()
731 * \see maskIdProvider()
732 * \since QGIS 3.12
733 */
setMaskIdProvider(QgsMaskIdProvider * provider)734 void setMaskIdProvider( QgsMaskIdProvider *provider ) { mMaskIdProvider = provider; }
735
736 /**
737 * Returns the mask id provider attached to the context.
738 * \see setMaskIdProvider()
739 * \since QGIS 3.12
740 */
maskIdProvider()741 const QgsMaskIdProvider *maskIdProvider() const { return mMaskIdProvider; }
742
743 /**
744 * Stores a mask id as the "current" one.
745 * \see currentMaskId()
746 * \since QGIS 3.12
747 */
setCurrentMaskId(int id)748 void setCurrentMaskId( int id ) { mCurrentMaskId = id; }
749
750 /**
751 * Returns the current mask id, which can be used with maskPainter()
752 * \see setCurrentMaskId()
753 * \see maskPainter()
754 * \since QGIS 3.12
755 */
currentMaskId()756 int currentMaskId() const { return mCurrentMaskId; }
757
758 /**
759 * Sets GUI preview mode.
760 * GUI preview mode is used to change the behavior of some renderings when
761 * they are done to preview of symbology in the GUI.
762 * This is especially used to display mask symbol layers rather than painting them
763 * in a mask painter, which is not meant to be visible, by definition.
764 * \see isGuiPreview
765 * \since QGIS 3.12
766 */
setIsGuiPreview(bool preview)767 void setIsGuiPreview( bool preview ) { mIsGuiPreview = preview; }
768
769 /**
770 * Returns the Gui preview mode.
771 * GUI preview mode is used to change the behavior of some renderings when
772 * they are done to preview of symbology in the GUI.
773 * This is especially used to display mask symbol layers rather than painting them
774 * in a mask painter, which is not meant to be visible, by definition.
775 * \see isGuiPreview
776 * \see setIsGuiPreview
777 * \since QGIS 3.12
778 */
isGuiPreview()779 bool isGuiPreview() const { return mIsGuiPreview; }
780
781 /**
782 * Gets custom rendering flags. Layers might honour these to alter their rendering.
783 * \returns a map of custom flags
784 * \see setCustomRenderingFlag()
785 * \since QGIS 3.12
786 */
customRenderingFlags()787 QVariantMap customRenderingFlags() const { return mCustomRenderingFlags; }
788
789 /**
790 * Sets a custom rendering flag. Layers might honour these to alter their rendering.
791 * \param flag the flag name
792 * \param value the flag value
793 * \see customRenderingFlags()
794 * \since QGIS 3.12
795 */
setCustomRenderingFlag(const QString & flag,const QVariant & value)796 void setCustomRenderingFlag( const QString &flag, const QVariant &value ) { mCustomRenderingFlags[flag] = value; }
797
798 /**
799 * Clears the specified custom rendering flag.
800 * \param flag the flag name
801 * \see setCustomRenderingFlag()
802 * \since QGIS 3.12
803 */
clearCustomRenderingFlag(const QString & flag)804 void clearCustomRenderingFlag( const QString &flag ) { mCustomRenderingFlags.remove( flag ); }
805
806 /**
807 * Returns the list of clipping regions to apply during the render.
808 *
809 * These regions are always in the final destination CRS for the map.
810 *
811 * \since QGIS 3.16
812 */
813 QList< QgsMapClippingRegion > clippingRegions() const;
814
815 /**
816 * Returns the geometry to use to clip features at render time.
817 *
818 * When vector features are rendered, they should be clipped to this geometry.
819 *
820 * \warning The clipping must take effect for rendering the feature's symbol only,
821 * and should never be applied directly to the feature being rendered. Doing so would
822 * impact the results of rendering rules which rely on feature geometry, such as
823 * a rule-based renderer using the feature's area.
824 *
825 * \see setFeatureClipGeometry()
826 *
827 * \since QGIS 3.16
828 */
829 QgsGeometry featureClipGeometry() const;
830
831 /**
832 * Sets a \a geometry to use to clip features at render time.
833 *
834 * \note This is not usually set directly, but rather specified by calling QgsMapSettings:addClippingRegion()
835 * prior to constructing a QgsRenderContext.
836 *
837 * \see featureClipGeometry()
838 * \since QGIS 3.16
839 */
840 void setFeatureClipGeometry( const QgsGeometry &geometry );
841
842 /**
843 * Returns the texture origin, which should be used as a brush transform when
844 * rendering using QBrush objects.
845 *
846 * \see setTextureOrigin()
847 * \since QGIS 3.16
848 */
849 QPointF textureOrigin() const;
850
851 /**
852 * Sets the texture \a origin, which should be used as a brush transform when
853 * rendering using QBrush objects.
854 *
855 * \see textureOrigin()
856 * \since QGIS 3.16
857 */
858 void setTextureOrigin( const QPointF &origin );
859
860 private:
861
862 Flags mFlags;
863
864 //! Painter for rendering operations
865 QPainter *mPainter = nullptr;
866
867 /**
868 * Mask painters for selective masking.
869 * Multiple mask painters can be defined for a rendering. The map key is a unique identifier for each mask painter.
870 * \see mMaskIdProvider
871 * \since QGIS 3.12
872 */
873 QMap<int, QPainter *> mMaskPainter;
874
875 /**
876 * Pointer to a mask id provider
877 * \see QgsMaskIdProvider
878 * \since QGIS 3.12
879 */
880 QgsMaskIdProvider *mMaskIdProvider = nullptr;
881
882 /**
883 * Current mask identifier
884 * \since QGIS 3.12
885 */
886 int mCurrentMaskId = -1;
887
888 /**
889 * Whether we are rendering a preview of a symbol / label
890 * \since QGIS 3.12
891 */
892 bool mIsGuiPreview = false;
893
894 //! For transformation between coordinate systems. Can be invalid if on-the-fly reprojection is not used
895 QgsCoordinateTransform mCoordTransform;
896
897 /**
898 * A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
899 * Will be used to convert meter distances to active MapUnit values for QgsUnitTypes::RenderMetersInMapUnits
900 * \since QGIS 3.0
901 */
902 QgsDistanceArea mDistanceArea;
903
904 QgsRectangle mExtent;
905 QgsRectangle mOriginalMapExtent;
906
907 QgsMapToPixel mMapToPixel;
908
909 //! True if the rendering has been canceled
910 bool mRenderingStopped = false;
911
912 //! Factor to scale line widths and point marker sizes
913 double mScaleFactor = 1.0;
914
915 //! Map scale
916 double mRendererScale = 1.0;
917
918 //! Newer labeling engine implementation (can be NULLPTR)
919 QgsLabelingEngine *mLabelingEngine = nullptr;
920
921 //! Color used for features that are marked as selected
922 QColor mSelectionColor;
923
924 //! Simplification object which holds the information about how to simplify the features for fast rendering
925 QgsVectorSimplifyMethod mVectorSimplifyMethod;
926
927 //! Expression context
928 QgsExpressionContext mExpressionContext;
929
930 //! Pointer to the (unsegmentized) geometry
931 const QgsAbstractGeometry *mGeometry = nullptr;
932
933 //! The feature filter provider
934 std::unique_ptr< QgsFeatureFilterProvider > mFeatureFilterProvider;
935
936 double mSegmentationTolerance = M_PI_2 / 90;
937
938 QgsAbstractGeometry::SegmentationToleranceType mSegmentationToleranceType = QgsAbstractGeometry::MaximumAngle;
939
940 QgsCoordinateTransformContext mTransformContext;
941
942 QgsPathResolver mPathResolver;
943
944 TextRenderFormat mTextRenderFormat = TextFormatAlwaysOutlines;
945 QList< QgsRenderedFeatureHandlerInterface * > mRenderedFeatureHandlers;
946 bool mHasRenderedFeatureHandlers = false;
947 QVariantMap mCustomRenderingFlags;
948
949 QSet<const QgsSymbolLayer *> mDisabledSymbolLayers;
950
951 QList< QgsMapClippingRegion > mClippingRegions;
952 QgsGeometry mFeatureClipGeometry;
953
954 QPointF mTextureOrigin;
955
956 #ifdef QGISDEBUG
957 bool mHasTransformContext = false;
958 #endif
959 };
960
Q_DECLARE_OPERATORS_FOR_FLAGS(QgsRenderContext::Flags)961 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsRenderContext::Flags )
962
963 #ifndef SIP_RUN
964
965 /**
966 * \ingroup core
967 *
968 * \brief Scoped object for temporary replacement of a QgsRenderContext destination painter.
969 *
970 * Temporarily swaps out the destination QPainter object for a QgsRenderContext for the lifetime of the object,
971 * before replacing it to the original painter on destruction.
972 *
973 * \note Not available in Python bindings
974 * \since QGIS 3.14
975 */
976 class QgsScopedRenderContextPainterSwap
977 {
978 public:
979
980 /**
981 * Constructor for QgsScopedRenderContextPainterSwap.
982 *
983 * Swaps the destination painter for \a context (set QgsRenderContext::setPainter() ) to
984 * \a temporaryPainter.
985 */
986 QgsScopedRenderContextPainterSwap( QgsRenderContext &context, QPainter *temporaryPainter )
987 : mContext( context )
988 , mPreviousPainter( context.painter() )
989 {
990 mContext.setPainter( temporaryPainter );
991 }
992
993 /**
994 * Resets the destination painter for the context back to the original QPainter object.
995 */
996 void reset()
997 {
998 if ( !mReleased )
999 {
1000 mContext.setPainter( mPreviousPainter );
1001 mReleased = true;
1002 }
1003 }
1004
1005 /**
1006 * Returns the destination painter for the context back to the original QPainter object.
1007 */
1008 ~QgsScopedRenderContextPainterSwap()
1009 {
1010 reset();
1011 }
1012
1013 private:
1014
1015 QgsRenderContext &mContext;
1016 QPainter *mPreviousPainter = nullptr;
1017 bool mReleased = false;
1018 };
1019
1020
1021 /**
1022 * \ingroup core
1023 *
1024 * \brief Scoped object for temporary scaling of a QgsRenderContext for millimeter based rendering.
1025 *
1026 * Temporarily scales the destination QPainter for a QgsRenderContext to use millimeter based units for the lifetime of the object,
1027 * before returning it to pixel based units on destruction.
1028 *
1029 * \note Not available in Python bindings
1030 * \since QGIS 3.14
1031 */
1032 class QgsScopedRenderContextScaleToMm
1033 {
1034 public:
1035
1036 /**
1037 * Constructor for QgsScopedRenderContextScaleToMm.
1038 *
1039 * Rescales the destination painter (see QgsRenderContext::painter() ) to use millimeter based units.
1040 *
1041 * \warning It is the caller's responsibility to ensure that \a context is initially scaled to use pixel based units!
1042 */
QgsScopedRenderContextScaleToMm(QgsRenderContext & context)1043 QgsScopedRenderContextScaleToMm( QgsRenderContext &context )
1044 : mContext( context )
1045 {
1046 if ( mContext.painter() )
1047 mContext.painter()->scale( mContext.scaleFactor(), mContext.scaleFactor() );
1048 }
1049
1050 /**
1051 * Returns the destination painter back to pixel based units.
1052 */
~QgsScopedRenderContextScaleToMm()1053 ~QgsScopedRenderContextScaleToMm()
1054 {
1055 if ( mContext.painter() )
1056 mContext.painter()->scale( 1.0 / mContext.scaleFactor(), 1.0 / mContext.scaleFactor() );
1057 }
1058
1059 private:
1060
1061 QgsRenderContext &mContext;
1062 };
1063
1064
1065 /**
1066 * \ingroup core
1067 *
1068 * \brief Scoped object for temporary scaling of a QgsRenderContext for pixel based rendering.
1069 *
1070 * Temporarily scales the destination QPainter for a QgsRenderContext to use pixel based units for the lifetime of the object,
1071 * before returning it to millimeter based units on destruction.
1072 *
1073 * \note Not available in Python bindings
1074 * \since QGIS 3.14
1075 */
1076 class QgsScopedRenderContextScaleToPixels
1077 {
1078 public:
1079
1080 /**
1081 * Constructor for QgsScopedRenderContextScaleToPixels.
1082 *
1083 * Rescales the destination painter (see QgsRenderContext::painter() ) to use pixel based units.
1084 *
1085 * \warning It is the caller's responsibility to ensure that \a context is initially scaled to use millimeter based units!
1086 */
QgsScopedRenderContextScaleToPixels(QgsRenderContext & context)1087 QgsScopedRenderContextScaleToPixels( QgsRenderContext &context )
1088 : mContext( context )
1089 {
1090 if ( mContext.painter() )
1091 mContext.painter()->scale( 1.0 / mContext.scaleFactor(), 1.0 / mContext.scaleFactor() );
1092 }
1093
1094 /**
1095 * Returns the destination painter back to millimeter based units.
1096 */
~QgsScopedRenderContextScaleToPixels()1097 ~QgsScopedRenderContextScaleToPixels()
1098 {
1099 if ( mContext.painter() )
1100 mContext.painter()->scale( mContext.scaleFactor(), mContext.scaleFactor() );
1101 }
1102
1103 private:
1104
1105 QgsRenderContext &mContext;
1106 };
1107
1108
1109 /**
1110 * \ingroup core
1111 *
1112 * \brief Scoped object for saving and restoring a QPainter object's state.
1113 *
1114 * Temporarily saves the QPainter state for the lifetime of the object, before restoring it
1115 * on destruction.
1116 *
1117 * \note Not available in Python bindings
1118 * \since QGIS 3.16
1119 */
1120 class QgsScopedQPainterState
1121 {
1122 public:
1123
1124 /**
1125 * Constructor for QgsScopedQPainterState.
1126 *
1127 * Saves the specified \a painter state.
1128 */
QgsScopedQPainterState(QPainter * painter)1129 QgsScopedQPainterState( QPainter *painter )
1130 : mPainter( painter )
1131 {
1132 mPainter->save();
1133 }
1134
1135 /**
1136 * Restores the painter back to its original state.
1137 */
~QgsScopedQPainterState()1138 ~QgsScopedQPainterState()
1139 {
1140 mPainter->restore();
1141 }
1142
1143 private:
1144
1145 QPainter *mPainter = nullptr;
1146 };
1147
1148 #endif
1149
1150 #endif
1151