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