Coverage Report

Created: 2026-08-17 07:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtsvg/src/svg/qsvgnode.cpp
Line
Count
Source
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
#include "qsvgnode_p.h"
7
#include "qsvgdocument_p.h"
8
#include "qsvggraphics_p.h"
9
#include <QtSvg/private/qsvgpaintserver_p.h>
10
11
#include <QLoggingCategory>
12
#include<QElapsedTimer>
13
#include <QtGui/qimageiohandler.h>
14
15
#include "qdebug.h"
16
17
#include <QtGui/private/qoutlinemapper_p.h>
18
19
#include <vector>
20
21
QT_BEGIN_NAMESPACE
22
23
using namespace Qt::StringLiterals;
24
25
#ifndef QT_NO_DEBUG
26
Q_STATIC_LOGGING_CATEGORY(lcSvgTiming, "qt.svg.timing")
27
#endif
28
29
#if !defined(QT_SVG_SIZE_LIMIT)
30
268k
#  define QT_SVG_SIZE_LIMIT QT_RASTER_COORD_LIMIT
31
#endif
32
33
QSvgNode::QSvgNode(QSvgNode *parent)
34
1.08M
    : m_parent(parent),
35
1.08M
      m_displayMode(BlockMode),
36
1.08M
      m_visible(true)
37
1.08M
{
38
1.08M
}
39
40
QSvgNode::~QSvgNode()
41
1.08M
{
42
43
1.08M
}
44
45
void QSvgNode::draw(QPainter *p, QSvgExtraStates &states)
46
93.1k
{
47
93.1k
#ifndef QT_NO_DEBUG
48
93.1k
    QElapsedTimer qtSvgTimer; qtSvgTimer.start();
49
93.1k
#endif
50
51
93.1k
    if (shouldDrawNode(p, states)) {
52
83.4k
        quint8 remainingDepth = states.trustedSource ? states.remainingNestedNodes
53
83.4k
                                                     : states.remainingNestedNodes - 1;
54
83.4k
        QScopedValueRollback<quint8> nestedNodesGuard(states.remainingNestedNodes, remainingDepth);
55
83.4k
        if (states.remainingNestedNodes == 0) {
56
0
            qCWarning(lcSvgDraw).noquote() << "Too many nested nodes at" << typeName()
57
0
                                 << "exceeding max nested limit of" << QtSvg::renderingMaxNestedNodes << "."
58
0
                                 << "Enable AssumeTrustedSource in QSvgHandler or set QT_SVG_DEFAULT_OPTIONS=2 to disable this check.";
59
0
            return;
60
0
        }
61
62
83.4k
        applyStyle(p, states);
63
83.4k
        applyAnimatedStyle(p, states);
64
83.4k
        QSvgNode *maskNode = this->hasMask() ? document()->namedNode(this->maskId()) : nullptr;
65
83.4k
        QSvgFilterContainer *filterNode = this->hasFilter() ? static_cast<QSvgFilterContainer*>(document()->namedNode(this->filterId()))
66
83.4k
                                                            : nullptr;
67
83.4k
        if (filterNode && filterNode->type() == QSvgNode::Filter && filterNode->supported()) {
68
0
            QTransform xf = p->transform();
69
0
            p->resetTransform();
70
0
            QRectF localRect = internalBounds(p, states);
71
0
            p->setTransform(xf);
72
0
            QRectF boundsRect = xf.mapRect(filterNode->filterRegion(localRect));
73
0
            QImage proxy = drawIntoBuffer(p, states, boundsRect.toRect());
74
0
            proxy = filterNode->applyFilter(proxy, p, localRect);
75
0
            if (maskNode && maskNode->type() == QSvgNode::Mask) {
76
0
                boundsRect = QRectF(proxy.offset(), proxy.size());
77
0
                localRect = p->transform().inverted().mapRect(boundsRect);
78
0
                QImage mask = static_cast<QSvgMask*>(maskNode)->createMask(p, states, localRect, &boundsRect);
79
0
                applyMaskToBuffer(&proxy, mask);
80
0
            }
81
0
            applyBufferToCanvas(p, proxy);
82
83
83.4k
        } else if (maskNode && maskNode->type() == QSvgNode::Mask) {
84
0
            QRectF boundsRect;
85
0
            QImage mask = static_cast<QSvgMask*>(maskNode)->createMask(p, states, this, &boundsRect);
86
0
            drawWithMask(p, states, mask, boundsRect.toRect());
87
83.4k
        } else if (!qFuzzyCompare(p->opacity(), qreal(1.0)) && requiresGroupRendering()) {
88
0
            QTransform xf = p->transform();
89
0
            p->resetTransform();
90
91
0
            QRectF localRect = decoratedInternalBounds(p, states);
92
            // adding safety border needed because of the antialiazing effects
93
0
            QRectF boundsRect = xf.mapRect(localRect);
94
0
            const int deltaX = boundsRect.width() * 0.1;
95
0
            const int deltaY = boundsRect.height() * 0.1;
96
0
            boundsRect = boundsRect.adjusted(-deltaX, -deltaY, deltaX, deltaY);
97
98
0
            p->setTransform(xf);
99
100
0
            QImage proxy = drawIntoBuffer(p, states, boundsRect.toAlignedRect());
101
0
            applyBufferToCanvas(p, proxy);
102
83.4k
        } else {
103
83.4k
            if (separateFillStroke(p, states))
104
40.9k
                fillThenStroke(p, states);
105
42.4k
            else
106
42.4k
                drawCommand(p, states);
107
108
83.4k
        }
109
83.4k
        revertAnimatedStyle(p ,states);
110
83.4k
        revertStyle(p, states);
111
83.4k
    }
112
113
93.1k
#ifndef QT_NO_DEBUG
114
93.1k
    if (Q_UNLIKELY(lcSvgTiming().isDebugEnabled()))
115
93.1k
        qCDebug(lcSvgTiming) << "Drawing" << typeName() << "took" << (qtSvgTimer.nsecsElapsed() / 1000000.0f) << "ms";
116
93.1k
#endif
117
93.1k
}
118
119
void QSvgNode::fillThenStroke(QPainter *p, QSvgExtraStates &states)
120
40.9k
{
121
40.9k
    qreal oldOpacity = p->opacity();
122
40.9k
    if (p->brush().style() != Qt::NoBrush) {
123
40.3k
        QPen oldPen = p->pen();
124
40.3k
        p->setPen(Qt::NoPen);
125
40.3k
        p->setOpacity(oldOpacity * states.fillOpacity);
126
127
40.3k
        drawCommand(p, states);
128
129
40.3k
        p->setPen(oldPen);
130
40.3k
    }
131
40.9k
    if (p->pen() != Qt::NoPen && p->pen().brush() != Qt::NoBrush && p->pen().widthF() != 0) {
132
33.6k
        QBrush oldBrush = p->brush();
133
33.6k
        p->setOpacity(oldOpacity * states.strokeOpacity);
134
33.6k
        p->setBrush(Qt::NoBrush);
135
136
33.6k
        drawCommand(p, states);
137
138
33.6k
        p->setBrush(oldBrush);
139
33.6k
    }
140
40.9k
    p->setOpacity(oldOpacity);
141
40.9k
}
142
143
void QSvgNode::drawWithMask(QPainter *p, QSvgExtraStates &states, const QImage &mask, const QRect &boundsRect)
144
0
{
145
0
    QImage proxy = drawIntoBuffer(p, states, boundsRect);
146
0
    if (proxy.isNull())
147
0
        return;
148
0
    applyMaskToBuffer(&proxy, mask);
149
150
0
    p->save();
151
0
    p->resetTransform();
152
0
    p->drawImage(boundsRect, proxy);
153
0
    p->restore();
154
0
}
155
156
QImage QSvgNode::drawIntoBuffer(QPainter *p, QSvgExtraStates &states, const QRect &boundsRect)
157
0
{
158
0
    QImage proxy;
159
0
    if (!QImageIOHandler::allocateImage(boundsRect.size(), QImage::Format_ARGB32_Premultiplied, &proxy)) {
160
0
        qCWarning(lcSvgDraw) << "The requested buffer size is too big, ignoring";
161
0
        return proxy;
162
0
    }
163
0
    proxy.setOffset(boundsRect.topLeft());
164
0
    proxy.fill(Qt::transparent);
165
0
    QPainter proxyPainter(&proxy);
166
0
    proxyPainter.setPen(p->pen());
167
0
    proxyPainter.setBrush(p->brush());
168
0
    proxyPainter.setFont(p->font());
169
0
    proxyPainter.translate(-boundsRect.topLeft());
170
0
    proxyPainter.setTransform(p->transform(), true);
171
0
    proxyPainter.setRenderHints(p->renderHints());
172
0
    if (separateFillStroke(p, states))
173
0
        fillThenStroke(&proxyPainter, states);
174
0
    else
175
0
        drawCommand(&proxyPainter, states);
176
0
    return proxy;
177
0
}
178
179
void QSvgNode::applyMaskToBuffer(QImage *proxy, const QImage &mask) const
180
0
{
181
0
    QPainter proxyPainter(proxy);
182
0
    proxyPainter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
183
0
    proxyPainter.resetTransform();
184
0
    proxyPainter.drawImage(QRect(0, 0, mask.width(), mask.height()), mask);
185
0
}
186
187
void QSvgNode::applyBufferToCanvas(QPainter *p, const QImage &proxy) const
188
0
{
189
0
    QTransform xf = p->transform();
190
0
    p->resetTransform();
191
0
    p->drawImage(QRect(proxy.offset(), proxy.size()), proxy);
192
0
    p->setTransform(xf);
193
0
}
194
195
bool QSvgNode::isDescendantOf(const QSvgNode *parent) const
196
425k
{
197
425k
    const QSvgNode *n = this;
198
16.3M
    while (n) {
199
15.9M
        if (n == parent)
200
642
            return true;
201
15.9M
        n = n->m_parent;
202
15.9M
    }
203
424k
    return false;
204
425k
}
205
206
void QSvgNode::appendStyleProperty(QSvgStylePropertyPtr prop)
207
332k
{
208
332k
    m_style.appendProperty(std::move(prop));
209
332k
}
210
211
void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) const
212
1.74M
{
213
1.74M
    m_style.apply(p, this, states);
214
1.74M
}
215
216
/*!
217
    \internal
218
219
    Apply the styles of all parents to the painter and the states.
220
    The styles are applied from the top level node to the current node.
221
    This function can be used to set the correct style for a node
222
    if it's draw function is triggered out of the ordinary draw context,
223
    for example the mask node, that is cross-referenced.
224
*/
225
void QSvgNode::applyStyleRecursive(QPainter *p, QSvgExtraStates &states) const
226
0
{
227
0
    std::vector<const QSvgNode *> parents;
228
229
0
    const QSvgNode *current = this;
230
0
    do {
231
0
        parents.push_back(current);
232
0
        current = current->parent();
233
0
    } while (current);
234
235
0
    for (auto i = parents.crbegin(); i != parents.crend(); ++i)
236
0
        (*i)->applyStyle(p, states);
237
0
}
238
239
void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) const
240
1.74M
{
241
1.74M
    m_style.revert(p, states);
242
1.74M
}
243
244
void QSvgNode::revertStyleRecursive(QPainter *p, QSvgExtraStates &states) const
245
0
{
246
0
    const QSvgNode *current = this;
247
0
    do {
248
0
        current->revertStyle(p, states);
249
0
        current = current->parent();
250
0
    } while (current);
251
0
}
252
253
void QSvgNode::applyAnimatedStyle(QPainter *p, QSvgExtraStates &states) const
254
83.4k
{
255
83.4k
    if (document()->animated())
256
0
        m_animatedStyle.apply(p, this, states);
257
83.4k
}
258
259
void QSvgNode::revertAnimatedStyle(QPainter *p, QSvgExtraStates &states) const
260
83.4k
{
261
83.4k
    if (document()->animated())
262
0
        m_animatedStyle.revert(p, states);
263
83.4k
}
264
265
QSvgStyleProperty *QSvgNode::styleProperty(QSvgStyleProperty::Type type) const
266
312k
{
267
312k
    const QSvgNode *node = this;
268
531k
    while (node) {
269
439k
        if (QSvgStyleProperty *prop = node->m_style.property(type))
270
220k
            return prop;
271
272
219k
        node = node->parent();
273
219k
    }
274
275
91.5k
    return nullptr;
276
312k
}
277
278
QRectF QSvgNode::internalFastBounds(QPainter *p, QSvgExtraStates &states) const
279
0
{
280
0
    return internalBounds(p, states);
281
0
}
282
283
QRectF QSvgNode::internalBounds(QPainter *, QSvgExtraStates &) const
284
0
{
285
0
    return QRectF(0, 0, 0, 0);
286
0
}
287
288
QRectF QSvgNode::bounds() const
289
28.0k
{
290
28.0k
    if (!m_cachedBounds.isEmpty())
291
0
        return m_cachedBounds;
292
293
28.0k
    QImage dummy(1, 1, QImage::Format_RGB32);
294
28.0k
    QPainter p(&dummy);
295
28.0k
    initPainter(&p);
296
28.0k
    QSvgExtraStates states;
297
298
28.0k
    if (parent())
299
0
        parent()->applyStyleRecursive(&p, states);
300
28.0k
    p.setWorldTransform(QTransform());
301
28.0k
    m_cachedBounds = bounds(&p, states);
302
28.0k
    if (parent()) // always revert the style to not store old transformations
303
0
        parent()->revertStyleRecursive(&p, states);
304
28.0k
    return m_cachedBounds;
305
28.0k
}
306
307
QSvgDocument * QSvgNode::document() const
308
369k
{
309
369k
    QSvgDocument *doc = nullptr;
310
369k
    QSvgNode *node = const_cast<QSvgNode*>(this);
311
16.3M
    while (node && node->type() != QSvgNode::Doc) {
312
15.9M
        node = node->parent();
313
15.9M
    }
314
369k
    doc = static_cast<QSvgDocument*>(node);
315
316
369k
    return doc;
317
369k
}
318
319
QLatin1StringView QSvgNode::typeName() const
320
45.2M
{
321
45.2M
    switch (type()) {
322
79.7k
    case Doc: return "svg"_L1;
323
32.2M
    case Group: return "g"_L1;
324
11.6M
    case Defs: return "defs"_L1;
325
456k
    case Switch: return "switch"_L1;
326
0
    case AnimateColor: return "animateColor"_L1;
327
0
    case AnimateTransform: return "animateTransform"_L1;
328
0
    case Circle: return "circle"_L1;
329
0
    case Ellipse: return "ellipse"_L1;
330
0
    case Image: return "image"_L1;
331
40
    case Line: return "line"_L1;
332
6.76k
    case Path: return "path"_L1;
333
0
    case Polygon: return "polygon"_L1;
334
0
    case Polyline: return "polyline"_L1;
335
0
    case Rect: return "rect"_L1;
336
64
    case Text: return "text"_L1;
337
0
    case Textarea: return "textarea"_L1;
338
0
    case Tspan: return "tspan"_L1;
339
747k
    case Use: return "use"_L1;
340
0
    case Video: return "video"_L1;
341
2.34k
    case Mask: return "mask"_L1;
342
0
    case Symbol: return "symbol"_L1;
343
0
    case Marker: return "marker"_L1;
344
0
    case Pattern: return "pattern"_L1;
345
0
    case Filter: return "filter"_L1;
346
0
    case FeMerge: return "feMerge"_L1;
347
0
    case FeMergenode: return "feMergeNode"_L1;
348
0
    case FeColormatrix: return "feColorMatrix"_L1;
349
0
    case FeGaussianblur: return "feGaussianBlur"_L1;
350
0
    case FeOffset: return "feOffset"_L1;
351
0
    case FeComposite: return "feComposite"_L1;
352
0
    case FeFlood: return "feFlood"_L1;
353
0
    case FeBlend: return "feBlend"_L1;
354
0
    case FeUnsupported: return "feUnsupported"_L1;
355
45.2M
    }
356
0
    return "unknown"_L1;
357
45.2M
}
358
359
void QSvgNode::setRequiredFeatures(const QStringList &lst)
360
1.07M
{
361
1.07M
    m_requiredFeatures = lst;
362
1.07M
}
363
364
const QStringList & QSvgNode::requiredFeatures() const
365
0
{
366
0
    return m_requiredFeatures;
367
0
}
368
369
void QSvgNode::setRequiredExtensions(const QStringList &lst)
370
1.07M
{
371
1.07M
    m_requiredExtensions = lst;
372
1.07M
}
373
374
const QStringList & QSvgNode::requiredExtensions() const
375
0
{
376
0
    return m_requiredExtensions;
377
0
}
378
379
void QSvgNode::setRequiredLanguages(const QStringList &lst)
380
1.07M
{
381
1.07M
    m_requiredLanguages = lst;
382
1.07M
}
383
384
const QStringList & QSvgNode::requiredLanguages() const
385
0
{
386
0
    return m_requiredLanguages;
387
0
}
388
389
void QSvgNode::setRequiredFormats(const QStringList &lst)
390
1.07M
{
391
1.07M
    m_requiredFormats = lst;
392
1.07M
}
393
394
const QStringList & QSvgNode::requiredFormats() const
395
0
{
396
0
    return m_requiredFormats;
397
0
}
398
399
void QSvgNode::setRequiredFonts(const QStringList &lst)
400
1.07M
{
401
1.07M
    m_requiredFonts = lst;
402
1.07M
}
403
404
const QStringList & QSvgNode::requiredFonts() const
405
0
{
406
0
    return m_requiredFonts;
407
0
}
408
409
void QSvgNode::setVisible(bool visible)
410
1.07M
{
411
    //propagate visibility change of true to the parent
412
    //not propagating false is just a small performance
413
    //degradation since we'll iterate over children without
414
    //drawing any of them
415
1.07M
    if (m_parent && visible && !m_parent->isVisible())
416
0
        m_parent->setVisible(true);
417
418
1.07M
    m_visible = visible;
419
1.07M
}
420
421
QRectF QSvgNode::bounds(QPainter *p, QSvgExtraStates &states) const
422
1.64M
{
423
1.64M
    applyStyle(p, states);
424
1.64M
    QRectF rect = internalBounds(p, states);
425
1.64M
    revertStyle(p, states);
426
1.64M
    return rect;
427
1.64M
}
428
429
QRectF QSvgNode::decoratedInternalBounds(QPainter *p, QSvgExtraStates &states) const
430
0
{
431
0
    return filterRegion(internalBounds(p, states));
432
0
}
433
434
QRectF QSvgNode::decoratedBounds(QPainter *p, QSvgExtraStates &states) const
435
0
{
436
0
    applyStyle(p, states);
437
0
    QRectF rect = decoratedInternalBounds(p, states);
438
0
    revertStyle(p, states);
439
0
    return rect;
440
0
}
441
442
void QSvgNode::setNodeId(const QString &i)
443
1.07M
{
444
1.07M
    m_id = i;
445
1.07M
}
446
447
void QSvgNode::setXmlClass(const QString &str)
448
1.07M
{
449
1.07M
    m_class = str;
450
1.07M
}
451
452
QString QSvgNode::maskId() const
453
0
{
454
0
    return m_maskId;
455
0
}
456
457
void QSvgNode::setMaskId(const QString &str)
458
0
{
459
0
    m_maskId = str;
460
0
}
461
462
bool QSvgNode::hasMask() const
463
83.4k
{
464
83.4k
    return !m_maskId.isEmpty();
465
83.4k
}
466
467
QString QSvgNode::filterId() const
468
0
{
469
0
    return m_filterId;
470
0
}
471
472
void QSvgNode::setFilterId(const QString &str)
473
0
{
474
0
    m_filterId = str;
475
0
}
476
477
bool QSvgNode::hasFilter() const
478
83.4k
{
479
83.4k
    return !m_filterId.isEmpty();
480
83.4k
}
481
482
QString QSvgNode::markerStartId() const
483
0
{
484
0
    return m_markerStartId;
485
0
}
486
487
void QSvgNode::setMarkerStartId(const QString &str)
488
0
{
489
0
    m_markerStartId = str;
490
0
}
491
492
bool QSvgNode::hasMarkerStart() const
493
107k
{
494
107k
    return !m_markerStartId.isEmpty();
495
107k
}
496
497
QString QSvgNode::markerMidId() const
498
0
{
499
0
    return m_markerMidId;
500
0
}
501
502
void QSvgNode::setMarkerMidId(const QString &str)
503
0
{
504
0
    m_markerMidId = str;
505
0
}
506
507
bool QSvgNode::hasMarkerMid() const
508
107k
{
509
107k
    return !m_markerMidId.isEmpty();
510
107k
}
511
512
QString QSvgNode::markerEndId() const
513
0
{
514
0
    return m_markerEndId;
515
0
}
516
517
void QSvgNode::setMarkerEndId(const QString &str)
518
0
{
519
0
    m_markerEndId = str;
520
0
}
521
522
bool QSvgNode::hasMarkerEnd() const
523
107k
{
524
107k
    return !m_markerEndId.isEmpty();
525
107k
}
526
527
bool QSvgNode::hasAnyMarker() const
528
107k
{
529
107k
    return hasMarkerStart() || hasMarkerMid() || hasMarkerEnd();
530
107k
}
531
532
bool QSvgNode::requiresGroupRendering() const
533
0
{
534
0
    return false;
535
0
}
536
537
void QSvgNode::setDisplayMode(DisplayMode mode)
538
7.31k
{
539
7.31k
    m_displayMode = mode;
540
7.31k
}
541
542
QSvgNode::DisplayMode QSvgNode::displayMode() const
543
100k
{
544
100k
    return m_displayMode;
545
100k
}
546
547
qreal QSvgNode::strokeWidth(QPainter *p)
548
54.5k
{
549
54.5k
    const QPen &pen = p->pen();
550
54.5k
    if (pen.style() == Qt::NoPen || pen.brush().style() == Qt::NoBrush || pen.isCosmetic())
551
26.3k
        return 0;
552
28.1k
    return pen.widthF();
553
54.5k
}
554
555
void QSvgNode::initPainter(QPainter *p)
556
35.7k
{
557
35.7k
    QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::SvgMiterJoin);
558
35.7k
    pen.setMiterLimit(4);
559
35.7k
    p->setPen(pen);
560
35.7k
    p->setBrush(Qt::black);
561
35.7k
    p->setRenderHint(QPainter::Antialiasing);
562
35.7k
    p->setRenderHint(QPainter::SmoothPixmapTransform);
563
35.7k
    QFont font(p->font());
564
35.7k
    if (font.pointSize() < 0 && font.pixelSize() > 0) {
565
0
        font.setPointSizeF(font.pixelSize() * 72.0 / p->device()->logicalDpiY());
566
0
        p->setFont(font);
567
0
    }
568
35.7k
}
569
570
QRectF QSvgNode::boundsOnStroke(QPainter *p, const QPainterPath &path,
571
                                qreal width, BoundsMode mode)
572
28.1k
{
573
28.1k
    QPainterPathStroker stroker;
574
28.1k
    stroker.setWidth(width);
575
28.1k
    if (mode == BoundsMode::IncludeMiterLimit) {
576
0
        stroker.setJoinStyle(p->pen().joinStyle());
577
0
        stroker.setMiterLimit(p->pen().miterLimit());
578
0
    }
579
28.1k
    QPainterPath stroke = stroker.createStroke(path);
580
28.1k
    return p->transform().map(stroke).boundingRect();
581
28.1k
}
582
583
bool QSvgNode::shouldDrawNode(QPainter *p, QSvgExtraStates &states) const
584
91.7k
{
585
91.7k
    if (m_displayMode == DisplayMode::NoneMode)
586
0
        return false;
587
588
91.7k
    if (document() && states.trustedSource)
589
0
        return true;
590
591
91.7k
    QRectF brect = internalFastBounds(p, states);
592
91.7k
    if (brect.width() <= QT_SVG_SIZE_LIMIT && brect.height() <= QT_SVG_SIZE_LIMIT) {
593
83.1k
        return true;
594
83.1k
    } else {
595
8.57k
        qCWarning(lcSvgDraw) << "Shape of type" << type() << "ignored because it will take too long to rasterize (bounding rect=" << brect << ")."
596
8.57k
                             << "Enable AssumeTrustedSource in QSvgHandler or set QT_SVG_DEFAULT_OPTIONS=2 to disable this check.";
597
8.57k
        return false;
598
8.57k
    }
599
91.7k
}
600
601
QRectF QSvgNode::filterRegion(QRectF bounds) const
602
0
{
603
0
    QSvgFilterContainer *filterNode = hasFilter()
604
0
            ? static_cast<QSvgFilterContainer*>(document()->namedNode(filterId()))
605
0
            : nullptr;
606
607
0
    if (filterNode && filterNode->type() == QSvgNode::Filter && filterNode->supported())
608
0
        return filterNode->filterRegion(bounds);
609
610
0
    return bounds;
611
0
}
612
613
QT_END_NAMESPACE