/src/qtsvg/src/svg/qsvggraphics_p.h
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 | | |
4 | | #ifndef QSVGGRAPHICS_P_H |
5 | | #define QSVGGRAPHICS_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 "qsvgnode_p.h" |
19 | | |
20 | | #include "QtGui/qpainterpath.h" |
21 | | #include "QtGui/qimage.h" |
22 | | #include "QtGui/qtextlayout.h" |
23 | | #include "QtCore/qloggingcategory.h" |
24 | | |
25 | | #include <optional> |
26 | | |
27 | | QT_BEGIN_NAMESPACE |
28 | | |
29 | | Q_DECLARE_LOGGING_CATEGORY(lcSvgDraw); |
30 | | |
31 | | class QSvgGlyph; |
32 | | class QTextCharFormat; |
33 | | |
34 | | class Q_SVG_EXPORT QSvgDummyNode : public QSvgNode |
35 | | { |
36 | | public: |
37 | | void drawCommand(QPainter *, QSvgExtraStates &) override; |
38 | | Type type() const override; |
39 | | }; |
40 | | |
41 | | class Q_SVG_EXPORT QSvgEllipse : public QSvgNode |
42 | | { |
43 | | public: |
44 | | QSvgEllipse(QSvgNode *parent, const QRectF &rect); |
45 | | bool separateFillStroke(const QSvgExtraStates &) const override; |
46 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
47 | | Type type() const override; |
48 | | QRectF internalFastBounds(QPainter *p, QSvgExtraStates &states) const override; |
49 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
50 | | QRectF decoratedInternalBounds(QPainter *p, QSvgExtraStates &states) const override; |
51 | 0 | QRectF rect() const { return m_bounds; } |
52 | | private: |
53 | | QRectF m_bounds; |
54 | | }; |
55 | | |
56 | | class Q_SVG_EXPORT QSvgCircle : public QSvgEllipse |
57 | | { |
58 | | public: |
59 | 0 | QSvgCircle(QSvgNode *parent, const QRectF &rect) : QSvgEllipse(parent, rect) { } |
60 | | Type type() const override; |
61 | | }; |
62 | | |
63 | | class Q_SVG_EXPORT QSvgImage : public QSvgNode |
64 | | { |
65 | | public: |
66 | | QSvgImage(QSvgNode *parent, |
67 | | const QImage &image, |
68 | | const QString &filename, |
69 | | const QRectF &bounds); |
70 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
71 | | Type type() const override; |
72 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
73 | | |
74 | 0 | QRectF rect() const { return m_bounds; } |
75 | 0 | const QImage &image() const { return m_image; } |
76 | 0 | QString filename() const { return m_filename; } |
77 | | private: |
78 | | QString m_filename; |
79 | | QImage m_image; |
80 | | QRectF m_bounds; |
81 | | }; |
82 | | |
83 | | class Q_SVG_EXPORT QSvgLine : public QSvgNode |
84 | | { |
85 | | public: |
86 | | QSvgLine(QSvgNode *parent, const QLineF &line); |
87 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
88 | | Type type() const override; |
89 | | QRectF internalFastBounds(QPainter *p, QSvgExtraStates &states) const override; |
90 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
91 | | QRectF decoratedInternalBounds(QPainter *p, QSvgExtraStates &states) const override; |
92 | | bool requiresGroupRendering() const override; |
93 | 0 | QLineF line() const { return m_line; } |
94 | | private: |
95 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states, BoundsMode mode) const; |
96 | | QLineF m_line; |
97 | | }; |
98 | | |
99 | | class Q_SVG_EXPORT QSvgPath : public QSvgNode |
100 | | { |
101 | | public: |
102 | | QSvgPath(QSvgNode *parent, const QPainterPath &qpath); |
103 | | bool separateFillStroke(const QSvgExtraStates &) const override; |
104 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
105 | | Type type() const override; |
106 | | QRectF internalFastBounds(QPainter *p, QSvgExtraStates &states) const override; |
107 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
108 | | QRectF decoratedInternalBounds(QPainter *p, QSvgExtraStates &states) const override; |
109 | | bool requiresGroupRendering() const override; |
110 | 15.4k | const QPainterPath &path() const { return m_path; } |
111 | | private: |
112 | | QPainterPath m_path; |
113 | | }; |
114 | | |
115 | | class Q_SVG_EXPORT QSvgPolygon : public QSvgNode |
116 | | { |
117 | | public: |
118 | | QSvgPolygon(QSvgNode *parent, const QPolygonF &poly); |
119 | | bool separateFillStroke(const QSvgExtraStates &) const override; |
120 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
121 | | Type type() const override; |
122 | | QRectF internalFastBounds(QPainter *p, QSvgExtraStates &states) const override; |
123 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
124 | | QRectF decoratedInternalBounds(QPainter *p, QSvgExtraStates &states) const override; |
125 | | bool requiresGroupRendering() const override; |
126 | 0 | const QPolygonF &polygon() const { return m_poly; } |
127 | | private: |
128 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states, BoundsMode mode) const; |
129 | | QPolygonF m_poly; |
130 | | }; |
131 | | |
132 | | class Q_SVG_EXPORT QSvgPolyline : public QSvgNode |
133 | | { |
134 | | public: |
135 | | QSvgPolyline(QSvgNode *parent, const QPolygonF &poly); |
136 | | bool separateFillStroke(const QSvgExtraStates &) const override; |
137 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
138 | | Type type() const override; |
139 | | QRectF internalFastBounds(QPainter *p, QSvgExtraStates &states) const override; |
140 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
141 | | QRectF decoratedInternalBounds(QPainter *p, QSvgExtraStates &states) const override; |
142 | | bool requiresGroupRendering() const override; |
143 | 0 | const QPolygonF &polygon() const { return m_poly; } |
144 | | private: |
145 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states, BoundsMode mode) const; |
146 | | QPolygonF m_poly; |
147 | | }; |
148 | | |
149 | | class Q_SVG_EXPORT QSvgRect : public QSvgNode |
150 | | { |
151 | | public: |
152 | | QSvgRect(QSvgNode *paren, const QRectF &rect, qreal rx=0, qreal ry=0); |
153 | | Type type() const override; |
154 | | bool separateFillStroke(const QSvgExtraStates &) const override; |
155 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
156 | | QRectF internalFastBounds(QPainter *p, QSvgExtraStates &states) const override; |
157 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
158 | | QRectF decoratedInternalBounds(QPainter *p, QSvgExtraStates &states) const override; |
159 | 0 | QRectF rect() const { return m_rect; } |
160 | 0 | QPointF radius() const { return { m_rx, m_ry }; } |
161 | | private: |
162 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states, BoundsMode mode) const; |
163 | | QRectF m_rect; |
164 | | qreal m_rx, m_ry; |
165 | | }; |
166 | | |
167 | | class QSvgTspan; |
168 | | |
169 | | class Q_SVG_EXPORT QSvgText : public QSvgNode |
170 | | { |
171 | | public: |
172 | | enum WhitespaceMode |
173 | | { |
174 | | Default, |
175 | | Preserve |
176 | | }; |
177 | | |
178 | | QSvgText(QSvgNode *parent, const QPointF &coord); |
179 | | ~QSvgText(); |
180 | | void setTextArea(const QSizeF &size); |
181 | | |
182 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
183 | | bool shouldDrawNode(QPainter *p, QSvgExtraStates &states) const override; |
184 | | Type type() const override; |
185 | | bool separateFillStroke(const QSvgExtraStates &) const override; |
186 | | |
187 | 0 | void addTspan(QSvgTspan *tspan) {m_tspans.append(tspan);} |
188 | 0 | const QList<QSvgTspan *> tspans() const { return m_tspans; } |
189 | | void addText(QStringView text); |
190 | 0 | void addLineBreak() {m_tspans.append(LINEBREAK);} |
191 | 0 | void setWhitespaceMode(WhitespaceMode mode) {m_mode = mode;} |
192 | | |
193 | | QRectF internalFastBounds(QPainter *p, QSvgExtraStates &states) const override; |
194 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
195 | | |
196 | 0 | QPointF position() const { return m_coord; } |
197 | 0 | QSizeF size() const { return m_size; } |
198 | 0 | WhitespaceMode whitespaceMode() const { return m_mode; } |
199 | | |
200 | | private: |
201 | | void draw_helper(QPainter *p, QSvgExtraStates &states, QRectF *boundingRect = nullptr) const; |
202 | | |
203 | | static QSvgTspan * const LINEBREAK; |
204 | | |
205 | | QPointF m_coord; |
206 | | QSizeF m_size; |
207 | | |
208 | | // 'm_tspans' is also used to store characters outside tspans and line breaks. |
209 | | // If a 'm_tspan' item is null, it indicates a line break. |
210 | | QList<QSvgTspan *> m_tspans; |
211 | | |
212 | | Type m_type; |
213 | | WhitespaceMode m_mode; |
214 | | |
215 | | mutable std::optional<QList<const QSvgGlyph *> > m_glyphsToDraw; |
216 | | }; |
217 | | |
218 | | class Q_SVG_EXPORT QSvgTspan : public QSvgNode |
219 | | { |
220 | | public: |
221 | | // tspans are also used to store normal text, so the 'isProperTspan' is used to separate text from tspan. |
222 | | QSvgTspan(QSvgNode *parent, bool isProperTspan = true) |
223 | 0 | : QSvgNode(parent), m_mode(QSvgText::Default), m_isTspan(isProperTspan) |
224 | 0 | { |
225 | 0 | } |
226 | 0 | ~QSvgTspan() { }; |
227 | 0 | Type type() const override { return Tspan; } |
228 | 0 | void drawCommand(QPainter *, QSvgExtraStates &) override { Q_ASSERT(!"Tspans should be drawn through QSvgText::draw()."); } |
229 | 0 | void addText(QStringView text) {m_text += text;} |
230 | 0 | const QString &text() const {return m_text;} |
231 | 0 | bool isTspan() const {return m_isTspan;} |
232 | 0 | void setWhitespaceMode(QSvgText::WhitespaceMode mode) {m_mode = mode;} |
233 | 0 | QSvgText::WhitespaceMode whitespaceMode() const {return m_mode;} |
234 | | private: |
235 | | QString m_text; |
236 | | QSvgText::WhitespaceMode m_mode; |
237 | | bool m_isTspan; |
238 | | }; |
239 | | |
240 | | class QSvgUse : public QSvgNode |
241 | | { |
242 | | public: |
243 | | QSvgUse(const QPointF &start, QSvgNode *parent, QSvgNode *link); |
244 | | QSvgUse(const QPointF &start, QSvgNode *parent, const QString &linkId) |
245 | 0 | : QSvgUse(start, parent, nullptr) |
246 | 0 | { m_linkId = linkId; } |
247 | | void drawCommand(QPainter *p, QSvgExtraStates &states) override; |
248 | | Type type() const override; |
249 | | QRectF internalBounds(QPainter *p, QSvgExtraStates &states) const override; |
250 | | QRectF decoratedInternalBounds(QPainter *p, QSvgExtraStates &states) const override; |
251 | 0 | bool isResolved() const { return m_link != nullptr; } |
252 | 0 | const QString &linkId() const { return m_linkId; } |
253 | 0 | void setLink(QSvgNode *link) { m_link = link; } |
254 | 0 | QSvgNode *link() const { return m_link; } |
255 | 0 | QPointF start() const { return m_start; } |
256 | 0 | bool isRecursing() const { return m_recursing; } |
257 | | |
258 | | private: |
259 | | QSvgNode *m_link; |
260 | | QPointF m_start; |
261 | | QString m_linkId; |
262 | | mutable bool m_recursing; |
263 | | }; |
264 | | |
265 | | class QSvgVideo : public QSvgNode |
266 | | { |
267 | | public: |
268 | 0 | void drawCommand(QPainter *, QSvgExtraStates &) override {}; |
269 | | Type type() const override; |
270 | | }; |
271 | | |
272 | | QT_END_NAMESPACE |
273 | | |
274 | | #endif // QSVGGRAPHICS_P_H |