From fb635664de79ac4eeffda651ef88b51705c78f16 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jun 2024 15:36:15 +0200 Subject: [PATCH] special code for corner cases disabled --- src/common/QskArcMetrics.cpp | 36 ++++++++++--------- src/nodes/QskArcNode.cpp | 70 +++++++++++++++++++++++------------- src/nodes/QskArcRenderer.cpp | 9 +++-- src/nodes/QskArcRenderer.h | 6 ++-- 4 files changed, 72 insertions(+), 49 deletions(-) diff --git a/src/common/QskArcMetrics.cpp b/src/common/QskArcMetrics.cpp index 2b3dcaf9..b938aa05 100644 --- a/src/common/QskArcMetrics.cpp +++ b/src/common/QskArcMetrics.cpp @@ -130,12 +130,17 @@ QPainterPath QskArcMetrics::painterPath( const QRectF& ellipseRect ) const if ( t <= 0.0 || qFuzzyIsNull( m_spanAngle ) ) 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 ); - - QPainterPath path; - if ( innerRect.isEmpty() ) { + QPainterPath path; + if ( qAbs( m_spanAngle ) >= 360.0 ) { path.addEllipse( ellipseRect ); @@ -148,24 +153,23 @@ QPainterPath QskArcMetrics::painterPath( const QRectF& ellipseRect ) const path.lineTo( ellipseRect.center() ); path.closeSubpath(); } + + return path; } - else - { - const auto t2 = 0.5 * t; - const auto r = ellipseRect.adjusted( t2, t2, -t2, -t2 ); +#endif - QPainterPath arcPath; - arcPath.arcMoveTo( r, m_startAngle ); // replaces the dummy arcMoveTo above - arcPath.arcTo( r, m_startAngle, m_spanAngle ); + const auto t2 = 0.5 * t; + const auto r = ellipseRect.adjusted( t2, t2, -t2, -t2 ); - QPainterPathStroker stroker; - stroker.setCapStyle( Qt::FlatCap ); - stroker.setWidth( t ); + QPainterPath path; + path.arcMoveTo( r, m_startAngle ); // replaces the dummy arcMoveTo above + 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 diff --git a/src/nodes/QskArcNode.cpp b/src/nodes/QskArcNode.cpp index dc84e8fd..1fe2862d 100644 --- a/src/nodes/QskArcNode.cpp +++ b/src/nodes/QskArcNode.cpp @@ -7,6 +7,7 @@ #include "QskArcMetrics.h" #include "QskArcShadowNode.h" #include "QskArcRenderNode.h" +#include "QskArcRenderer.h" #include "QskMargins.h" #include "QskGradient.h" #include "QskShapeNode.h" @@ -17,7 +18,6 @@ #include // #define ARC_BORDER_NODE -#define ARC_FILL_NODE #ifdef ARC_BORDER_NODE using BorderNode = QskArcRenderNode; @@ -26,18 +26,15 @@ using BorderNode = QskStrokeNode; #endif -#ifdef ARC_FILL_NODE - using FillNode = QskArcRenderNode; -#else - using FillNode = QskShapeNode; -#endif - namespace { enum NodeRole { ShadowRole, - FillRole, + + PathRole, + ArcRole, + BorderRole }; } @@ -84,7 +81,8 @@ static inline QRectF qskEffectiveRect( 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 ); 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* >( QskSGNode::findChildNode( this, ShadowRole ) ); - auto fillNode = static_cast< FillNode* >( - QskSGNode::findChildNode( this, FillRole ) ); + auto pathNode = static_cast< QskShapeNode* >( + QskSGNode::findChildNode( this, PathRole ) ); + + auto arcNode = static_cast< QskArcRenderNode* >( + QskSGNode::findChildNode( this, ArcRole ) ); auto borderNode = static_cast< BorderNode* >( QskSGNode::findChildNode( this, BorderRole ) ); const auto arcRect = qskEffectiveRect( rect, borderWidth ); - if ( arcRect.isEmpty() ) + if ( metricsArc.isNull() || arcRect.isEmpty() ) { delete shadowNode; - delete fillNode; + delete pathNode; + delete arcNode; delete borderNode; return; } @@ -172,22 +174,39 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics if ( isFillNodeVisible ) { - if ( fillNode == nullptr ) + if ( QskArcRenderer::isGradientSupported( gradient ) ) { - fillNode = new FillNode; - QskSGNode::setNodeRole( fillNode, FillRole ); - } + delete pathNode; + pathNode = nullptr; -#ifdef ARC_FILL_NODE - fillNode->updateNode( arcRect, metricsArc, gradient ); -#else - fillNode->updateNode( path, QTransform(), arcRect, gradient ); -#endif + if ( arcNode == nullptr ) + { + arcNode = new QskArcRenderNode; + QskSGNode::setNodeRole( arcNode, ArcRole ); + } + + 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 { - delete fillNode; - fillNode = nullptr; + delete pathNode; + pathNode = nullptr; + + delete arcNode; + arcNode = nullptr; } if ( isStrokeNodeVisible ) @@ -214,6 +233,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics } qskUpdateChildren( this, ShadowRole, shadowNode ); - qskUpdateChildren( this, FillRole, fillNode ); + qskUpdateChildren( this, PathRole, pathNode ); + qskUpdateChildren( this, ArcRole, arcNode ); qskUpdateChildren( this, BorderRole, borderNode ); } diff --git a/src/nodes/QskArcRenderer.cpp b/src/nodes/QskArcRenderer.cpp index b6366d94..755ffed3 100644 --- a/src/nodes/QskArcRenderer.cpp +++ b/src/nodes/QskArcRenderer.cpp @@ -264,13 +264,12 @@ void QskArcRenderer::renderFillGeometry( const QRectF& rect, renderFillGeometry( rect, metrics, 0.0, geometry ); } -bool QskArcRenderer::isGradientSupported( - const QskArcMetrics& metrics, const QskGradient& gradient ) +bool QskArcRenderer::isGradientSupported( const QskGradient& gradient ) { - if ( metrics.isNull() || !gradient.isVisible() || gradient.isMonochrome() ) - return true; + if ( gradient.isVisible() && !gradient.isMonochrome() ) + return gradient.type() == QskGradient::Stops; - return gradient.type() == QskGradient::Stops; + return true; } void QskArcRenderer::renderArc( const QRectF& rect, diff --git a/src/nodes/QskArcRenderer.h b/src/nodes/QskArcRenderer.h index 6989374e..dc7e7375 100644 --- a/src/nodes/QskArcRenderer.h +++ b/src/nodes/QskArcRenderer.h @@ -22,7 +22,7 @@ namespace QskArcRenderer see QSGGeometry::defaultAttributes_Point2D() - clip nodes - - using shaders setting the color information + - using shaders setting the colors */ QSK_EXPORT void renderBorderGeometry( const QRectF&, @@ -35,10 +35,10 @@ namespace QskArcRenderer const QskArcMetrics&, QSGGeometry& ); /* - Filling the geometry usually with color information: + Filling the geometry with color information: see QSGGeometry::defaultAttributes_ColoredPoint2D() */ - QSK_EXPORT bool isGradientSupported( const QskArcMetrics&, const QskGradient& ); + QSK_EXPORT bool isGradientSupported( const QskGradient& ); QSK_EXPORT void renderArc( const QRectF&, const QskArcMetrics&, qreal borderWidth, const QColor& borderColor,