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