From 0d87964727c50e984ea031346f559d4d48676dbc Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 17 Jul 2024 14:19:54 +0200 Subject: [PATCH] QskArcRenderNode stays inside its given rectangle --- playground/shadows/ArcPage.cpp | 5 ++++- src/nodes/QskArcNode.cpp | 30 ++++++++++-------------------- src/nodes/QskArcRenderNode.cpp | 9 +++++++-- src/nodes/QskArcRenderer.cpp | 5 ++--- 4 files changed, 23 insertions(+), 26 deletions(-) diff --git a/playground/shadows/ArcPage.cpp b/playground/shadows/ArcPage.cpp index 7ccd7dbe..ffd93bc6 100644 --- a/playground/shadows/ArcPage.cpp +++ b/playground/shadows/ArcPage.cpp @@ -8,6 +8,7 @@ #include "Slider.h" #include +#include namespace { @@ -54,6 +55,9 @@ namespace public: Arc() { + setBackgroundColor( QskRgb::LemonChiffon ); + setClip( true ); // for testing if the arc stays inside its bounding rectangle + setStartAngle( 45.0 ); setSpanAngle( 270.0 ); setThickness( 10.0 ); @@ -101,7 +105,6 @@ ArcPage::ArcPage( QQuickItem* parent ) : QskLinearBox( Qt::Vertical, parent ) { auto arc = new Arc(); - arc->setMargins( 40 ); // some extra space for testing the offsets auto panel = new ControlPanel( arc ); panel->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed ); diff --git a/src/nodes/QskArcNode.cpp b/src/nodes/QskArcNode.cpp index 7f3a869e..dcb5fd3b 100644 --- a/src/nodes/QskArcNode.cpp +++ b/src/nodes/QskArcNode.cpp @@ -56,15 +56,6 @@ static inline QskGradient qskEffectiveGradient( return gradient; } -static inline QRectF qskEffectiveRect( - const QRectF& rect, const qreal borderWidth ) -{ - if ( borderWidth <= 0.0 ) - return rect; - - return qskValidOrEmptyInnerRect( rect, QskMargins( 0.5 * borderWidth ) ); -} - static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node ) { static const QVector< quint8 > roles = @@ -114,8 +105,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics auto borderNode = static_cast< BorderNode* >( QskSGNode::findChildNode( this, BorderRole ) ); - const auto arcRect = qskEffectiveRect( rect, borderWidth ); - if ( metricsArc.isNull() || arcRect.isEmpty() ) + if ( metricsArc.isNull() || rect.isEmpty() ) { delete shadowNode; delete pathNode; @@ -125,12 +115,10 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics } const auto isFillNodeVisible = gradient.isVisible(); - const auto isStrokeNodeVisible = ( borderWidth > 0.0 ) && ( borderColor.alpha() > 0 ); + const auto isBorderNodeVisible = ( borderWidth > 0.0 ) && ( borderColor.alpha() > 0 ); const auto isShadowNodeVisible = isFillNodeVisible && shadowColor.isValid() && ( shadowColor.alpha() > 0.0 ); - const auto path = metricsArc.painterPath( arcRect, radial ); - if ( isShadowNodeVisible ) { if ( shadowNode == nullptr ) @@ -146,8 +134,8 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics and not only to its radius. TODO ... */ - const auto sm = shadowMetrics.toAbsolute( arcRect.size() ); - const auto shadowRect = sm.shadowRect( arcRect ); + const auto sm = shadowMetrics.toAbsolute( rect.size() ); + const auto shadowRect = sm.shadowRect( rect ); const auto spreadRadius = sm.spreadRadius() + 0.5 * metricsArc.thickness(); shadowNode->setShadowData( shadowRect, spreadRadius, sm.blurRadius(), @@ -172,7 +160,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics QskSGNode::setNodeRole( arcNode, ArcRole ); } - arcNode->updateNode( arcRect, metricsArc, radial, + arcNode->updateNode( rect, metricsArc, radial, borderWidth, QColor(), gradient ); } else @@ -186,7 +174,8 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics QskSGNode::setNodeRole( pathNode, PathRole ); } - pathNode->updateNode( path, QTransform(), arcRect, + const auto path = metricsArc.painterPath( rect, radial ); + pathNode->updateNode( path, QTransform(), rect, qskEffectiveGradient( gradient, metricsArc ) ); } } @@ -199,7 +188,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics arcNode = nullptr; } - if ( isStrokeNodeVisible ) + if ( isBorderNodeVisible ) { if ( borderNode == nullptr ) { @@ -208,12 +197,13 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics } #ifdef ARC_BORDER_NODE - borderNode->updateNode( arcRect, metricsArc, radial, + borderNode->updateNode( rect, metricsArc, radial, borderWidth, borderColor, QskGradient() ); #else QPen pen( borderColor, borderWidth ); pen.setCapStyle( Qt::FlatCap ); + const auto path = metricsArc.painterPath( rect, radial ); borderNode->updateNode( path, QTransform(), pen ); #endif } diff --git a/src/nodes/QskArcRenderNode.cpp b/src/nodes/QskArcRenderNode.cpp index 2d783ac2..85ad57b6 100644 --- a/src/nodes/QskArcRenderNode.cpp +++ b/src/nodes/QskArcRenderNode.cpp @@ -68,11 +68,15 @@ void QskArcRenderNode::updateNode( Q_D( QskArcRenderNode ); const auto metrics = arcMetrics.toAbsolute( rect.size() ); + const auto borderMax = 0.5 * metrics.thickness(); + + const auto hasFilling = gradient.isVisible() + && ( borderWidth < borderMax ); bool visible = !( rect.isEmpty() || metrics.isNull() ); if ( visible ) { - visible = gradient.isVisible(); + visible = hasFilling; if ( !visible ) { visible = ( borderWidth > 0.0 ) @@ -103,11 +107,12 @@ void QskArcRenderNode::updateNode( if ( borderWidth > 0.0 && borderColor.isValid() ) { + borderWidth = std::min( borderWidth, borderMax ); QskArcRenderer::renderBorder( rect, metrics, radial, borderWidth, borderColor, *geometry() ); } - if ( gradient.isVisible() ) + if ( hasFilling ) { QskArcRenderer::renderFillGeometry( rect, metrics, radial, borderWidth, gradient, *geometry() ); diff --git a/src/nodes/QskArcRenderer.cpp b/src/nodes/QskArcRenderer.cpp index a385bf4e..51bd912d 100644 --- a/src/nodes/QskArcRenderer.cpp +++ b/src/nodes/QskArcRenderer.cpp @@ -378,8 +378,7 @@ void QskArcRenderer::renderFillGeometry( const QRectF& rect, { geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); - const auto b2 = 0.5 * borderWidth; - const auto r = rect.adjusted( b2, b2, -b2, -b2 ); + const auto r = rect.adjusted( borderWidth, borderWidth, -borderWidth, -borderWidth ); FillStroker stroker( r, metrics, radial, gradient ); @@ -390,7 +389,7 @@ void QskArcRenderer::renderFillGeometry( const QRectF& rect, return; const auto effectiveCount = stroker.setLines( - metrics.thickness() - borderWidth, lines ); + metrics.thickness() - 2 * borderWidth, lines ); if ( effectiveCount > lineCount ) {