QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
qgsannotationlayerrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsannotationlayerrenderer.cpp
3  ------------------
4  copyright : (C) 2019 by Sandro Mani
5  email : smani at sourcepole dot ch
6  ***************************************************************************/
7 
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
18 #include "qgsannotationlayer.h"
19 #include "qgsfeedback.h"
21 #include "qgspainteffect.h"
22 #include "qgsrendercontext.h"
23 #include <optional>
24 
26  : QgsMapLayerRenderer( layer->id(), &context )
27  , mFeedback( std::make_unique< QgsFeedback >() )
28  , mLayerOpacity( layer->opacity() )
29 {
30  // Clone items from layer which fall inside the rendered extent
31  // Because some items have scale dependent bounds, we have to accept some limitations here.
32  // first, we can use the layer's spatial index to very quickly retrieve items we know will fall within the visible
33  // extent. This will ONLY apply to items which have a non-scale-dependent bounding box though.
34 
35  const QStringList itemsList = layer->queryIndex( context.extent() );
36  QSet< QString > items( itemsList.begin(), itemsList.end() );
37 
38  // we also have NO choice but to clone ALL non-indexed items (i.e. those with a scale-dependent bounding box)
39  // since these won't be in the layer's spatial index, and it's too expensive to determine their actual bounding box
40  // upfront (we are blocking the main thread right now!)
41 
42  // TODO -- come up with some brilliant way to avoid this and also index scale-dependent items ;)
43  items.unite( layer->mNonIndexedItems );
44 
45  mItems.reserve( items.size() );
46  std::transform( items.begin(), items.end(), std::back_inserter( mItems ),
47  [layer]( const QString & id ) ->std::pair< QString, std::unique_ptr< QgsAnnotationItem > >
48  {
49  return std::make_pair( id, std::unique_ptr< QgsAnnotationItem >( layer->item( id )->clone() ) );
50  } );
51 
52  std::sort( mItems.begin(), mItems.end(), [](
53  const std::pair< QString, std::unique_ptr< QgsAnnotationItem > > &a,
54  const std::pair< QString, std::unique_ptr< QgsAnnotationItem > > &b )
55  { return a.second->zIndex() < b.second->zIndex(); } );
56 
57  if ( layer->paintEffect() && layer->paintEffect()->enabled() )
58  {
59  mPaintEffect.reset( layer->paintEffect()->clone() );
60  }
61 }
62 
64 
66 {
67  return mFeedback.get();
68 }
69 
71 {
72  QgsRenderContext &context = *renderContext();
73 
74  if ( mPaintEffect )
75  {
76  mPaintEffect->begin( context );
77  }
78 
79  bool canceled = false;
80  for ( const std::pair< QString, std::unique_ptr< QgsAnnotationItem > > &item : std::as_const( mItems ) )
81  {
82  if ( mFeedback->isCanceled() )
83  {
84  canceled = true;
85  break;
86  }
87 
88  if ( !item.second->enabled() )
89  continue;
90 
91  std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
92  if ( item.second->useSymbologyReferenceScale() )
93  {
94  referenceScaleOverride.emplace( QgsScopedRenderContextReferenceScaleOverride( context, item.second->symbologyReferenceScale() ) );
95  }
96 
97  const QgsRectangle bounds = item.second->boundingBox( context );
98  if ( bounds.intersects( context.extent() ) )
99  {
100  item.second->render( context, mFeedback.get() );
101  std::unique_ptr< QgsRenderedAnnotationItemDetails > details = std::make_unique< QgsRenderedAnnotationItemDetails >( mLayerID, item.first );
102  details->setBoundingBox( bounds );
103  appendRenderedItemDetails( details.release() );
104  }
105  }
106 
107  if ( mPaintEffect )
108  {
109  mPaintEffect->end( context );
110  }
111 
112  return !canceled;
113 }
114 
116 {
117  return renderContext()->testFlag( Qgis::RenderContextFlag::UseAdvancedEffects ) && ( !qgsDoubleNear( mLayerOpacity, 1.0 ) );
118 }
@ UseAdvancedEffects
Enable layer opacity and blending effects.
bool forceRasterRender() const override
Returns true if the renderer must be rendered to a raster paint device (e.g.
~QgsAnnotationLayerRenderer() override
bool render() override
Do the rendering (based on data stored in the class).
QgsFeedback * feedback() const override
Access to feedback object of the layer renderer (may be nullptr)
QgsAnnotationLayerRenderer(QgsAnnotationLayer *layer, QgsRenderContext &context)
Constructor for a QgsAnnotationLayerRenderer, for the specified layer.
Represents a map layer containing a set of georeferenced annotations, e.g.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
Base class for utility classes that encapsulate information necessary for rendering of map layers.
void appendRenderedItemDetails(QgsRenderedItemDetails *details)
Appends the details of a rendered item to the renderer.
QgsRenderContext * renderContext()
Returns the render context associated with the renderer.
virtual QgsPaintEffect * clone() const =0
Duplicates an effect by creating a deep copy of the effect.
bool enabled() const
Returns whether the effect is enabled.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
Definition: qgsrectangle.h:371
Contains information about the context of a rendering operation.
double symbologyReferenceScale() const
Returns the symbology reference scale.
bool testFlag(Qgis::RenderContextFlag flag) const
Check whether a particular flag is enabled.
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
Scoped object for temporary override of the symbologyReferenceScale property of a QgsRenderContext.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:5172