QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskFillNode.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskFillNode.h"
7#include "QskGradientMaterial.h"
8#include "QskFillNodePrivate.h"
9#include "QskSGNode.h"
10
11#include <qsgflatcolormaterial.h>
12#include <qsgvertexcolormaterial.h>
13#include <qglobalstatic.h>
14
15Q_GLOBAL_STATIC( QSGVertexColorMaterial, qskMaterialColorVertex )
16
17static inline QskGradient::Type qskGradientType( QskFillNode::Coloring coloring )
18{
19 const auto type = QskGradient::Linear + coloring - QskFillNode::Linear;
20 return static_cast< QskGradient::Type >( type );
21}
22
23static inline QskFillNode::Coloring qskColoring( QskGradient::Type type )
24{
25 const auto coloring = QskFillNode::Linear + type - QskGradient::Linear;
26 return static_cast< QskFillNode::Coloring >( coloring );
27}
28
29static inline QskFillNode::Hints qskDefaultFillNodeHints()
30{
31 extern bool qskHasEnvironment( const char* );
32
33 QskFillNode::Hints hints;
34 if ( !qskHasEnvironment( "QSK_PREFER_SHADER_COLORS" ) )
35 hints |= QskFillNode::PreferColoredGeometry;
36
37 return hints;
38}
39
40QskFillNode::QskFillNode()
41 : QskFillNode( *new QskFillNodePrivate )
42{
43}
44
45QskFillNode::QskFillNode( QskFillNodePrivate& dd )
46 : QSGGeometryNode( dd )
47{
48 static const auto hints = qskDefaultFillNodeHints();
49
50 dd.hints = hints;
51 setGeometry( &dd.geometry );
52
53 setMaterial( qskMaterialColorVertex );
54 setFlag( QSGNode::OwnsMaterial, false );
55}
56
57QskFillNode::~QskFillNode()
58{
59}
60
61void QskFillNode::resetGeometry()
62{
63 QskSGNode::resetGeometry( this );
64}
65
66void QskFillNode::setColoring( Coloring coloring )
67{
68 Q_D( QskFillNode );
69
70 if ( coloring == d->coloring )
71 return;
72
73 d->coloring = coloring;
74
75 switch( coloring )
76 {
77 case Monochrome:
78 {
79 setMaterial( new QSGFlatColorMaterial() );
80 break;
81 }
82
83 case Polychrome:
84 {
85 setMaterial( qskMaterialColorVertex );
86 break;
87 }
88
89 /*
90 QSGDefaultInternalRectangleNode is using QSGSmoothColorMaterial.
91 Can we do something useful with it too ? TODO ...
92 */
93
94 default:
95 {
96 const auto gradientType = qskGradientType( coloring );
97 setMaterial( QskGradientMaterial::createMaterial( gradientType ) );
98 }
99 }
100
101 if ( material() == qskMaterialColorVertex )
102 {
103 /*
104 All color information is stored in the geometry and we can share
105 the material regardless of the specific colors.
106
107 As nodes with the same material can be batched it might make sense
108 to use this type of coloring for monochrome fillings: memory vs. performance.
109 */
110 setFlag( QSGNode::OwnsMaterial, false ); // shared: do not delete
111
112 if ( !isGeometryColored() )
113 {
114 const QSGGeometry g( QSGGeometry::defaultAttributes_ColoredPoint2D(), 0 );
115 memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
116 }
117 }
118 else
119 {
120 setFlag( QSGNode::OwnsMaterial, true );
121
122 if ( isGeometryColored() )
123 {
124 const QSGGeometry g( QSGGeometry::defaultAttributes_Point2D(), 0 );
125 memcpy( ( void* ) &d->geometry, ( void* ) &g, sizeof( QSGGeometry ) );
126 }
127 }
128}
129
130QskFillNode::Coloring QskFillNode::coloring() const
131{
132 return static_cast< QskFillNode::Coloring >( d_func()->coloring );
133}
134
135void QskFillNode::setColoring( const QColor& color )
136{
137 setColoring( Monochrome );
138
139 const auto colorRgb = color.toRgb();
140
141 auto mat = static_cast< QSGFlatColorMaterial* >( material() );
142 if ( mat->color() != colorRgb )
143 {
144 mat->setColor( colorRgb );
145 markDirty( QSGNode::DirtyMaterial );
146 }
147}
148
149void QskFillNode::setColoring( const QRectF& rect, const QskGradient& gradient )
150{
151 if ( gradient.isMonochrome() )
152 {
153 setColoring( gradient.startColor() );
154 }
155 else
156 {
157 if ( gradient.type() == QskGradient::Stops )
158 {
159 qWarning() << "QskFillNode::setColoring:"
160 << "QskGradient::Stops is not supported, using the first color instead.";
161
162 setColoring( gradient.startColor() );
163 }
164 else
165 {
166 setColoring( qskColoring( gradient.type() ) );
167
168 auto mat = static_cast< QskGradientMaterial* >( material() );
169 if ( mat->updateGradient( rect, gradient ) )
170 markDirty( QSGNode::DirtyMaterial );
171 }
172 }
173}
174
175void QskFillNode::setHint( Hint hint, bool on )
176{
177 Q_D( QskFillNode );
178
179 if ( on )
180 d->hints |= hint;
181 else
182 d->hints &= ~hint;
183}
184
185void QskFillNode::setHints( Hints hints )
186{
187 d_func()->hints = hints;
188}
189
190QskFillNode::Hints QskFillNode::hints() const
191{
192 return static_cast< QskFillNode::Hints >( d_func()->hints );
193}
194
195bool QskFillNode::hasHint( Hint hint ) const
196{
197 return d_func()->hints & hint;
198}
199
200bool QskFillNode::isGeometryColored() const
201{
202 return d_func()->geometry.attributeCount() != 1;
203}
204
205#include "moc_QskFillNode.cpp"