Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickitemgenerator.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 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
5#include "utils_p.h"
6#include "qquicknodeinfo_p.h"
7
8#include <private/qsgcurveprocessor_p.h>
9#include <private/qquickshape_p.h>
10#include <private/qquadpath_p.h>
11#include <private/qquickitem_p.h>
12#include <private/qquickimagebase_p_p.h>
13
14#include <QtCore/qloggingcategory.h>
15
17
18Q_DECLARE_LOGGING_CATEGORY(lcQuickVectorImage)
19
22{
23 Q_ASSERT(parentItem);
24 m_items.push(parentItem);
25 m_parentItem = parentItem;
26}
27
31
33{
34 if (!info.isDefaultTransform) {
35 auto sx = info.transform.m11();
36 auto sy = info.transform.m22();
37 auto x = info.transform.m31();
38 auto y = info.transform.m32();
39
40 auto xformProp = currentItem()->transform();
41 if (info.transform.type() == QTransform::TxTranslate) {
42 auto *translate = new QQuickTranslate;
43 translate->setX(x);
44 translate->setY(y);
45 xformProp.append(&xformProp, translate);
46 } else if (info.transform.type() == QTransform::TxScale && !x && !y) {
47 auto scale = new QQuickScale;
48 scale->setParent(currentItem());
49 scale->setXScale(sx);
50 scale->setYScale(sy);
51 xformProp.append(&xformProp, scale);
52 } else {
53 const QMatrix4x4 m(info.transform);
54 auto xform = new QQuickMatrix4x4;
56 xformProp.append(&xformProp, xform);
57 }
58 }
59 if (!info.isDefaultOpacity) {
60 currentItem()->setOpacity(info.opacity);
61 }
62}
63
65{
67
68 return false;
69}
70
72{
73 if (!isNodeVisible(info))
74 return;
75
76 auto *imageItem = new QQuickImage;
77 auto *imagePriv = static_cast<QQuickImageBasePrivate*>(QQuickItemPrivate::get(imageItem));
78 imagePriv->currentPix->setImage(info.image);
79
80 imageItem->setX(info.rect.x());
81 imageItem->setY(info.rect.y());
82 imageItem->setWidth(info.rect.width());
83 imageItem->setHeight(info.rect.height());
84
86
87 addCurrentItem(imageItem, info);
88 m_items.pop();
89}
90
92{
93 if (!isNodeVisible(info))
94 return;
95
96 if (m_inShapeItem) {
97 if (!info.isDefaultTransform)
98 qCWarning(lcQuickVectorImage) << "Skipped transform for node" << info.nodeId << "type" << info.typeName << "(this is not supposed to happen)";
100 } else {
101 auto *shapeItem = new QQuickShape;
103 shapeItem->setPreferredRendererType(QQuickShape::CurveRenderer);
104 shapeItem->setContainsMode(QQuickShape::ContainsMode::FillContains); // TODO: configurable?
105 addCurrentItem(shapeItem, info);
106 m_parentShapeItem = shapeItem;
107 m_inShapeItem = true;
108
110
112 //qCDebug(lcQuickVectorGraphics) << *node->qpath();
113 m_items.pop();
114 m_inShapeItem = false;
115 m_parentShapeItem = nullptr;
116 }
117}
118
120{
121 Q_UNUSED(pathSelector)
122 Q_ASSERT(painterPath || quadPath);
123
124 const bool noPen = info.strokeStyle.color == QColorConstants::Transparent;
125 if (pathSelector == QQuickVectorImageGenerator::StrokePath && noPen)
126 return;
127
128 const bool noFill = info.grad.type() == QGradient::NoGradient && info.fillColor == QColorConstants::Transparent;
129
130 if (pathSelector == QQuickVectorImageGenerator::FillPath && noFill)
131 return;
132
133 QQuickShapePath::FillRule fillRule = QQuickShapePath::FillRule(painterPath ? painterPath->fillRule() : quadPath->fillRule());
134
135 QQuickShapePath *shapePath = new QQuickShapePath;
136 Q_ASSERT(shapePath);
137
138 if (!info.nodeId.isEmpty())
139 shapePath->setObjectName(QStringLiteral("svg_path:") + info.nodeId);
140
141 if (noPen || !(pathSelector & QQuickVectorImageGenerator::StrokePath)) {
142 shapePath->setStrokeColor(Qt::transparent);
143 } else {
144 shapePath->setStrokeColor(info.strokeStyle.color);
145 shapePath->setStrokeWidth(info.strokeStyle.width);
146 shapePath->setCapStyle(QQuickShapePath::CapStyle(info.strokeStyle.lineCapStyle));
147 shapePath->setJoinStyle(QQuickShapePath::JoinStyle(info.strokeStyle.lineJoinStyle));
148 shapePath->setMiterLimit(info.strokeStyle.miterLimit);
149 if (info.strokeStyle.dashArray.length() != 0) {
150 shapePath->setStrokeStyle(QQuickShapePath::DashLine);
151 shapePath->setDashPattern(info.strokeStyle.dashArray.toVector());
152 shapePath->setDashOffset(info.strokeStyle.dashOffset);
153 }
154 }
155
156 if (!(pathSelector & QQuickVectorImageGenerator::FillPath))
157 shapePath->setFillColor(Qt::transparent);
158 else if (info.grad.type() != QGradient::NoGradient)
159 generateGradient(&info.grad, shapePath, boundingRect);
160 else
161 shapePath->setFillColor(info.fillColor);
162
163 shapePath->setFillRule(fillRule);
164
166
167 auto *pathSvg = new QQuickPathSvg;
168 pathSvg->setPath(svgPathString);
169 pathSvg->setParent(shapePath);
170
171 auto pathElementProp = shapePath->pathElements();
172 pathElementProp.append(&pathElementProp, pathSvg);
173
174 shapePath->setParent(currentItem());
175 auto shapeDataProp = m_parentShapeItem->data();
176 shapeDataProp.append(&shapeDataProp, shapePath);
177}
178
179void QQuickItemGenerator::generateGradient(const QGradient *grad, QQuickShapePath *shapePath, const QRectF &boundingRect)
180{
181 if (!shapePath)
182 return;
183
184 auto setStops = [=](QQuickShapeGradient *quickGrad, const QGradientStops &stops) {
185 auto stopsProp = quickGrad->stops();
186 for (auto &stop : stops) {
187 auto *stopObj = new QQuickGradientStop(quickGrad);
188 stopObj->setPosition(stop.first);
189 stopObj->setColor(stop.second);
190 stopsProp.append(&stopsProp, stopObj);
191 }
192 };
193
194 if (grad->type() == QGradient::LinearGradient) {
195 auto *linGrad = static_cast<const QLinearGradient *>(grad);
196
197 QRectF gradRect(linGrad->start(), linGrad->finalStop());
198 QRectF logRect = linGrad->coordinateMode() == QGradient::LogicalMode ? gradRect : QQuickVectorImageGenerator::Utils::mapToQtLogicalMode(gradRect, boundingRect);
199
200 auto *quickGrad = new QQuickShapeLinearGradient(shapePath);
201 quickGrad->setX1(logRect.left());
202 quickGrad->setY1(logRect.top());
203 quickGrad->setX2(logRect.right());
204 quickGrad->setY2(logRect.bottom());
205 setStops(quickGrad, linGrad->stops());
206
207 shapePath->setFillGradient(quickGrad);
208 } else if (grad->type() == QGradient::RadialGradient) {
209 auto *radGrad = static_cast<const QRadialGradient*>(grad);
210 auto *quickGrad = new QQuickShapeRadialGradient(shapePath);
211 quickGrad->setCenterX(radGrad->center().x());
212 quickGrad->setCenterY(radGrad->center().y());
213 quickGrad->setCenterRadius(radGrad->radius());
214 quickGrad->setFocalX(radGrad->focalPoint().x());
215 quickGrad->setFocalY(radGrad->focalPoint().y());
216 setStops(quickGrad, radGrad->stops());
217
218 shapePath->setFillGradient(quickGrad);
219 }
220}
221
223{
224 if (!isNodeVisible(info))
225 return;
226
227 qCWarning(lcQuickVectorImage) << "SVG NODE NOT IMPLEMENTED: "
228 << info.nodeId
229 << " type: " << info.typeName;
230}
231
233{
234 if (!isNodeVisible(info))
235 return;
236
237 QQuickItem *alignItem = nullptr;
238 QQuickText *textItem = nullptr;
239
240 QQuickItem *containerItem = new QQuickItem(currentItem());
241 addCurrentItem(containerItem, info);
242
244
245 if (!info.isTextArea) {
246 alignItem = new QQuickItem(currentItem());
247 alignItem->setX(info.position.x());
248 alignItem->setY(info.position.y());
249 }
250
251 textItem = new QQuickText(containerItem);
252 addCurrentItem(textItem, info);
253
254 if (info.isTextArea) {
255 textItem->setX(info.position.x());
256 textItem->setY(info.position.y());
257 if (info.size.width() > 0)
258 textItem->setWidth(info.size.width());
259 if (info.size.height() > 0)
260 textItem->setHeight(info.size.height());
261 textItem->setWrapMode(QQuickText::Wrap);
262 textItem->setClip(true);
263 } else {
264 auto *anchors = QQuickItemPrivate::get(textItem)->anchors();
265 auto *alignPrivate = QQuickItemPrivate::get(alignItem);
266 anchors->setBaseline(alignPrivate->top());
267
268 switch (info.alignment) {
269 case Qt::AlignHCenter:
270 anchors->setHorizontalCenter(alignPrivate->left());
271 break;
272 case Qt::AlignRight:
273 anchors->setRight(alignPrivate->left());
274 break;
275 default:
276 qCDebug(lcQuickVectorImage) << "Unexpected text alignment" << info.alignment;
278 case Qt::AlignLeft:
279 anchors->setLeft(alignPrivate->left());
280 break;
281 }
282 }
283
284 textItem->setColor(info.fillColor);
285 textItem->setTextFormat(info.needsRichText ? QQuickText::RichText : QQuickText::StyledText);
286 textItem->setText(info.text);
287 textItem->setFont(info.font);
288
289 if (info.strokeColor != QColorConstants::Transparent) {
290 textItem->setStyleColor(info.strokeColor);
291 textItem->setStyle(QQuickText::Outline);
292 }
293
294 m_items.pop(); m_items.pop();
295}
296
298{
299 if (!isNodeVisible(info))
300 return;
301
302 if (info.stage == StructureNodeStage::Start) {
303 QQuickItem *item = new QQuickItem();
304 item->setPosition(info.startPos);
305 addCurrentItem(item, info);
307 } else {
308 m_items.pop();
309 }
310
311}
312
314{
315 if (!isNodeVisible(info))
316 return false;
317
318 if (info.stage == StructureNodeStage::Start) {
319 if (!info.forceSeparatePaths && info.isPathContainer) {
320 m_inShapeItem = true;
321 auto *shapeItem = new QQuickShape;
323 shapeItem->setPreferredRendererType(QQuickShape::CurveRenderer);
324 m_parentShapeItem = shapeItem;
325 addCurrentItem(shapeItem, info);
326 } else {
327 QQuickItem *item = !info.viewBox.isEmpty() ? new QQuickVectorImageGenerator::Utils::ViewBoxItem(info.viewBox) : new QQuickItem;
328 addCurrentItem(item, info);
329 }
330
332 } else {
333 m_inShapeItem = false;
334 m_parentShapeItem = nullptr;
335 m_items.pop();
336 }
337
338 return true;
339}
340
342{
343 if (!isNodeVisible(info)) {
344 QQuickItem *item = new QQuickItem();
345 item->setParentItem(m_parentItem);
346
347 if (info.size.width() > 0)
348 m_parentItem->setImplicitWidth(info.size.width());
349
350 if (info.size.height() > 0)
351 m_parentItem->setImplicitHeight(info.size.height());
352
353 item->setWidth(m_parentItem->implicitWidth());
354 item->setHeight(m_parentItem->implicitHeight());
355
356 return false;
357 }
358
359 if (info.stage == StructureNodeStage::Start) {
360 QQuickItem *item = !info.viewBox.isEmpty() ? new QQuickVectorImageGenerator::Utils::ViewBoxItem(info.viewBox) : new QQuickItem;
361 addCurrentItem(item, info);
362 if (info.size.width() > 0)
363 m_parentItem->setImplicitWidth(info.size.width());
364
365 if (info.size.height() > 0)
366 m_parentItem->setImplicitHeight(info.size.height());
367
368 item->setWidth(m_parentItem->implicitWidth());
369 item->setHeight(m_parentItem->implicitHeight());
371 } else {
372 m_inShapeItem = false;
373 m_parentShapeItem = nullptr;
374 m_items.pop();
375 }
376
377 return true;
378}
379
380QQuickItem *QQuickItemGenerator::currentItem()
381{
382 return m_items.top();
383}
384
385void QQuickItemGenerator::addCurrentItem(QQuickItem *item, const NodeInfo &info)
386{
387 item->setParentItem(currentItem());
388 m_items.push(item);
389 QStringView name = !info.nodeId.isEmpty() ? info.nodeId : info.typeName;
390 item->setObjectName(name);
391}
392
\inmodule QtGui
Definition qbrush.h:135
@ LogicalMode
Definition qbrush.h:154
Type type() const
Returns the type of gradient.
Definition qbrush.h:344
@ LinearGradient
Definition qbrush.h:139
@ NoGradient
Definition qbrush.h:142
@ RadialGradient
Definition qbrush.h:140
void setParentItem(QGraphicsItem *parent)
Sets this item's parent item to newParent.
\inmodule QtGui
Definition qbrush.h:394
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
\inmodule QtGui
Qt::FillRule fillRule() const
Returns the painter path's currently set fill rule.
void setHorizontalCenter(const QQuickAnchorLine &edge)
void setBaseline(const QQuickAnchorLine &edge)
void setRight(const QQuickAnchorLine &edge)
void setLeft(const QQuickAnchorLine &edge)
void optimizePaths(const PathNodeInfo &info)
QQuickVectorImageGenerator::GeneratorFlags m_flags
bool isNodeVisible(const NodeInfo &info)
void generateNodeBase(const NodeInfo &info) override
void outputShapePath(const PathNodeInfo &info, const QPainterPath *path, const QQuadPath *quadPath, QQuickVectorImageGenerator::PathSelector pathSelector, const QRectF &boundingRect) override
bool generateStructureNode(const StructureNodeInfo &info) override
void generateNode(const NodeInfo &info) override
void generatePath(const PathNodeInfo &info) override
void generateUseNode(const UseNodeInfo &info) override
void generateImageNode(const ImageNodeInfo &info) override
bool generateDefsNode(const NodeInfo &info) override
void generateTextNode(const TextNodeInfo &info) override
bool generateRootNode(const StructureNodeInfo &info) override
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
void setOpacity(qreal)
qreal implicitWidth
Definition qquickitem.h:114
qreal implicitHeight
Definition qquickitem.h:115
void setImplicitHeight(qreal)
void setImplicitWidth(qreal)
QQmlListProperty< QQuickTransform > transform
\qmlproperty list<Transform> QtQuick::Item::transform This property holds the list of transformations...
Definition qquickitem.h:110
void setPath(const QString &path)
void setImage(const QImage &)
void setContainsMode(ContainsMode containsMode)
FINALQQmlListProperty< QObject > data
\qmlproperty list<Object> QtQuick.Shapes::Shape::data
\inmodule QtGui
Definition qbrush.h:412
\inmodule QtCore\reentrant
Definition qrect.h:484
T & top()
Returns a reference to the stack's top item.
Definition qstack.h:19
T pop()
Removes the top item from the stack and returns it.
Definition qstack.h:18
void push(const T &t)
Adds element t to the top of the stack.
Definition qstack.h:17
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void setMatrix(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33)
Sets the matrix elements to the specified values, m11, m12, m13 m21, m22, m23 m31,...
constexpr QColor Transparent
Definition qcolor.h:310
QRectF mapToQtLogicalMode(const QRectF &objModeRect, const QRectF &boundingRect)
Definition utils_p.h:120
QString toSvgString(const QPainterPath &path)
Definition utils_p.h:145
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:146
@ AlignHCenter
Definition qnamespace.h:148
@ AlignLeft
Definition qnamespace.h:144
@ transparent
Definition qnamespace.h:47
#define Q_FALLTHROUGH()
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLbitfield flags
GLuint name
GLint y
GLenum GLenum GLenum GLenum GLenum scale
static const QRectF boundingRect(const QPointF *points, int pointCount)
QQuickAnchors * anchors(QQuickItem *item)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
#define Q_UNUSED(x)
static bool translate(xcb_connection_t *connection, xcb_window_t child, xcb_window_t parent, int *x, int *y)
QGraphicsItem * item
QHostInfo info
[0]