Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsvgstyle_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
6#ifndef QSVGSTYLE_P_H
7#define QSVGSTYLE_P_H
8
9//
10// W A R N I N G
11// -------------
12//
13// This file is not part of the Qt API. It exists purely as an
14// implementation detail. This header file may change from version to
15// version without notice, or even be removed.
16//
17// We mean it.
18//
19
20#include "QtCore/qstack.h"
21#include "QtGui/qpainter.h"
22#include "QtGui/qpainterpath.h"
23#include "QtGui/qpen.h"
24#include "QtGui/qbrush.h"
25#include "QtGui/qtransform.h"
26#include "QtGui/qfont.h"
27#include <qdebug.h>
28#include "qtsvgglobal_p.h"
29#include <QtSvg/private/qsvgpaintserver_p.h>
30
32
33class QPainter;
34class QSvgNode;
35class QSvgFont;
36class QSvgDocument;
37
38template <class T> class QSvgRefCounter
39{
40public:
41 QSvgRefCounter() { t = nullptr; }
42 explicit QSvgRefCounter(T *_t)
43 {
44 t = _t;
45 if (t)
46 t->ref();
47 }
48
50 {
51 t = other.t;
52 if (t)
53 t->ref();
54 }
55
57 : t{std::exchange(other.t, nullptr)} {}
58
60 {
61 if(other.t)
62 other.t->ref();
63 if (t)
64 t->deref();
65 t = other.t;
66 return *this;
67 }
68
69 // both T and users are a bounded set, so we can use PURE_SWAP,
70 // and manage expectations
72
74 {
75 if (t)
76 t->deref();
77 }
78
79 void swap(QSvgRefCounter &other) noexcept
80 { qt_ptr_swap(t, other.t); }
81
82 void reset(T *other = nullptr)
83 { QSvgRefCounter(other).swap(*this); }
84
85 inline T *operator->() const { return t; }
86 inline operator T*() const { return t; }
87
88 inline bool isDefault() const { return !t || t->isDefault(); }
89
90private:
91 T *t;
92};
93
94class Q_SVG_EXPORT QSvgRefCounted
95{
96 Q_DISABLE_COPY_MOVE(QSvgRefCounted)
97public:
98 QSvgRefCounted() { _ref = 0; }
99 virtual ~QSvgRefCounted();
100
101 void ref() {
102 ++_ref;
103// qDebug() << this << ": adding ref, now " << _ref;
104 }
105 void deref() {
106// qDebug() << this << ": removing ref, now " << _ref;
107 if(!--_ref) {
108// qDebug(" deleting");
109 delete this;
110 }
111 }
112private:
113 int _ref;
114};
115
116struct Q_SVG_EXPORT QSvgExtraStates
117{
118 QSvgExtraStates();
119
122 QSvgFont *svgFont;
129 bool trustedSource = false;
130 quint8 remainingNestedNodes = QtSvg::renderingMaxNestedNodes;
131 bool vectorEffect; // true if pen is cosmetic
132 qint8 imageRendering; // QSvgQualityStyle::ImageRendering
133 bool inUse = false; // true if currently in QSvgUseNode
134};
135
136class Q_SVG_EXPORT QSvgStyleProperty : public QSvgRefCounted
137{
138public:
139 enum Type
140 {
141 QUALITY,
142 FILL,
143 VIEWPORT_FILL,
144 FONT,
145 STROKE,
146 TRANSFORM,
147 OPACITY,
148 COMP_OP,
149 OFFSET,
150 };
151public:
152 virtual ~QSvgStyleProperty();
153
154 virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) = 0;
155 virtual void revert(QPainter *p, QSvgExtraStates &states) =0;
156 virtual Type type() const=0;
157 bool isDefault() const { return false; } // [not virtual since called from templated class]
158};
159
160class Q_SVG_EXPORT QSvgQualityStyle : public QSvgStyleProperty
161{
162public:
163 enum ImageRendering: qint8 {
164 ImageRenderingAuto = 0,
165 ImageRenderingOptimizeSpeed = 1,
166 ImageRenderingOptimizeQuality = 2,
167 };
168
169 QSvgQualityStyle(int color);
170 ~QSvgQualityStyle() override;
171
172 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
173 void revert(QPainter *p, QSvgExtraStates &states) override;
174 Type type() const override;
175
176 void setImageRendering(ImageRendering);
177private:
178 // color-render ing v v 'auto' | 'optimizeSpeed' |
179 // 'optimizeQuality' | 'inherit'
180 //int m_colorRendering;
181
182 // shape-rendering v v 'auto' | 'optimizeSpeed' | 'crispEdges' |
183 // 'geometricPrecision' | 'inherit'
184 //QSvgShapeRendering m_shapeRendering;
185
186
187 // text-rendering v v 'auto' | 'optimizeSpeed' | 'optimizeLegibility'
188 // | 'geometricPrecision' | 'inherit'
189 //QSvgTextRendering m_textRendering;
190
191
192 // vector-effect v x 'default' | 'non-scaling-stroke' | 'inherit'
193 //QSvgVectorEffect m_vectorEffect;
194
195 // image-rendering v v 'auto' | 'optimizeSpeed' | 'optimizeQuality' |
196 // 'inherit'
197 qint32 m_imageRendering: 4;
198 qint32 m_oldImageRendering: 4;
199 quint32 m_imageRenderingSet: 1;
200};
201
202
203
204class Q_SVG_EXPORT QSvgOpacityStyle : public QSvgStyleProperty
205{
206public:
207 QSvgOpacityStyle(qreal opacity);
208 ~QSvgOpacityStyle() override;
209
210 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
211 void revert(QPainter *p, QSvgExtraStates &states) override;
212 Type type() const override;
213 qreal opacity() const { return m_opacity; }
214 bool isDefault() const { return qFuzzyCompare(m_opacity, qreal(1.0)); }
215
216private:
217 qreal m_opacity;
218 qreal m_oldOpacity;
219};
220
221class Q_SVG_EXPORT QSvgFillStyle : public QSvgStyleProperty
222{
223public:
224 QSvgFillStyle();
225 ~QSvgFillStyle() override;
226
227 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
228 void revert(QPainter *p, QSvgExtraStates &states) override;
229 Type type() const override;
230
231 void setFillRule(Qt::FillRule f);
232 void setFillOpacity(qreal opacity);
233 void setPaintServer(QSvgPaintServerSharedPtr paintServer);
234 void setBrush(QBrush brush);
235
236 const QBrush & qbrush() const
237 {
238 return m_fill;
239 }
240
241 qreal fillOpacity() const
242 {
243 return m_fillOpacity;
244 }
245
246 Qt::FillRule fillRule() const
247 {
248 return m_fillRule;
249 }
250
251 QSvgPaintServer *paintServer() const
252 {
253 return m_paintServer.get();
254 }
255
256 void setPaintStyleId(const QString &Id)
257 {
258 m_paintStyleId = Id;
259 }
260
261 QString paintStyleId() const
262 {
263 return m_paintStyleId;
264 }
265
266private:
267 // fill v v 'inherit' | <Paint.datatype>
268 // fill-opacity v v 'inherit' | <OpacityValue.datatype>
269 QBrush m_fill;
270 QBrush m_oldFill;
271 QSvgPaintServerSharedPtr m_paintServer;
272
273 Qt::FillRule m_fillRule{Qt::WindingFill};
274 Qt::FillRule m_oldFillRule{Qt::WindingFill};
275 qreal m_fillOpacity{1.0};
276 qreal m_oldFillOpacity{0.};
277
278 QString m_paintStyleId;
279
280 uint m_fillRuleSet : 1;
281 uint m_fillOpacitySet : 1;
282 uint m_fillSet : 1;
283};
284
285class Q_SVG_EXPORT QSvgViewportFillStyle : public QSvgStyleProperty
286{
287public:
288 QSvgViewportFillStyle(const QBrush &brush);
289 ~QSvgViewportFillStyle() override;
290
291 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
292 void revert(QPainter *p, QSvgExtraStates &states) override;
293 Type type() const override;
294
295 const QBrush & qbrush() const
296 {
297 return m_viewportFill;
298 }
299private:
300 // viewport-fill v x 'inherit' | <Paint.datatype>
301 // viewport-fill-opacity v x 'inherit' | <OpacityValue.datatype>
302 QBrush m_viewportFill;
303
304 QBrush m_oldFill;
305};
306
307class Q_SVG_EXPORT QSvgFontStyle : public QSvgStyleProperty
308{
309public:
310 static const int LIGHTER = -1;
311 static const int BOLDER = 1;
312
313 QSvgFontStyle(QSvgFont *font, QSvgDocument *doc);
314 QSvgFontStyle();
315 ~QSvgFontStyle() override;
316
317 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
318 void revert(QPainter *p, QSvgExtraStates &states) override;
319 Type type() const override;
320
321 void setSize(qreal size)
322 {
323 // Store the _pixel_ size in the font. Since QFont::setPixelSize() only takes an int, call
324 // QFont::SetPointSize() instead. Set proper font size just before rendering.
325 m_qfont.setPointSizeF(size);
326 m_sizeSet = 1;
327 }
328
329 void setTextAnchor(Qt::Alignment anchor)
330 {
331 m_textAnchor = anchor;
332 m_textAnchorSet = 1;
333 }
334
335 void setFamily(const QString &family)
336 {
337 m_qfont.setFamilies({family});
338 m_familySet = 1;
339 }
340
341 void setStyle(QFont::Style fontStyle) {
342 m_qfont.setStyle(fontStyle);
343 m_styleSet = 1;
344 }
345
346 void setVariant(QFont::Capitalization fontVariant)
347 {
348 m_qfont.setCapitalization(fontVariant);
349 m_variantSet = 1;
350 }
351
352 void setWeight(int weight)
353 {
354 m_weight = weight;
355 m_weightSet = 1;
356 }
357
358 QSvgFont * svgFont() const
359 {
360 return m_svgFont;
361 }
362
363 const QFont &qfont() const
364 {
365 return m_qfont;
366 }
367
368 QSvgDocument *doc() const {return m_doc;}
369
370private:
371 QSvgFont *m_svgFont;
372 QSvgDocument *m_doc;
373 QFont m_qfont;
374
375 int m_weight = 0;
376 Qt::Alignment m_textAnchor;
377
378 QSvgFont *m_oldSvgFont = nullptr;
379 QFont m_oldQFont;
380 Qt::Alignment m_oldTextAnchor;
381 int m_oldWeight = 0;
382
383 uint m_familySet : 1;
384 uint m_sizeSet : 1;
385 uint m_styleSet : 1;
386 uint m_variantSet : 1;
387 uint m_weightSet : 1;
388 uint m_textAnchorSet : 1;
389};
390
391class Q_SVG_EXPORT QSvgStrokeStyle : public QSvgStyleProperty
392{
393public:
394 QSvgStrokeStyle();
395 ~QSvgStrokeStyle() override;
396
397 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
398 void revert(QPainter *p, QSvgExtraStates &states) override;
399 Type type() const override;
400
401 void setStroke(QBrush brush)
402 {
403 m_stroke.setBrush(brush);
404 m_paintServer.reset();
405 m_strokeSet = 1;
406 }
407
408 void setPaintServer(QSvgPaintServerSharedPtr paintServer)
409 {
410 m_paintServer = std::move(paintServer);
411 m_strokeSet = 1;
412 }
413
414 void setDashArray(const QList<qreal> &dashes);
415
416 void setDashArrayNone()
417 {
418 m_stroke.setStyle(Qt::SolidLine);
419 m_strokeDashArraySet = 1;
420 }
421
422 void setDashOffset(qreal offset)
423 {
424 m_strokeDashOffset = offset;
425 m_strokeDashOffsetSet = 1;
426 }
427
428 void setLineCap(Qt::PenCapStyle cap)
429 {
430 m_stroke.setCapStyle(cap);
431 m_strokeLineCapSet = 1;
432 }
433
434 void setLineJoin(Qt::PenJoinStyle join)
435 {
436 m_stroke.setJoinStyle(join);
437 m_strokeLineJoinSet = 1;
438 }
439
440 void setMiterLimit(qreal limit)
441 {
442 m_stroke.setMiterLimit(limit);
443 m_strokeMiterLimitSet = 1;
444 }
445
446 void setOpacity(qreal opacity)
447 {
448 m_strokeOpacity = opacity;
449 m_strokeOpacitySet = 1;
450 }
451
452 void setWidth(qreal width)
453 {
454 m_stroke.setWidthF(width);
455 m_strokeWidthSet = 1;
456 Q_ASSERT(!m_strokeDashArraySet); // set width before dash array.
457 }
458
459 qreal width()
460 {
461 return m_stroke.widthF();
462 }
463
464 void setVectorEffect(bool nonScalingStroke)
465 {
466 m_vectorEffect = nonScalingStroke;
467 m_vectorEffectSet = 1;
468 }
469
470 QSvgPaintServer *paintServer() const
471 {
472 return m_paintServer.get();
473 }
474
475 void setPaintStyleId(const QString &Id)
476 {
477 m_paintStyleId = Id;
478 }
479
480 QString paintStyleId() const
481 {
482 return m_paintStyleId;
483 }
484
485 QPen stroke() const
486 {
487 return m_stroke;
488 }
489
490private:
491 // stroke v v 'inherit' | <Paint.datatype>
492 // stroke-dasharray v v 'inherit' | <StrokeDashArrayValue.datatype>
493 // stroke-dashoffset v v 'inherit' | <StrokeDashOffsetValue.datatype>
494 // stroke-linecap v v 'butt' | 'round' | 'square' | 'inherit'
495 // stroke-linejoin v v 'miter' | 'round' | 'bevel' | 'inherit'
496 // stroke-miterlimit v v 'inherit' | <StrokeMiterLimitValue.datatype>
497 // stroke-opacity v v 'inherit' | <OpacityValue.datatype>
498 // stroke-width v v 'inherit' | <StrokeWidthValue.datatype>
499 QPen m_stroke;
500 QPen m_oldStroke;
501 qreal m_strokeOpacity{1.0};
502 qreal m_oldStrokeOpacity{0.};
503 qreal m_strokeDashOffset{0.};
504 qreal m_oldStrokeDashOffset{0.};
505
506 QSvgPaintServerSharedPtr m_paintServer;
507 QString m_paintStyleId;
508 uint m_vectorEffect : 1;
509 uint m_oldVectorEffect : 1;
510
511 uint m_strokeSet : 1;
512 uint m_strokeDashArraySet : 1;
513 uint m_strokeDashOffsetSet : 1;
514 uint m_strokeLineCapSet : 1;
515 uint m_strokeLineJoinSet : 1;
516 uint m_strokeMiterLimitSet : 1;
517 uint m_strokeOpacitySet : 1;
518 uint m_strokeWidthSet : 1;
519 uint m_vectorEffectSet : 1;
520};
521
522class Q_SVG_EXPORT QSvgTransformStyle : public QSvgStyleProperty
523{
524public:
525 QSvgTransformStyle(const QTransform &transform);
526 ~QSvgTransformStyle() override;
527
528 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
529 void revert(QPainter *p, QSvgExtraStates &states) override;
530 Type type() const override;
531
532 const QTransform & qtransform() const
533 {
534 return m_transform;
535 }
536 bool isDefault() const { return m_transform.isIdentity(); }
537private:
538 //7.6 The transform attribute
539 QTransform m_transform;
540 QStack<QTransform> m_oldWorldTransform;
541};
542
543class Q_SVG_EXPORT QSvgCompOpStyle : public QSvgStyleProperty
544{
545public:
546 QSvgCompOpStyle(QPainter::CompositionMode mode);
547 ~QSvgCompOpStyle() override;
548
549 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
550 void revert(QPainter *p, QSvgExtraStates &states) override;
551 Type type() const override;
552
553 const QPainter::CompositionMode & compOp() const
554 {
555 return m_mode;
556 }
557private:
558 //comp-op attribute
559 QPainter::CompositionMode m_mode;
560
561 QPainter::CompositionMode m_oldMode{QPainter::CompositionMode_SourceOver};
562};
563
564class Q_SVG_EXPORT QSvgOffsetStyle : public QSvgStyleProperty
565{
566public:
567 QSvgOffsetStyle() = default;
568 ~QSvgOffsetStyle() override;
569
570 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
571 void revert(QPainter *p, QSvgExtraStates &states) override;
572 Type type() const override;
573
574 void setPath(const QPainterPath &path)
575 {
576 m_path = path;
577 }
578
579 const QPainterPath &path() const
580 {
581 return m_path;
582 }
583
584 void setRotateAngle(qreal angle)
585 {
586 m_rotateAngle = angle;
587 }
588
589 qreal rotateAngle() const
590 {
591 return m_rotateAngle;
592 }
593
594 void setRotateType(QtSvg::OffsetRotateType type)
595 {
596 m_rotateType = type;
597 }
598
599 QtSvg::OffsetRotateType rotateType() const
600 {
601 return m_rotateType;
602 }
603
604 void setDistance(qreal distance)
605 {
606 m_distance = distance;
607 }
608
609 qreal distance() const
610 {
611 return m_distance;
612 }
613
614private:
615 QPainterPath m_path;
616 qreal m_distance{0.};
617 qreal m_rotateAngle{0.};
618 QtSvg::OffsetRotateType m_rotateType{QtSvg::OffsetRotateType::Auto};
619};
620
621class Q_SVG_EXPORT QSvgStaticStyle
622{
623public:
624 QSvgStaticStyle();
625 ~QSvgStaticStyle();
626
627 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states);
628 void revert(QPainter *p, QSvgExtraStates &states);
629 QSvgRefCounter<QSvgQualityStyle> quality;
630 QSvgRefCounter<QSvgFillStyle> fill;
631 QSvgRefCounter<QSvgViewportFillStyle> viewportFill;
632 QSvgRefCounter<QSvgFontStyle> font;
633 QSvgRefCounter<QSvgStrokeStyle> stroke;
634 QSvgRefCounter<QSvgTransformStyle> transform;
635 QSvgRefCounter<QSvgOpacityStyle> opacity;
636 QSvgRefCounter<QSvgCompOpStyle> compop;
637 QSvgRefCounter<QSvgOffsetStyle> offset;
638};
639
640class QSvgAbstractAnimation;
641
655
656class Q_SVG_EXPORT QSvgAnimatedStyle
657{
658public:
659 QSvgAnimatedStyle();
660 ~QSvgAnimatedStyle();
661
662 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states);
663 void revert(QPainter *p, QSvgExtraStates &states);
664
665private:
666 void savePaintingState(const QPainter *p, const QSvgNode *node, QSvgExtraStates &states);
667 void fetchStyleState(const QSvgAbstractAnimation *animation, QSvgStyleState &currentStyle);
668 void applyStyle(QPainter *p, QSvgExtraStates &states, const QSvgStyleState &currentStyle);
669
670private:
671 QTransform m_worldTransform;
672 QTransform m_transformToNode;
673 QSvgStyleState m_static;
674};
675
676/********************************************************/
677// NOT implemented:
678
679// color v v 'inherit' | <Color.datatype>
680//QColor m_color;
681
682// display v x 'inline' | 'block' | 'list-item'
683// | 'run-in' | 'compact' | 'marker' |
684// 'table' | 'inline-table' |
685// 'table-row-group' | 'table-header-group' |
686// 'table-footer-group' | 'table-row' |
687// 'table-column-group' | 'table-column' |
688// 'table-cell' | 'table-caption' |
689// 'none' | 'inherit'
690//QSvgDisplayStyle m_display;
691
692// display-align v v 'auto' | 'before' | 'center' | 'after' | 'inherit'
693//QSvgDisplayAlign m_displayAlign;
694
695// line-increment v v 'auto' | 'inherit' | <Number.datatype>
696//int m_lineIncrement;
697
698// text-anchor v v 'start' | 'middle' | 'end' | 'inherit'
699//QSvgTextAnchor m_textAnchor;
700
701// visibility v v 'visible' | 'hidden' | 'inherit'
702//QSvgVisibility m_visibility;
703
704/******************************************************/
705// the following do not make sense for us
706
707// pointer-events v v 'visiblePainted' | 'visibleFill' | 'visibleStroke' |
708// 'visible' | 'painted' | 'fill' | 'stroke' | 'all' |
709// 'none' | 'inherit'
710//QSvgPointEvents m_pointerEvents;
711
712// audio-level v x 'inherit' | <Number.datatype>
713
714QT_END_NAMESPACE
715
716#endif // QSVGSTYLE_P_H
friend class QPainter
QSvgRefCounter(T *_t)
Definition qsvgstyle_p.h:42
QSvgRefCounter(const QSvgRefCounter &other)
Definition qsvgstyle_p.h:49
QSvgRefCounter(QSvgRefCounter &&other) noexcept
Definition qsvgstyle_p.h:56
QSvgRefCounter & operator=(const QSvgRefCounter &other)
Definition qsvgstyle_p.h:59
Combined button and popup list for selecting options.
QSvgFont * svgFont
Qt::Alignment textAnchor
Qt::FillRule fillRule
quint8 remainingNestedNodes
QTransform transform
QtSvg::OffsetRotateType offsetRotateType
std::optional< QPainterPath > offsetPath