special code for corner cases disabled

This commit is contained in:
Uwe Rathmann 2024-06-03 15:36:15 +02:00
parent beb31f9f1f
commit fb635664de
4 changed files with 72 additions and 49 deletions

View File

@ -130,12 +130,17 @@ QPainterPath QskArcMetrics::painterPath( const QRectF& ellipseRect ) const
if ( t <= 0.0 || qFuzzyIsNull( m_spanAngle ) ) if ( t <= 0.0 || qFuzzyIsNull( m_spanAngle ) )
return QPainterPath(); return QPainterPath();
#if 0
/*
We do not have a proper solution for situations, where
the width leads to overlapping upper/lower or left/right parts.
*/
const auto innerRect = ellipseRect.adjusted( t, t, -t, -t ); const auto innerRect = ellipseRect.adjusted( t, t, -t, -t );
QPainterPath path;
if ( innerRect.isEmpty() ) if ( innerRect.isEmpty() )
{ {
QPainterPath path;
if ( qAbs( m_spanAngle ) >= 360.0 ) if ( qAbs( m_spanAngle ) >= 360.0 )
{ {
path.addEllipse( ellipseRect ); path.addEllipse( ellipseRect );
@ -148,24 +153,23 @@ QPainterPath QskArcMetrics::painterPath( const QRectF& ellipseRect ) const
path.lineTo( ellipseRect.center() ); path.lineTo( ellipseRect.center() );
path.closeSubpath(); path.closeSubpath();
} }
return path;
} }
else #endif
{
const auto t2 = 0.5 * t;
const auto r = ellipseRect.adjusted( t2, t2, -t2, -t2 );
QPainterPath arcPath; const auto t2 = 0.5 * t;
arcPath.arcMoveTo( r, m_startAngle ); // replaces the dummy arcMoveTo above const auto r = ellipseRect.adjusted( t2, t2, -t2, -t2 );
arcPath.arcTo( r, m_startAngle, m_spanAngle );
QPainterPathStroker stroker; QPainterPath path;
stroker.setCapStyle( Qt::FlatCap ); path.arcMoveTo( r, m_startAngle ); // replaces the dummy arcMoveTo above
stroker.setWidth( t ); path.arcTo( r, m_startAngle, m_spanAngle );
path = stroker.createStroke( arcPath ); QPainterPathStroker stroker;
} stroker.setCapStyle( Qt::FlatCap );
stroker.setWidth( t );
return path; return stroker.createStroke( path );
} }
QRectF QskArcMetrics::boundingRect( const QRectF& ellipseRect ) const QRectF QskArcMetrics::boundingRect( const QRectF& ellipseRect ) const

View File

@ -7,6 +7,7 @@
#include "QskArcMetrics.h" #include "QskArcMetrics.h"
#include "QskArcShadowNode.h" #include "QskArcShadowNode.h"
#include "QskArcRenderNode.h" #include "QskArcRenderNode.h"
#include "QskArcRenderer.h"
#include "QskMargins.h" #include "QskMargins.h"
#include "QskGradient.h" #include "QskGradient.h"
#include "QskShapeNode.h" #include "QskShapeNode.h"
@ -17,7 +18,6 @@
#include <qpainterpath.h> #include <qpainterpath.h>
// #define ARC_BORDER_NODE // #define ARC_BORDER_NODE
#define ARC_FILL_NODE
#ifdef ARC_BORDER_NODE #ifdef ARC_BORDER_NODE
using BorderNode = QskArcRenderNode; using BorderNode = QskArcRenderNode;
@ -26,18 +26,15 @@
using BorderNode = QskStrokeNode; using BorderNode = QskStrokeNode;
#endif #endif
#ifdef ARC_FILL_NODE
using FillNode = QskArcRenderNode;
#else
using FillNode = QskShapeNode;
#endif
namespace namespace
{ {
enum NodeRole enum NodeRole
{ {
ShadowRole, ShadowRole,
FillRole,
PathRole,
ArcRole,
BorderRole BorderRole
}; };
} }
@ -84,7 +81,8 @@ static inline QRectF qskEffectiveRect(
static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node ) static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node )
{ {
static const QVector< quint8 > roles = { ShadowRole, FillRole, BorderRole }; static const QVector< quint8 > roles =
{ ShadowRole, PathRole, ArcRole, BorderRole };
auto oldNode = QskSGNode::findChildNode( parentNode, role ); auto oldNode = QskSGNode::findChildNode( parentNode, role );
QskSGNode::replaceChildNode( roles, role, parentNode, oldNode, node ); QskSGNode::replaceChildNode( roles, role, parentNode, oldNode, node );
@ -120,17 +118,21 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
auto shadowNode = static_cast< QskArcShadowNode* >( auto shadowNode = static_cast< QskArcShadowNode* >(
QskSGNode::findChildNode( this, ShadowRole ) ); QskSGNode::findChildNode( this, ShadowRole ) );
auto fillNode = static_cast< FillNode* >( auto pathNode = static_cast< QskShapeNode* >(
QskSGNode::findChildNode( this, FillRole ) ); QskSGNode::findChildNode( this, PathRole ) );
auto arcNode = static_cast< QskArcRenderNode* >(
QskSGNode::findChildNode( this, ArcRole ) );
auto borderNode = static_cast< BorderNode* >( auto borderNode = static_cast< BorderNode* >(
QskSGNode::findChildNode( this, BorderRole ) ); QskSGNode::findChildNode( this, BorderRole ) );
const auto arcRect = qskEffectiveRect( rect, borderWidth ); const auto arcRect = qskEffectiveRect( rect, borderWidth );
if ( arcRect.isEmpty() ) if ( metricsArc.isNull() || arcRect.isEmpty() )
{ {
delete shadowNode; delete shadowNode;
delete fillNode; delete pathNode;
delete arcNode;
delete borderNode; delete borderNode;
return; return;
} }
@ -172,22 +174,39 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
if ( isFillNodeVisible ) if ( isFillNodeVisible )
{ {
if ( fillNode == nullptr ) if ( QskArcRenderer::isGradientSupported( gradient ) )
{ {
fillNode = new FillNode; delete pathNode;
QskSGNode::setNodeRole( fillNode, FillRole ); pathNode = nullptr;
}
#ifdef ARC_FILL_NODE if ( arcNode == nullptr )
fillNode->updateNode( arcRect, metricsArc, gradient ); {
#else arcNode = new QskArcRenderNode;
fillNode->updateNode( path, QTransform(), arcRect, gradient ); QskSGNode::setNodeRole( arcNode, ArcRole );
#endif }
arcNode->updateNode( arcRect, metricsArc, gradient );
}
else
{
delete arcNode;
arcNode = nullptr;
if ( pathNode == nullptr )
{
pathNode = new QskShapeNode;
QskSGNode::setNodeRole( pathNode, PathRole );
}
pathNode->updateNode( path, QTransform(), arcRect, gradient );
}
} }
else else
{ {
delete fillNode; delete pathNode;
fillNode = nullptr; pathNode = nullptr;
delete arcNode;
arcNode = nullptr;
} }
if ( isStrokeNodeVisible ) if ( isStrokeNodeVisible )
@ -214,6 +233,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
} }
qskUpdateChildren( this, ShadowRole, shadowNode ); qskUpdateChildren( this, ShadowRole, shadowNode );
qskUpdateChildren( this, FillRole, fillNode ); qskUpdateChildren( this, PathRole, pathNode );
qskUpdateChildren( this, ArcRole, arcNode );
qskUpdateChildren( this, BorderRole, borderNode ); qskUpdateChildren( this, BorderRole, borderNode );
} }

View File

@ -264,13 +264,12 @@ void QskArcRenderer::renderFillGeometry( const QRectF& rect,
renderFillGeometry( rect, metrics, 0.0, geometry ); renderFillGeometry( rect, metrics, 0.0, geometry );
} }
bool QskArcRenderer::isGradientSupported( bool QskArcRenderer::isGradientSupported( const QskGradient& gradient )
const QskArcMetrics& metrics, const QskGradient& gradient )
{ {
if ( metrics.isNull() || !gradient.isVisible() || gradient.isMonochrome() ) if ( gradient.isVisible() && !gradient.isMonochrome() )
return true; return gradient.type() == QskGradient::Stops;
return gradient.type() == QskGradient::Stops; return true;
} }
void QskArcRenderer::renderArc( const QRectF& rect, void QskArcRenderer::renderArc( const QRectF& rect,

View File

@ -22,7 +22,7 @@ namespace QskArcRenderer
see QSGGeometry::defaultAttributes_Point2D() see QSGGeometry::defaultAttributes_Point2D()
- clip nodes - clip nodes
- using shaders setting the color information - using shaders setting the colors
*/ */
QSK_EXPORT void renderBorderGeometry( const QRectF&, QSK_EXPORT void renderBorderGeometry( const QRectF&,
@ -35,10 +35,10 @@ namespace QskArcRenderer
const QskArcMetrics&, QSGGeometry& ); const QskArcMetrics&, QSGGeometry& );
/* /*
Filling the geometry usually with color information: Filling the geometry with color information:
see QSGGeometry::defaultAttributes_ColoredPoint2D() see QSGGeometry::defaultAttributes_ColoredPoint2D()
*/ */
QSK_EXPORT bool isGradientSupported( const QskArcMetrics&, const QskGradient& ); QSK_EXPORT bool isGradientSupported( const QskGradient& );
QSK_EXPORT void renderArc( const QRectF&, QSK_EXPORT void renderArc( const QRectF&,
const QskArcMetrics&, qreal borderWidth, const QColor& borderColor, const QskArcMetrics&, qreal borderWidth, const QColor& borderColor,