QSkinny 0.8.0
C++/Qt UI toolkit
All Classes Namespaces Functions Variables Enumerations Enumerator Properties Pages
QskShapeNode.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskShapeNode.h"
7#include "QskGradient.h"
8#include "QskGradientDirection.h"
9#include "QskVertex.h"
10#include "QskFillNodePrivate.h"
11#include "QskInternalMacros.h"
12
13QSK_QT_PRIVATE_BEGIN
14#include <private/qvectorpath_p.h>
15#include <private/qtriangulator_p.h>
16QSK_QT_PRIVATE_END
17
18#if 0
19
20// keeping the index list
21static void qskUpdateGeometry( const QPainterPath& path,
22 const QTransform& transform, const QColor&, QSGGeometry& geometry )
23{
24 const auto ts = qTriangulate( path, transform, 1, false );
25
26 geometry.allocate( ts.vertices.size(), ts.indices.size() );
27
28 auto vertexData = reinterpret_cast< float* >( geometry.vertexData() );
29 const auto points = ts.vertices.constData();
30
31 for ( int i = 0; i < ts.vertices.count(); i++ )
32 vertexData[i] = points[i];
33
34 memcpy( geometry.indexData(), ts.indices.data(),
35 ts.indices.size() * sizeof( quint16 ) );
36}
37
38#else
39
40static void qskUpdateGeometry( const QPainterPath& path,
41 const QTransform& transform, const QColor& color, QSGGeometry& geometry )
42{
43 const auto ts = qTriangulate( path, transform, 1, false );
44
45 /*
46 The triangulation of a random path usually does not lead to index lists
47 that allow substantially reducing the number of vertices.
48
49 As we have to iterate over the vertex buffer to copy qreal to float
50 anyway we reorder according to the index buffer and drop
51 the index buffer.
52
53 QTriangleSet:
54
55 vertices: (x[i[n]], y[i[n]]), (x[j[n]], y[j[n]]), (x[k[n]], y[k[n]]), n = 0, 1, ...
56 QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...]
57 QVector<quint16> indices; // [i[0], j[0], k[0], i[1], j[1], k[1], i[2], ...]
58 */
59
60 const auto points = ts.vertices.constData();
61 const auto indices = reinterpret_cast< const quint16* >( ts.indices.data() );
62
63 geometry.allocate( ts.indices.size() );
64
65 if ( color.isValid() )
66 {
67 const QskVertex::Color c = color;
68
69 auto vertexData = geometry.vertexDataAsColoredPoint2D();
70 for ( int i = 0; i < ts.indices.size(); i++ )
71 {
72 const int j = 2 * indices[i];
73 vertexData[i].set( points[j], points[j + 1], c.r, c.g, c.b, c.a );
74 }
75 }
76 else
77 {
78 auto vertexData = geometry.vertexDataAsPoint2D();
79 for ( int i = 0; i < ts.indices.size(); i++ )
80 {
81 const int j = 2 * indices[i];
82 vertexData[i].set( points[j], points[j + 1] );
83 }
84 }
85}
86
87#endif
88
89class QskShapeNodePrivate final : public QskFillNodePrivate
90{
91 public:
92 /*
93 Is there a better way to find out if the path has changed
94 beside storing a copy ( even, when internally with Copy On Write ) ?
95 */
96 QPainterPath path;
97 QTransform transform;
98};
99
100QskShapeNode::QskShapeNode()
101 : QskFillNode( *new QskShapeNodePrivate )
102{
103#if 1
104 /*
105 for some reason we have a broken geometry for some of
106 contours of shapes example, when not setting Monochrome.
107 Does not make any sense and needs to be understood: TODO
108 */
109 setColoring( Monochrome );
110#endif
111
112 geometry()->setDrawingMode( QSGGeometry::DrawTriangles );
113}
114
115QskShapeNode::~QskShapeNode()
116{
117}
118
119void QskShapeNode::updatePath( const QPainterPath& path,
120 const QTransform& transform, const QRectF& rect, const QskGradient& gradient )
121{
122 Q_D( QskShapeNode );
123
124 if ( path.isEmpty() || !gradient.isVisible() )
125 {
126 d->path = QPainterPath();
127 d->transform = QTransform();
128 resetGeometry();
129
130 return;
131 }
132
133 QColor c;
134
135 if ( gradient.isMonochrome() && hasHint( PreferColoredGeometry ) )
136 c = gradient.startColor();
137
138 const bool isDirty = ( isGeometryColored() != c.isValid() );
139
140 if ( c.isValid() )
141 setColoring( QskFillNode::Polychrome );
142 else
143 setColoring( rect, gradient );
144
145 if ( isDirty || ( transform != d->transform ) || ( path != d->path ) )
146 {
147 d->path = path;
148 d->transform = transform;
149
150 qskUpdateGeometry( path, transform, c, *geometry() );
151
152 geometry()->markVertexDataDirty();
153 markDirty( QSGNode::DirtyGeometry );
154 }
155}