1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt SVG module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qsvgstructure_p.h"
41
42#include "qsvgnode_p.h"
43#include "qsvgstyle_p.h"
44#include "qsvgtinydocument_p.h"
45
46#include "qpainter.h"
47#include "qlocale.h"
48#include "qdebug.h"
49
50#include <qscopedvaluerollback.h>
51
52QT_BEGIN_NAMESPACE
53
54QSvgG::QSvgG(QSvgNode *parent)
55 : QSvgStructureNode(parent)
56{
57
58}
59
60QSvgStructureNode::~QSvgStructureNode()
61{
62 qDeleteAll(c: m_renderers);
63}
64
65void QSvgG::draw(QPainter *p, QSvgExtraStates &states)
66{
67 QList<QSvgNode*>::iterator itr = m_renderers.begin();
68 applyStyle(p, states);
69
70 while (itr != m_renderers.end()) {
71 QSvgNode *node = *itr;
72 if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode))
73 node->draw(p, states);
74 ++itr;
75 }
76 revertStyle(p, states);
77}
78
79QSvgNode::Type QSvgG::type() const
80{
81 return G;
82}
83
84QSvgStructureNode::QSvgStructureNode(QSvgNode *parent)
85 :QSvgNode(parent)
86{
87
88}
89
90QSvgNode * QSvgStructureNode::scopeNode(const QString &id) const
91{
92 QSvgTinyDocument *doc = document();
93 return doc ? doc->namedNode(id) : 0;
94}
95
96void QSvgStructureNode::addChild(QSvgNode *child, const QString &id)
97{
98 m_renderers.append(t: child);
99
100 if (id.isEmpty())
101 return; //we can't add it to scope without id
102
103 QSvgTinyDocument *doc = document();
104 if (doc)
105 doc->addNamedNode(id, node: child);
106}
107
108QSvgDefs::QSvgDefs(QSvgNode *parent)
109 : QSvgStructureNode(parent)
110{
111}
112
113void QSvgDefs::draw(QPainter *, QSvgExtraStates &)
114{
115 //noop
116}
117
118QSvgNode::Type QSvgDefs::type() const
119{
120 return DEFS;
121}
122
123/*
124 Below is a lookup function based on the gperf output using the following set:
125
126 http://www.w3.org/Graphics/SVG/feature/1.2/#SVG
127 http://www.w3.org/Graphics/SVG/feature/1.2/#SVG-static
128 http://www.w3.org/Graphics/SVG/feature/1.2/#CoreAttribute
129 http://www.w3.org/Graphics/SVG/feature/1.2/#Structure
130 http://www.w3.org/Graphics/SVG/feature/1.2/#ConditionalProcessing
131 http://www.w3.org/Graphics/SVG/feature/1.2/#ConditionalProcessingAttribute
132 http://www.w3.org/Graphics/SVG/feature/1.2/#Image
133 http://www.w3.org/Graphics/SVG/feature/1.2/#Prefetch
134 http://www.w3.org/Graphics/SVG/feature/1.2/#Shape
135 http://www.w3.org/Graphics/SVG/feature/1.2/#Text
136 http://www.w3.org/Graphics/SVG/feature/1.2/#PaintAttribute
137 http://www.w3.org/Graphics/SVG/feature/1.2/#OpacityAttribute
138 http://www.w3.org/Graphics/SVG/feature/1.2/#GraphicsAttribute
139 http://www.w3.org/Graphics/SVG/feature/1.2/#Gradient
140 http://www.w3.org/Graphics/SVG/feature/1.2/#SolidColor
141 http://www.w3.org/Graphics/SVG/feature/1.2/#XlinkAttribute
142 http://www.w3.org/Graphics/SVG/feature/1.2/#ExternalResourcesRequiredAttribute
143 http://www.w3.org/Graphics/SVG/feature/1.2/#Font
144 http://www.w3.org/Graphics/SVG/feature/1.2/#Hyperlinking
145 http://www.w3.org/Graphics/SVG/feature/1.2/#Extensibility
146*/
147
148// ----- begin of generated code -----
149
150/* C code produced by gperf version 3.0.2 */
151/* Command-line: gperf -c -L c svg */
152/* Computed positions: -k'45-46' */
153
154#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
155 && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
156 && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
157 && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
158 && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
159 && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
160 && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
161 && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
162 && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
163 && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
164 && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
165 && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
166 && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
167 && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
168 && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
169 && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
170 && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
171 && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
172 && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
173 && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
174 && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
175 && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
176 && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
177/* The character set is not based on ISO-646. */
178#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
179#endif
180
181enum {
182 TOTAL_KEYWORDS = 20,
183 MIN_WORD_LENGTH = 47,
184 MAX_WORD_LENGTH = 78,
185 MIN_HASH_VALUE = 48,
186 MAX_HASH_VALUE = 88
187};
188/* maximum key range = 41, duplicates = 0 */
189
190inline static bool isSupportedSvgFeature(const QString &str)
191{
192 static const unsigned char asso_values[] = {
193 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
194 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
195 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
196 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
197 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
198 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
199 89, 89, 89, 89, 89, 89, 89, 0, 89, 5,
200 15, 5, 0, 10, 89, 89, 89, 89, 89, 0,
201 15, 89, 89, 0, 0, 89, 5, 89, 0, 89,
202 89, 89, 89, 89, 89, 89, 89, 0, 89, 89,
203 89, 0, 89, 89, 0, 89, 89, 89, 0, 5,
204 89, 0, 0, 89, 5, 89, 0, 89, 89, 89,
205 5, 0, 89, 89, 89, 89, 89, 89, 89, 89,
206 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
207 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
208 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
209 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
210 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
211 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
212 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
213 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
214 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
215 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
216 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
217 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
218 89, 89, 89, 89, 89, 89
219 };
220
221 static const char * wordlist[] = {
222 "", "", "", "", "", "", "", "", "",
223 "", "", "", "", "", "", "", "", "",
224 "", "", "", "", "", "", "", "", "",
225 "", "", "", "", "", "", "", "", "",
226 "", "", "", "", "", "", "", "", "",
227 "", "", "",
228 "http://www.w3.org/Graphics/SVG/feature/1.2/#Text",
229 "http://www.w3.org/Graphics/SVG/feature/1.2/#Shape",
230 "", "",
231 "http://www.w3.org/Graphics/SVG/feature/1.2/#SVG",
232 "http://www.w3.org/Graphics/SVG/feature/1.2/#Structure",
233 "http://www.w3.org/Graphics/SVG/feature/1.2/#SolidColor",
234 "",
235 "http://www.w3.org/Graphics/SVG/feature/1.2/#Hyperlinking",
236 "http://www.w3.org/Graphics/SVG/feature/1.2/#CoreAttribute",
237 "http://www.w3.org/Graphics/SVG/feature/1.2/#XlinkAttribute",
238 "http://www.w3.org/Graphics/SVG/feature/1.2/#SVG-static",
239 "http://www.w3.org/Graphics/SVG/feature/1.2/#OpacityAttribute",
240 "",
241 "http://www.w3.org/Graphics/SVG/feature/1.2/#Gradient",
242 "http://www.w3.org/Graphics/SVG/feature/1.2/#Font",
243 "http://www.w3.org/Graphics/SVG/feature/1.2/#Image",
244 "http://www.w3.org/Graphics/SVG/feature/1.2/#ConditionalProcessing",
245 "",
246 "http://www.w3.org/Graphics/SVG/feature/1.2/#Extensibility",
247 "", "", "",
248 "http://www.w3.org/Graphics/SVG/feature/1.2/#GraphicsAttribute",
249 "http://www.w3.org/Graphics/SVG/feature/1.2/#Prefetch",
250 "http://www.w3.org/Graphics/SVG/feature/1.2/#PaintAttribute",
251 "http://www.w3.org/Graphics/SVG/feature/1.2/#ConditionalProcessingAttribute",
252 "", "", "", "", "", "", "", "", "",
253 "", "", "", "",
254 "http://www.w3.org/Graphics/SVG/feature/1.2/#ExternalResourcesRequiredAttribute"
255 };
256
257 if (str.length() <= MAX_WORD_LENGTH && str.length() >= MIN_WORD_LENGTH) {
258 const int key = str.length()
259 + asso_values[str.at(i: 45).unicode()]
260 + asso_values[str.at(i: 44).unicode()];
261 if (key <= MAX_HASH_VALUE && key >= 0)
262 return str == QLatin1String(wordlist[key]);
263 }
264 return false;
265}
266
267// ----- end of generated code -----
268
269static inline bool isSupportedSvgExtension(const QString &)
270{
271 return false;
272}
273
274
275QSvgSwitch::QSvgSwitch(QSvgNode *parent)
276 : QSvgStructureNode(parent)
277{
278 init();
279}
280
281void QSvgSwitch::draw(QPainter *p, QSvgExtraStates &states)
282{
283 QList<QSvgNode*>::iterator itr = m_renderers.begin();
284 applyStyle(p, states);
285
286 while (itr != m_renderers.end()) {
287 QSvgNode *node = *itr;
288 if (node->isVisible() && (node->displayMode() != QSvgNode::NoneMode)) {
289 const QStringList &features = node->requiredFeatures();
290 const QStringList &extensions = node->requiredExtensions();
291 const QStringList &languages = node->requiredLanguages();
292 const QStringList &formats = node->requiredFormats();
293 const QStringList &fonts = node->requiredFonts();
294
295 bool okToRender = true;
296 if (!features.isEmpty()) {
297 QStringList::const_iterator sitr = features.constBegin();
298 for (; sitr != features.constEnd(); ++sitr) {
299 if (!isSupportedSvgFeature(str: *sitr)) {
300 okToRender = false;
301 break;
302 }
303 }
304 }
305
306 if (okToRender && !extensions.isEmpty()) {
307 QStringList::const_iterator sitr = extensions.constBegin();
308 for (; sitr != extensions.constEnd(); ++sitr) {
309 if (!isSupportedSvgExtension(*sitr)) {
310 okToRender = false;
311 break;
312 }
313 }
314 }
315
316 if (okToRender && !languages.isEmpty()) {
317 QStringList::const_iterator sitr = languages.constBegin();
318 okToRender = false;
319 for (; sitr != languages.constEnd(); ++sitr) {
320 if ((*sitr).startsWith(s: m_systemLanguagePrefix)) {
321 okToRender = true;
322 break;
323 }
324 }
325 }
326
327 if (okToRender && !formats.isEmpty()) {
328 okToRender = false;
329 }
330
331 if (okToRender && !fonts.isEmpty()) {
332 okToRender = false;
333 }
334
335 if (okToRender) {
336 node->draw(p, states);
337 break;
338 }
339 }
340 ++itr;
341 }
342 revertStyle(p, states);
343}
344
345QSvgNode::Type QSvgSwitch::type() const
346{
347 return SWITCH;
348}
349
350void QSvgSwitch::init()
351{
352 QLocale locale;
353 m_systemLanguage = locale.name().replace(before: QLatin1Char('_'), after: QLatin1Char('-'));
354 int idx = m_systemLanguage.indexOf(c: QLatin1Char('-'));
355 m_systemLanguagePrefix = m_systemLanguage.mid(position: 0, n: idx);
356}
357
358QRectF QSvgStructureNode::bounds(QPainter *p, QSvgExtraStates &states) const
359{
360 QRectF bounds;
361 if (!m_recursing) {
362 QScopedValueRollback<bool> guard(m_recursing, true);
363 for (QSvgNode *node : qAsConst(t: m_renderers))
364 bounds |= node->transformedBounds(p, states);
365 }
366 return bounds;
367}
368
369QSvgNode * QSvgStructureNode::previousSiblingNode(QSvgNode *n) const
370{
371 QSvgNode *prev = 0;
372 QList<QSvgNode*>::const_iterator itr = m_renderers.constBegin();
373 for (; itr != m_renderers.constEnd(); ++itr) {
374 QSvgNode *node = *itr;
375 if (node == n)
376 return prev;
377 prev = node;
378 }
379 return prev;
380}
381
382QT_END_NAMESPACE
383

source code of qtsvg/src/svg/qsvgstructure.cpp