Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgssvgcache.h
3 : : ------------------------------
4 : : begin : 2011
5 : : copyright : (C) 2011 by Marco Hugentobler
6 : : email : marco dot hugentobler at sourcepole 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 QGSSVGCACHE_H
19 : : #define QGSSVGCACHE_H
20 : :
21 : : #include "qgsabstractcontentcache.h"
22 : : #include "qgis.h"
23 : :
24 : : #include <QPicture>
25 : :
26 : : class QDomElement;
27 : :
28 : : #ifndef SIP_RUN
29 : :
30 : : ///@cond PRIVATE
31 : :
32 : : /**
33 : : * \ingroup core
34 : : * \class QgsSvgCacheEntry
35 : : */
36 : 80 : class CORE_EXPORT QgsSvgCacheEntry : public QgsAbstractContentCacheEntry
37 : : {
38 : : public:
39 : :
40 : : /**
41 : : * Constructor.
42 : : * \param path Absolute path to SVG file (relative paths are not resolved).
43 : : * \param size
44 : : * \param strokeWidth width of stroke
45 : : * \param widthScaleFactor width scale factor
46 : : * \param fill color of fill
47 : : * \param stroke color of stroke
48 : : * \param fixedAspectRatio fixed aspect ratio (optional)
49 : : * \param parameters an optional map of parameters to dynamically replace content in the SVG
50 : : */
51 : : QgsSvgCacheEntry( const QString &path, double size, double strokeWidth, double widthScaleFactor, const QColor &fill, const QColor &stroke,
52 : : double fixedAspectRatio = 0, const QMap<QString, QString> ¶meters = QMap<QString, QString>() ) ;
53 : :
54 : : //! QgsSvgCacheEntry cannot be copied.
55 : : QgsSvgCacheEntry( const QgsSvgCacheEntry &rh ) = delete;
56 : : //! QgsSvgCacheEntry cannot be copied.
57 : : QgsSvgCacheEntry &operator=( const QgsSvgCacheEntry &rh ) = delete;
58 : :
59 : : double size = 0.0; //size in pixels (cast to int for QImage)
60 : : double strokeWidth = 0;
61 : : double widthScaleFactor = 1.0;
62 : :
63 : : //! Fixed aspect ratio
64 : : double fixedAspectRatio = 0;
65 : :
66 : : /**
67 : : * SVG viewbox size.
68 : : * \since QGIS 2.14
69 : : */
70 : : QSizeF viewboxSize;
71 : :
72 : : QColor fill = Qt::black;
73 : : QColor stroke = Qt::black;
74 : : QMap<QString, QString> parameters;
75 : :
76 : : std::unique_ptr< QImage > image;
77 : : std::unique_ptr< QPicture > picture;
78 : : //content (with params replaced)
79 : : QByteArray svgContent;
80 : :
81 : : /**
82 : : * TRUE if the image represents a broken/missing path.
83 : : *
84 : : * \since QGIS 3.14
85 : : */
86 : : bool isMissingImage = false;
87 : :
88 : : bool isEqual( const QgsAbstractContentCacheEntry *other ) const override;
89 : : int dataSize() const override;
90 : : void dump() const override;
91 : :
92 : : };
93 : :
94 : : ///@endcond
95 : : #endif
96 : :
97 : : /**
98 : : * \ingroup core
99 : : * \brief A cache for images / pictures derived from SVG files
100 : : *
101 : : * This class supports parameter replacement in SVG files according to the SVG params specification
102 : : * (http://www.w3.org/TR/2009/WD-SVGParamPrimer-20090616/).
103 : : *
104 : : * Supported parameters are:
105 : : *
106 : : * - \a param(fill): fill color (with no opacity value)
107 : : * - \a param(fill-opacity): fill color opacity
108 : : * - \a param(outline): outline color (with no opacity value)
109 : : * - \a param(outline-opacity): outline color opacity
110 : : * - \a param(outline-width): width of outline strokes
111 : : *
112 : : * E.g:
113 : : *
114 : : * <circle fill="param(fill-color red)" stroke="param(pen-color black)" stroke-width="param(outline-width 1)"
115 : : *
116 : : * \note QgsSvgCache is not usually directly created, but rather accessed through QgsApplication::svgCache().
117 : : */
118 : : #ifdef SIP_RUN
119 : : class CORE_EXPORT QgsSvgCache : public QgsAbstractContentCacheBase // for sip we skip to the base class and avoid the template difficulty
120 : : {
121 : : #else
122 : : class CORE_EXPORT QgsSvgCache : public QgsAbstractContentCache< QgsSvgCacheEntry >
123 : : {
124 : : #endif
125 : 0 : Q_OBJECT
126 : :
127 : : public:
128 : :
129 : : /**
130 : : * Constructor for QgsSvgCache.
131 : : */
132 : : QgsSvgCache( QObject *parent SIP_TRANSFERTHIS = nullptr );
133 : :
134 : : /**
135 : : * Returns an SVG drawing as a QImage.
136 : : *
137 : : * \param path Absolute path to SVG file.
138 : : * \param size size of cached image
139 : : * \param fill color of fill
140 : : * \param stroke color of stroke
141 : : * \param strokeWidth width of stroke
142 : : * \param widthScaleFactor width scale factor
143 : : * \param fitsInCache
144 : : * \param fixedAspectRatio fixed aspect ratio (optional)
145 : : * \param blocking forces to wait for loading before returning image (optional).
146 : : * \param parameters is a map of parameters to dynamically replace content in SVG.
147 : : *
148 : : * \warning The \a blocking parameter must NEVER be TRUE from GUI based applications (like the main QGIS
149 : : * application) or crashes will result. Only for use in external scripts or QGIS server.
150 : : */
151 : : QImage svgAsImage( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
152 : : double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio = 0, bool blocking = false,
153 : : const QMap<QString, QString> ¶meters = QMap<QString, QString>() );
154 : :
155 : : /**
156 : : * Returns an SVG drawing as a QPicture.
157 : : *
158 : : * \param path Absolute path to SVG file.
159 : : * \param size size of cached image
160 : : * \param fill color of fill
161 : : * \param stroke color of stroke
162 : : * \param strokeWidth width of stroke
163 : : * \param widthScaleFactor width scale factor
164 : : * \param forceVectorOutput
165 : : * \param fixedAspectRatio fixed aspect ratio (optional)
166 : : * \param blocking forces to wait for loading before returning image (optional)
167 : : * \param parameters is a map of parameters to dynamically replace content in SVG.
168 : : *
169 : : * \note The returned QPicture contains the SVG file centered over the picture origin. I.e. if it is rendered
170 : : * using QPainter::drawPicture( QPointF( 5, 10 ), picture ) it will be drawn centered over the point (5, 10).
171 : : * Appropriate translation to the destination painter based on the picture's boundingRect may need to be applied
172 : : * if rendering the SVG using the top-left or other reference point is desired.
173 : : *
174 : : * \warning The \a blocking parameter must NEVER be TRUE from GUI based applications (like the main QGIS
175 : : * application) or crashes will result. Only for use in external scripts or QGIS server.
176 : : */
177 : : QPicture svgAsPicture( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
178 : : double widthScaleFactor, bool forceVectorOutput = false, double fixedAspectRatio = 0, bool blocking = false,
179 : : const QMap<QString, QString> ¶meters = QMap<QString, QString>() );
180 : :
181 : : /**
182 : : * Calculates the viewbox size of a (possibly cached) SVG file.
183 : : * \param path Absolute path to SVG file.
184 : : * \param size size of cached image
185 : : * \param fill color of fill
186 : : * \param stroke color of stroke
187 : : * \param strokeWidth width of stroke
188 : : * \param widthScaleFactor width scale factor
189 : : * \param fixedAspectRatio fixed aspect ratio (optional)
190 : : * \param blocking forces to wait for loading before returning image (optional).
191 : : * \param parameters is a map of parameters to dynamically replace content in SVG.
192 : : * \returns viewbox size set in SVG file
193 : : *
194 : : * \warning The blocking parameter must NEVER be TRUE from GUI based applications (like the main QGIS
195 : : * application) or crashes will result. Only for use in external scripts or QGIS server.
196 : : *
197 : : * \since QGIS 2.14
198 : : */
199 : : QSizeF svgViewboxSize( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
200 : : double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QMap<QString, QString> ¶meters = QMap<QString, QString>() );
201 : :
202 : : /**
203 : : * Tests if an SVG file contains parameters for fill, stroke color, stroke width. If yes, possible default values are returned. If there are several
204 : : * default values in the SVG file, only the first one is considered. Blocking forces to wait for loading before returning image (optional). WARNING: the
205 : : * blocking parameter must NEVER be TRUE from GUI based applications (like the main QGIS application) or crashes will result. Only for use in external
206 : : * scripts or QGIS server.
207 : : */
208 : : void containsParams( const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam,
209 : : double &defaultStrokeWidth, bool blocking = false ) const;
210 : :
211 : : /**
212 : : * Tests if an SVG file contains parameters for fill, stroke color, stroke width. If yes, possible default values are returned. If there are several
213 : : * default values in the SVG file, only the first one is considered.
214 : : * \param path path to SVG file
215 : : * \param hasFillParam will be TRUE if fill param present in SVG
216 : : * \param hasDefaultFillParam will be TRUE if fill param has a default value specified
217 : : * \param defaultFillColor will be set to default fill color specified in SVG, if present
218 : : * \param hasFillOpacityParam will be TRUE if fill opacity param present in SVG
219 : : * \param hasDefaultFillOpacity will be TRUE if fill opacity param has a default value specified
220 : : * \param defaultFillOpacity will be set to default fill opacity specified in SVG, if present
221 : : * \param hasStrokeParam will be TRUE if stroke param present in SVG
222 : : * \param hasDefaultStrokeColor will be TRUE if stroke param has a default value specified
223 : : * \param defaultStrokeColor will be set to default stroke color specified in SVG, if present
224 : : * \param hasStrokeWidthParam will be TRUE if stroke width param present in SVG
225 : : * \param hasDefaultStrokeWidth will be TRUE if stroke width param has a default value specified
226 : : * \param defaultStrokeWidth will be set to default stroke width specified in SVG, if present
227 : : * \param hasStrokeOpacityParam will be TRUE if stroke opacity param present in SVG
228 : : * \param hasDefaultStrokeOpacity will be TRUE if stroke opacity param has a default value specified
229 : : * \param defaultStrokeOpacity will be set to default stroke opacity specified in SVG, if present
230 : : * \param blocking forces to wait for loading before returning image (optional).
231 : : *
232 : : * \note Available in Python bindings as containsParamsV3
233 : : *
234 : : * \warning The \a blocking parameter must NEVER be TRUE from GUI based applications (like the main QGIS
235 : : * application) or crashes will result. Only for use in external scripts or QGIS server.
236 : : *
237 : : * \since QGIS 2.14
238 : : */
239 : : void containsParams( const QString &path, bool &hasFillParam, bool &hasDefaultFillParam, QColor &defaultFillColor,
240 : : bool &hasFillOpacityParam, bool &hasDefaultFillOpacity, double &defaultFillOpacity,
241 : : bool &hasStrokeParam, bool &hasDefaultStrokeColor, QColor &defaultStrokeColor,
242 : : bool &hasStrokeWidthParam, bool &hasDefaultStrokeWidth, double &defaultStrokeWidth,
243 : : bool &hasStrokeOpacityParam, bool &hasDefaultStrokeOpacity, double &defaultStrokeOpacity,
244 : : bool blocking = false ) const SIP_PYNAME( containsParamsV3 );
245 : :
246 : : /**
247 : : * Gets the SVG content corresponding to the given \a path.
248 : : *
249 : : * \a path may be a local file, remote (HTTP) url, or a base 64 encoded string (with a "base64:" prefix).
250 : : *
251 : : * The class default missingContent byte array is returned if the \a path could not be resolved or is broken. If
252 : : * the \a path corresponds to a remote URL, then class default fetchingContent will be returned while the content
253 : : * is in the process of being fetched.
254 : : * The \a blocking boolean forces to wait for loading before returning result. The content is loaded
255 : : * in the same thread to ensure provided the remote content.
256 : : *
257 : : * \warning The \a blocking parameter must NEVER be TRUE from GUI based applications (like the main QGIS application)
258 : : * or crashes will result. Only for use in external scripts or QGIS server.
259 : : */
260 : : QByteArray getImageData( const QString &path, bool blocking = false ) const;
261 : :
262 : : /**
263 : : * Gets the SVG content corresponding to the given \a path.
264 : : *
265 : : * \a path may be a local file, remote (HTTP) url, or a base 64 encoded string (with a "base64:" prefix).
266 : : *
267 : : * The parameters \a size, \a strokeWidth for width of stroke, \a widthScaleFactor for width scale factor,
268 : : * \a fill for color of fill, \a stroke for color of stroke and \a fixedAspectRatio for fixed aspect ratio (optional)
269 : : * are needed to get the entry from cache or creates a new entry if it does not exist already.
270 : : *
271 : : * The \a blocking boolean forces to wait for loading before returning image. The content is loaded
272 : : * in the same thread to ensure provided the image.
273 : : *
274 : : * \warning The \a blocking parameter must NEVER be TRUE from GUI based applications (like the main QGIS application)
275 : : * or crashes will result. Only for use in external scripts or QGIS server.
276 : : */
277 : : #ifndef SIP_RUN
278 : : QByteArray svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
279 : : double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QMap<QString, QString> ¶meters = QMap<QString, QString>(), bool *isMissingImage = nullptr );
280 : : #else
281 : : QByteArray svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
282 : : double widthScaleFactor, double fixedAspectRatio = 0, bool blocking = false, const QMap<QString, QString> ¶meters = QMap<QString, QString>() );
283 : : #endif
284 : :
285 : : signals:
286 : :
287 : : /**
288 : : * Emit a signal to be caught by qgisapp and display a msg on status bar.
289 : : * \deprecated Deprecated since QGIS 3.6 -- no longer emitted.
290 : : */
291 : : Q_DECL_DEPRECATED void statusChanged( const QString &statusQString ) SIP_DEPRECATED;
292 : :
293 : : /**
294 : : * Emitted when the cache has finished retrieving an SVG file from a remote \a url.
295 : : * \since QGIS 3.2
296 : : */
297 : : void remoteSvgFetched( const QString &url );
298 : :
299 : : protected:
300 : :
301 : : bool checkReply( QNetworkReply *reply, const QString &path ) const override;
302 : :
303 : : private:
304 : :
305 : : void replaceParamsAndCacheSvg( QgsSvgCacheEntry *entry, bool blocking = false );
306 : : void cacheImage( QgsSvgCacheEntry *entry );
307 : : void cachePicture( QgsSvgCacheEntry *entry, bool forceVectorOutput = false );
308 : : //! Returns entry from cache or creates a new entry if it does not exist already
309 : : QgsSvgCacheEntry *cacheEntry( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
310 : : double widthScaleFactor, double fixedAspectRatio = 0, const QMap<QString, QString> ¶meters = QMap<QString, QString>(), bool blocking = false, bool *isMissingImage = nullptr );
311 : :
312 : : //! Replaces parameters in elements of a dom node and calls method for all child nodes
313 : : void replaceElemParams( QDomElement &elem, const QColor &fill, const QColor &stroke, double strokeWidth, const QMap<QString, QString> ¶meters );
314 : :
315 : : void containsElemParams( const QDomElement &elem,
316 : : bool &hasFillParam, bool &hasDefaultFill, QColor &defaultFill,
317 : : bool &hasFillOpacityParam, bool &hasDefaultFillOpacity, double &defaultFillOpacity,
318 : : bool &hasStrokeParam, bool &hasDefaultStroke, QColor &defaultStroke,
319 : : bool &hasStrokeWidthParam, bool &hasDefaultStrokeWidth, double &defaultStrokeWidth,
320 : : bool &hasStrokeOpacityParam, bool &hasDefaultStrokeOpacity, double &defaultStrokeOpacity ) const SIP_PYNAME( containsParamsV3 );
321 : :
322 : : //! Calculates scaling for rendered image sizes to SVG logical sizes
323 : : double calcSizeScaleFactor( QgsSvgCacheEntry *entry, const QDomElement &docElem, QSizeF &viewboxSize ) const;
324 : :
325 : : /**
326 : : * Returns the target size (in pixels) and calculates the \a viewBoxSize
327 : : * for a cache \a entry.
328 : : */
329 : : QSize sizeForImage( const QgsSvgCacheEntry &entry, QSizeF &viewBoxSize, QSizeF &scaledSize ) const;
330 : :
331 : : /**
332 : : * Returns a rendered image for a cached picture \a entry.
333 : : */
334 : : QImage imageFromCachedPicture( const QgsSvgCacheEntry &entry ) const;
335 : :
336 : : //! SVG content to be rendered if SVG file was not found.
337 : : QByteArray mMissingSvg;
338 : :
339 : : QByteArray mFetchingSvg;
340 : :
341 : : friend class TestQgsSvgCache;
342 : : };
343 : :
344 : : #endif // QGSSVGCACHE_H
|