qskinny/src/nodes/QskArcRenderNode.cpp

157 lines
4.3 KiB
C++

/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskArcRenderNode.h"
#include "QskGradient.h"
#include "QskArcRenderer.h"
#include "QskArcMetrics.h"
#include "QskGradient.h"
#include "QskSGNode.h"
#include "QskFillNodePrivate.h"
class QskArcRenderNodePrivate final : public QskFillNodePrivate
{
public:
inline void resetNode( QskArcRenderNode* node )
{
hash = 0;
node->resetGeometry();
}
inline bool updateHash( const QRectF& rect, const QskArcMetrics& metrics,
bool radial, qreal borderWidth, const QColor& borderColor,
const QskGradient& gradient )
{
QskHashValue value = 3496;
value = qHashBits( &rect, sizeof( QRectF ), value );
value = metrics.hash( value );
value = qHash( radial, value );
value = qHash( borderWidth, value );
value = qHashBits( &borderColor, sizeof( borderColor ), value );
if ( gradient.isVisible() )
value = gradient.hash( value );
if ( hash != value )
{
hash = value;
return true;
}
return false;
}
private:
QskHashValue hash = 0;
};
QskArcRenderNode::QskArcRenderNode()
: QskFillNode( *new QskArcRenderNodePrivate )
{
}
QskArcRenderNode::~QskArcRenderNode()
{
}
void QskArcRenderNode::updateFilling( const QRectF& rect,
const QskArcMetrics& metrics, const QskGradient& gradient )
{
updateFilling( rect, metrics, false, 0.0, gradient );
}
void QskArcRenderNode::updateFilling( const QRectF& rect,
const QskArcMetrics& arcMetrics, bool radial,
qreal borderWidth, const QskGradient& gradient )
{
Q_D( QskArcRenderNode );
const auto metrics = arcMetrics.toAbsolute( rect.size() );
const auto borderMax = 0.5 * metrics.thickness();
const bool hasFill = gradient.isVisible() && ( borderWidth < borderMax );
const bool hasBorder = false;
if ( rect.isEmpty() || metrics.isNull() || !( hasFill || hasBorder ) )
{
d->resetNode( this );
return;
}
borderWidth = qMin( borderWidth, borderMax );
if ( !d->updateHash( rect, metrics, radial, borderWidth, QColor(), gradient ) )
{
d->resetNode( this );
return;
}
#if 1
const bool coloredGeometry = hasHint( PreferColoredGeometry )
&& QskArcRenderer::isGradientSupported( rect, metrics, gradient );
Q_ASSERT( coloredGeometry ); // TODO ...
#endif
auto& geometry = *this->geometry();
setColoring( QskFillNode::Polychrome );
QskArcRenderer::setColoredFillLines( rect, metrics, radial,
borderWidth, gradient, geometry );
markDirty( QSGNode::DirtyGeometry );
}
void QskArcRenderNode::updateBorder( const QRectF& rect,
const QskArcMetrics& metrics, bool radial,
qreal borderWidth, const QColor& borderColor )
{
updateArc( rect, metrics, radial, borderWidth, borderColor, QskGradient() );
}
void QskArcRenderNode::updateArc(
const QRectF& rect, const QskArcMetrics& arcMetrics, bool radial,
qreal borderWidth, const QColor& borderColor, const QskGradient& gradient )
{
Q_D( QskArcRenderNode );
const auto metrics = arcMetrics.toAbsolute( rect.size() );
const auto borderMax = 0.5 * metrics.thickness();
const bool hasFill = gradient.isVisible() && ( borderWidth < borderMax );
const bool hasBorder = ( borderWidth > 0.0 )
&& borderColor.isValid() && ( borderColor.alpha() > 0 );
if ( rect.isEmpty() || metrics.isNull() || !( hasFill || hasBorder ) )
{
d->resetNode( this );
return;
}
borderWidth = qMin( borderWidth, borderMax );
if ( !d->updateHash( rect, metrics, radial, borderWidth, borderColor, gradient ) )
{
d->resetNode( this );
return;
}
#if 1
const bool coloredGeometry = hasHint( PreferColoredGeometry )
&& QskArcRenderer::isGradientSupported( rect, metrics, gradient );
Q_ASSERT( coloredGeometry ); // TODO ...
#endif
auto& geometry = *this->geometry();
setColoring( QskFillNode::Polychrome );
QskArcRenderer::setColoredBorderAndFillLines( rect, metrics, radial,
borderWidth, borderColor, gradient, geometry );
markDirty( QSGNode::DirtyGeometry );
}