6#include "QskArcRenderNode.h"
7#include "QskGradient.h"
8#include "QskArcRenderer.h"
9#include "QskArcMetrics.h"
10#include "QskGradient.h"
12#include "QskRgbValue.h"
13#include "QskFillNodePrivate.h"
15static inline bool qskHasBorder( qreal width,
const QColor& color )
17 return ( width > 0.0 ) && QskRgb::isVisible( color );
20class QskArcRenderNodePrivate final :
public QskFillNodePrivate
25 m_metricsHash = m_colorsHash = 0;
26 node->resetGeometry();
29 inline bool updateMetrics(
const QRectF& rect,
30 const QskArcMetrics& metrics,
bool radial, qreal borderWidth )
32 QskHashValue hash = 13000;
34 hash = qHashBits( &rect,
sizeof( rect ), hash );
35 hash = metrics.hash( hash );
36 hash = qHash( radial, hash );
37 hash = qHash( borderWidth, hash );
39 return updateHash( m_metricsHash, hash );
42 inline bool updateColors(
const QColor& borderColor,
const QskGradient& gradient )
44 QskHashValue hash = 13000;
46 if ( QskRgb::isVisible( borderColor ) )
47 hash = qHashBits( &borderColor,
sizeof( borderColor ), hash );
49 if ( gradient.isVisible() )
50 hash = gradient.hash( hash );
52 return updateHash( m_colorsHash, hash );
56 inline bool updateHash( QskHashValue& value,
const QskHashValue newValue )
const
58 if ( newValue != value )
68 QskHashValue m_metricsHash = 0;
69 QskHashValue m_colorsHash = 0;
72QskArcRenderNode::QskArcRenderNode()
77QskArcRenderNode::~QskArcRenderNode()
81void QskArcRenderNode::updateFilling(
const QRectF& rect,
84 updateFilling( rect, metrics,
false, 0.0, gradient );
87void QskArcRenderNode::updateFilling(
const QRectF& rect,
93 if ( rect.isEmpty() || arcMetrics.isNull() || !gradient.isVisible() )
99 const auto metrics = arcMetrics.toAbsolute( rect.size() );
101 if ( borderWidth >= 0.5 * metrics.thickness() )
103 d->resetNode(
this );
107 bool coloredGeometry = hasHint( PreferColoredGeometry );
108 if ( coloredGeometry )
111 coloredGeometry = QskArcRenderer::isGradientSupported( rect, metrics, gradient );
116 coloredGeometry = ( gradient.type() == QskGradient::Stops );
119 bool dirtyGeometry = d->updateMetrics( rect, metrics, radial, borderWidth );
120 bool dirtyMaterial = d->updateColors( QColor(), gradient );
122 if ( coloredGeometry != isGeometryColored() )
123 dirtyGeometry = dirtyMaterial =
true;
125 if ( dirtyGeometry || dirtyMaterial )
127 if ( coloredGeometry )
129 setColoring( QskFillNode::Polychrome );
131 QskArcRenderer::setColoredFillLines( rect, metrics, radial,
132 borderWidth, gradient, *geometry() );
134 markDirty( QSGNode::DirtyGeometry );
138 setColoring( rect, gradient );
142 QskArcRenderer::setFillLines( rect, metrics,
143 radial, borderWidth, *geometry() );
145 markDirty( QSGNode::DirtyGeometry );
151void QskArcRenderNode::updateBorder(
const QRectF& rect,
153 qreal borderWidth,
const QColor& borderColor )
157 if ( rect.isEmpty() || arcMetrics.isNull()
158 || !qskHasBorder( borderWidth, borderColor ) )
160 d->resetNode(
this );
164 const bool coloredGeometry = hasHint( PreferColoredGeometry );
166 bool dirtyGeometry = d->updateMetrics( rect, arcMetrics, radial, borderWidth );
167 bool dirtyMaterial = d->updateColors( borderColor,
QskGradient() );
169 if ( coloredGeometry != isGeometryColored() )
170 dirtyGeometry = dirtyMaterial =
true;
172 if ( dirtyGeometry || dirtyMaterial )
174 const auto metrics = arcMetrics.toAbsolute( rect.size() );
175 borderWidth = qMin( borderWidth, 0.5 * metrics.thickness() );
177 if ( coloredGeometry )
179 setColoring( QskFillNode::Polychrome );
181 QskArcRenderer::setColoredBorderLines( rect, metrics, radial,
182 borderWidth, borderColor, *geometry() );
184 markDirty( QSGNode::DirtyGeometry );
188 setColoring( borderColor );
192 QskArcRenderer::setBorderLines( rect, metrics, radial,
193 borderWidth, *geometry() );
195 markDirty( QSGNode::DirtyGeometry );
201void QskArcRenderNode::updateArc(
202 const QRectF& rect,
const QskArcMetrics& arcMetrics,
bool radial,
203 qreal borderWidth,
const QColor& borderColor,
const QskGradient& gradient )
207 const auto metrics = arcMetrics.toAbsolute( rect.size() );
208 if ( rect.isEmpty() || metrics.isNull() )
210 d->resetNode(
this );
214 const auto borderMax = 0.5 * metrics.thickness();
216 const bool hasFill = gradient.isVisible() && ( borderWidth < borderMax );
217 const bool hasBorder = qskHasBorder( borderWidth, borderColor );
219 if ( hasBorder && hasFill )
226 borderWidth = qMin( borderWidth, borderMax );
228 const bool isDirty = d->updateMetrics( rect, arcMetrics, radial, borderWidth )
229 || d->updateColors( borderColor, gradient ) || !isGeometryColored();
233 setColoring( QskFillNode::Polychrome );
235 QskArcRenderer::setColoredBorderAndFillLines( rect, metrics, radial,
236 borderWidth, borderColor, gradient, *geometry() );
238 markDirty( QSGNode::DirtyGeometry );
241 else if ( hasBorder )
243 updateBorder( rect, arcMetrics, radial, borderWidth, borderColor );
247 updateFilling( rect, arcMetrics, radial, borderWidth, gradient );
251 d->resetNode(
this );