diff --git a/playground/shadows/ArcPage.cpp b/playground/shadows/ArcPage.cpp index ffd93bc6..105a251c 100644 --- a/playground/shadows/ArcPage.cpp +++ b/playground/shadows/ArcPage.cpp @@ -60,9 +60,9 @@ namespace setStartAngle( 45.0 ); setSpanAngle( 270.0 ); - setThickness( 10.0 ); + setThickness( 30.0 ); - setBorderWidth( 2.0 ); + setBorderWidth( 5.0 ); setBorderColor( QColor( 0, 0, 0, 150 ) ); #if 0 diff --git a/playground/shadows/ShadowedArc.cpp b/playground/shadows/ShadowedArc.cpp index 1b135c0b..069d207e 100644 --- a/playground/shadows/ShadowedArc.cpp +++ b/playground/shadows/ShadowedArc.cpp @@ -99,7 +99,7 @@ ShadowedArc::ShadowedArc( QQuickItem* parent ) // initial settings - setArcMetrics( { 0.0, 360.0, 1.0, Qt::RelativeSize } ); + setArcMetrics( { 0.0, 360.0, 1.0, Qt::AbsoluteSize } ); setFillGradient( Qt::darkRed ); diff --git a/src/nodes/QskArcRenderer.cpp b/src/nodes/QskArcRenderer.cpp index 51bd912d..eac848a6 100644 --- a/src/nodes/QskArcRenderer.cpp +++ b/src/nodes/QskArcRenderer.cpp @@ -31,10 +31,13 @@ namespace class OrthogonalStroker { public: - OrthogonalStroker( const QRectF& rect, qreal length ) - : m_l2( 0.5 * length ) - , m_rx( 0.5 * ( rect.width() - length ) ) - , m_ry( 0.5 * ( rect.height() - length ) ) + OrthogonalStroker( const QRectF& rect, qreal thickness, qreal border ) + : m_thickness( thickness ) + , m_border( border ) + , m_rx( 0.5 * ( rect.width() - m_thickness ) ) + , m_ry( 0.5 * ( rect.height() - m_thickness ) ) + , m_offsetOut( 0.5 * m_thickness ) + , m_offsetIn( m_offsetOut - border ) , m_aspectRatio( m_rx / m_ry ) , m_cx( rect.x() + 0.5 * rect.width() ) , m_cy( rect.y() + 0.5 * rect.height() ) @@ -49,11 +52,46 @@ namespace const auto x = m_cx + m_rx * cos; const auto y = m_cy - m_ry * sin; - const auto v = normalVector( cos, sin ) * m_l2; + + const auto v = normalVector( cos, sin ) * m_offsetIn; line.setLine( x + v.x(), y - v.y(), x - v.x(), y + v.y(), color ); } + inline void setBorderLines( const qreal radians, + const QskVertex::Color color, QskVertex::ColoredLine& outer, + QskVertex::ColoredLine& inner ) const + { + const auto cos = qFastCos( radians ); + const auto sin = qFastSin( radians ); + + const auto x = m_cx + m_rx * cos; + const auto y = m_cy - m_ry * sin; + + const auto v = normalVector( cos, sin ); + + const auto v1 = v * m_offsetOut; + const auto v2 = v * m_offsetIn; + + outer.setLine( x + v1.x(), y - v1.y(), x + v2.x(), y - v2.y(), color ); + inner.setLine( x - v1.x(), y + v1.y(), x - v2.x(), y + v2.y(), color ); + } + + inline void setClosingBorderLines( const QSGGeometry::ColoredPoint2D& pos, + QskVertex::ColoredLine* lines, qreal sign, const QskVertex::Color color ) const + { + const auto& l0 = lines[0]; + + const auto dx = sign * l0.dy(); + const auto dy = sign * l0.dx(); + + lines[-3].setLine( pos.x, pos.y, pos.x, pos.y, color ); + lines[-2].setLine( pos.x + dx, pos.y - dy, pos.x, pos.y, color ); + lines[-1].setLine( l0.x1() + dx, l0.y1() - dy, l0.x1(), l0.y1(), color ); + } + + private: + inline QPointF normalVector( const qreal radians ) const { return normalVector( qFastCos( radians ), qFastSin( radians ) ); @@ -87,45 +125,34 @@ namespace return { dx, m * dx }; } - inline void setBorderLines( const qreal radians, qreal border, - const QskVertex::Color color, QskVertex::ColoredLine& outer, - QskVertex::ColoredLine& inner ) const - { - const auto cos = qFastCos( radians ); - const auto sin = qFastSin( radians ); + const qreal m_thickness; + const qreal m_border; - const auto x = m_cx + m_rx * cos; - const auto y = m_cy - m_ry * sin; - const auto v = normalVector( cos, sin ); + // radii t the middle of the arc + const qreal m_rx, m_ry; - const auto v1 = v * m_l2; - const auto v2 = v * ( m_l2 - border ); + // distances between the middle and inner/outer of the border + const qreal m_offsetOut, m_offsetIn; - outer.setLine( x + v1.x(), y - v1.y(), x + v2.x(), y - v2.y(), color ); - inner.setLine( x - v1.x(), y + v1.y(), x - v2.x(), y + v2.y(), color ); - } - - const qreal m_l2; // half of the length - - // radius - const qreal m_rx; - const qreal m_ry; const qreal m_aspectRatio; // m_rx / m_ry // center - const qreal m_cx; - const qreal m_cy; + const qreal m_cx, m_cy; }; class RadialStroker { public: - RadialStroker( const QRectF& rect, qreal length ) - : m_length( length ) + RadialStroker( const QRectF& rect, qreal thickness, qreal border ) + : m_inner( thickness - 2 * border ) , m_rx1( 0.5 * rect.width() ) , m_ry1( 0.5 * rect.height() ) - , m_rx2( m_rx1 - ( ( m_rx1 > m_ry1 ) ? length * m_rx1 / m_ry1 : length ) ) - , m_ry2( m_ry1 - ( ( m_ry1 > m_rx1 ) ? length * m_ry1 / m_rx1 : length ) ) + , m_rx2( m_rx1 - border ) + , m_ry2( m_ry1 - border ) + , m_rx3( m_rx2 - ( ( m_rx1 > m_ry1 ) ? m_inner * m_rx1 / m_ry1 : m_inner ) ) + , m_ry3( m_ry2 - ( ( m_rx1 < m_ry1 ) ? m_inner * m_ry1 / m_rx1 : m_inner ) ) + , m_rx4( m_rx3 - border ) + , m_ry4( m_ry3 - border ) , m_cx( rect.x() + m_rx1 ) , m_cy( rect.y() + m_ry1 ) { @@ -137,24 +164,50 @@ namespace const auto cos = qFastCos( radians ); const auto sin = qFastSin( radians ); - line.setLine( m_cx + m_rx1 * cos, m_cy - m_ry1 * sin, + line.setLine( m_cx + m_rx2 * cos, m_cy - m_ry2 * sin, + m_cx + m_rx3 * cos, m_cy - m_ry3 * sin, color ); + } + + inline void setBorderLines( const qreal radians, + const QskVertex::Color color, QskVertex::ColoredLine& outer, + QskVertex::ColoredLine& inner ) const + { + const auto cos = qFastCos( radians ); + const auto sin = qFastSin( radians ); + + outer.setLine( m_cx + m_rx1 * cos, m_cy - m_ry1 * sin, m_cx + m_rx2 * cos, m_cy - m_ry2 * sin, color ); + + inner.setLine( m_cx + m_rx3 * cos, m_cy - m_ry3 * sin, + m_cx + m_rx4 * cos, m_cy - m_ry4 * sin, color ); + } + + inline void setClosingBorderLines( const QSGGeometry::ColoredPoint2D& pos, + QskVertex::ColoredLine* lines, qreal sign, const QskVertex::Color color ) const + { + // TODO ... +#if 1 + Q_UNUSED( pos ); + Q_UNUSED( sign ); + + const auto& l0 = lines[0]; + const qreal dx = 0.0; + const qreal dy = 0.0; + + lines[-3].setLine( l0.x1() + dx, l0.y1() - dy, l0.x1(), l0.y1(), color ); + lines[-2].setLine( l0.x1() + dx, l0.y1() - dy, l0.x1(), l0.y1(), color ); + lines[-1].setLine( l0.x1() + dx, l0.y1() - dy, l0.x1(), l0.y1(), color ); +#endif } private: - const qreal m_length; + const qreal m_inner; - // outer radii - const qreal m_rx1; - const qreal m_ry1; - - // inner radii - const qreal m_rx2; - const qreal m_ry2; + // radii: out->in + const qreal m_rx1, m_ry1, m_rx2, m_ry2, m_rx3, m_ry3, m_rx4, m_ry4; // center point - const qreal m_cx; - const qreal m_cy; + const qreal m_cx, m_cy; }; } @@ -207,7 +260,7 @@ namespace bool radial, const QskGradient& ); int lineCount() const; - int setLines( qreal length, QskVertex::ColoredLine* ) const; + int setLines( qreal thickness, qreal border, QskVertex::ColoredLine* ) const; private: template< class LineStroker > @@ -228,17 +281,17 @@ namespace return arcLineCount() + m_gradient.stepCount() - 1; } - inline int FillStroker::setLines( - const qreal length, QskVertex::ColoredLine* lines ) const + inline int FillStroker::setLines( const qreal thickness, + const qreal border, QskVertex::ColoredLine* lines ) const { if ( m_radial ) { - const RadialStroker lineStroker( m_rect, length ); + const RadialStroker lineStroker( m_rect, thickness, border ); return renderLines( lineStroker, lines ); } else { - const OrthogonalStroker lineStroker( m_rect, length ); + const OrthogonalStroker lineStroker( m_rect, thickness, border ); return renderLines( lineStroker, lines ); } } @@ -292,11 +345,11 @@ namespace bool radial, const QColor& color ); int lineCount() const; - int setLines( qreal length, qreal border, QskVertex::ColoredLine* ) const; + int setLines( qreal thickness, qreal border, QskVertex::ColoredLine* ) const; private: - void setClosingLines( const QSGGeometry::ColoredPoint2D&, - QskVertex::ColoredLine* ) const; + template< class LineStroker > + int renderLines( const LineStroker&, QskVertex::ColoredLine* ) const; const QskVertex::Color m_color; }; @@ -317,7 +370,23 @@ namespace return count; } - int BorderStroker::setLines( qreal length, qreal border, + int BorderStroker::setLines( const qreal thickness, const qreal border, + QskVertex::ColoredLine* lines ) const + { + if ( m_radial ) + { + const RadialStroker stroker( m_rect, thickness, border ); + return renderLines( stroker, lines ); + } + else + { + const OrthogonalStroker stroker( m_rect, thickness, border ); + return renderLines( stroker, lines ); + } + } + + template< class LineStroker > + inline int BorderStroker::renderLines( const LineStroker& stroker, QskVertex::ColoredLine* lines ) const { const auto count = arcLineCount(); @@ -333,35 +402,22 @@ namespace if ( !m_closed ) inner += 3; - OrthogonalStroker stroker( m_rect, length ); for ( int i = 0; i < count; i++ ) { stroker.setBorderLines( m_radians1 + i * stepSize, - border, m_color, outer[i], inner[count - 1 - i] ); + m_color, outer[i], inner[count - 1 - i] ); } if ( !m_closed ) { - setClosingLines( inner[count - 1].p1, outer ); - setClosingLines( outer[count - 1].p1, inner ); + const auto sign = ( stepSize > 0.0 ) ? 1.0 : -1.0; + + stroker.setClosingBorderLines( inner[count - 1].p1, outer, sign, m_color ); + stroker.setClosingBorderLines( outer[count - 1].p1, inner, sign, m_color ); } return 2 * ( count + ( m_closed ? 0 : 3 ) ); } - - void BorderStroker::setClosingLines( const QSGGeometry::ColoredPoint2D& pos, - QskVertex::ColoredLine* lines ) const - { - const auto& l0 = lines[0]; - - const auto sign = ( m_radians1 <= m_radians2 ) ? 1.0 : -1.0; - const auto dx = sign * l0.dy(); - const auto dy = sign * l0.dx(); - - lines[-3].setLine( pos.x, pos.y, pos.x, pos.y, m_color ); - lines[-2].setLine( pos.x + dx, pos.y - dy, pos.x, pos.y, m_color ); - lines[-1].setLine( l0.x1() + dx, l0.y1() - dy, l0.x1(), l0.y1(), m_color ); - } } bool QskArcRenderer::isGradientSupported( const QskGradient& gradient ) @@ -378,9 +434,7 @@ void QskArcRenderer::renderFillGeometry( const QRectF& rect, { geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); - const auto r = rect.adjusted( borderWidth, borderWidth, -borderWidth, -borderWidth ); - - FillStroker stroker( r, metrics, radial, gradient ); + FillStroker stroker( rect, metrics, radial, gradient ); const auto lineCount = stroker.lineCount(); @@ -389,7 +443,7 @@ void QskArcRenderer::renderFillGeometry( const QRectF& rect, return; const auto effectiveCount = stroker.setLines( - metrics.thickness() - 2 * borderWidth, lines ); + metrics.thickness(), borderWidth, lines ); if ( effectiveCount > lineCount ) {