Coverage Report

Created: 2026-08-17 07:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtsvg/src/svg/qsvgstyle.cpp
Line
Count
Source
1
// Copyright (C) 2021 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
#include "qsvgstyle_p.h"
7
8
#include "qsvgfont_p.h"
9
#include "qsvgnode_p.h"
10
#include "private/qsvganimate_p.h"
11
#include "qsvgdocument_p.h"
12
13
#include "qpainter.h"
14
#include "qcolor.h"
15
#include "qdebug.h"
16
17
QT_BEGIN_NAMESPACE
18
19
0
QSvgRefCounted::~QSvgRefCounted()
20
    = default;
21
22
QSvgExtraStates::QSvgExtraStates()
23
92.3k
    : fillOpacity(1.0),
24
92.3k
      strokeOpacity(1.0),
25
92.3k
      svgFont(0),
26
92.3k
      textAnchor(Qt::AlignLeft),
27
92.3k
      fontWeight(QFont::Normal),
28
92.3k
      fillRule(Qt::WindingFill),
29
92.3k
      strokeDashOffset(0),
30
92.3k
      vectorEffect(false),
31
92.3k
      imageRendering(QSvgQualityStyle::ImageRenderingAuto)
32
92.3k
{
33
92.3k
}
34
35
332k
QSvgStyleProperty::~QSvgStyleProperty()
36
    = default;
37
38
QSvgQualityStyle::QSvgQualityStyle(int color)
39
0
    : m_imageRendering(QSvgQualityStyle::ImageRenderingAuto)
40
0
    , m_oldImageRendering(QSvgQualityStyle::ImageRenderingAuto)
41
0
    , m_imageRenderingSet(0)
42
0
{
43
0
    Q_UNUSED(color);
44
0
}
45
46
QSvgQualityStyle::~QSvgQualityStyle()
47
    = default;
48
49
0
void QSvgQualityStyle::setImageRendering(ImageRendering hint) {
50
0
    m_imageRendering = hint;
51
0
    m_imageRenderingSet = 1;
52
0
}
53
54
void QSvgQualityStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states)
55
0
{
56
0
   m_oldImageRendering = states.imageRendering;
57
0
   if (m_imageRenderingSet) {
58
0
       states.imageRendering = m_imageRendering;
59
0
   }
60
0
   if (m_imageRenderingSet) {
61
0
       bool smooth = false;
62
0
       if (m_imageRendering == ImageRenderingAuto)
63
           // auto (the spec says to prefer quality)
64
0
           smooth = true;
65
0
       else
66
0
           smooth = (m_imageRendering == ImageRenderingOptimizeQuality);
67
0
       p->setRenderHint(QPainter::SmoothPixmapTransform, smooth);
68
0
   }
69
0
}
70
71
void QSvgQualityStyle::revert(QPainter *p, QSvgExtraStates &states)
72
0
{
73
0
    if (m_imageRenderingSet) {
74
0
        states.imageRendering = m_oldImageRendering;
75
0
        bool smooth = false;
76
0
        if (m_oldImageRendering == ImageRenderingAuto)
77
0
            smooth = true;
78
0
        else
79
0
            smooth = (m_oldImageRendering == ImageRenderingOptimizeQuality);
80
0
        p->setRenderHint(QPainter::SmoothPixmapTransform, smooth);
81
0
    }
82
0
}
83
84
QSvgFillStyle::QSvgFillStyle()
85
141k
    : m_fillRuleSet(0)
86
141k
    , m_fillOpacitySet(0)
87
141k
    , m_fillSet(0)
88
141k
{
89
141k
}
90
91
141k
QSvgFillStyle::~QSvgFillStyle()
92
    = default;
93
94
void QSvgFillStyle::setFillRule(Qt::FillRule f)
95
39.4k
{
96
39.4k
    m_fillRuleSet = 1;
97
39.4k
    m_fillRule = f;
98
39.4k
}
99
100
void QSvgFillStyle::setFillOpacity(qreal opacity)
101
67.3k
{
102
67.3k
    m_fillOpacitySet = 1;
103
67.3k
    m_fillOpacity = opacity;
104
67.3k
}
105
106
void QSvgFillStyle::setPaintServer(QSvgPaintServerSharedPtr paintServer)
107
0
{
108
0
    m_paintServer = std::move(paintServer);
109
0
    m_fillSet = 1;
110
0
}
111
112
void QSvgFillStyle::setBrush(QBrush brush)
113
26.3k
{
114
26.3k
    m_fill = std::move(brush);
115
26.3k
    m_paintServer.reset();
116
26.3k
    m_fillSet = 1;
117
26.3k
}
118
119
void QSvgFillStyle::apply(QPainter *p, const QSvgNode *n, QSvgExtraStates &states)
120
115k
{
121
115k
    m_oldFill = p->brush();
122
115k
    m_oldFillRule = states.fillRule;
123
115k
    m_oldFillOpacity = states.fillOpacity;
124
125
115k
    if (m_fillRuleSet)
126
38.2k
        states.fillRule = m_fillRule;
127
115k
    if (m_fillSet) {
128
15.1k
        if (m_paintServer)
129
0
            p->setBrush(m_paintServer->brush(p, n, states));
130
15.1k
        else
131
15.1k
            p->setBrush(m_fill);
132
15.1k
    }
133
115k
    if (m_fillOpacitySet)
134
74.4k
        states.fillOpacity = m_fillOpacity;
135
115k
}
136
137
void QSvgFillStyle::revert(QPainter *p, QSvgExtraStates &states)
138
115k
{
139
115k
    if (m_fillOpacitySet)
140
74.4k
        states.fillOpacity = m_oldFillOpacity;
141
115k
    if (m_fillSet)
142
15.1k
        p->setBrush(m_oldFill);
143
115k
    if (m_fillRuleSet)
144
38.2k
        states.fillRule = m_oldFillRule;
145
115k
}
146
147
QSvgViewportFillStyle::QSvgViewportFillStyle(const QBrush &brush)
148
0
    : m_viewportFill(brush)
149
0
{
150
0
}
151
152
0
QSvgViewportFillStyle::~QSvgViewportFillStyle()
153
    = default;
154
155
void QSvgViewportFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &)
156
0
{
157
0
    m_oldFill = p->brush();
158
0
    p->setBrush(m_viewportFill);
159
0
}
160
161
void QSvgViewportFillStyle::revert(QPainter *p, QSvgExtraStates &)
162
0
{
163
0
    p->setBrush(m_oldFill);
164
0
}
165
166
const int QSvgFontStyle::LIGHTER;
167
const int QSvgFontStyle::BOLDER;
168
169
QSvgFontStyle::QSvgFontStyle(QSvgFont *font)
170
0
    : m_svgFont(font)
171
0
    , m_familySet(0)
172
0
    , m_sizeSet(0)
173
0
    , m_styleSet(0)
174
0
    , m_variantSet(0)
175
0
    , m_weightSet(0)
176
0
    , m_textAnchorSet(0)
177
0
{
178
0
}
179
180
QSvgFontStyle::QSvgFontStyle()
181
19.8k
    : m_svgFont(0)
182
19.8k
    , m_familySet(0)
183
19.8k
    , m_sizeSet(0)
184
19.8k
    , m_styleSet(0)
185
19.8k
    , m_variantSet(0)
186
19.8k
    , m_weightSet(0)
187
19.8k
    , m_textAnchorSet(0)
188
19.8k
{
189
19.8k
}
190
191
19.8k
QSvgFontStyle::~QSvgFontStyle()
192
    = default;
193
194
void QSvgFontStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states)
195
7.34k
{
196
7.34k
    m_oldQFont = p->font();
197
7.34k
    m_oldSvgFont = states.svgFont;
198
7.34k
    m_oldTextAnchor = states.textAnchor;
199
7.34k
    m_oldWeight = states.fontWeight;
200
201
7.34k
    if (m_textAnchorSet)
202
0
        states.textAnchor = m_textAnchor;
203
204
7.34k
    QFont font = m_oldQFont;
205
7.34k
    if (m_familySet) {
206
0
        states.svgFont = m_svgFont;
207
0
        font.setFamilies(m_qfont.families());
208
0
    }
209
210
7.34k
    if (m_sizeSet)
211
1.36k
        font.setPointSizeF(m_qfont.pointSizeF());
212
213
7.34k
    if (m_styleSet)
214
0
        font.setStyle(m_qfont.style());
215
216
7.34k
    if (m_variantSet)
217
0
        font.setCapitalization(m_qfont.capitalization());
218
219
7.34k
    if (m_weightSet) {
220
6.07k
        if (m_weight == BOLDER) {
221
744
            states.fontWeight = qMin(states.fontWeight, QFont::Weight::Black - 100) + 100;
222
5.32k
        } else if (m_weight == LIGHTER) {
223
0
            states.fontWeight = qMax(states.fontWeight, QFont::Weight::Thin + 100) - 100;
224
5.32k
        } else {
225
5.32k
            states.fontWeight = m_weight;
226
5.32k
        }
227
6.07k
        font.setWeight(QFont::Weight(qBound(static_cast<int>(QFont::Weight::Thin),
228
6.07k
                                            states.fontWeight,
229
6.07k
                                            static_cast<int>(QFont::Weight::Black))));
230
6.07k
    }
231
232
7.34k
    p->setFont(font);
233
7.34k
}
234
235
void QSvgFontStyle::revert(QPainter *p, QSvgExtraStates &states)
236
7.34k
{
237
7.34k
    p->setFont(m_oldQFont);
238
7.34k
    states.svgFont = m_oldSvgFont;
239
7.34k
    states.textAnchor = m_oldTextAnchor;
240
7.34k
    states.fontWeight = m_oldWeight;
241
7.34k
}
242
243
QSvgStrokeStyle::QSvgStrokeStyle()
244
128k
    : m_vectorEffect(0)
245
128k
    , m_oldVectorEffect(0)
246
128k
    , m_strokeSet(0)
247
128k
    , m_strokeDashArraySet(0)
248
128k
    , m_strokeDashOffsetSet(0)
249
128k
    , m_strokeLineCapSet(0)
250
128k
    , m_strokeLineJoinSet(0)
251
128k
    , m_strokeMiterLimitSet(0)
252
128k
    , m_strokeOpacitySet(0)
253
128k
    , m_strokeWidthSet(0)
254
128k
    , m_vectorEffectSet(0)
255
128k
{
256
128k
}
257
258
128k
QSvgStrokeStyle::~QSvgStrokeStyle()
259
    = default;
260
261
void QSvgStrokeStyle::apply(QPainter *p, const QSvgNode *n, QSvgExtraStates &states)
262
414k
{
263
414k
    m_oldStroke = p->pen();
264
414k
    m_oldStrokeOpacity = states.strokeOpacity;
265
414k
    m_oldStrokeDashOffset = states.strokeDashOffset;
266
414k
    m_oldVectorEffect = states.vectorEffect;
267
268
414k
    QPen pen = p->pen();
269
270
414k
    qreal oldWidth = pen.widthF();
271
414k
    qreal width = m_stroke.widthF();
272
414k
    if (oldWidth == 0)
273
0
        oldWidth = 1;
274
414k
    if (width == 0)
275
0
        width = 1;
276
414k
    qreal scale = oldWidth / width;
277
278
414k
    if (m_strokeOpacitySet)
279
636
        states.strokeOpacity = m_strokeOpacity;
280
281
414k
    if (m_vectorEffectSet)
282
0
        states.vectorEffect = m_vectorEffect;
283
284
414k
    if (m_strokeSet) {
285
91.0k
        if (m_paintServer)
286
0
            pen.setBrush(m_paintServer->brush(p, n, states));
287
91.0k
        else
288
91.0k
            pen.setBrush(m_stroke.brush());
289
91.0k
    }
290
291
414k
    if (m_strokeWidthSet)
292
0
        pen.setWidthF(m_stroke.widthF());
293
294
414k
    bool setDashOffsetNeeded = false;
295
296
414k
    if (m_strokeDashOffsetSet) {
297
0
        states.strokeDashOffset = m_strokeDashOffset;
298
0
        setDashOffsetNeeded = true;
299
0
    }
300
301
414k
    if (m_strokeDashArraySet) {
302
0
        if (m_stroke.style() == Qt::SolidLine) {
303
0
            pen.setStyle(Qt::SolidLine);
304
0
        } else if (m_strokeWidthSet || oldWidth == 1) {
305
            // If both width and dash array was set, the dash array is already scaled correctly.
306
0
            pen.setDashPattern(m_stroke.dashPattern());
307
0
            setDashOffsetNeeded = true;
308
0
        } else {
309
            // If dash array was set, but not the width, the dash array has to be scaled with respect to the old width.
310
0
            QList<qreal> dashes = m_stroke.dashPattern();
311
0
            for (int i = 0; i < dashes.size(); ++i)
312
0
                dashes[i] /= oldWidth;
313
0
            pen.setDashPattern(dashes);
314
0
            setDashOffsetNeeded = true;
315
0
        }
316
414k
    } else if (m_strokeWidthSet && pen.style() != Qt::SolidLine && scale != 1) {
317
        // If the width was set, but not the dash array, the old dash array must be scaled with respect to the new width.
318
0
        QList<qreal> dashes = pen.dashPattern();
319
0
        for (int i = 0; i < dashes.size(); ++i)
320
0
            dashes[i] *= scale;
321
0
        pen.setDashPattern(dashes);
322
0
        setDashOffsetNeeded = true;
323
0
    }
324
325
414k
    if (m_strokeLineCapSet)
326
0
        pen.setCapStyle(m_stroke.capStyle());
327
414k
    if (m_strokeLineJoinSet)
328
0
        pen.setJoinStyle(m_stroke.joinStyle());
329
414k
    if (m_strokeMiterLimitSet)
330
0
        pen.setMiterLimit(m_stroke.miterLimit());
331
332
    // You can have dash offset on solid strokes in SVG files, but not in Qt.
333
    // QPen::setDashOffset() will set the pen style to Qt::CustomDashLine,
334
    // so don't call the method if the pen is solid.
335
414k
    if (setDashOffsetNeeded && pen.style() != Qt::SolidLine) {
336
0
        qreal currentWidth = pen.widthF();
337
0
        if (currentWidth == 0)
338
0
            currentWidth = 1;
339
0
        pen.setDashOffset(states.strokeDashOffset / currentWidth);
340
0
    }
341
342
414k
    pen.setCosmetic(states.vectorEffect);
343
344
414k
    p->setPen(pen);
345
414k
}
346
347
void QSvgStrokeStyle::revert(QPainter *p, QSvgExtraStates &states)
348
414k
{
349
414k
    p->setPen(m_oldStroke);
350
414k
    states.strokeOpacity = m_oldStrokeOpacity;
351
414k
    states.strokeDashOffset = m_oldStrokeDashOffset;
352
414k
    states.vectorEffect = m_oldVectorEffect;
353
414k
}
354
355
void QSvgStrokeStyle::setDashArray(const QList<qreal> &dashes)
356
0
{
357
0
    if (m_strokeWidthSet) {
358
0
        QList<qreal> d = dashes;
359
0
        qreal w = m_stroke.widthF();
360
0
        if (w != 0 && w != 1) {
361
0
            for (int i = 0; i < d.size(); ++i)
362
0
                d[i] /= w;
363
0
        }
364
0
        m_stroke.setDashPattern(d);
365
0
    } else {
366
0
        m_stroke.setDashPattern(dashes);
367
0
    }
368
0
    m_strokeDashArraySet = 1;
369
0
}
370
371
QSvgTransformStyle::QSvgTransformStyle(const QTransform &trans)
372
0
    : m_transform(trans)
373
0
{
374
0
}
375
376
0
QSvgTransformStyle::~QSvgTransformStyle()
377
    = default;
378
379
void QSvgTransformStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &)
380
0
{
381
0
    m_oldWorldTransform.push(p->worldTransform());
382
0
    p->setWorldTransform(m_transform, true);
383
0
}
384
385
void QSvgTransformStyle::revert(QPainter *p, QSvgExtraStates &)
386
0
{
387
0
    p->setWorldTransform(m_oldWorldTransform.pop(), false /* don't combine */);
388
0
}
389
390
QSvgStyleProperty::Type QSvgQualityStyle::type() const
391
0
{
392
0
    return Quality;
393
0
}
394
395
QSvgStyleProperty::Type QSvgFillStyle::type() const
396
293k
{
397
293k
    return Fill;
398
293k
}
399
400
QSvgStyleProperty::Type QSvgViewportFillStyle::type() const
401
0
{
402
0
    return ViewportFill;
403
0
}
404
405
QSvgStyleProperty::Type QSvgFontStyle::type() const
406
39.6k
{
407
39.6k
    return Font;
408
39.6k
}
409
410
QSvgStyleProperty::Type QSvgStrokeStyle::type() const
411
288k
{
412
288k
    return Stroke;
413
288k
}
414
415
QSvgStyleProperty::Type QSvgTransformStyle::type() const
416
0
{
417
0
    return Transform;
418
0
}
419
420
421
QSvgCompOpStyle::QSvgCompOpStyle(QPainter::CompositionMode mode)
422
0
    : m_mode(mode)
423
0
{
424
425
0
}
426
427
QSvgCompOpStyle::~QSvgCompOpStyle()
428
    = default;
429
430
void QSvgCompOpStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &)
431
0
{
432
0
    m_oldMode = p->compositionMode();
433
0
    p->setCompositionMode(m_mode);
434
0
}
435
436
void QSvgCompOpStyle::revert(QPainter *p, QSvgExtraStates &)
437
0
{
438
0
    p->setCompositionMode(m_oldMode);
439
0
}
440
441
QSvgStyleProperty::Type QSvgCompOpStyle::type() const
442
0
{
443
0
    return CompOp;
444
0
}
445
446
0
QSvgOffsetStyle::~QSvgOffsetStyle()
447
    = default;
448
449
void QSvgOffsetStyle::apply(QPainter *, const QSvgNode *, QSvgExtraStates &)
450
0
{
451
0
}
452
453
void QSvgOffsetStyle::revert(QPainter *, QSvgExtraStates &)
454
0
{
455
0
}
456
457
QSvgStyleProperty::Type QSvgOffsetStyle::type() const
458
0
{
459
0
    return Offset;
460
0
}
461
462
QSvgOpacityStyle::QSvgOpacityStyle(qreal opacity)
463
41.9k
    : m_opacity(opacity), m_oldOpacity(0)
464
41.9k
{
465
466
41.9k
}
467
468
QSvgOpacityStyle::~QSvgOpacityStyle()
469
    = default;
470
471
void QSvgOpacityStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &)
472
24.6k
{
473
24.6k
    m_oldOpacity = p->opacity();
474
24.6k
    p->setOpacity(m_opacity * m_oldOpacity);
475
24.6k
}
476
477
void QSvgOpacityStyle::revert(QPainter *p, QSvgExtraStates &)
478
24.6k
{
479
24.6k
    p->setOpacity(m_oldOpacity);
480
24.6k
}
481
482
QSvgStyleProperty::Type QSvgOpacityStyle::type() const
483
83.9k
{
484
83.9k
    return Opacity;
485
83.9k
}
486
487
1.08M
QSvgStaticStyle::QSvgStaticStyle()
488
    = default;
489
1.08M
QSvgStaticStyle::~QSvgStaticStyle()
490
    = default;
491
492
void QSvgStaticStyle::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states)
493
1.74M
{
494
15.6M
    for (auto &prop : m_properties) {
495
15.6M
        if (prop)
496
561k
            prop->apply(p, node, states);
497
15.6M
    }
498
1.74M
}
499
500
void QSvgStaticStyle::revert(QPainter *p, QSvgExtraStates &states)
501
1.74M
{
502
15.6M
    for (auto &prop : m_properties) {
503
15.6M
        if (prop)
504
561k
            prop->revert(p, states);
505
15.6M
    }
506
1.74M
}
507
508
namespace {
509
510
QColor sumValue(const QColor &c1, const QColor &c2)
511
0
{
512
0
    QRgb rgb1 = c1.rgba();
513
0
    QRgb rgb2 = c2.rgba();
514
0
    int sumRed = qRed(rgb1) + qRed(rgb2);
515
0
    int sumGreen = qGreen(rgb1) + qGreen(rgb2);
516
0
    int sumBlue = qBlue(rgb1) + qBlue(rgb2);
517
518
0
    QRgb sumRgb = qRgba(qBound(0, sumRed, 255),
519
0
                        qBound(0, sumGreen, 255),
520
0
                        qBound(0, sumBlue, 255),
521
0
                        255);
522
523
0
    return QColor(sumRgb);
524
0
}
525
526
qreal sumValue(qreal value1, qreal value2)
527
0
{
528
0
    qreal sumValue = value1 + value2;
529
0
    return qBound(0.0, sumValue, 1.0);
530
0
}
531
532
}
533
534
QSvgAnimatedStyle::QSvgAnimatedStyle()
535
1.08M
{
536
1.08M
}
537
538
QSvgAnimatedStyle::~QSvgAnimatedStyle()
539
1.08M
{
540
1.08M
}
541
542
void QSvgAnimatedStyle::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states)
543
0
{
544
0
    QSharedPointer<QSvgAbstractAnimator> animator = node->document()->animator();
545
0
    QList<QSvgAbstractAnimation *> nodeAnims = animator->animationsForNode(node);
546
547
0
    savePaintingState(p, node, states);
548
0
    if (nodeAnims.isEmpty())
549
0
        return;
550
551
0
    QSvgStyleState currentStyle = m_static;
552
0
    for (const QSvgAbstractAnimation *anim : std::as_const(nodeAnims)) {
553
0
        if (!anim->isActive())
554
0
            continue;
555
556
0
        fetchStyleState(anim, currentStyle);
557
0
    }
558
559
0
    applyStyle(p, states, currentStyle);
560
0
}
561
562
void QSvgAnimatedStyle::revert(QPainter *p, QSvgExtraStates &states)
563
0
{
564
0
    p->setWorldTransform(m_worldTransform);
565
0
    p->setBrush(m_static.fill);
566
0
    p->setPen(m_static.stroke);
567
0
    p->setOpacity(m_static.opacity);
568
0
    states.fillOpacity = m_static.fillOpacity;
569
0
    states.strokeOpacity = m_static.strokeOpacity;
570
0
}
571
572
void QSvgAnimatedStyle::savePaintingState(const QPainter *p, const QSvgNode *node, QSvgExtraStates &states)
573
0
{
574
0
    m_worldTransform = p->worldTransform();
575
0
    if (auto prop = node->style().property(QSvgStyleProperty::Transform))
576
0
        m_static.transform = (static_cast<QSvgTransformStyle*>(prop))->qtransform();
577
578
0
    if (auto prop = node->style().property(QSvgStyleProperty::Offset)) {
579
0
        QSvgOffsetStyle *offset = static_cast<QSvgOffsetStyle*>(prop);
580
0
        m_static.offsetPath = offset->path();
581
0
        m_static.offsetRotateType = offset->rotateType();
582
0
        m_static.offsetRotate = offset->rotateAngle();
583
0
    }
584
585
0
    m_static.fill = p->brush();
586
0
    m_static.stroke = p->pen();
587
0
    m_static.fillOpacity = states.fillOpacity;
588
0
    m_static.strokeOpacity = states.strokeOpacity;
589
0
    m_static.opacity = p->opacity();
590
0
    m_transformToNode = m_static.transform.inverted() * m_worldTransform;
591
0
}
592
593
void QSvgAnimatedStyle::fetchStyleState(const QSvgAbstractAnimation *animation, QSvgStyleState &currentStyle)
594
0
{
595
0
    bool replace = animation->animationType() == QSvgAbstractAnimation::CSS ? true :
596
0
                       (static_cast<const QSvgAnimateNode *>(animation))->additiveType() == QSvgAnimateNode::Replace;
597
598
0
    QList<QSvgAbstractAnimatedProperty *> properties = animation->properties();
599
0
    for (const QSvgAbstractAnimatedProperty *property : std::as_const(properties)) {
600
0
        if (property->propertyName() == QStringLiteral("fill")) {
601
0
            QBrush brush = currentStyle.fill;
602
0
            QColor brushColor = brush.color();
603
0
            QColor animatedColor = property->interpolatedValue().value<QColor>();
604
0
            QColor sumOrReplaceColor = replace ? animatedColor : sumValue(brushColor, animatedColor);
605
0
            brush.setColor(sumOrReplaceColor);
606
0
            currentStyle.fill = brush;
607
0
        } else if (property->propertyName() == QStringLiteral("stroke")) {
608
0
            QPen &pen = currentStyle.stroke;
609
0
            QBrush penBrush = pen.brush();
610
0
            QColor penColor = penBrush.color();
611
0
            QColor animatedColor = property->interpolatedValue().value<QColor>();
612
0
            QColor sumOrReplaceColor = replace ? animatedColor : sumValue(penColor, animatedColor);
613
0
            penBrush.setColor(sumOrReplaceColor);
614
0
            penBrush.setStyle(Qt::SolidPattern);
615
0
            pen.setBrush(penBrush);
616
0
        } else if (property->propertyName() == QStringLiteral("transform")) {
617
0
            QTransform animatedTransform = property->interpolatedValue().value<QTransform>();
618
0
            QTransform sumOrReplaceTransform = replace ? animatedTransform : animatedTransform * currentStyle.transform;
619
0
            currentStyle.transform = sumOrReplaceTransform;
620
0
        } else if (property->propertyName() == QStringLiteral("fill-opacity")) {
621
0
            qreal animatedFillOpacity = property->interpolatedValue().value<qreal>();
622
0
            qreal sumOrReplaceOpacity = replace ? animatedFillOpacity : sumValue(currentStyle.fillOpacity, animatedFillOpacity);
623
0
            currentStyle.fillOpacity = sumOrReplaceOpacity;
624
0
        } else if (property->propertyName() == QStringLiteral("stroke-opacity")) {
625
0
            qreal animatedStrokeOpacity = property->interpolatedValue().value<qreal>();
626
0
            qreal sumOrReplaceOpacity = replace ? animatedStrokeOpacity : sumValue(currentStyle.strokeOpacity, animatedStrokeOpacity);
627
0
            currentStyle.strokeOpacity = sumOrReplaceOpacity;
628
0
        } else if (property->propertyName() == QStringLiteral("opacity")) {
629
0
            qreal animatedOpacity = property->interpolatedValue().value<qreal>();
630
0
            qreal sumOrReplaceOpacity = replace ? animatedOpacity : sumValue(currentStyle.opacity, animatedOpacity);
631
0
            currentStyle.opacity = sumOrReplaceOpacity;
632
0
        } else if (property->propertyName() == QStringLiteral("offset-distance")) {
633
0
            qreal offsetDistance = property->interpolatedValue().value<qreal>();
634
0
            currentStyle.offsetDistance = offsetDistance;
635
0
        }
636
0
    }
637
0
}
638
639
void QSvgAnimatedStyle::applyStyle(QPainter *p, QSvgExtraStates &states, const QSvgStyleState &currentStyle)
640
0
{
641
0
    p->setBrush(currentStyle.fill);
642
0
    states.fillOpacity = currentStyle.fillOpacity;
643
0
    p->setPen(currentStyle.stroke);
644
0
    states.strokeOpacity = currentStyle.strokeOpacity;
645
0
    p->setOpacity(currentStyle.opacity);
646
647
0
    QTransform transform = currentStyle.transform;
648
0
    QTransform offset;
649
0
    if (m_static.offsetPath) {
650
0
        qreal offsetDistance = currentStyle.offsetDistance;
651
0
        qreal angle = m_static.offsetPath.value().angleAtPercent(offsetDistance);
652
0
        QPointF position = m_static.offsetPath.value().pointAtPercent(offsetDistance);
653
0
        offset.translate(position.x(), position.y());
654
655
0
        switch (m_static.offsetRotateType) {
656
0
        case QtSvg::OffsetRotateType::Auto:
657
0
            offset.rotate(-angle);
658
0
            break;
659
0
        case QtSvg::OffsetRotateType::Angle:
660
0
            offset.rotate(m_static.offsetRotate);
661
0
            break;
662
0
        case QtSvg::OffsetRotateType::AutoAngle:
663
0
            offset.rotate(m_static.offsetRotate - angle);
664
0
            break;
665
0
        case QtSvg::OffsetRotateType::Reverse:
666
0
            offset.rotate(180 - angle);
667
0
            break;
668
0
        case QtSvg::OffsetRotateType::ReverseAngle:
669
0
            offset.rotate(180 + m_static.offsetRotate - angle);
670
0
            break;
671
0
        }
672
0
    }
673
674
0
    QTransform combinedTransform = transform * offset * m_transformToNode;
675
0
    p->setWorldTransform(combinedTransform);
676
0
}
677
678
QT_END_NAMESPACE