From ac68b66b4ee97ffaa2361128e684800691c5c49c Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 12 Jun 2024 12:10:57 +0200 Subject: [PATCH] radial arcs added --- playground/charts/CircularChartSkinlet.cpp | 177 +-------------------- playground/shadows/ArcPage.cpp | 13 +- src/common/QskArcMetrics.cpp | 151 ++++++++++++------ src/common/QskArcMetrics.h | 18 ++- src/nodes/QskArcNode.cpp | 21 +-- src/nodes/QskArcNode.h | 10 +- src/nodes/QskArcRenderNode.cpp | 23 +-- src/nodes/QskArcRenderNode.h | 4 +- src/nodes/QskArcRenderer.cpp | 88 ++++++++-- src/nodes/QskArcRenderer.h | 8 +- 10 files changed, 240 insertions(+), 273 deletions(-) diff --git a/playground/charts/CircularChartSkinlet.cpp b/playground/charts/CircularChartSkinlet.cpp index 1fd0a540..efdabda4 100644 --- a/playground/charts/CircularChartSkinlet.cpp +++ b/playground/charts/CircularChartSkinlet.cpp @@ -9,153 +9,10 @@ #include #include -#include +#include -#include #include -#define PAINTED_NODE 0 - -#if PAINTED_NODE - -/* - This is a fallback implementation for a user who is using an outdated - version of QSkinny where only shaders for linear gradients are available. - */ -#include -#include -#include -#include -#include - -namespace -{ - QConicalGradient qskQConicalGradient( - const QskGradientStops& stops, qreal startAngle, qreal spanAngle ) - { - QskGradientStops scaledStops; - scaledStops.reserve( stops.size() ); - - const auto ratio = qAbs( spanAngle ) / 360.0; - - if ( spanAngle > 0.0 ) - { - for ( auto it = stops.cbegin(); it != stops.cend(); ++it ) - scaledStops += { ratio * it->position(), it->color() }; - } - else - { - for ( auto it = stops.crbegin(); it != stops.crend(); ++it ) - scaledStops += { 1.0 - ratio * it->position(), it->color() }; - } - - QConicalGradient qGradient( QPointF(), startAngle ); - qGradient.setStops( qskToQGradientStops( scaledStops ) ); - - return qGradient; - } - - class PaintedArcNode : public QskPaintedNode - { - public: - void setArcData( const QRectF&, const QskArcMetrics&, - qreal, const QColor&, const QskGradient&, QQuickWindow* ); - - protected: - void paint( QPainter*, const QSize&, const void* nodeData ) override; - QskHashValue hash( const void* nodeData ) const override; - - private: - QskHashValue arcHash( const QRectF&, const QskArcMetrics&, - qreal, const QColor&, const QskGradient& ) const; - - QBrush fillBrush( const QskGradient&, const QRectF&, qreal, qreal ) const; - - struct ArcData - { - QPointF translation; - QPen pen; - QBrush brush; - QPainterPath path; - - QskHashValue hash; - }; - }; - - void PaintedArcNode::setArcData( - const QRectF& rect, const QskArcMetrics& metrics, - qreal borderWidth, const QColor& borderColor, - const QskGradient& gradient, QQuickWindow* window ) - { - const auto hash = arcHash( rect, metrics, borderWidth, borderColor, gradient ); - - const auto brush = fillBrush( gradient, rect, - metrics.startAngle(), metrics.spanAngle() ); - - QPen pen( borderColor, borderWidth ); - if ( borderWidth <= 0.0 ) - pen.setStyle( Qt::NoPen ); - - const auto path = metrics.painterPath( rect ); - const auto r = path.controlPointRect(); - - const ArcData arcData { r.topLeft(), pen, brush, path, hash }; - update( window, r, QSizeF(), &arcData ); - } - - void PaintedArcNode::paint( QPainter* painter, const QSize&, const void* nodeData ) - { - const auto arcData = reinterpret_cast< const ArcData* >( nodeData ); - - painter->setRenderHint( QPainter::Antialiasing, true ); - painter->translate( -arcData->translation ); - painter->setPen( arcData->pen ); - painter->setBrush( arcData->brush ); - painter->drawPath( arcData->path ); - } - - QskHashValue PaintedArcNode::hash( const void* nodeData ) const - { - const auto arcData = reinterpret_cast< const ArcData* >( nodeData ); - return arcData->hash; - } - - QBrush PaintedArcNode::fillBrush( const QskGradient& gradient, - const QRectF& rect, qreal startAngle, qreal spanAngle ) const - { - const auto qGradient = qskQConicalGradient( - gradient.stops(), startAngle, spanAngle ); - - const qreal sz = qMax( rect.width(), rect.height() ); - const qreal sx = rect.width() / sz; - const qreal sy = rect.height() / sz; - - QTransform t; - t.scale( sx, sy ); - t.translate( rect.center().x() / sx, rect.center().y() / sy ); - - QBrush brush( qGradient ); - brush.setTransform( t ); - - return brush; - } - - inline QskHashValue PaintedArcNode::arcHash( - const QRectF& rect, const QskArcMetrics& metrics, qreal borderWidth, - const QColor& borderColor, const QskGradient& gradient ) const - { - auto hash = metrics.hash( 6753 ); - hash = qHashBits( &rect, sizeof( rect ), hash ); - hash = qHash( borderWidth, hash ); - hash = qHash( borderColor.rgba(), hash ); - hash = gradient.hash( hash ); - - return hash; - } -} - -#endif // PAINTED_NODE - namespace { inline QskArcMetrics segmentMetrics( @@ -334,38 +191,16 @@ QSGNode* CircularChartSkinlet::updateSampleNode( const QskSkinnable* skinnable, return nullptr; } -QSGNode* CircularChartSkinlet::updateArcSegmentNode( const QskSkinnable* skinnable, +QSGNode* CircularChartSkinlet::updateArcSegmentNode( const QskSkinnable*, QSGNode* node, qreal borderWidth, const QColor& borderColor, const QskGradient& gradient, const QskArcMetrics& metrics ) const { -#if PAINTED_NODE - auto arcNode = static_cast< PaintedArcNode* >( node ); + auto arcNode = static_cast< QskArcRenderNode* >( node ); if ( arcNode == nullptr ) - arcNode = new PaintedArcNode(); + arcNode = new QskArcRenderNode(); - const auto chart = static_cast< const CircularChart* >( skinnable ); - - arcNode->setArcData( m_data->closedArcRect, metrics, - borderWidth, borderColor, gradient, chart->window() ); -#else - Q_UNUSED( skinnable ) - - auto fillGradient = gradient; - - if ( fillGradient.type() == QskGradient::Stops ) - { - fillGradient.setStretchMode( QskGradient::StretchToSize ); - fillGradient.setConicDirection( 0.5, 0.5, - metrics.startAngle(), metrics.spanAngle() ); - } - - auto arcNode = static_cast< QskArcNode* >( node ); - if ( arcNode == nullptr ) - arcNode = new QskArcNode(); - - arcNode->setArcData( m_data->closedArcRect, metrics, - borderWidth, borderColor, fillGradient ); -#endif + arcNode->updateNode( m_data->closedArcRect, metrics, true, + borderWidth, borderColor, gradient ); return arcNode; } diff --git a/playground/shadows/ArcPage.cpp b/playground/shadows/ArcPage.cpp index 25498877..7916a843 100644 --- a/playground/shadows/ArcPage.cpp +++ b/playground/shadows/ArcPage.cpp @@ -71,7 +71,8 @@ namespace { 0.75, Qt::darkBlue }, { 0.75, Qt::darkRed } }; -#else +#endif +#if 0 const QskGradientStops stops = { { 0.1, Qt::darkRed }, @@ -80,6 +81,16 @@ namespace { 1.0, Qt::darkRed } }; #endif +#if 1 + QskGradientStops stops; + for ( int i = 0; i < 100; i++ ) + { + const auto pos = i * 1.0 / 100; + + stops += { pos, ( i % 2 ) ? Qt::darkRed : Qt::darkBlue }; + stops += { pos, ( i % 2 ) ? Qt::darkBlue : Qt::darkRed }; + } +#endif setFillGradient( stops ); } diff --git a/src/common/QskArcMetrics.cpp b/src/common/QskArcMetrics.cpp index b938aa05..220630f9 100644 --- a/src/common/QskArcMetrics.cpp +++ b/src/common/QskArcMetrics.cpp @@ -21,6 +21,83 @@ static void qskRegisterArcMetrics() Q_CONSTRUCTOR_FUNCTION( qskRegisterArcMetrics ) +static inline QPainterPath qskRadialPathPath( + const QRectF& rect, qreal startAngle, qreal spanAngle, qreal width ) +{ + const auto sz = qMin( rect.width(), rect.height() ); + + const auto tx = width * rect.width() / sz; + const auto ty = width * rect.height() / sz; + + const auto innerRect = rect.adjusted( tx, ty, -tx, -ty ); + + QPainterPath path; + + if ( innerRect.isEmpty() ) + { + if ( qAbs( spanAngle ) >= 360.0 ) + { + path.addEllipse( rect ); + } + else + { + // pie + path.arcMoveTo( rect, startAngle ); + path.arcTo( rect, startAngle, spanAngle ); + path.lineTo( rect.center() ); + path.closeSubpath(); + } + } + else + { + if ( qAbs( spanAngle ) >= 360.0 ) + { + path.addEllipse( rect ); + + QPainterPath innerPath; + innerPath.addEllipse( innerRect ); + path -= innerPath; + } + else + { + /* + We need the end point of the inner arc to add the line that connects + the inner/outer arcs. As QPainterPath does not offer such a method + we insert a dummy arcMoveTo and grab the calculated position. + */ + path.arcMoveTo( innerRect, startAngle + spanAngle ); + const auto pos = path.currentPosition(); + + path.arcMoveTo( rect, startAngle ); // replaces the dummy arcMoveTo above + path.arcTo( rect, startAngle, spanAngle ); + + path.lineTo( pos ); + path.arcTo( innerRect, startAngle + spanAngle, -spanAngle ); + + path.closeSubpath(); + } + } + + return path; +} + +static inline QPainterPath qskOrthogonalPath( + const QRectF& rect, qreal startAngle, qreal spanAngle, qreal width ) +{ + const auto t2 = 0.5 * width; + const auto r = rect.adjusted( t2, t2, -t2, -t2 ); + + QPainterPath arcPath; + arcPath.arcMoveTo( r, startAngle ); + arcPath.arcTo( r, startAngle, spanAngle ); + + QPainterPathStroker stroker; + stroker.setCapStyle( Qt::FlatCap ); + stroker.setWidth( width ); + + return stroker.createStroke( arcPath ); +} + static inline qreal qskInterpolated( qreal from, qreal to, qreal ratio ) { return from + ( to - from ) * ratio; @@ -97,6 +174,11 @@ QVariant QskArcMetrics::interpolate( return QVariant::fromValue( from.interpolated( to, progress ) ); } +QskArcMetrics QskArcMetrics::toAbsolute( const QSizeF& size ) const noexcept +{ + return toAbsolute( 0.5 * size.width(), 0.5 * size.height() ); +} + QskArcMetrics QskArcMetrics::toAbsolute( qreal radiusX, qreal radiusY ) const noexcept { if ( radiusX < 0.0 ) @@ -117,59 +199,30 @@ QskArcMetrics QskArcMetrics::toAbsolute( qreal radius ) const noexcept return QskArcMetrics( m_startAngle, m_spanAngle, t, Qt::AbsoluteSize ); } -QPainterPath QskArcMetrics::painterPath( const QRectF& ellipseRect ) const +QPainterPath QskArcMetrics::painterPath( const QRectF& rect, bool radial ) const { - qreal t = m_thickness; - - if ( m_relativeSize ) - { - const auto sz = qMin( ellipseRect.width(), ellipseRect.height() ); - t = qskEffectiveThickness( 0.5 * sz, t ); - } - - 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 ); - if ( innerRect.isEmpty() ) - { - QPainterPath path; - - if ( qAbs( m_spanAngle ) >= 360.0 ) - { - path.addEllipse( ellipseRect ); - } - else - { - // pie - path.arcMoveTo( ellipseRect, m_startAngle ); - path.arcTo( ellipseRect, m_startAngle, m_spanAngle ); - path.lineTo( ellipseRect.center() ); - path.closeSubpath(); - } - - return path; - } -#endif - - const auto t2 = 0.5 * t; - const auto r = ellipseRect.adjusted( t2, t2, -t2, -t2 ); - QPainterPath path; - path.arcMoveTo( r, m_startAngle ); // replaces the dummy arcMoveTo above - path.arcTo( r, m_startAngle, m_spanAngle ); - QPainterPathStroker stroker; - stroker.setCapStyle( Qt::FlatCap ); - stroker.setWidth( t ); + if ( !qFuzzyIsNull( m_spanAngle ) ) + { + qreal t = m_thickness; - return stroker.createStroke( path ); + if ( m_relativeSize ) + { + const auto sz = qMin( rect.width(), rect.height() ); + t = qskEffectiveThickness( 0.5 * sz, t ); + } + + if ( t > 0.0 ) + { + if ( radial ) + path = qskRadialPathPath( rect, m_startAngle, m_spanAngle, t ); + else + path = qskOrthogonalPath( rect, m_startAngle, m_spanAngle, t ); + } + } + + return path; } QRectF QskArcMetrics::boundingRect( const QRectF& ellipseRect ) const diff --git a/src/common/QskArcMetrics.h b/src/common/QskArcMetrics.h index 9e04eedc..608e9d8e 100644 --- a/src/common/QskArcMetrics.h +++ b/src/common/QskArcMetrics.h @@ -58,10 +58,26 @@ class QSK_EXPORT QskArcMetrics QskArcMetrics interpolated( const QskArcMetrics&, qreal value ) const noexcept; + QskArcMetrics toAbsolute( const QSizeF& ) const noexcept; QskArcMetrics toAbsolute( qreal radiusX, qreal radiusY ) const noexcept; QskArcMetrics toAbsolute( qreal radius ) const noexcept; - QPainterPath painterPath( const QRectF& ellipseRect ) const; + /* + The arc is interpolated by pairs of points, where one point is on + the outer and the other on the inner side of the arc. The length between + these points depends on the thickness. + + When radial is set the inner point lies on the line between the outer point + and the center of the arc. This corresponds to the lines of a conic gradient. + + Otherwise the line between the inner and outer point is orthogonal to the + tangent at the point in the middle of the arc. This is how the width + of the pen is expanded by QPainter::drawArc. + + Note, that the radial flag is irrelevant for circular arcs as the tangent + is always orthogonal to any point on the circle. + */ + QPainterPath painterPath( const QRectF& ellipseRect, bool radial = false ) const; QRectF boundingRect( const QRectF& ellipseRect ) const; QSizeF boundingSize( const QSizeF& ellipseSize ) const; diff --git a/src/nodes/QskArcNode.cpp b/src/nodes/QskArcNode.cpp index 895affc5..9d184161 100644 --- a/src/nodes/QskArcNode.cpp +++ b/src/nodes/QskArcNode.cpp @@ -56,20 +56,6 @@ static inline QskGradient qskEffectiveGradient( 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 ) { @@ -112,7 +98,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics const qreal borderWidth, const QColor& borderColor, const QskGradient& gradient, const QColor& shadowColor, const QskShadowMetrics& shadowMetrics ) { - const auto metricsArc = qskEffectiveMetrics( arcMetrics, rect ); + const auto metricsArc = arcMetrics.toAbsolute( rect.size() ); auto shadowNode = static_cast< QskArcShadowNode* >( QskSGNode::findChildNode( this, ShadowRole ) ); @@ -136,7 +122,7 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics return; } - const auto isFillNodeVisible = gradient.isVisible() && !metricsArc.isNull(); + const auto isFillNodeVisible = gradient.isVisible(); const auto isStrokeNodeVisible = ( borderWidth > 0.0 ) && ( borderColor.alpha() > 0 ); const auto isShadowNodeVisible = isFillNodeVisible && shadowColor.isValid() && ( shadowColor.alpha() > 0.0 ); @@ -184,7 +170,8 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics QskSGNode::setNodeRole( arcNode, ArcRole ); } - arcNode->updateNode( arcRect, metricsArc, gradient ); + arcNode->updateNode( arcRect, metricsArc, false, + borderWidth, QColor(), gradient ); } else { diff --git a/src/nodes/QskArcNode.h b/src/nodes/QskArcNode.h index c4fa330a..b641533e 100644 --- a/src/nodes/QskArcNode.h +++ b/src/nodes/QskArcNode.h @@ -6,18 +6,14 @@ #ifndef QSK_ARC_NODE_H #define QSK_ARC_NODE_H -#include "QskShapeNode.h" +#include "QskGlobal.h" +#include class QskArcMetrics; class QskGradient; class QskShadowMetrics; -/* - For the moment a QPainterPath/QskShapeNode. - But we can do better by creatig vertex lists manually - like what is done by the box renderer. TODO ... - */ -class QSK_EXPORT QskArcNode : public QskShapeNode +class QSK_EXPORT QskArcNode : public QSGNode { public: QskArcNode(); diff --git a/src/nodes/QskArcRenderNode.cpp b/src/nodes/QskArcRenderNode.cpp index a7043802..66c58baa 100644 --- a/src/nodes/QskArcRenderNode.cpp +++ b/src/nodes/QskArcRenderNode.cpp @@ -52,21 +52,23 @@ QskArcRenderNode::QskArcRenderNode() void QskArcRenderNode::updateNode( const QRectF& rect, const QskArcMetrics& metrics, const QskGradient& gradient ) { - updateNode( rect, metrics, 0.0, QColor(), gradient ); + updateNode( rect, metrics, false, 0.0, QColor(), gradient ); } void QskArcRenderNode::updateNode( const QRectF& rect, const QskArcMetrics& metrics, qreal borderWidth, const QColor& borderColor ) { - updateNode( rect, metrics, borderWidth, borderColor, QskGradient() ); + updateNode( rect, metrics, false, borderWidth, borderColor, QskGradient() ); } void QskArcRenderNode::updateNode( - const QRectF& rect, const QskArcMetrics& metrics, qreal borderWidth, - const QColor& borderColor, const QskGradient& gradient ) + const QRectF& rect, const QskArcMetrics& arcMetrics, bool radial, + qreal borderWidth, const QColor& borderColor, const QskGradient& gradient ) { Q_D( QskArcRenderNode ); + const auto metrics = arcMetrics.toAbsolute( rect.size() ); + bool visible = !( rect.isEmpty() || metrics.isNull() ); if ( visible ) { @@ -93,21 +95,22 @@ void QskArcRenderNode::updateNode( hash = qHash( borderColor.rgba(), hash ); hash = metrics.hash( hash ); hash = gradient.hash( hash ); + hash = qHash( radial, hash ); if ( hash != d->hash ) { d->hash = hash; +#if 0 if ( borderWidth > 0.0 ) { QskArcRenderer::renderBorder( - rect, metrics, borderWidth, borderColor, *geometry() ); - } - else - { - QskArcRenderer::renderFillGeometry( - rect, metrics, borderWidth, gradient, *geometry() ); + rect, metrics, borderWidth, radial, borderColor, *geometry() ); } +#endif + + QskArcRenderer::renderFillGeometry( + rect, metrics, radial, borderWidth, gradient, *geometry() ); markDirty( QSGNode::DirtyGeometry ); markDirty( QSGNode::DirtyMaterial ); diff --git a/src/nodes/QskArcRenderNode.h b/src/nodes/QskArcRenderNode.h index 70a06e89..82e6f3f6 100644 --- a/src/nodes/QskArcRenderNode.h +++ b/src/nodes/QskArcRenderNode.h @@ -25,8 +25,8 @@ class QSK_EXPORT QskArcRenderNode : public QSGGeometryNode void updateNode( const QRectF&, const QskArcMetrics&, qreal borderWidth, const QColor& borderColor ); - void updateNode( const QRectF&, const QskArcMetrics&, qreal borderWidth, - const QColor& borderColor, const QskGradient& ); + void updateNode( const QRectF&, const QskArcMetrics&, bool radial, + qreal borderWidth, const QColor& borderColor, const QskGradient& ); private: Q_DECLARE_PRIVATE( QskArcRenderNode ) diff --git a/src/nodes/QskArcRenderer.cpp b/src/nodes/QskArcRenderer.cpp index 8022f98a..2826e230 100644 --- a/src/nodes/QskArcRenderer.cpp +++ b/src/nodes/QskArcRenderer.cpp @@ -31,7 +31,7 @@ namespace class EllipseStroker { public: - EllipseStroker( const QRectF&, const QskArcMetrics&, + EllipseStroker( const QRectF&, const QskArcMetrics&, bool orthogonal, qreal borderWidth, const QskGradient& ); int fillCount() const; @@ -44,10 +44,14 @@ namespace int arcLineCount() const; qreal radiansAt( qreal progress ) const; - void setFillLine( const qreal radians, + void setOrthogonalLine( const qreal radians, + const QskVertex::Color, QskVertex::ColoredLine& ) const; + + void setRadialLine( const qreal radians, const QskVertex::Color, QskVertex::ColoredLine& ) const; const qreal m_extent; + const bool m_orthogonal; // radius const qreal m_rx; @@ -60,13 +64,14 @@ namespace const qreal m_radians1; const qreal m_radians2; - const QskGradient& m_gradient; }; EllipseStroker::EllipseStroker( const QRectF& rect, - const QskArcMetrics& m, qreal borderWidth, const QskGradient& gradient ) + const QskArcMetrics& m, bool orthogonal, qreal borderWidth, + const QskGradient& gradient ) : m_extent( 0.5 * ( m.thickness() - borderWidth ) ) + , m_orthogonal( orthogonal ) , m_rx( 0.5 * rect.width() - m_extent ) , m_ry( 0.5 * rect.height() - m_extent ) , m_cx( rect.center().x() ) @@ -107,7 +112,7 @@ namespace return 0; } - inline void EllipseStroker::setFillLine( const qreal radians, + inline void EllipseStroker::setOrthogonalLine( const qreal radians, const QskVertex::Color color, QskVertex::ColoredLine& line ) const { const auto cos = qFastCos( radians ); @@ -151,6 +156,34 @@ namespace line.setLine( x + dx, y - dy, x - dx, y + dy, color ); } + inline void EllipseStroker::setRadialLine( const qreal radians, + const QskVertex::Color color, QskVertex::ColoredLine& line ) const + { + const auto cos = qFastCos( radians ); + const auto sin = qFastSin( radians ); + + const auto t = 2.0 * m_extent; + + const auto w = 2.0 * m_rx + t; + const auto h = 2.0 * m_ry + t; + + const auto x1 = 0.5 * w * cos; + const auto y1 = 0.5 * h * sin; + + const auto sz = qMin( w, h ); + + const auto tx = t * w / sz; + const auto ty = t * h / sz; + + const auto w2 = w - 2 * tx; + const auto h2 = h - 2 * ty; + + const auto x2 = 0.5 * w2 * cos; + const auto y2 = 0.5 * h2 * sin; + + line.setLine( m_cx + x1, m_cy - y1, m_cx + x2, m_cy - y2, color ); + } + int EllipseStroker::setFillLines( QskVertex::ColoredLine* lines ) const { auto l = lines; @@ -177,12 +210,20 @@ namespace while( !it.isDone() && ( it.position() < progress ) ) { - setFillLine( radiansAt( it.position() ), it.color(), *l++ ); + if ( m_orthogonal ) + setOrthogonalLine( radiansAt( it.position() ), it.color(), *l++ ); + else + setRadialLine( radiansAt( it.position() ), it.color(), *l++ ); + it.advance(); } const auto color = it.colorAt( progress ); - setFillLine( m_radians1 + i * stepSize, color, *l++ ); + + if ( m_orthogonal ) + setOrthogonalLine( m_radians1 + i * stepSize, color, *l++ ); + else + setRadialLine( m_radians1 + i * stepSize, color, *l++ ); } return l - lines; @@ -203,12 +244,16 @@ bool QskArcRenderer::isGradientSupported( const QskGradient& gradient ) } void QskArcRenderer::renderFillGeometry( const QRectF& rect, - const QskArcMetrics& metrics, qreal borderWidth, + const QskArcMetrics& metrics, bool radial, qreal borderWidth, const QskGradient& gradient, QSGGeometry& geometry ) { +#if 1 + // TODO ... + borderWidth = 0.0; +#endif geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); - EllipseStroker stroker( rect, metrics, borderWidth, gradient ); + EllipseStroker stroker( rect, metrics, !radial, borderWidth, gradient ); const auto lineCount = stroker.fillCount(); @@ -236,11 +281,11 @@ void QskArcRenderer::renderFillGeometry( const QRectF& rect, } void QskArcRenderer::renderBorder( const QRectF& rect, const QskArcMetrics& metrics, - qreal borderWidth, const QColor& borderColor, QSGGeometry& geometry ) + bool radial, qreal borderWidth, const QColor& borderColor, QSGGeometry& geometry ) { geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); - EllipseStroker stroker( rect, metrics, borderWidth, QskGradient() ); + EllipseStroker stroker( rect, metrics, !radial, borderWidth, QskGradient() ); const auto lineCount = stroker.borderCount(); @@ -254,3 +299,24 @@ void QskArcRenderer::renderBorder( const QRectF& rect, const QskArcMetrics& metr } } } + +void QskArcRenderer::renderBorderGeometry( const QRectF& rect, + const QskArcMetrics& metrics, bool radial, qreal borderWidth, QSGGeometry& geometry ) +{ + Q_UNUSED( rect ); + Q_UNUSED( metrics ); + Q_UNUSED( radial ); + Q_UNUSED( borderWidth ); + Q_UNUSED( geometry ); +} + +void QskArcRenderer::renderFillGeometry( const QRectF& rect, + const QskArcMetrics& metrics, bool radial, qreal borderWidth, QSGGeometry& geometry ) +{ + Q_UNUSED( rect ); + Q_UNUSED( metrics ); + Q_UNUSED( radial ); + Q_UNUSED( borderWidth ); + Q_UNUSED( geometry ); +} + diff --git a/src/nodes/QskArcRenderer.h b/src/nodes/QskArcRenderer.h index d4ab18d3..2a8abe02 100644 --- a/src/nodes/QskArcRenderer.h +++ b/src/nodes/QskArcRenderer.h @@ -26,10 +26,10 @@ namespace QskArcRenderer */ QSK_EXPORT void renderBorderGeometry( const QRectF&, - const QskArcMetrics&, qreal borderWidth, QSGGeometry& ); + const QskArcMetrics&, bool radial, qreal borderWidth, QSGGeometry& ); QSK_EXPORT void renderFillGeometry( const QRectF&, - const QskArcMetrics&, qreal borderWidth, QSGGeometry& ); + const QskArcMetrics&, bool radial, qreal borderWidth, QSGGeometry& ); /* Filling the geometry with color information: @@ -38,10 +38,10 @@ namespace QskArcRenderer QSK_EXPORT bool isGradientSupported( const QskGradient& ); QSK_EXPORT void renderBorder( const QRectF&, const QskArcMetrics&, - qreal borderWidth, const QColor& borderColor, QSGGeometry& ); + bool radial, qreal borderWidth, const QColor& borderColor, QSGGeometry& ); QSK_EXPORT void renderFillGeometry( const QRectF&, const QskArcMetrics&, - qreal borderWidth, const QskGradient&, QSGGeometry& ); + bool radial, qreal borderWidth, const QskGradient&, QSGGeometry& ); } #endif