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
4#ifndef QSVGSTYLE_P_H
5#define QSVGSTYLE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "QtGui/qpainter.h"
19#include "QtGui/qpen.h"
20#include "QtGui/qbrush.h"
21#include "QtGui/qtransform.h"
22#include "QtGui/qcolor.h"
23#include "QtGui/qfont.h"
24#include <qdebug.h>
25#include "qtsvgglobal_p.h"
26
27QT_BEGIN_NAMESPACE
28
29class QPainter;
30class QSvgNode;
31class QSvgFont;
32class QSvgTinyDocument;
33
34template <class T> class QSvgRefCounter
35{
36public:
37 QSvgRefCounter() { t = nullptr; }
38 QSvgRefCounter(T *_t)
39 {
40 t = _t;
41 if (t)
42 t->ref();
43 }
44 QSvgRefCounter(const QSvgRefCounter &other)
45 {
46 t = other.t;
47 if (t)
48 t->ref();
49 }
50 QSvgRefCounter &operator =(T *_t)
51 {
52 if(_t)
53 _t->ref();
54 if (t)
55 t->deref();
56 t = _t;
57 return *this;
58 }
59 QSvgRefCounter &operator =(const QSvgRefCounter &other)
60 {
61 if(other.t)
62 other.t->ref();
63 if (t)
64 t->deref();
65 t = other.t;
66 return *this;
67 }
68 ~QSvgRefCounter()
69 {
70 if (t)
71 t->deref();
72 }
73
74 inline T *operator->() const { return t; }
75 inline operator T*() const { return t; }
76
77private:
78 T *t;
79};
80
81class Q_SVG_PRIVATE_EXPORT QSvgRefCounted
82{
83public:
84 QSvgRefCounted() { _ref = 0; }
85 virtual ~QSvgRefCounted() {}
86 void ref() {
87 ++_ref;
88// qDebug() << this << ": adding ref, now " << _ref;
89 }
90 void deref() {
91// qDebug() << this << ": removing ref, now " << _ref;
92 if(!--_ref) {
93// qDebug(" deleting");
94 delete this;
95 }
96 }
97private:
98 int _ref;
99};
100
101struct Q_SVG_PRIVATE_EXPORT QSvgExtraStates
102{
103 QSvgExtraStates();
104
105 qreal fillOpacity;
106 qreal strokeOpacity;
107 QSvgFont *svgFont;
108 Qt::Alignment textAnchor;
109 int fontWeight;
110 Qt::FillRule fillRule;
111 qreal strokeDashOffset;
112 int nestedUseLevel = 0;
113 int nestedUseCount = 0;
114 bool vectorEffect; // true if pen is cosmetic
115 qint8 imageRendering; // QSvgQualityStyle::ImageRendering
116};
117
118class Q_SVG_PRIVATE_EXPORT QSvgStyleProperty : public QSvgRefCounted
119{
120public:
121 enum Type
122 {
123 QUALITY,
124 FILL,
125 VIEWPORT_FILL,
126 FONT,
127 STROKE,
128 SOLID_COLOR,
129 GRADIENT,
130 TRANSFORM,
131 ANIMATE_TRANSFORM,
132 ANIMATE_COLOR,
133 OPACITY,
134 COMP_OP
135 };
136public:
137 virtual ~QSvgStyleProperty();
138 virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) = 0;
139 virtual void revert(QPainter *p, QSvgExtraStates &states) =0;
140 virtual Type type() const=0;
141};
142
143class Q_SVG_PRIVATE_EXPORT QSvgFillStyleProperty : public QSvgStyleProperty
144{
145public:
146 virtual QBrush brush(QPainter *p, QSvgExtraStates &states) = 0;
147 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
148 void revert(QPainter *p, QSvgExtraStates &states) override;
149};
150
151class Q_SVG_PRIVATE_EXPORT QSvgQualityStyle : public QSvgStyleProperty
152{
153public:
154 enum ImageRendering: qint8 {
155 ImageRenderingAuto = 0,
156 ImageRenderingOptimizeSpeed = 1,
157 ImageRenderingOptimizeQuality = 2,
158 };
159
160 QSvgQualityStyle(int color);
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 setImageRendering(ImageRendering);
166private:
167 // color-render ing v v 'auto' | 'optimizeSpeed' |
168 // 'optimizeQuality' | 'inherit'
169 //int m_colorRendering;
170
171 // shape-rendering v v 'auto' | 'optimizeSpeed' | 'crispEdges' |
172 // 'geometricPrecision' | 'inherit'
173 //QSvgShapeRendering m_shapeRendering;
174
175
176 // text-rendering v v 'auto' | 'optimizeSpeed' | 'optimizeLegibility'
177 // | 'geometricPrecision' | 'inherit'
178 //QSvgTextRendering m_textRendering;
179
180
181 // vector-effect v x 'default' | 'non-scaling-stroke' | 'inherit'
182 //QSvgVectorEffect m_vectorEffect;
183
184 // image-rendering v v 'auto' | 'optimizeSpeed' | 'optimizeQuality' |
185 // 'inherit'
186 qint32 m_imageRendering: 4;
187 qint32 m_oldImageRendering: 4;
188 quint32 m_imageRenderingSet: 1;
189};
190
191
192
193class Q_SVG_PRIVATE_EXPORT QSvgOpacityStyle : public QSvgStyleProperty
194{
195public:
196 QSvgOpacityStyle(qreal opacity);
197 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
198 void revert(QPainter *p, QSvgExtraStates &states) override;
199 Type type() const override;
200private:
201 qreal m_opacity;
202 qreal m_oldOpacity;
203};
204
205class Q_SVG_PRIVATE_EXPORT QSvgFillStyle : public QSvgStyleProperty
206{
207public:
208 QSvgFillStyle();
209 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
210 void revert(QPainter *p, QSvgExtraStates &states) override;
211 Type type() const override;
212
213 void setFillRule(Qt::FillRule f);
214 void setFillOpacity(qreal opacity);
215 void setFillStyle(QSvgFillStyleProperty* style);
216 void setBrush(QBrush brush);
217
218 const QBrush & qbrush() const
219 {
220 return m_fill;
221 }
222
223 qreal fillOpacity() const
224 {
225 return m_fillOpacity;
226 }
227
228 Qt::FillRule fillRule() const
229 {
230 return m_fillRule;
231 }
232
233 QSvgFillStyleProperty* style() const
234 {
235 return m_style;
236 }
237
238 void setGradientId(const QString &Id)
239 {
240 m_gradientId = Id;
241 }
242
243 QString gradientId() const
244 {
245 return m_gradientId;
246 }
247
248 void setGradientResolved(bool resolved)
249 {
250 m_gradientResolved = resolved;
251 }
252
253 bool isGradientResolved() const
254 {
255 return m_gradientResolved;
256 }
257
258private:
259 // fill v v 'inherit' | <Paint.datatype>
260 // fill-opacity v v 'inherit' | <OpacityValue.datatype>
261 QBrush m_fill;
262 QBrush m_oldFill;
263 QSvgFillStyleProperty *m_style;
264
265 Qt::FillRule m_fillRule;
266 Qt::FillRule m_oldFillRule;
267 qreal m_fillOpacity;
268 qreal m_oldFillOpacity;
269
270 QString m_gradientId;
271 uint m_gradientResolved : 1;
272
273 uint m_fillRuleSet : 1;
274 uint m_fillOpacitySet : 1;
275 uint m_fillSet : 1;
276};
277
278class Q_SVG_PRIVATE_EXPORT QSvgViewportFillStyle : public QSvgStyleProperty
279{
280public:
281 QSvgViewportFillStyle(const QBrush &brush);
282 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
283 void revert(QPainter *p, QSvgExtraStates &states) override;
284 Type type() const override;
285
286 const QBrush & qbrush() const
287 {
288 return m_viewportFill;
289 }
290private:
291 // viewport-fill v x 'inherit' | <Paint.datatype>
292 // viewport-fill-opacity v x 'inherit' | <OpacityValue.datatype>
293 QBrush m_viewportFill;
294
295 QBrush m_oldFill;
296};
297
298class Q_SVG_PRIVATE_EXPORT QSvgFontStyle : public QSvgStyleProperty
299{
300public:
301 static const int LIGHTER = -1;
302 static const int BOLDER = 1;
303
304 QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc);
305 QSvgFontStyle();
306 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
307 void revert(QPainter *p, QSvgExtraStates &states) override;
308 Type type() const override;
309
310 void setSize(qreal size)
311 {
312 // Store the _pixel_ size in the font. Since QFont::setPixelSize() only takes an int, call
313 // QFont::SetPointSize() instead. Set proper font size just before rendering.
314 m_qfont.setPointSizeF(size);
315 m_sizeSet = 1;
316 }
317
318 void setTextAnchor(Qt::Alignment anchor)
319 {
320 m_textAnchor = anchor;
321 m_textAnchorSet = 1;
322 }
323
324 void setFamily(const QString &family)
325 {
326 m_qfont.setFamilies({family});
327 m_familySet = 1;
328 }
329
330 void setStyle(QFont::Style fontStyle) {
331 m_qfont.setStyle(fontStyle);
332 m_styleSet = 1;
333 }
334
335 void setVariant(QFont::Capitalization fontVariant)
336 {
337 m_qfont.setCapitalization(fontVariant);
338 m_variantSet = 1;
339 }
340
341 void setWeight(int weight)
342 {
343 m_weight = weight;
344 m_weightSet = 1;
345 }
346
347 QSvgFont * svgFont() const
348 {
349 return m_svgFont;
350 }
351
352 const QFont &qfont() const
353 {
354 return m_qfont;
355 }
356
357 QSvgTinyDocument *doc() const {return m_doc;}
358
359private:
360 QSvgFont *m_svgFont;
361 QSvgTinyDocument *m_doc;
362 QFont m_qfont;
363
364 int m_weight;
365 Qt::Alignment m_textAnchor;
366
367 QSvgFont *m_oldSvgFont;
368 QFont m_oldQFont;
369 Qt::Alignment m_oldTextAnchor;
370 int m_oldWeight;
371
372 uint m_familySet : 1;
373 uint m_sizeSet : 1;
374 uint m_styleSet : 1;
375 uint m_variantSet : 1;
376 uint m_weightSet : 1;
377 uint m_textAnchorSet : 1;
378};
379
380class Q_SVG_PRIVATE_EXPORT QSvgStrokeStyle : public QSvgStyleProperty
381{
382public:
383 QSvgStrokeStyle();
384 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
385 void revert(QPainter *p, QSvgExtraStates &states) override;
386 Type type() const override;
387
388 void setStroke(QBrush brush)
389 {
390 m_stroke.setBrush(brush);
391 m_style = nullptr;
392 m_strokeSet = 1;
393 }
394
395 void setStyle(QSvgFillStyleProperty *style)
396 {
397 m_style = style;
398 m_strokeSet = 1;
399 }
400
401 void setDashArray(const QList<qreal> &dashes);
402
403 void setDashArrayNone()
404 {
405 m_stroke.setStyle(Qt::SolidLine);
406 m_strokeDashArraySet = 1;
407 }
408
409 void setDashOffset(qreal offset)
410 {
411 m_strokeDashOffset = offset;
412 m_strokeDashOffsetSet = 1;
413 }
414
415 void setLineCap(Qt::PenCapStyle cap)
416 {
417 m_stroke.setCapStyle(cap);
418 m_strokeLineCapSet = 1;
419 }
420
421 void setLineJoin(Qt::PenJoinStyle join)
422 {
423 m_stroke.setJoinStyle(join);
424 m_strokeLineJoinSet = 1;
425 }
426
427 void setMiterLimit(qreal limit)
428 {
429 m_stroke.setMiterLimit(limit);
430 m_strokeMiterLimitSet = 1;
431 }
432
433 void setOpacity(qreal opacity)
434 {
435 m_strokeOpacity = opacity;
436 m_strokeOpacitySet = 1;
437 }
438
439 void setWidth(qreal width)
440 {
441 m_stroke.setWidthF(width);
442 m_strokeWidthSet = 1;
443 Q_ASSERT(!m_strokeDashArraySet); // set width before dash array.
444 }
445
446 qreal width()
447 {
448 return m_stroke.widthF();
449 }
450
451 void setVectorEffect(bool nonScalingStroke)
452 {
453 m_vectorEffect = nonScalingStroke;
454 m_vectorEffectSet = 1;
455 }
456
457 QSvgFillStyleProperty* style() const
458 {
459 return m_style;
460 }
461
462 void setGradientId(const QString &Id)
463 {
464 m_gradientId = Id;
465 }
466
467 QString gradientId() const
468 {
469 return m_gradientId;
470 }
471
472 void setGradientResolved(bool resolved)
473 {
474 m_gradientResolved = resolved;
475 }
476
477 bool isGradientResolved() const
478 {
479 return m_gradientResolved;
480 }
481
482 QPen stroke() const
483 {
484 return m_stroke;
485 }
486
487private:
488 // stroke v v 'inherit' | <Paint.datatype>
489 // stroke-dasharray v v 'inherit' | <StrokeDashArrayValue.datatype>
490 // stroke-dashoffset v v 'inherit' | <StrokeDashOffsetValue.datatype>
491 // stroke-linecap v v 'butt' | 'round' | 'square' | 'inherit'
492 // stroke-linejoin v v 'miter' | 'round' | 'bevel' | 'inherit'
493 // stroke-miterlimit v v 'inherit' | <StrokeMiterLimitValue.datatype>
494 // stroke-opacity v v 'inherit' | <OpacityValue.datatype>
495 // stroke-width v v 'inherit' | <StrokeWidthValue.datatype>
496 QPen m_stroke;
497 QPen m_oldStroke;
498 qreal m_strokeOpacity;
499 qreal m_oldStrokeOpacity;
500 qreal m_strokeDashOffset;
501 qreal m_oldStrokeDashOffset;
502
503 QSvgFillStyleProperty *m_style;
504 QString m_gradientId;
505 uint m_gradientResolved : 1;
506 uint m_vectorEffect : 1;
507 uint m_oldVectorEffect : 1;
508
509 uint m_strokeSet : 1;
510 uint m_strokeDashArraySet : 1;
511 uint m_strokeDashOffsetSet : 1;
512 uint m_strokeLineCapSet : 1;
513 uint m_strokeLineJoinSet : 1;
514 uint m_strokeMiterLimitSet : 1;
515 uint m_strokeOpacitySet : 1;
516 uint m_strokeWidthSet : 1;
517 uint m_vectorEffectSet : 1;
518};
519
520class Q_SVG_PRIVATE_EXPORT QSvgSolidColorStyle : public QSvgFillStyleProperty
521{
522public:
523 QSvgSolidColorStyle(const QColor &color);
524 Type type() const override;
525
526 const QColor & qcolor() const
527 {
528 return m_solidColor;
529 }
530
531 QBrush brush(QPainter *, QSvgExtraStates &) override
532 {
533 return m_solidColor;
534 }
535
536private:
537 // solid-color v x 'inherit' | <SVGColor.datatype>
538 // solid-opacity v x 'inherit' | <OpacityValue.datatype>
539 QColor m_solidColor;
540
541 QBrush m_oldFill;
542 QPen m_oldStroke;
543};
544
545class Q_SVG_PRIVATE_EXPORT QSvgGradientStyle : public QSvgFillStyleProperty
546{
547public:
548 QSvgGradientStyle(QGradient *grad);
549 ~QSvgGradientStyle() { delete m_gradient; }
550 Type type() const override;
551
552 void setStopLink(const QString &link, QSvgTinyDocument *doc);
553 QString stopLink() const { return m_link; }
554 void resolveStops();
555 void resolveStops_helper(QStringList *visited);
556
557 void setTransform(const QTransform &transform);
558 QTransform qtransform() const
559 {
560 return m_transform;
561 }
562
563 QGradient *qgradient() const
564 {
565 return m_gradient;
566 }
567
568 bool gradientStopsSet() const
569 {
570 return m_gradientStopsSet;
571 }
572
573 void setGradientStopsSet(bool set)
574 {
575 m_gradientStopsSet = set;
576 }
577
578 QBrush brush(QPainter *, QSvgExtraStates &) override;
579private:
580 QGradient *m_gradient;
581 QTransform m_transform;
582
583 QSvgTinyDocument *m_doc;
584 QString m_link;
585 bool m_gradientStopsSet;
586};
587
588class Q_SVG_PRIVATE_EXPORT QSvgTransformStyle : public QSvgStyleProperty
589{
590public:
591 QSvgTransformStyle(const QTransform &transform);
592 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
593 void revert(QPainter *p, QSvgExtraStates &states) override;
594 Type type() const override;
595
596 const QTransform & qtransform() const
597 {
598 return m_transform;
599 }
600private:
601 //7.6 The transform attribute
602 QTransform m_transform;
603 QTransform m_oldWorldTransform;
604};
605
606
607class Q_SVG_PRIVATE_EXPORT QSvgAnimateTransform : public QSvgStyleProperty
608{
609public:
610 enum TransformType
611 {
612 Empty,
613 Translate,
614 Scale,
615 Rotate,
616 SkewX,
617 SkewY
618 };
619 enum Additive
620 {
621 Sum,
622 Replace
623 };
624public:
625 QSvgAnimateTransform(int startMs, int endMs, int by = 0);
626 void setArgs(TransformType type, Additive additive, const QList<qreal> &args);
627 void setFreeze(bool freeze);
628 void setRepeatCount(qreal repeatCount);
629 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
630 void revert(QPainter *p, QSvgExtraStates &states) override;
631 Type type() const override;
632 QSvgAnimateTransform::Additive additiveType() const
633 {
634 return m_additive;
635 }
636
637 bool animActive(qreal totalTimeElapsed)
638 {
639 if (totalTimeElapsed < m_from)
640 return false;
641 if (m_freeze || m_repeatCount < 0) // fill="freeze" or repeat="indefinite"
642 return true;
643 if (m_totalRunningTime == 0)
644 return false;
645 qreal animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime;
646 if (animationFrame > m_repeatCount)
647 return false;
648 return true;
649 }
650
651 bool transformApplied() const
652 {
653 return m_transformApplied;
654 }
655
656 // Call this instead of revert if you know that revert is unnecessary.
657 void clearTransformApplied()
658 {
659 m_transformApplied = false;
660 }
661
662protected:
663 void resolveMatrix(const QSvgNode *node);
664private:
665 qreal m_from;
666 qreal m_totalRunningTime;
667 TransformType m_type;
668 Additive m_additive;
669 QList<qreal> m_args;
670 int m_count;
671 QTransform m_transform;
672 QTransform m_oldWorldTransform;
673 bool m_finished;
674 bool m_freeze;
675 qreal m_repeatCount;
676 bool m_transformApplied;
677};
678
679
680class Q_SVG_PRIVATE_EXPORT QSvgAnimateColor : public QSvgStyleProperty
681{
682public:
683 QSvgAnimateColor(int startMs, int endMs, int by = 0);
684 void setArgs(bool fill, const QList<QColor> &colors);
685 void setFreeze(bool freeze);
686 void setRepeatCount(qreal repeatCount);
687 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
688 void revert(QPainter *p, QSvgExtraStates &states) override;
689 Type type() const override;
690private:
691 qreal m_from;
692 qreal m_totalRunningTime;
693 QList<QColor> m_colors;
694 QBrush m_oldBrush;
695 QPen m_oldPen;
696 bool m_fill;
697 bool m_finished;
698 bool m_freeze;
699 qreal m_repeatCount;
700};
701
702
703class Q_SVG_PRIVATE_EXPORT QSvgCompOpStyle : public QSvgStyleProperty
704{
705public:
706 QSvgCompOpStyle(QPainter::CompositionMode mode);
707 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) override;
708 void revert(QPainter *p, QSvgExtraStates &states) override;
709 Type type() const override;
710
711 const QPainter::CompositionMode & compOp() const
712 {
713 return m_mode;
714 }
715private:
716 //comp-op attribute
717 QPainter::CompositionMode m_mode;
718
719 QPainter::CompositionMode m_oldMode;
720};
721
722
723class Q_SVG_PRIVATE_EXPORT QSvgStyle
724{
725public:
726 QSvgStyle()
727 : quality(0),
728 fill(0),
729 viewportFill(0),
730 font(0),
731 stroke(0),
732 solidColor(0),
733 gradient(0),
734 transform(0),
735 animateColor(0),
736 opacity(0),
737 compop(0)
738 {}
739 ~QSvgStyle();
740
741 void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states);
742 void revert(QPainter *p, QSvgExtraStates &states);
743 QSvgRefCounter<QSvgQualityStyle> quality;
744 QSvgRefCounter<QSvgFillStyle> fill;
745 QSvgRefCounter<QSvgViewportFillStyle> viewportFill;
746 QSvgRefCounter<QSvgFontStyle> font;
747 QSvgRefCounter<QSvgStrokeStyle> stroke;
748 QSvgRefCounter<QSvgSolidColorStyle> solidColor;
749 QSvgRefCounter<QSvgGradientStyle> gradient;
750 QSvgRefCounter<QSvgTransformStyle> transform;
751 QSvgRefCounter<QSvgAnimateColor> animateColor;
752 QList<QSvgRefCounter<QSvgAnimateTransform> > animateTransforms;
753 QSvgRefCounter<QSvgOpacityStyle> opacity;
754 QSvgRefCounter<QSvgCompOpStyle> compop;
755};
756
757/********************************************************/
758// NOT implemented:
759
760// color v v 'inherit' | <Color.datatype>
761//QColor m_color;
762
763// display v x 'inline' | 'block' | 'list-item'
764// | 'run-in' | 'compact' | 'marker' |
765// 'table' | 'inline-table' |
766// 'table-row-group' | 'table-header-group' |
767// 'table-footer-group' | 'table-row' |
768// 'table-column-group' | 'table-column' |
769// 'table-cell' | 'table-caption' |
770// 'none' | 'inherit'
771//QSvgDisplayStyle m_display;
772
773// display-align v v 'auto' | 'before' | 'center' | 'after' | 'inherit'
774//QSvgDisplayAlign m_displayAlign;
775
776// line-increment v v 'auto' | 'inherit' | <Number.datatype>
777//int m_lineIncrement;
778
779// text-anchor v v 'start' | 'middle' | 'end' | 'inherit'
780//QSvgTextAnchor m_textAnchor;
781
782// visibility v v 'visible' | 'hidden' | 'inherit'
783//QSvgVisibility m_visibility;
784
785/******************************************************/
786// the following do not make sense for us
787
788// pointer-events v v 'visiblePainted' | 'visibleFill' | 'visibleStroke' |
789// 'visible' | 'painted' | 'fill' | 'stroke' | 'all' |
790// 'none' | 'inherit'
791//QSvgPointEvents m_pointerEvents;
792
793// audio-level v x 'inherit' | <Number.datatype>
794
795QT_END_NAMESPACE
796
797#endif // QSVGSTYLE_P_H
798

source code of qtsvg/src/svg/qsvgstyle_p.h