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#include "qquickshapesoftwarerenderer_p.h"
5#include <private/qquickpath_p_p.h>
6
7QT_BEGIN_NAMESPACE
8
9void QQuickShapeSoftwareRenderer::beginSync(int totalCount, bool *countChanged)
10{
11 if (m_sp.size() != totalCount) {
12 m_sp.resize(size: totalCount);
13 m_accDirty |= DirtyList;
14 *countChanged = true;
15 } else {
16 *countChanged = false;
17 }
18}
19
20void QQuickShapeSoftwareRenderer::setPath(int index, const QQuickPath *path)
21{
22 setPath(index, path: path ? path->path() : QPainterPath());
23}
24
25void QQuickShapeSoftwareRenderer::setPath(int index, const QPainterPath &path, QQuickShapePath::PathHints)
26{
27 ShapePathGuiData &d(m_sp[index]);
28 d.path = path;
29 d.dirty |= DirtyPath;
30 m_accDirty |= DirtyPath;
31}
32
33void QQuickShapeSoftwareRenderer::setStrokeColor(int index, const QColor &color)
34{
35 ShapePathGuiData &d(m_sp[index]);
36 d.pen.setColor(color);
37 d.dirty |= DirtyPen;
38 m_accDirty |= DirtyPen;
39}
40
41void QQuickShapeSoftwareRenderer::setStrokeWidth(int index, qreal w)
42{
43 ShapePathGuiData &d(m_sp[index]);
44 d.strokeWidth = w;
45 if (w > 0.0f)
46 d.pen.setWidthF(w);
47 d.dirty |= DirtyPen;
48 m_accDirty |= DirtyPen;
49}
50
51void QQuickShapeSoftwareRenderer::setFillColor(int index, const QColor &color)
52{
53 ShapePathGuiData &d(m_sp[index]);
54 d.fillColor = color;
55 d.brush.setColor(color);
56 d.dirty |= DirtyBrush;
57 m_accDirty |= DirtyBrush;
58}
59
60void QQuickShapeSoftwareRenderer::setFillRule(int index, QQuickShapePath::FillRule fillRule)
61{
62 ShapePathGuiData &d(m_sp[index]);
63 d.fillRule = Qt::FillRule(fillRule);
64 d.dirty |= DirtyFillRule;
65 m_accDirty |= DirtyFillRule;
66}
67
68void QQuickShapeSoftwareRenderer::setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit)
69{
70 ShapePathGuiData &d(m_sp[index]);
71 d.pen.setJoinStyle(Qt::PenJoinStyle(joinStyle));
72 d.pen.setMiterLimit(miterLimit);
73 d.dirty |= DirtyPen;
74 m_accDirty |= DirtyPen;
75}
76
77void QQuickShapeSoftwareRenderer::setCapStyle(int index, QQuickShapePath::CapStyle capStyle)
78{
79 ShapePathGuiData &d(m_sp[index]);
80 d.pen.setCapStyle(Qt::PenCapStyle(capStyle));
81 d.dirty |= DirtyPen;
82 m_accDirty |= DirtyPen;
83}
84
85void QQuickShapeSoftwareRenderer::setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
86 qreal dashOffset, const QVector<qreal> &dashPattern)
87{
88 ShapePathGuiData &d(m_sp[index]);
89 switch (strokeStyle) {
90 case QQuickShapePath::SolidLine:
91 d.pen.setStyle(Qt::SolidLine);
92 break;
93 case QQuickShapePath::DashLine:
94 d.pen.setStyle(Qt::CustomDashLine);
95 d.pen.setDashPattern(dashPattern);
96 d.pen.setDashOffset(dashOffset);
97 break;
98 default:
99 break;
100 }
101 d.dirty |= DirtyPen;
102 m_accDirty |= DirtyPen;
103}
104
105static inline void setupPainterGradient(QGradient *painterGradient, const QQuickShapeGradient &g)
106{
107 painterGradient->setStops(g.gradientStops()); // sorted
108 switch (g.spread()) {
109 case QQuickShapeGradient::PadSpread:
110 painterGradient->setSpread(QGradient::PadSpread);
111 break;
112 case QQuickShapeGradient::RepeatSpread:
113 painterGradient->setSpread(QGradient::RepeatSpread);
114 break;
115 case QQuickShapeGradient::ReflectSpread:
116 painterGradient->setSpread(QGradient::ReflectSpread);
117 break;
118 default:
119 break;
120 }
121}
122
123void QQuickShapeSoftwareRenderer::setFillGradient(int index, QQuickShapeGradient *gradient)
124{
125 ShapePathGuiData &d(m_sp[index]);
126 if (QQuickShapeLinearGradient *g = qobject_cast<QQuickShapeLinearGradient *>(object: gradient)) {
127 QLinearGradient painterGradient(g->x1(), g->y1(), g->x2(), g->y2());
128 setupPainterGradient(painterGradient: &painterGradient, g: *g);
129 d.brush = QBrush(painterGradient);
130 } else if (QQuickShapeRadialGradient *g = qobject_cast<QQuickShapeRadialGradient *>(object: gradient)) {
131 QRadialGradient painterGradient(g->centerX(), g->centerY(), g->centerRadius(),
132 g->focalX(), g->focalY(), g->focalRadius());
133 setupPainterGradient(painterGradient: &painterGradient, g: *g);
134 d.brush = QBrush(painterGradient);
135 } else if (QQuickShapeConicalGradient *g = qobject_cast<QQuickShapeConicalGradient *>(object: gradient)) {
136 QConicalGradient painterGradient(g->centerX(), g->centerY(), g->angle());
137 setupPainterGradient(painterGradient: &painterGradient, g: *g);
138 d.brush = QBrush(painterGradient);
139 } else {
140 d.brush = QBrush(d.fillColor);
141 }
142 d.dirty |= DirtyBrush;
143 m_accDirty |= DirtyBrush;
144}
145
146void QQuickShapeSoftwareRenderer::setFillTextureProvider(int index, QQuickItem *textureProviderItem)
147{
148 Q_UNUSED(index);
149 Q_UNUSED(textureProviderItem);
150}
151
152void QQuickShapeSoftwareRenderer::handleSceneChange(QQuickWindow *window)
153{
154 Q_UNUSED(window);
155 // No action needed
156}
157
158void QQuickShapeSoftwareRenderer::setFillTransform(int index, const QSGTransform &transform)
159{
160 ShapePathGuiData &d(m_sp[index]);
161 if (!(transform.isIdentity() && d.brush.transform().isIdentity())) // No need to copy if both==I
162 d.brush.setTransform(transform.matrix().toTransform());
163 d.dirty |= DirtyBrush;
164 m_accDirty |= DirtyBrush;
165}
166
167void QQuickShapeSoftwareRenderer::endSync(bool)
168{
169}
170
171void QQuickShapeSoftwareRenderer::setNode(QQuickShapeSoftwareRenderNode *node)
172{
173 m_node = node;
174 m_accDirty |= DirtyList;
175}
176
177void QQuickShapeSoftwareRenderer::updateNode()
178{
179 if (!m_accDirty)
180 return;
181
182 const int count = m_sp.size();
183 const bool listChanged = m_accDirty & DirtyList;
184 if (listChanged)
185 m_node->m_sp.resize(size: count);
186
187 m_node->m_boundingRect = QRectF();
188
189 for (int i = 0; i < count; ++i) {
190 ShapePathGuiData &src(m_sp[i]);
191 QQuickShapeSoftwareRenderNode::ShapePathRenderData &dst(m_node->m_sp[i]);
192
193 if (listChanged || (src.dirty & DirtyPath)) {
194 dst.path = src.path;
195 dst.path.setFillRule(src.fillRule);
196 }
197
198 if (listChanged || (src.dirty & DirtyFillRule))
199 dst.path.setFillRule(src.fillRule);
200
201 if (listChanged || (src.dirty & DirtyPen)) {
202 dst.pen = src.pen;
203 dst.strokeWidth = src.strokeWidth;
204 }
205
206 if (listChanged || (src.dirty & DirtyBrush))
207 dst.brush = src.brush;
208
209 src.dirty = 0;
210
211 QRectF br = dst.path.boundingRect();
212 const float sw = qMax(a: 1.0f, b: dst.strokeWidth);
213 br.adjust(xp1: -sw, yp1: -sw, xp2: sw, yp2: sw);
214 m_node->m_boundingRect |= br;
215 }
216
217 m_node->markDirty(bits: QSGNode::DirtyMaterial);
218 m_accDirty = 0;
219}
220
221QQuickShapeSoftwareRenderNode::QQuickShapeSoftwareRenderNode(QQuickShape *item)
222 : m_item(item)
223{
224}
225
226QQuickShapeSoftwareRenderNode::~QQuickShapeSoftwareRenderNode()
227{
228 releaseResources();
229}
230
231void QQuickShapeSoftwareRenderNode::releaseResources()
232{
233}
234
235void QQuickShapeSoftwareRenderNode::render(const RenderState *state)
236{
237 if (m_sp.isEmpty())
238 return;
239
240 QSGRendererInterface *rif = m_item->window()->rendererInterface();
241 QPainter *p = static_cast<QPainter *>(rif->getResource(window: m_item->window(), resource: QSGRendererInterface::PainterResource));
242 Q_ASSERT(p);
243
244 const QRegion *clipRegion = state->clipRegion();
245 if (clipRegion && !clipRegion->isEmpty())
246 p->setClipRegion(*clipRegion, op: Qt::ReplaceClip); // must be done before setTransform
247
248 p->setTransform(transform: matrix()->toTransform());
249 p->setOpacity(inheritedOpacity());
250
251 for (const ShapePathRenderData &d : std::as_const(t&: m_sp)) {
252 p->setPen(d.strokeWidth > 0.0f && d.pen.color() != Qt::transparent ? d.pen : Qt::NoPen);
253 p->setBrush(d.brush.color() != Qt::transparent ? d.brush : Qt::NoBrush);
254 p->drawPath(path: d.path);
255 }
256}
257
258QSGRenderNode::StateFlags QQuickShapeSoftwareRenderNode::changedStates() const
259{
260 return {};
261}
262
263QSGRenderNode::RenderingFlags QQuickShapeSoftwareRenderNode::flags() const
264{
265 return BoundedRectRendering; // avoid fullscreen updates by saying we won't draw outside rect()
266}
267
268QRectF QQuickShapeSoftwareRenderNode::rect() const
269{
270 return m_boundingRect;
271}
272
273QT_END_NAMESPACE
274

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/quickshapes/qquickshapesoftwarerenderer.cpp