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