qskinny/src/nodes/QskArcNode.cpp

137 lines
3.3 KiB
C++
Raw Normal View History

2023-04-06 09:23:37 +02:00
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
2023-04-06 09:23:37 +02:00
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskArcNode.h"
#include "QskArcMetrics.h"
#include "QskMargins.h"
2022-06-01 16:57:57 +02:00
#include "QskGradient.h"
#include "QskShapeNode.h"
#include "QskStrokeNode.h"
#include "QskSGNode.h"
#include <qpen.h>
#include <qpainterpath.h>
2022-06-01 16:57:57 +02:00
static inline QskGradient qskEffectiveGradient(
2023-04-17 17:29:47 +02:00
const QskGradient& gradient, const QskArcMetrics& metrics )
2023-04-14 09:47:10 +02:00
{
if ( !gradient.isMonochrome() )
{
2023-04-14 09:47:10 +02:00
if ( gradient.type() == QskGradient::Stops )
{
QskGradient g( gradient.stops() );
2023-04-17 17:29:47 +02:00
g.setConicDirection( 0.5, 0.5, metrics.startAngle(), 360.0 );
2023-04-14 09:47:10 +02:00
return g;
}
}
2023-04-14 09:47:10 +02:00
return gradient;
2022-06-01 16:57:57 +02:00
}
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()
{
}
QskArcNode::~QskArcNode()
{
}
void QskArcNode::setArcData( const QRectF& rect,
const QskArcMetrics& arcMetrics, const QskGradient& fillGradient )
{
setArcData( rect, arcMetrics, 0.0, QColor(), fillGradient );
}
void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics,
2023-04-17 10:54:44 +02:00
qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient )
{
enum NodeRole
{
FillRole,
BorderRole
};
const auto metrics = qskEffectiveMetrics( arcMetrics, rect );
2023-04-17 17:29:47 +02:00
const auto gradient = qskEffectiveGradient( fillGradient, 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 = metrics.painterPath( arcRect );
if ( gradient.isVisible() && !metrics.isNull() )
{
if ( fillNode == nullptr )
{
fillNode = new QskShapeNode;
QskSGNode::setNodeRole( fillNode, FillRole );
2023-04-14 09:47:10 +02:00
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;
}
}