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
qsvgvisitor.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 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
7#include <QStack>
8#include <utility>
9
10QT_BEGIN_NAMESPACE
11
12namespace {
13
14bool isStructure(const QSvgNode *node)
15{
16 switch (node->type()) {
17 case QSvgNode::Switch:
18 case QSvgNode::Doc:
19 case QSvgNode::Defs:
20 case QSvgNode::Group:
21 case QSvgNode::Mask:
22 case QSvgNode::Symbol:
23 case QSvgNode::Filter:
24 case QSvgNode::FeMerge:
25 case QSvgNode::FeMergenode:
26 case QSvgNode::FeColormatrix:
27 case QSvgNode::FeGaussianblur:
28 case QSvgNode::FeOffset:
29 case QSvgNode::FeComposite:
30 case QSvgNode::FeFlood:
31 case QSvgNode::FeBlend:
32 case QSvgNode::FeUnsupported:
33 case QSvgNode::Marker:
34 case QSvgNode::Pattern:
35 return true;
36 case QSvgNode::AnimateColor:
37 case QSvgNode::AnimateTransform:
38 case QSvgNode::Circle:
39 case QSvgNode::Ellipse:
40 case QSvgNode::Image:
41 case QSvgNode::Line:
42 case QSvgNode::Path:
43 case QSvgNode::Polygon:
44 case QSvgNode::Polyline:
45 case QSvgNode::Rect:
46 case QSvgNode::Text:
47 case QSvgNode::Textarea:
48 case QSvgNode::Tspan:
49 case QSvgNode::Use:
50 case QSvgNode::Video:
51 case QSvgNode::Font:
52 return false;
53 }
54
55 Q_UNREACHABLE_RETURN(false);
56}
57
58} // namespace
59
60QSvgVisitor::~QSvgVisitor()
61 = default;
62
63void QSvgVisitor::traverse(const QSvgNode *node)
64{
65 // A pair that keeps track of a node and a visited flag.
66 using NodeState = std::pair<const QSvgNode *, bool>;
67 QStack<NodeState> nodes;
68 nodes.push({node, false});
69
70 do {
71 NodeState state = nodes.pop();
72 const QSvgNode *current = state.first;
73 const bool visited = state.second;
74 if (isStructure(current)) {
75 const QSvgStructureNode *structure = static_cast<const QSvgStructureNode *>(current);
76 if (!visited) {
77 if (!traverseStructureNodeStart(structure))
78 continue;
79 nodes.push({structure, true});
80 for (auto it = structure->renderers().crbegin(); it != structure->renderers().crend(); it++)
81 nodes.push({it->get(), false});
82 } else {
83 traverseStructureNodeEnd(structure);
84 }
85 } else {
86 traverseLeafNode(current);
87 }
88
89 } while (!nodes.isEmpty());
90}
91
92bool QSvgVisitor::traverseStructureNodeStart(const QSvgStructureNode *node)
93{
94 switch (node->type()) {
95 case QSvgNode::Switch:
96 return visitSwitchNodeStart(static_cast<const QSvgSwitch *>(node));
97 case QSvgNode::Doc:
98 return visitDocumentNodeStart(static_cast<const QSvgDocument *>(node));
99 case QSvgNode::Defs:
100 return visitDefsNodeStart(static_cast<const QSvgDefs *>(node));
101 case QSvgNode::Group:
102 return visitGroupNodeStart(static_cast<const QSvgG *>(node));
103 case QSvgNode::Mask:
104 return visitMaskNodeStart(static_cast<const QSvgMask *>(node));
105 case QSvgNode::Symbol:
106 return visitSymbolNodeStart(static_cast<const QSvgSymbol *>(node));
107 case QSvgNode::Filter:
108 return visitFilterNodeStart(static_cast<const QSvgFilterContainer *>(node));
109 case QSvgNode::Marker:
110 return visitMarkerNodeStart(static_cast<const QSvgMarker *>(node));
111 case QSvgNode::Pattern:
112 return visitPatternNodeStart(static_cast<const QSvgPattern *>(node));
113 case QSvgNode::FeMerge:
114 case QSvgNode::FeMergenode:
115 case QSvgNode::FeColormatrix:
116 case QSvgNode::FeGaussianblur:
117 case QSvgNode::FeOffset:
118 case QSvgNode::FeComposite:
119 case QSvgNode::FeFlood:
120 case QSvgNode::FeBlend:
121 return visitFeFilterPrimitiveNodeStart(static_cast<const QSvgFeFilterPrimitive *>(node));
122 // Enum values that are either not supported or should not be visited:
123 case QSvgNode::FeUnsupported:
124 qDebug() << "Unhandled type in switch" << node->type();
125 break;
126 default:
127 Q_UNREACHABLE();
128 break;
129 }
130
131 return true;
132}
133
134void QSvgVisitor::traverseStructureNodeEnd(const QSvgStructureNode *node)
135{
136 switch (node->type()) {
137 case QSvgNode::Switch:
138 visitSwitchNodeEnd(static_cast<const QSvgSwitch *>(node));
139 break;
140 case QSvgNode::Doc:
141 visitDocumentNodeEnd(static_cast<const QSvgDocument *>(node));
142 break;
143 case QSvgNode::Defs:
144 visitDefsNodeEnd(static_cast<const QSvgDefs *>(node));
145 break;
146 case QSvgNode::Group:
147 visitGroupNodeEnd(static_cast<const QSvgG *>(node));
148 break;
149 case QSvgNode::Mask:
150 visitMaskNodeEnd(static_cast<const QSvgMask *>(node));
151 break;
152 case QSvgNode::Symbol:
153 visitSymbolNodeEnd(static_cast<const QSvgSymbol *>(node));
154 break;
155 case QSvgNode::Filter:
156 visitFilterNodeEnd(static_cast<const QSvgFilterContainer *>(node));
157 break;
158 case QSvgNode::Marker:
159 visitMarkerNodeEnd(static_cast<const QSvgMarker *>(node));
160 break;
161 case QSvgNode::Pattern:
162 visitPatternNodeEnd(static_cast<const QSvgPattern *>(node));
163 break;
164 case QSvgNode::FeMerge:
165 case QSvgNode::FeMergenode:
166 case QSvgNode::FeColormatrix:
167 case QSvgNode::FeGaussianblur:
168 case QSvgNode::FeOffset:
169 case QSvgNode::FeComposite:
170 case QSvgNode::FeFlood:
171 case QSvgNode::FeBlend:
172 visitFeFilterPrimitiveNodeEnd(static_cast<const QSvgFeFilterPrimitive *>(node));
173 break;
174 // Enum values that are either not supported or should not be visited:
175 case QSvgNode::FeUnsupported:
176 qDebug() << "Unhandled type in switch" << node->type();
177 break;
178 default:
179 Q_UNREACHABLE();
180 break;
181 }
182}
183
184void QSvgVisitor::traverseLeafNode(const QSvgNode *node)
185{
186 switch (node->type()) {
187 case QSvgNode::AnimateColor:
188 case QSvgNode::AnimateTransform:
189 visitAnimateNode(static_cast<const QSvgAnimateNode *>(node));
190 break;
191 case QSvgNode::Circle:
192 case QSvgNode::Ellipse:
193 visitEllipseNode(static_cast<const QSvgEllipse *>(node));
194 break;
195 case QSvgNode::Image:
196 visitImageNode(static_cast<const QSvgImage *>(node));
197 break;
198 case QSvgNode::Line:
199 visitLineNode(static_cast<const QSvgLine *>(node));
200 break;
201 case QSvgNode::Path:
202 visitPathNode(static_cast<const QSvgPath *>(node));
203 break;
204 case QSvgNode::Polygon:
205 visitPolygonNode(static_cast<const QSvgPolygon *>(node));
206 break;
207 case QSvgNode::Polyline:
208 visitPolylineNode(static_cast<const QSvgPolyline *>(node));
209 break;
210 case QSvgNode::Rect:
211 visitRectNode(static_cast<const QSvgRect *>(node));
212 break;
213 case QSvgNode::Text:
214 case QSvgNode::Textarea:
215 visitTextNode(static_cast<const QSvgText *>(node));
216 break;
217 case QSvgNode::Tspan:
218 visitTspanNode(static_cast<const QSvgTspan *>(node));
219 break;
220 case QSvgNode::Use:
221 visitUseNode(static_cast<const QSvgUse *>(node));
222 break;
223 case QSvgNode::Video:
224 visitVideoNode(static_cast<const QSvgVideo *>(node));
225 break;
226 // Enum values that are either not supported or should not be visited:
227 case QSvgNode::Font:
228 qDebug() << "Unhandled type in switch" << node->type();
229 break;
230 default:
231 Q_UNREACHABLE();
232 break;
233 }
234}
235
236QT_END_NAMESPACE
bool isStructure(const QSvgNode *node)