File indexing completed on 2023-10-01 04:11:46
0001 /* 0002 SPDX-FileCopyrightText: 2006-2007 Aaron Seigo <aseigo@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef PLASMA_SVG_H 0008 #define PLASMA_SVG_H 0009 0010 #include <QObject> 0011 #include <QPixmap> 0012 0013 #include <plasma/plasma_export.h> 0014 #include <plasma/theme.h> 0015 0016 class QPainter; 0017 class QPoint; 0018 class QPointF; 0019 class QRect; 0020 class QRectF; 0021 class QSize; 0022 class QSizeF; 0023 class QMatrix; 0024 0025 namespace Plasma 0026 { 0027 class FrameSvgPrivate; 0028 class SvgPrivate; 0029 0030 /** 0031 * @class Svg plasma/svg.h <Plasma/Svg> 0032 * 0033 * @short A theme aware image-centric SVG class 0034 * 0035 * Plasma::Svg provides a class for rendering SVG images to a QPainter in a 0036 * convenient manner. Unless an absolute path to a file is provided, it loads 0037 * the SVG document using Plasma::Theme. It also provides a number of internal 0038 * optimizations to help lower the cost of painting SVGs, such as caching. 0039 * 0040 * @see Plasma::FrameSvg 0041 **/ 0042 class PLASMA_EXPORT Svg : public QObject 0043 { 0044 Q_OBJECT 0045 Q_PROPERTY(QSize size READ size WRITE resize NOTIFY sizeChanged) 0046 Q_PROPERTY(bool multipleImages READ containsMultipleImages WRITE setContainsMultipleImages) 0047 Q_PROPERTY(QString imagePath READ imagePath WRITE setImagePath NOTIFY imagePathChanged) 0048 Q_PROPERTY(bool usingRenderingCache READ isUsingRenderingCache WRITE setUsingRenderingCache) 0049 Q_PROPERTY(bool fromCurrentTheme READ fromCurrentTheme NOTIFY fromCurrentThemeChanged) 0050 Q_PROPERTY(Plasma::Theme::ColorGroup colorGroup READ colorGroup WRITE setColorGroup NOTIFY colorGroupChanged) 0051 Q_PROPERTY(Plasma::Svg::Status status READ status WRITE setStatus NOTIFY statusChanged) 0052 0053 public: 0054 enum Status { 0055 Normal = 0, 0056 Selected, 0057 Inactive, 0058 }; 0059 Q_ENUM(Status) 0060 0061 /** 0062 * Constructs an SVG object that implicitly shares and caches rendering. 0063 * 0064 * Unlike QSvgRenderer, which this class uses internally, 0065 * Plasma::Svg represents an image generated from an SVG. As such, it 0066 * has a related size and transform matrix (the latter being provided 0067 * by the painter used to paint the image). 0068 * 0069 * The size is initialized to be the SVG's native size. 0070 * 0071 * @param parent options QObject to parent this to 0072 * 0073 * @related Plasma::Theme 0074 */ 0075 explicit Svg(QObject *parent = nullptr); 0076 ~Svg() override; 0077 0078 /** 0079 * Set the device pixel ratio for the Svg. This is the ratio between 0080 * image pixels and device-independent pixels. 0081 * The Svg will produce pixmaps scaled by devicePixelRatio, but all the sizes and element 0082 * rects will not be altered. 0083 * The default value is 1.0 and the scale will be done rounded to the floor integer 0084 * Setting it to something more, will make all the elements of this svg appear bigger. 0085 */ 0086 void setDevicePixelRatio(qreal ratio); 0087 0088 /** 0089 * @return the device pixel ratio for this Svg. 0090 */ 0091 qreal devicePixelRatio(); 0092 0093 /** 0094 * Setting a scale factor greater than one it will result in final images scaled by it. 0095 * Unlike devicePixelRatio, every size and element rect will be scaled accordingly. 0096 * @return how much to scale the rendered image. 0097 */ 0098 qreal scaleFactor() const; 0099 0100 /** 0101 * Setting a scale factor greater than one it will result in final images scaled by it. 0102 * Unlike devicePixelRatio, every size and element rect will be scaled accordingly. 0103 * The default value is 1.0 and the scale will be done rounded to the floor integer. 0104 * @param how much to scale the Svg 0105 */ 0106 void setScaleFactor(qreal factor); 0107 0108 /** 0109 * Set a color group for the Svg. 0110 * if the Svg uses stylesheets and has elements 0111 * that are either TextColor or BackgroundColor class, 0112 * make them use ButtonTextColor/ButtonBackgroundColor 0113 * or ViewTextColor/ViewBackgroundColor 0114 */ 0115 void setColorGroup(Plasma::Theme::ColorGroup group); 0116 0117 /** 0118 * @return the color group for this Svg 0119 */ 0120 Plasma::Theme::ColorGroup colorGroup() const; 0121 0122 /** 0123 * Returns a pixmap of the SVG represented by this object. 0124 * 0125 * The size of the pixmap will be the size of this Svg object (size()) 0126 * if containsMultipleImages is @c true; otherwise, it will be the 0127 * size of the requested element after the whole SVG has been scaled 0128 * to size(). 0129 * 0130 * @param elementId the ID string of the element to render, or an empty 0131 * string for the whole SVG (the default) 0132 * @return a QPixmap of the rendered SVG 0133 */ 0134 Q_INVOKABLE QPixmap pixmap(const QString &elementID = QString()); 0135 0136 /** 0137 * Returns an image of the SVG represented by this object. 0138 * 0139 * The size of the image will be the size of this Svg object (size()) 0140 * if containsMultipleImages is @c true; otherwise, it will be the 0141 * size of the requested element after the whole SVG has been scaled 0142 * to size(). 0143 * 0144 * @param elementId the ID string of the element to render, or an empty 0145 * string for the whole SVG (the default) 0146 * @return a QPixmap of the rendered SVG 0147 */ 0148 Q_INVOKABLE QImage image(const QSize &size, const QString &elementID = QString()); 0149 0150 /** 0151 * Paints all or part of the SVG represented by this object 0152 * 0153 * The size of the painted area will be the size of this Svg object 0154 * (size()) if containsMultipleImages is @c true; otherwise, it will 0155 * be the size of the requested element after the whole SVG has been 0156 * scaled to size(). 0157 * 0158 * @param painter the QPainter to use 0159 * @param point the position to start drawing; the entire svg will be 0160 * drawn starting at this point. 0161 * @param elementId the ID string of the element to render, or an empty 0162 * string for the whole SVG (the default) 0163 */ 0164 Q_INVOKABLE void paint(QPainter *painter, const QPointF &point, const QString &elementID = QString()); 0165 0166 /** 0167 * Paints all or part of the SVG represented by this object 0168 * 0169 * The size of the painted area will be the size of this Svg object 0170 * (size()) if containsMultipleImages is @c true; otherwise, it will 0171 * be the size of the requested element after the whole SVG has been 0172 * scaled to size(). 0173 * 0174 * @param painter the QPainter to use 0175 * @param x the horizontal coordinate to start painting from 0176 * @param y the vertical coordinate to start painting from 0177 * @param elementId the ID string of the element to render, or an empty 0178 * string for the whole SVG (the default) 0179 */ 0180 Q_INVOKABLE void paint(QPainter *painter, int x, int y, const QString &elementID = QString()); 0181 0182 /** 0183 * Paints all or part of the SVG represented by this object 0184 * 0185 * @param painter the QPainter to use 0186 * @param rect the rect to draw into; if smaller than the current size 0187 * the drawing is starting at this point. 0188 * @param elementId the ID string of the element to render, or an empty 0189 * string for the whole SVG (the default) 0190 */ 0191 Q_INVOKABLE void paint(QPainter *painter, const QRectF &rect, const QString &elementID = QString()); 0192 0193 /** 0194 * Paints all or part of the SVG represented by this object 0195 * 0196 * @param painter the QPainter to use 0197 * @param x the horizontal coordinate to start painting from 0198 * @param y the vertical coordinate to start painting from 0199 * @param width the width of the element to draw 0200 * @param height the height of the element do draw 0201 * @param elementId the ID string of the element to render, or an empty 0202 * string for the whole SVG (the default) 0203 */ 0204 Q_INVOKABLE void paint(QPainter *painter, int x, int y, int width, int height, const QString &elementID = QString()); 0205 0206 /** 0207 * The size of the SVG. 0208 * 0209 * If the SVG has been resized with resize(), that size will be 0210 * returned; otherwise, the natural size of the SVG will be returned. 0211 * 0212 * If containsMultipleImages is @c true, each element of the SVG 0213 * will be rendered at this size by default. 0214 * 0215 * @return the current size of the SVG 0216 **/ 0217 QSize size() const; 0218 0219 /** 0220 * Resizes the rendered image. 0221 * 0222 * Rendering will actually take place on the next call to paint. 0223 * 0224 * If containsMultipleImages is @c true, each element of the SVG 0225 * will be rendered at this size by default; otherwise, the entire 0226 * image will be scaled to this size and each element will be 0227 * scaled appropriately. 0228 * 0229 * @param width the new width 0230 * @param height the new height 0231 **/ 0232 Q_INVOKABLE void resize(qreal width, qreal height); 0233 0234 /** 0235 * Resizes the rendered image. 0236 * 0237 * Rendering will actually take place on the next call to paint. 0238 * 0239 * If containsMultipleImages is @c true, each element of the SVG 0240 * will be rendered at this size by default; otherwise, the entire 0241 * image will be scaled to this size and each element will be 0242 * scaled appropriately. 0243 * 0244 * @param size the new size of the image 0245 **/ 0246 Q_INVOKABLE void resize(const QSizeF &size); 0247 0248 /** 0249 * Resizes the rendered image to the natural size of the SVG. 0250 * 0251 * Rendering will actually take place on the next call to paint. 0252 **/ 0253 Q_INVOKABLE void resize(); 0254 0255 /** 0256 * Find the size of a given element. 0257 * 0258 * This is the size of the element with ID @p elementId after the SVG 0259 * has been scaled (see resize()). Note that this is unaffected by 0260 * the containsMultipleImages property. 0261 * 0262 * @param elementId the id of the element to check 0263 * @return the size of a given element, given the current size of the SVG 0264 **/ 0265 Q_INVOKABLE QSize elementSize(const QString &elementId) const; 0266 0267 QSize elementSize(QStringView elementId) const; 0268 0269 /** 0270 * The bounding rect of a given element. 0271 * 0272 * This is the bounding rect of the element with ID @p elementId after 0273 * the SVG has been scaled (see resize()). Note that this is 0274 * unaffected by the containsMultipleImages property. 0275 * 0276 * @param elementId the id of the element to check 0277 * @return the current rect of a given element, given the current size of the SVG 0278 **/ 0279 Q_INVOKABLE QRectF elementRect(const QString &elementId) const; 0280 0281 QRectF elementRect(QStringView elementId) const; 0282 0283 /** 0284 * Check whether an element exists in the loaded SVG. 0285 * 0286 * @param elementId the id of the element to check for 0287 * @return @c true if the element is defined in the SVG, otherwise @c false 0288 **/ 0289 Q_INVOKABLE bool hasElement(const QString &elementId) const; 0290 0291 bool hasElement(QStringView elementId) const; 0292 0293 /** 0294 * Check whether this object is backed by a valid SVG file. 0295 * 0296 * This method can be expensive as it causes disk access. 0297 * 0298 * @return @c true if the SVG file exists and the document is valid, 0299 * otherwise @c false. 0300 **/ 0301 Q_INVOKABLE bool isValid() const; 0302 0303 /** 0304 * Set whether the SVG contains a single image or multiple ones. 0305 * 0306 * If this is set to @c true, the SVG will be treated as a 0307 * collection of related images, rather than a consistent 0308 * drawing. 0309 * 0310 * In particular, when individual elements are rendered, this 0311 * affects whether the elements are resized to size() by default. 0312 * See paint() and pixmap(). 0313 * 0314 * @param multiple true if the svg contains multiple images 0315 */ 0316 void setContainsMultipleImages(bool multiple); 0317 0318 /** 0319 * Whether the SVG contains multiple images. 0320 * 0321 * If this is @c true, the SVG will be treated as a 0322 * collection of related images, rather than a consistent 0323 * drawing. 0324 * 0325 * @return @c true if the SVG will be treated as containing 0326 * multiple images, @c false if it will be treated 0327 * as a coherent image. 0328 */ 0329 bool containsMultipleImages() const; 0330 0331 /** 0332 * Set the SVG file to render. 0333 * 0334 * Relative paths are looked for in the current Plasma theme, 0335 * and should not include the file extension (.svg and .svgz 0336 * files will be searched for). See Theme::imagePath(). 0337 * 0338 * If the parent object of this Svg is a Plasma::Applet, 0339 * relative paths will be searched for in the applet's package 0340 * first. 0341 * 0342 * @param svgFilePath either an absolute path to an SVG file, or 0343 * an image name 0344 */ 0345 virtual void setImagePath(const QString &svgFilePath); 0346 0347 /** 0348 * The SVG file to render. 0349 * 0350 * If this SVG is themed, this will be a relative path, and will not 0351 * include a file extension. 0352 * 0353 * @return either an absolute path to an SVG file, or an image name 0354 * @see Theme::imagePath() 0355 */ 0356 QString imagePath() const; 0357 0358 /** 0359 * Sets whether or not to cache the results of rendering to pixmaps. 0360 * 0361 * If the SVG is resized and re-rendered often (and does not keep using the 0362 * same small set of pixmap dimensions), then it may be less efficient to do 0363 * disk caching. A good example might be a progress meter that uses an Svg 0364 * object to paint itself: the meter will be changing often enough, with 0365 * enough unpredictability and without re-use of the previous pixmaps to 0366 * not get a gain from caching. 0367 * 0368 * Most Svg objects should use the caching feature, however. 0369 * Therefore, the default is to use the render cache. 0370 * 0371 * @param useCache true to cache rendered pixmaps 0372 * @since 4.3 0373 */ 0374 void setUsingRenderingCache(bool useCache); 0375 0376 /** 0377 * Whether the rendering cache is being used. 0378 * 0379 * @return @c true if the Svg object is using caching for rendering results 0380 * @since 4.3 0381 */ 0382 bool isUsingRenderingCache() const; 0383 0384 /** 0385 * Whether the current theme has this Svg, without any fallback 0386 * to the default theme involved 0387 * 0388 * @return true if the svg is loaded from the current theme 0389 * @see Theme::currentThemeHasImage 0390 */ 0391 bool fromCurrentTheme() const; 0392 0393 /** 0394 * Sets whether the Svg uses the global system theme for its colors or 0395 * the Plasma theme. Default is False. 0396 * 0397 * @since 5.16 0398 */ 0399 void setUseSystemColors(bool system); 0400 0401 /** 0402 * @returns True if colors from the system theme are used. 0403 * Default is False 0404 * @since 5.16 0405 */ 0406 bool useSystemColors() const; 0407 0408 /** 0409 * Sets the Plasma::Theme to use with this Svg object. 0410 * 0411 * By default, Svg objects use Plasma::Theme::default(). 0412 * 0413 * This determines how relative image paths are interpreted. 0414 * 0415 * @param theme the theme object to use 0416 * @since 4.3 0417 */ 0418 void setTheme(Plasma::Theme *theme); 0419 0420 /** 0421 * The Plasma::Theme used by this Svg object. 0422 * 0423 * This determines how relative image paths are interpreted. 0424 * 0425 * @return the theme used by this Svg 0426 */ 0427 Theme *theme() const; 0428 0429 /** 0430 * Sets the image in a selected status. 0431 * Svgs can be colored with system color themes, if the status is selected, 0432 * the TextColor will become HighlightedText color and BackgroundColor 0433 * will become HighlightColor, making the svg graphics (for instance an icon) 0434 * will look correct together selected text 0435 * Supported statuses as of 5.23 are Normal and Selected 0436 * @since 5.23 0437 */ 0438 void setStatus(Svg::Status status); 0439 0440 /** 0441 * @return the status of the Svg 0442 * @since 5.23 0443 */ 0444 Svg::Status status() const; 0445 0446 Q_SIGNALS: 0447 /** 0448 * Emitted whenever the SVG data has changed in such a way that a repaint is required. 0449 * Any usage of an Svg object that does the painting itself must connect to this signal 0450 * and respond by updating the painting. Note that connected to Theme::themeChanged is 0451 * incorrect in such a use case as the Svg itself may not be updated yet nor may theme 0452 * change be the only case when a repaint is needed. Also note that classes or QML code 0453 * which take Svg objects as parameters for their own painting all respond to this signal 0454 * so that in those cases manually responding to the signal is unnecessary; ONLY when 0455 * direct, manual painting with an Svg object is done in application code is this signal 0456 * used. 0457 */ 0458 void repaintNeeded(); 0459 0460 /** 0461 * Emitted whenever the size of the Svg is changed. @see resize() 0462 */ 0463 void sizeChanged(); 0464 0465 /** 0466 * Emitted whenever the image path of the Svg is changed. 0467 */ 0468 void imagePathChanged(); 0469 0470 /** 0471 * Emitted whenever the color hint has changed. 0472 */ 0473 void colorHintChanged(); 0474 0475 /** 0476 * Emitted whenever the color group has changed. 0477 */ 0478 void colorGroupChanged(); 0479 0480 /** 0481 * Emitted when fromCurrentTheme() value has changed 0482 */ 0483 void fromCurrentThemeChanged(bool fromCurrentTheme); 0484 0485 /** 0486 * Emitted when the status changes 0487 * @since 5.23 0488 */ 0489 void statusChanged(Plasma::Svg::Status status); 0490 0491 private: 0492 SvgPrivate *const d; 0493 bool eventFilter(QObject *watched, QEvent *event) override; 0494 0495 Q_PRIVATE_SLOT(d, void themeChanged()) 0496 Q_PRIVATE_SLOT(d, void colorsChanged()) 0497 0498 friend class SvgPrivate; 0499 friend class FrameSvgPrivate; 0500 friend class FrameSvg; 0501 }; 0502 0503 } // Plasma namespace 0504 0505 #endif // multiple inclusion guard