QskArcNode as composite of fill/border nodes

This commit is contained in:
Uwe Rathmann 2023-04-14 12:44:49 +02:00
parent 73dd618626
commit 328e6a9e6f
3 changed files with 107 additions and 21 deletions

View File

@ -205,25 +205,16 @@ static inline QSGNode* qskUpdateBoxNode(
static inline QSGNode* qskUpdateArcNode(
const QskSkinnable*, QSGNode* node, const QRectF& rect,
const QskGradient& fillGradient, const QskArcMetrics& metrics )
const QskGradient& gradient, const QskArcMetrics& metrics )
{
if ( rect.isEmpty() )
return nullptr;
const auto rx = 0.5 * rect.width();
const auto ry = 0.5 * rect.height();
const auto absoluteMetrics = metrics.toAbsolute( rx, ry );
if ( !qskIsArcVisible( absoluteMetrics, fillGradient ) )
if ( rect.isEmpty() || !qskIsArcVisible( metrics, gradient ) )
return nullptr;
auto arcNode = static_cast< QskArcNode* >( node );
if ( arcNode == nullptr )
arcNode = new QskArcNode();
arcNode->setArcData( rect, absoluteMetrics, fillGradient );
arcNode->setArcData( rect, metrics, gradient );
return arcNode;
}

View File

@ -6,16 +6,21 @@
#include "QskArcNode.h"
#include "QskArcRenderer.h"
#include "QskArcMetrics.h"
#include "QskMargins.h"
#include "QskGradient.h"
#include "QskGradientDirection.h"
#include "QskShapeNode.h"
#include "QskStrokeNode.h"
#include "QskSGNode.h"
#include <qpen.h>
#include <qpainterpath.h>
#define LINEAR_GRADIENT_HACK 1
#if LINEAR_GRADIENT_HACK
static inline QskGradient buildGradient( QskGradient::Type type,
static inline QskGradient qskBuildGradient( QskGradient::Type type,
const QRectF& rect, const QskArcMetrics& metrics,
const QskGradientStops& stops )
{
@ -63,8 +68,9 @@ static inline QskGradient buildGradient( QskGradient::Type type,
#endif
static inline QskGradient effectiveGradient( const QRectF& rect,
const QskArcMetrics& metrics, const QskGradient& gradient )
static inline QskGradient qskEffectiveGradient(
const QskGradient& gradient, const QRectF& rect,
const QskArcMetrics& metrics )
{
if ( !gradient.isMonochrome() )
{
@ -91,7 +97,7 @@ static inline QskGradient effectiveGradient( const QRectF& rect,
const auto type = gradient.linearDirection().isHorizontal()
? QskGradient::Conic : QskGradient::Radial;
return buildGradient( type, rect, metrics, gradient.stops() );
return qskBuildGradient( type, rect, metrics, gradient.stops() );
}
#endif
}
@ -99,6 +105,29 @@ static inline QskGradient effectiveGradient( const QRectF& rect,
return gradient;
}
static inline QskArcMetrics qskEffectiveMetrics(
const QskArcMetrics& metrics, const QRectF& rect )
{
if ( metrics.sizeMode() == Qt::RelativeSize )
{
const auto rx = 0.5 * rect.width();
const auto ry = 0.5 * rect.height();
return metrics.toAbsolute( rx, ry );
}
return metrics;
}
static inline QRectF qskEffectiveRect(
const QRectF& rect, const qreal borderWidth )
{
if ( borderWidth <= 0.0 )
return rect;
return qskValidOrEmptyInnerRect( rect, QskMargins( 0.5 * borderWidth ) );
}
QskArcNode::QskArcNode()
{
}
@ -108,10 +137,74 @@ QskArcNode::~QskArcNode()
}
void QskArcNode::setArcData( const QRectF& rect,
const QskArcMetrics& metrics, const QskGradient& gradient )
const QskArcMetrics& arcMetrics, const QskGradient& fillGradient )
{
const auto path = QskArcRenderer::arcPath( rect, metrics );
updateNode( path, QTransform(), rect,
effectiveGradient( rect, metrics, gradient ) );
setArcData( rect, arcMetrics, 0.0, QColor(), fillGradient );
}
void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics,
qreal borderWidth, const QColor borderColor, const QskGradient& fillGradient )
{
enum NodeRole
{
FillRole,
BorderRole
};
const auto metrics = qskEffectiveMetrics( arcMetrics, rect );
const auto gradient = qskEffectiveGradient( fillGradient, rect, metrics );
auto fillNode = static_cast< QskShapeNode* >(
QskSGNode::findChildNode( this, FillRole ) );
auto borderNode = static_cast< QskStrokeNode* >(
QskSGNode::findChildNode( this, BorderRole ) );
const auto arcRect = qskEffectiveRect( rect, borderWidth );
if ( arcRect.isEmpty() )
{
delete fillNode;
delete borderNode;
return;
}
const auto path = QskArcRenderer::arcPath( arcRect, metrics );
if ( gradient.isVisible() && !metrics.isNull() )
{
if ( fillNode == nullptr )
{
fillNode = new QskShapeNode;
QskSGNode::setNodeRole( fillNode, FillRole );
prependChildNode( fillNode );
}
fillNode->updateNode( path, QTransform(), arcRect, gradient );
}
else
{
delete fillNode;
}
if ( borderWidth > 0.0 && borderColor.alpha() > 0 )
{
if ( borderNode == nullptr )
{
borderNode = new QskStrokeNode;
QskSGNode::setNodeRole( borderNode, BorderRole );
appendChildNode( borderNode );
}
QPen pen( borderColor, borderWidth );
pen.setCapStyle( Qt::FlatCap );
borderNode->updateNode( path, QTransform(), pen );
}
else
{
delete borderNode;
}
}

View File

@ -23,6 +23,8 @@ class QSK_EXPORT QskArcNode : public QskShapeNode
~QskArcNode() override;
void setArcData( const QRectF&, const QskArcMetrics&, const QskGradient& );
void setArcData( const QRectF&, const QskArcMetrics&,
qreal borderWidth, const QColor borderColor, const QskGradient& );
};
#endif