Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsmaprenderercache.h 3 : : -------------------------------------- 4 : : Date : December 2013 5 : : Copyright : (C) 2013 by Martin Dobias 6 : : Email : wonder dot sk at gmail dot com 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : 16 : : #ifndef QGSMAPRENDERERCACHE_H 17 : : #define QGSMAPRENDERERCACHE_H 18 : : 19 : : #include "qgis_core.h" 20 : : #include <QMap> 21 : : #include <QImage> 22 : : #include <QMutex> 23 : : 24 : : #include "qgsrectangle.h" 25 : : #include "qgsmaplayer.h" 26 : : 27 : : 28 : : /** 29 : : * \ingroup core 30 : : * \brief This class is responsible for keeping cache of rendered images resulting from 31 : : * a map rendering job. 32 : : * 33 : : * Once a job has a rendered image stored in the cache (using setCacheImage(...)), 34 : : * the cache listens to repaintRequested() signals from dependent layers. 35 : : * If triggered, the cache removes the rendered image (and disconnects from the 36 : : * layers). 37 : : * 38 : : * When user pans/zooms the canvas, the cache is also used in rendering period 39 : : * for particular layers between the first render update and the moment the layer 40 : : * actually has partially rendered something in the resulting image. 41 : : * 42 : : * The class is thread-safe (multiple classes can access the same instance safely). 43 : : * 44 : : * \since QGIS 2.4 45 : : */ 46 : : class CORE_EXPORT QgsMapRendererCache : public QObject 47 : : { 48 : : Q_OBJECT 49 : : public: 50 : : 51 : : QgsMapRendererCache(); 52 : : 53 : : /** 54 : : * Invalidates the cache contents, clearing all cached images. 55 : : * \see clearCacheImage() 56 : : */ 57 : : void clear(); 58 : : 59 : : /** 60 : : * Initialize cache: sets extent and scale parameters and clears the cache if any 61 : : * parameters have changed since last initialization. 62 : : * 63 : : * \returns flag whether the parameters are the same as last time 64 : : * \deprecated since QGIS 3.18 - will be removed in QGIS 4.0. Use the updateParameters() and clear() 65 : : */ 66 : : Q_DECL_DEPRECATED bool init( const QgsRectangle &extent, double scale ) SIP_DEPRECATED; 67 : : 68 : : /** 69 : : * Sets extent and scale parameters 70 : : * 71 : : * \returns flag whether the parameters are the same as last time 72 : : * 73 : : * \since QGIS 3.18 74 : : */ 75 : : bool updateParameters( const QgsRectangle &extent, const QgsMapToPixel &mtp ); 76 : : 77 : : /** 78 : : * Set the cached \a image for a particular \a cacheKey, using the current cache parameters. 79 : : * 80 : : * The \a cacheKey usually matches the QgsMapLayer::id() which the image is a render of. 81 : : * 82 : : * A list of \a dependentLayers should be passed containing all layer 83 : : * on which this cache image is dependent. If any of these layers triggers a 84 : : * repaint then the cache image will be cleared. 85 : : * 86 : : * \see setCacheImageWithParameters() 87 : : * \see cacheImage() 88 : : */ 89 : : void setCacheImage( const QString &cacheKey, const QImage &image, const QList< QgsMapLayer * > &dependentLayers = QList< QgsMapLayer * >() ); 90 : : 91 : : /** 92 : : * Set the cached \a image for a particular \a cacheKey, using a specific \a extent and \a mapToPixel 93 : : * (which may differ from the current cache parameters). 94 : : * 95 : : * The \a cacheKey usually matches the QgsMapLayer::id() which the image is a render of. 96 : : * 97 : : * A list of \a dependentLayers should be passed containing all layer 98 : : * on which this cache image is dependent. If any of these layers triggers a 99 : : * repaint then the cache image will be cleared. 100 : : * 101 : : * \see cacheImage() 102 : : * \since QGIS 3.18 103 : : */ 104 : : void setCacheImageWithParameters( const QString &cacheKey, 105 : : const QImage &image, 106 : : const QgsRectangle &extent, 107 : : const QgsMapToPixel &mapToPixel, 108 : : const QList< QgsMapLayer * > &dependentLayers = QList< QgsMapLayer * >() ); 109 : : 110 : : /** 111 : : * Returns TRUE if the cache contains an image with the specified \a cacheKey 112 : : * that has the same extent and scale as the cache's global extent and scale 113 : : * 114 : : * \see cacheImage() 115 : : * \since QGIS 3.0 116 : : */ 117 : : bool hasCacheImage( const QString &cacheKey ) const; 118 : : 119 : : /** 120 : : * Returns TRUE if the cache contains an image with the specified \a cacheKey 121 : : * with any cache's parameters (extent and scale) 122 : : * 123 : : * The optional \a minimumScaleThreshold and \a maximumScaleThreshold arguments can be used to 124 : : * specify a range of acceptable cached scales vs current cache scale parameter. E.g. if the 125 : : * \a minimumScaleThreshold is 0.5 and \a maximumScaleThreshold is 2.0, then only cached images 126 : : * with a scale between 0.5 * current cache scale and 2.0 * current cache scale will be considered. 127 : : * 128 : : * \see transformedCacheImage() 129 : : * 130 : : * \since QGIS 3.18 131 : : */ 132 : : bool hasAnyCacheImage( const QString &cacheKey, double minimumScaleThreshold = 0, double maximumScaleThreshold = 0 ) const; 133 : : 134 : : /** 135 : : * Returns the cached image for the specified \a cacheKey. The \a cacheKey usually 136 : : * matches the QgsMapLayer::id() which the image is a render of. 137 : : * Returns a null image if it is not cached. 138 : : * \see setCacheImage() 139 : : * \see hasCacheImage() 140 : : */ 141 : : QImage cacheImage( const QString &cacheKey ) const; 142 : : 143 : : /** 144 : : * Returns the cached image for the specified \a cacheKey transformed 145 : : * to the particular extent and scale. 146 : : * 147 : : * The \a cacheKey usually matches the QgsMapLayer::id() which 148 : : * the image is a render of. 149 : : * Returns a null image if it is not cached. 150 : : * 151 : : * \see hasAnyCacheImage() 152 : : * 153 : : * \since QGIS 3.18 154 : : */ 155 : : QImage transformedCacheImage( const QString &cacheKey, const QgsMapToPixel &mtp ) const; 156 : : 157 : : /** 158 : : * Returns a list of map layers on which an image in the cache depends. 159 : : * \since QGIS 3.0 160 : : */ 161 : : QList< QgsMapLayer * > dependentLayers( const QString &cacheKey ) const; 162 : : 163 : : /** 164 : : * Removes an image from the cache with matching \a cacheKey. 165 : : * \see clear() 166 : : */ 167 : : void clearCacheImage( const QString &cacheKey ); 168 : : 169 : : /** 170 : : * Invalidates cached images which relate to the specified map \a layer. 171 : : * 172 : : * \since QGIS 3.14 173 : : */ 174 : : void invalidateCacheForLayer( QgsMapLayer *layer ); 175 : : 176 : : private slots: 177 : : //! Remove layer (that emitted the signal) from the cache 178 : : void layerRequestedRepaint(); 179 : : 180 : : private: 181 : : 182 : 0 : struct CacheParameters 183 : : { 184 : : QImage cachedImage; 185 : : QgsWeakMapLayerPointerList dependentLayers; 186 : : QgsRectangle cachedExtent; 187 : : QgsMapToPixel cachedMtp; 188 : : }; 189 : : 190 : : //! Invalidate cache contents (without locking) 191 : : void clearInternal(); 192 : : 193 : : //! Disconnects from layers we no longer care about 194 : : void dropUnusedConnections(); 195 : : 196 : : QSet< QgsWeakMapLayerPointer > dependentLayers() const; 197 : : 198 : : mutable QMutex mMutex; 199 : : QgsRectangle mExtent; 200 : : QgsMapToPixel mMtp; 201 : : 202 : : double mScale = -1.0; //DEPRECATED 203 : : 204 : : //! Map of cache key to cache parameters 205 : : QMap<QString, CacheParameters> mCachedImages; 206 : : //! List of all layers on which this cache is currently connected 207 : : QSet< QgsWeakMapLayerPointer > mConnectedLayers; 208 : : }; 209 : : 210 : : 211 : : #endif // QGSMAPRENDERERCACHE_H