6#include "QskBoxRectangleNode.h"
7#include "QskBoxBorderColors.h"
8#include "QskBoxBorderMetrics.h"
9#include "QskBoxRenderer.h"
10#include "QskBoxShapeMetrics.h"
11#include "QskGradient.h"
12#include "QskGradientDirection.h"
13#include "QskFillNodePrivate.h"
15static inline bool qskHasBorder(
18 return !metrics.isNull() && colors.isVisible();
21class QskBoxRectangleNodePrivate final :
public QskFillNodePrivate
26 m_metricsHash = m_colorsHash = 0;
27 node->resetGeometry();
30 inline bool updateMetrics(
const QRectF& rect,
33 QskHashValue hash = 13000;
35 hash = qHashBits( &rect,
sizeof( rect ), hash );
36 hash = shape.hash( hash );
37 hash = borderMetrics.hash( hash );
39 return updateHash( m_metricsHash, hash );
42 inline bool updateColors(
45 QskHashValue hash = 13000;
47 if ( borderColors.isVisible() )
48 hash = borderColors.hash( hash );
50 if ( gradient.isVisible() )
51 hash = gradient.hash( hash );
53 return updateHash( m_colorsHash, hash );
57 inline bool updateHash( QskHashValue& value,
const QskHashValue newValue )
const
59 if ( newValue != value )
69 QskHashValue m_metricsHash = 0;
70 QskHashValue m_colorsHash = 0;
73QskBoxRectangleNode::QskBoxRectangleNode()
78QskBoxRectangleNode::~QskBoxRectangleNode()
82void QskBoxRectangleNode::updateFilling(
const QQuickWindow* window,
85 updateFilling( window, rect,
89void QskBoxRectangleNode::updateFilling(
const QQuickWindow* window,
95void QskBoxRectangleNode::updateFilling(
const QQuickWindow* window,
101 if ( rect.isEmpty() || !gradient.isVisible() )
103 d->resetNode(
this );
107 const auto fillGradient = QskBoxRenderer::effectiveGradient( gradient );
108 const auto shape = shapeMetrics.toAbsolute( rect.size() );
110 const bool coloredGeometry = hasHint( PreferColoredGeometry )
111 && QskBoxRenderer::isGradientSupported( fillGradient );
113 bool dirtyGeometry = d->updateMetrics( rect, shape, borderMetrics );
116 if ( coloredGeometry != isGeometryColored() )
117 dirtyGeometry = dirtyMaterial =
true;
119 if ( dirtyGeometry || dirtyMaterial )
123 if ( coloredGeometry )
125 setColoring( QskFillNode::Polychrome );
127 renderer.setColoredFillLines( rect, shape,
128 borderMetrics, fillGradient, *geometry() );
130 markDirty( QSGNode::DirtyGeometry );
134 setColoring( rect, fillGradient );
138 renderer.setFillLines( rect, shape, borderMetrics, *geometry() );
139 markDirty( QSGNode::DirtyGeometry );
145void QskBoxRectangleNode::updateBorder(
const QQuickWindow* window,
151 if ( rect.isEmpty() || !qskHasBorder( borderMetrics, borderColors ) )
153 d->resetNode(
this );
157 const auto shape = shapeMetrics.toAbsolute( rect.size() );
159 const bool coloredGeometry = hasHint( PreferColoredGeometry )
160 || !borderColors.isMonochrome();
162 bool dirtyGeometry = d->updateMetrics( rect, shape, borderMetrics );
163 bool dirtyMaterial = d->updateColors( borderColors,
QskGradient() );
165 if ( coloredGeometry != isGeometryColored() )
166 dirtyGeometry = dirtyMaterial =
true;
168 if ( dirtyGeometry || dirtyMaterial )
172 if ( coloredGeometry )
174 setColoring( QskFillNode::Polychrome );
176 renderer.setColoredBorderLines( rect, shape,
177 borderMetrics, borderColors, *geometry() );
179 markDirty( QSGNode::DirtyGeometry );
183 setColoring( borderColors.left().rgbStart() );
187 renderer.setBorderLines( rect, shape,
188 borderMetrics, *geometry() );
190 markDirty( QSGNode::DirtyGeometry );
196void QskBoxRectangleNode::updateBox(
const QQuickWindow* window,
const QRectF& rect,
202 if ( rect.isEmpty() )
204 d->resetNode(
this );
208 const bool hasFill = gradient.isVisible();
209 const bool hasBorder = qskHasBorder( borderMetrics, borderColors );
211 if ( hasFill && hasBorder )
213 const auto shape = shapeMetrics.toAbsolute( rect.size() );
215 const bool isDirty = d->updateMetrics( rect, shape, borderMetrics )
216 || d->updateColors( borderColors, gradient ) || !isGeometryColored();
225 setColoring( QskFillNode::Polychrome );
227 auto fillGradient = QskBoxRenderer::effectiveGradient( gradient );
228 if ( !QskBoxRenderer::isGradientSupported( fillGradient ) )
230 qWarning() <<
"QskBoxRenderer does not support radial/conic gradients";
231 fillGradient.setDirection( QskGradient::Linear );
235 renderer.setColoredBorderAndFillLines( rect, shape, borderMetrics,
236 borderColors, fillGradient, *geometry() );
238 markDirty( QSGNode::DirtyGeometry );
243 updateFilling( window, rect, shapeMetrics, borderMetrics, gradient );
245 else if ( hasBorder )
247 updateBorder( window, rect, shapeMetrics, borderMetrics, borderColors );
251 d->resetNode(
this );
255bool QskBoxRectangleNode::isCombinedGeometrySupported(
const QskGradient& gradient )
257 return QskBoxRenderer::isGradientSupported( gradient );