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