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 QtQuick 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#ifndef QQUICKSHAPEGENERICRENDERER_P_H
41#define QQUICKSHAPEGENERICRENDERER_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists for the convenience
48// of a number of Qt sources files. This header file may change from
49// version to version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtQuickShapes/private/qquickshapesglobal_p.h>
55#include <QtQuickShapes/private/qquickshape_p_p.h>
56#include <qsgnode.h>
57#include <qsggeometry.h>
58#include <qsgmaterial.h>
59#include <qsgrendererinterface.h>
60#include <qsgtexture.h>
61#include <QtCore/qrunnable.h>
62
63QT_BEGIN_NAMESPACE
64
65class QQuickShapeGenericNode;
66class QQuickShapeGenericStrokeFillNode;
67class QQuickShapeFillRunnable;
68class QQuickShapeStrokeRunnable;
69
70class QQuickShapeGenericRenderer : public QQuickAbstractPathRenderer
71{
72public:
73 enum Dirty {
74 DirtyFillGeom = 0x01,
75 DirtyStrokeGeom = 0x02,
76 DirtyColor = 0x04,
77 DirtyFillGradient = 0x08,
78 DirtyList = 0x10 // only for accDirty
79 };
80
81 QQuickShapeGenericRenderer(QQuickItem *item)
82 : m_item(item),
83 m_api(QSGRendererInterface::Unknown),
84 m_rootNode(nullptr),
85 m_accDirty(0),
86 m_asyncCallback(nullptr),
87 m_asyncCallbackData(nullptr)
88 { }
89 ~QQuickShapeGenericRenderer();
90
91 void beginSync(int totalCount) override;
92 void setPath(int index, const QQuickPath *path) override;
93 void setStrokeColor(int index, const QColor &color) override;
94 void setStrokeWidth(int index, qreal w) override;
95 void setFillColor(int index, const QColor &color) override;
96 void setFillRule(int index, QQuickShapePath::FillRule fillRule) override;
97 void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override;
98 void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override;
99 void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle,
100 qreal dashOffset, const QVector<qreal> &dashPattern) override;
101 void setFillGradient(int index, QQuickShapeGradient *gradient) override;
102 void endSync(bool async) override;
103 void setAsyncCallback(void (*)(void *), void *) override;
104 Flags flags() const override { return SupportsAsync; }
105
106 void updateNode() override;
107
108 void setRootNode(QQuickShapeGenericNode *node);
109
110 struct Color4ub { unsigned char r, g, b, a; };
111 typedef QVector<QSGGeometry::ColoredPoint2D> VertexContainerType;
112 typedef QVector<quint32> IndexContainerType;
113
114 static void triangulateFill(const QPainterPath &path,
115 const Color4ub &fillColor,
116 VertexContainerType *fillVertices,
117 IndexContainerType *fillIndices,
118 QSGGeometry::Type *indexType,
119 bool supportsElementIndexUint);
120 static void triangulateStroke(const QPainterPath &path,
121 const QPen &pen,
122 const Color4ub &strokeColor,
123 VertexContainerType *strokeVertices,
124 const QSize &clipSize);
125
126private:
127 void maybeUpdateAsyncItem();
128
129 struct ShapePathData {
130 float strokeWidth;
131 QPen pen;
132 Color4ub strokeColor;
133 Color4ub fillColor;
134 Qt::FillRule fillRule;
135 QPainterPath path;
136 FillGradientType fillGradientActive;
137 GradientDesc fillGradient;
138 VertexContainerType fillVertices;
139 IndexContainerType fillIndices;
140 QSGGeometry::Type indexType;
141 VertexContainerType strokeVertices;
142 int syncDirty;
143 int effectiveDirty = 0;
144 QQuickShapeFillRunnable *pendingFill = nullptr;
145 QQuickShapeStrokeRunnable *pendingStroke = nullptr;
146 };
147
148 void updateShadowDataInNode(ShapePathData *d, QQuickShapeGenericStrokeFillNode *n);
149 void updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node);
150 void updateStrokeNode(ShapePathData *d, QQuickShapeGenericNode *node);
151
152 QQuickItem *m_item;
153 QSGRendererInterface::GraphicsApi m_api;
154 QQuickShapeGenericNode *m_rootNode;
155 QVector<ShapePathData> m_sp;
156 int m_accDirty;
157 void (*m_asyncCallback)(void *);
158 void *m_asyncCallbackData;
159};
160
161class QQuickShapeFillRunnable : public QObject, public QRunnable
162{
163 Q_OBJECT
164
165public:
166 void run() override;
167
168 bool orphaned = false;
169
170 // input
171 QPainterPath path;
172 QQuickShapeGenericRenderer::Color4ub fillColor;
173 bool supportsElementIndexUint;
174
175 // output
176 QQuickShapeGenericRenderer::VertexContainerType fillVertices;
177 QQuickShapeGenericRenderer::IndexContainerType fillIndices;
178 QSGGeometry::Type indexType;
179
180Q_SIGNALS:
181 void done(QQuickShapeFillRunnable *self);
182};
183
184class QQuickShapeStrokeRunnable : public QObject, public QRunnable
185{
186 Q_OBJECT
187
188public:
189 void run() override;
190
191 bool orphaned = false;
192
193 // input
194 QPainterPath path;
195 QPen pen;
196 QQuickShapeGenericRenderer::Color4ub strokeColor;
197 QSize clipSize;
198
199 // output
200 QQuickShapeGenericRenderer::VertexContainerType strokeVertices;
201
202Q_SIGNALS:
203 void done(QQuickShapeStrokeRunnable *self);
204};
205
206class QQuickShapeGenericStrokeFillNode : public QSGGeometryNode
207{
208public:
209 QQuickShapeGenericStrokeFillNode(QQuickWindow *window);
210
211 enum Material {
212 MatSolidColor,
213 MatLinearGradient,
214 MatRadialGradient,
215 MatConicalGradient
216 };
217
218 void activateMaterial(QQuickWindow *window, Material m);
219
220 // shadow data for custom materials
221 QQuickAbstractPathRenderer::GradientDesc m_fillGradient;
222
223private:
224 QScopedPointer<QSGMaterial> m_material;
225
226 friend class QQuickShapeGenericRenderer;
227};
228
229class QQuickShapeGenericNode : public QSGNode
230{
231public:
232 QQuickShapeGenericStrokeFillNode *m_fillNode = nullptr;
233 QQuickShapeGenericStrokeFillNode *m_strokeNode = nullptr;
234 QQuickShapeGenericNode *m_next = nullptr;
235};
236
237class QQuickShapeGenericMaterialFactory
238{
239public:
240 static QSGMaterial *createVertexColor(QQuickWindow *window);
241 static QSGMaterial *createLinearGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node);
242 static QSGMaterial *createRadialGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node);
243 static QSGMaterial *createConicalGradient(QQuickWindow *window, QQuickShapeGenericStrokeFillNode *node);
244};
245
246#if QT_CONFIG(opengl)
247
248 class QQuickShapeLinearGradientShader : public QSGMaterialShader
249{
250public:
251 QQuickShapeLinearGradientShader();
252
253 void initialize() override;
254 void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
255 char const *const *attributeNames() const override;
256
257private:
258 int m_opacityLoc = -1;
259 int m_matrixLoc = -1;
260 int m_gradStartLoc = -1;
261 int m_gradEndLoc = -1;
262};
263
264#endif // QT_CONFIG(opengl)
265
266class QQuickShapeLinearGradientRhiShader : public QSGMaterialRhiShader
267{
268public:
269 QQuickShapeLinearGradientRhiShader();
270
271 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
272 QSGMaterial *oldMaterial) override;
273 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
274 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
275
276private:
277 QVector2D m_gradA;
278 QVector2D m_gradB;
279};
280
281class QQuickShapeLinearGradientMaterial : public QSGMaterial
282{
283public:
284 QQuickShapeLinearGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
285 : m_node(node)
286 {
287 // Passing RequiresFullMatrix is essential in order to prevent the
288 // batch renderer from baking in simple, translate-only transforms into
289 // the vertex data. The shader will rely on the fact that
290 // vertexCoord.xy is the Shape-space coordinate and so no modifications
291 // are welcome.
292 setFlag(flags: Blending | RequiresFullMatrix | SupportsRhiShader);
293 }
294
295 QSGMaterialType *type() const override;
296 int compare(const QSGMaterial *other) const override;
297 QSGMaterialShader *createShader() const override;
298
299 QQuickShapeGenericStrokeFillNode *node() const { return m_node; }
300
301private:
302 QQuickShapeGenericStrokeFillNode *m_node;
303};
304
305#if QT_CONFIG(opengl)
306
307class QQuickShapeRadialGradientShader : public QSGMaterialShader
308{
309public:
310 QQuickShapeRadialGradientShader();
311
312 void initialize() override;
313 void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
314 char const *const *attributeNames() const override;
315
316private:
317 int m_opacityLoc = -1;
318 int m_matrixLoc = -1;
319 int m_translationPointLoc = -1;
320 int m_focalToCenterLoc = -1;
321 int m_centerRadiusLoc = -1;
322 int m_focalRadiusLoc = -1;
323};
324
325#endif // QT_CONFIG(opengl)
326
327class QQuickShapeRadialGradientRhiShader : public QSGMaterialRhiShader
328{
329public:
330 QQuickShapeRadialGradientRhiShader();
331
332 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
333 QSGMaterial *oldMaterial) override;
334 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
335 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
336
337private:
338 QVector2D m_focalPoint;
339 QVector2D m_focalToCenter;
340 float m_centerRadius;
341 float m_focalRadius;
342};
343
344class QQuickShapeRadialGradientMaterial : public QSGMaterial
345{
346public:
347 QQuickShapeRadialGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
348 : m_node(node)
349 {
350 setFlag(flags: Blending | RequiresFullMatrix | SupportsRhiShader);
351 }
352
353 QSGMaterialType *type() const override;
354 int compare(const QSGMaterial *other) const override;
355 QSGMaterialShader *createShader() const override;
356
357 QQuickShapeGenericStrokeFillNode *node() const { return m_node; }
358
359private:
360 QQuickShapeGenericStrokeFillNode *m_node;
361};
362
363#if QT_CONFIG(opengl)
364
365class QQuickShapeConicalGradientShader : public QSGMaterialShader
366{
367public:
368 QQuickShapeConicalGradientShader();
369
370 void initialize() override;
371 void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
372 char const *const *attributeNames() const override;
373
374private:
375 int m_opacityLoc = -1;
376 int m_matrixLoc = -1;
377 int m_angleLoc = -1;
378 int m_translationPointLoc = -1;
379};
380
381#endif // QT_CONFIG(opengl)
382
383class QQuickShapeConicalGradientRhiShader : public QSGMaterialRhiShader
384{
385public:
386 QQuickShapeConicalGradientRhiShader();
387
388 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
389 QSGMaterial *oldMaterial) override;
390 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
391 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
392
393private:
394 QVector2D m_centerPoint;
395 float m_angle;
396};
397
398class QQuickShapeConicalGradientMaterial : public QSGMaterial
399{
400public:
401 QQuickShapeConicalGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
402 : m_node(node)
403 {
404 setFlag(flags: Blending | RequiresFullMatrix | SupportsRhiShader);
405 }
406
407 QSGMaterialType *type() const override;
408 int compare(const QSGMaterial *other) const override;
409 QSGMaterialShader *createShader() const override;
410
411 QQuickShapeGenericStrokeFillNode *node() const { return m_node; }
412
413private:
414 QQuickShapeGenericStrokeFillNode *m_node;
415};
416
417QT_END_NAMESPACE
418
419#endif // QQUICKSHAPEGENERICRENDERER_P_H
420

source code of qtdeclarative/src/quickshapes/qquickshapegenericrenderer_p.h