diff --git a/playground/shadows/ShadowedArc.cpp b/playground/shadows/ShadowedArc.cpp index e2185161..4739745e 100644 --- a/playground/shadows/ShadowedArc.cpp +++ b/playground/shadows/ShadowedArc.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -107,14 +107,7 @@ namespace return nullptr; auto arcNode = QskSGNode::ensureNode< QskArcNode >( node ); - - const auto metrics = arc->arcMetricsHint( Q::Arc ); - const auto fillGradient = arc->gradientHint( Q::Arc ); - - const auto borderColor = arc->color( Q::Arc | QskAspect::Border ); - const auto borderWidth = arc->metric( Q::Arc | QskAspect::Border ); - - arcNode->setArcData( rect, metrics, borderWidth, borderColor, fillGradient ); + arcNode->setArcData( rect, arc->arcHints( Q::Arc ) ); return arcNode; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c86f6783..2c69fa06 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ list(APPEND HEADERS common/QskArcMetrics.h + common/QskArcHints.h common/QskAspect.h common/QskBoxBorderColors.h common/QskBoxBorderMetrics.h @@ -41,6 +42,7 @@ list(APPEND HEADERS list(APPEND SOURCES common/QskArcMetrics.cpp + common/QskArcHints.cpp common/QskAspect.cpp common/QskBoxBorderColors.cpp common/QskBoxBorderMetrics.cpp diff --git a/src/common/QskArcHints.cpp b/src/common/QskArcHints.cpp new file mode 100644 index 00000000..9a135573 --- /dev/null +++ b/src/common/QskArcHints.cpp @@ -0,0 +1,69 @@ +/****************************************************************************** + * QSkinny - Copyright (C) The authors + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskArcHints.h" +#include "QskRgbValue.h" + +static inline qreal qskInterpolated( qreal from, qreal to, qreal ratio ) +{ + return from + ( to - from ) * ratio; +} + +QskArcHints::QskArcHints() +{ +} + +QskArcHints::QskArcHints( const QskArcMetrics& metrics, qreal borderWidth, + const QColor& borderColor, const QskGradient& gradient ) + : metrics( metrics ) + , borderWidth( borderWidth ) + , borderColor( borderColor ) + , gradient( gradient ) +{ +} + +bool QskArcHints::isVisible() const +{ + if ( metrics.isNull() ) + return false; + + if ( borderWidth > 0.0 && borderColor.isValid() && borderColor.alpha() > 0 ) + return true; + + return gradient.isVisible(); +} + +QskArcHints QskArcHints::toAbsolute( const QSizeF& size ) const noexcept +{ + return QskArcHints( metrics.toAbsolute( size ), + borderWidth, borderColor, gradient ); +} + +QskArcHints QskArcHints::interpolated( + const QskArcHints& to, qreal value ) const noexcept +{ + return QskArcHints( + metrics.interpolated( to.metrics, value ), + qskInterpolated( borderWidth, to.borderWidth, value ), + QskRgb::interpolated( borderColor, to.borderColor, value ), + gradient.interpolated( to.gradient, value ) + ); +} + +#ifndef QT_NO_DEBUG_STREAM + +#include + +QDebug operator<<( QDebug debug, const QskArcHints& hints ) +{ + debug << hints.metrics << hints.borderWidth + << hints.borderColor << hints.gradient; + + return debug; +} + +#endif + +#include "moc_QskArcHints.cpp" diff --git a/src/common/QskArcHints.h b/src/common/QskArcHints.h new file mode 100644 index 00000000..7629c435 --- /dev/null +++ b/src/common/QskArcHints.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * QSkinny - Copyright (C) The authors + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_ARC_HINTS_H +#define QSK_ARC_HINTS_H + +#include "QskArcMetrics.h" +#include "QskGradient.h" +#include + +class QSK_EXPORT QskArcHints +{ + Q_GADGET + + Q_PROPERTY( QskArcMetrics metrics MEMBER metrics ) + Q_PROPERTY( qreal borderWidth MEMBER borderWidth ) + Q_PROPERTY( QColor borderColor MEMBER borderColor ) + + public: + QskArcHints(); + QskArcHints( const QskArcMetrics&, qreal borderWidth, + const QColor& borderColor, const QskGradient& ); + + QskArcHints toAbsolute( const QSizeF& ) const noexcept; + + QskArcHints interpolated( + const QskArcHints&, qreal value ) const noexcept; + + bool isVisible() const; + + QskArcMetrics metrics; + qreal borderWidth = 0.0; + + QColor borderColor; + QskGradient gradient; +}; + +#ifndef QT_NO_DEBUG_STREAM + +class QDebug; +QSK_EXPORT QDebug operator<<( QDebug, const QskArcHints& ); + +#endif + +#endif diff --git a/src/controls/QskProgressRingSkinlet.cpp b/src/controls/QskProgressRingSkinlet.cpp index bb8f8d25..f599b3a8 100644 --- a/src/controls/QskProgressRingSkinlet.cpp +++ b/src/controls/QskProgressRingSkinlet.cpp @@ -4,7 +4,7 @@ *****************************************************************************/ #include "QskProgressRingSkinlet.h" -#include "QskArcMetrics.h" +#include "QskArcHints.h" #include "QskProgressRing.h" #include "QskIntervalF.h" @@ -85,8 +85,12 @@ QSGNode* QskProgressRingSkinlet::updateGrooveNode( endAngle = fillAngles.first - 360.0 + spacing; } - return updateArcNode( ring, node, - startAngle, endAngle - startAngle, Q::Groove ); + auto hints = indicator->arcHints( Q::Groove ); + hints.metrics.setStartAngle( startAngle ); + hints.metrics.setSpanAngle( endAngle - startAngle ); + + const auto rect = indicator->subControlRect( Q::Groove ); + return updateArcNode( ring, node, rect, hints ); } } @@ -104,16 +108,14 @@ QSGNode* QskProgressRingSkinlet::updateFillNode( if ( rect.isEmpty() ) return nullptr; - const auto metrics = ring->arcMetricsHint( subControl ); - if ( metrics.isNull() ) - return nullptr; - - auto gradient = ring->gradientHint( subControl ); - if ( !gradient.isVisible() ) + auto hints = ring->arcHints( subControl ); + if ( !hints.isVisible() ) return nullptr; const auto intv = qskFillInterval( ring ); + auto& gradient = hints.gradient; + if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() ) { const auto stops = qskExtractedGradientStops( gradient.stops(), @@ -121,14 +123,15 @@ QSGNode* QskProgressRingSkinlet::updateFillNode( gradient.setStops( stops ); - if ( metrics.spanAngle() < 0.0 ) + if ( hints.metrics.spanAngle() < 0.0 ) gradient.reverse(); } - const auto angles = qskFillAngles( metrics, intv ); + const auto angles = qskFillAngles( hints.metrics, intv ); + hints.metrics.setStartAngle( angles.first ); + hints.metrics.setSpanAngle( angles.second - angles.first ); - return updateArcNode( ring, node, rect, gradient, - angles.first, angles.second - angles.first, subControl ); + return updateArcNode( ring, node, rect, hints ); } QSizeF QskProgressRingSkinlet::sizeHint( const QskSkinnable* skinnable, diff --git a/src/controls/QskSkinlet.cpp b/src/controls/QskSkinlet.cpp index 8a6caf7c..ae79be86 100644 --- a/src/controls/QskSkinlet.cpp +++ b/src/controls/QskSkinlet.cpp @@ -7,9 +7,7 @@ #include "QskArcNode.h" #include "QskAspect.h" -#include "QskArcMetrics.h" -#include "QskBoxBorderColors.h" -#include "QskBoxBorderMetrics.h" +#include "QskArcHints.h" #include "QskBoxNode.h" #include "QskBoxRectangleNode.h" #include "QskBoxShapeMetrics.h" @@ -156,18 +154,6 @@ static inline bool qskIsBoxVisible( const QskBoxBorderMetrics& borderMetrics, return !borderMetrics.isNull() && borderColors.isVisible(); } -static inline bool qskIsArcVisible( const QskArcMetrics& arcMetrics, - qreal borderWidth, const QColor borderColor, const QskGradient& gradient ) -{ - if ( arcMetrics.isNull() ) - return false; - - if ( borderWidth > 0.0 && borderColor.isValid() && borderColor.alpha() > 0 ) - return true; - - return gradient.isVisible(); -} - static inline bool qskIsLineVisible( const QColor& lineColor, qreal lineWidth ) { return ( lineWidth > 0.0 ) && lineColor.isValid() && ( lineColor.alpha() > 0 ); @@ -223,21 +209,20 @@ static inline QSGNode* qskUpdateBoxNode( const QskSkinnable* skinnable, return nullptr; } -static inline QSGNode* qskUpdateArcNode( - const QskSkinnable*, QSGNode* node, const QRectF& rect, - qreal borderWidth, const QColor borderColor, - const QskGradient& gradient, const QskArcMetrics& metrics ) +static inline QSGNode* qskUpdateArcNode( const QskSkinnable* skinnable, + QSGNode* node, const QRectF& rect, const QskArcHints& hints ) { - if ( rect.isEmpty() ) - return nullptr; + Q_UNUSED( skinnable ); - if ( !qskIsArcVisible( metrics, borderWidth, borderColor, gradient ) ) - return nullptr; + if ( !rect.isEmpty() && hints.isVisible() ) + { + auto arcNode = QskSGNode::ensureNode< QskArcNode >( node ); + arcNode->setArcData( rect, hints ); - auto arcNode = QskSGNode::ensureNode< QskArcNode >( node ); - arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient ); + return arcNode; + } - return arcNode; + return nullptr; } static inline QSGNode* qskUpdateLineNode( @@ -496,79 +481,24 @@ QSGNode* QskSkinlet::updateInterpolatedBoxNode( QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, QSGNode* node, QskAspect::Subcontrol subControl ) const { - const auto rect = qskSubControlRect( this, skinnable, subControl ); - return updateArcNode( skinnable, node, rect, subControl ); + auto rect = qskSubControlRect( this, skinnable, subControl ); + rect = rect.marginsRemoved( skinnable->marginHint( subControl ) ); + + return qskUpdateArcNode( skinnable, + node, rect, skinnable->arcHints( subControl ) ); +} + +QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, + QSGNode* node, const QRectF& rect, const QskArcHints& hints ) +{ + return qskUpdateArcNode( skinnable, node, rect, hints ); } QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl ) { - const auto fillGradient = skinnable->gradientHint( subControl ); - return updateArcNode( skinnable, node, rect, fillGradient, subControl ); -} - -QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, - QSGNode* node, const QRectF& rect, const QskGradient& fillGradient, - QskAspect::Subcontrol subControl ) -{ - const auto metrics = skinnable->arcMetricsHint( subControl ); - const auto r = rect.marginsRemoved( skinnable->marginHint( subControl ) ); - - const qreal borderWidth = skinnable->metric( subControl | QskAspect::Border ); - - QColor borderColor; - if ( borderWidth > 0.0 ) - borderColor = skinnable->color( subControl | QskAspect::Border ); - return qskUpdateArcNode( skinnable, node, - r, borderWidth, borderColor, fillGradient, metrics ); -} - -QSGNode* QskSkinlet::updateArcNode( - const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect, - qreal borderWidth, const QColor& borderColor, - const QskGradient& fillGradient, const QskArcMetrics& metrics ) -{ - return qskUpdateArcNode( skinnable, node, rect, - borderWidth, borderColor, fillGradient, metrics ); -} - -QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, - QSGNode* node, qreal startAngle, qreal spanAngle, - QskAspect::Subcontrol subControl ) const -{ - const auto rect = qskSubControlRect( this, skinnable, subControl ); - - return updateArcNode( skinnable, node, - rect, startAngle, spanAngle, subControl ); -} - -QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, - QSGNode* node, const QRectF& rect, qreal startAngle, qreal spanAngle, - QskAspect::Subcontrol subControl ) -{ - const auto fillGradient = skinnable->gradientHint( subControl ); - return updateArcNode( skinnable, node, rect, - fillGradient, startAngle, spanAngle, subControl ); -} - -QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, - QSGNode* node, const QRectF& rect, const QskGradient& fillGradient, - qreal startAngle, qreal spanAngle, QskAspect::Subcontrol subControl ) -{ - auto arcMetrics = skinnable->arcMetricsHint( subControl ); - arcMetrics.setStartAngle( startAngle ); - arcMetrics.setSpanAngle( spanAngle ); - - const qreal borderWidth = skinnable->metric( subControl | QskAspect::Border ); - - QColor borderColor; - if ( borderWidth > 0.0 ) - borderColor = skinnable->color( subControl | QskAspect::Border ); - - const auto r = rect.marginsRemoved( skinnable->marginHint( subControl ) ); - return updateArcNode( skinnable, node, r, - borderWidth, borderColor, fillGradient, arcMetrics ); + rect, skinnable->arcHints( subControl ) ); } QSGNode* QskSkinlet::updateLineNode( const QskSkinnable* skinnable, diff --git a/src/controls/QskSkinlet.h b/src/controls/QskSkinlet.h index cd4ffa0a..cf227580 100644 --- a/src/controls/QskSkinlet.h +++ b/src/controls/QskSkinlet.h @@ -23,10 +23,8 @@ class QskColorFilter; class QskGraphic; class QskTextOptions; class QskTextColors; -class QskBoxShapeMetrics; -class QskBoxBorderMetrics; -class QskBoxBorderColors; class QskBoxHints; +class QskArcHints; class QSGNode; @@ -87,18 +85,7 @@ class QSK_EXPORT QskSkinlet const QRectF&, QskAspect::Subcontrol ); static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*, - const QRectF&, const QskGradient&, QskAspect::Subcontrol ); - - static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*, - const QRectF&, qreal borderWidth, const QColor& borderColor, - const QskGradient&, const QskArcMetrics& ); - - static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*, - const QRectF&, qreal startAngle, qreal spanAngle, QskAspect::Subcontrol ); - - static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*, - const QRectF&, const QskGradient&, qreal startAngle, qreal spanAngle, - QskAspect::Subcontrol ); + const QRectF&, const QskArcHints& ); static QSGNode* updateLineNode( const QskSkinnable*, QSGNode*, const QLineF&, QskAspect::Subcontrol ); @@ -149,10 +136,6 @@ class QSK_EXPORT QskSkinlet QSGNode* updateArcNode( const QskSkinnable*, QSGNode*, QskAspect::Subcontrol ) const; - QSGNode* updateArcNode( const QskSkinnable*, QSGNode*, - qreal startAngle, qreal spanAngle, - QskAspect::Subcontrol ) const; - QSGNode* updateBoxClipNode( const QskSkinnable*, QSGNode*, QskAspect::Subcontrol ) const; diff --git a/src/controls/QskSkinnable.cpp b/src/controls/QskSkinnable.cpp index 844af312..7010fb39 100644 --- a/src/controls/QskSkinnable.cpp +++ b/src/controls/QskSkinnable.cpp @@ -6,7 +6,7 @@ #include "QskSkinnable.h" #include "QskAnimationHint.h" -#include "QskArcMetrics.h" +#include "QskArcHints.h" #include "QskAspect.h" #include "QskColorFilter.h" #include "QskControl.h" @@ -637,9 +637,23 @@ QColor QskSkinnable::shadowColorHint( QskAspect aspect, QskSkinHintStatus* statu QskBoxHints QskSkinnable::boxHints( QskAspect aspect ) const { return QskBoxHints( - boxShapeHint( aspect ), boxBorderMetricsHint( aspect ), - boxBorderColorsHint( aspect ), gradientHint( aspect ), - shadowMetricsHint( aspect ), shadowColorHint( aspect ) ); + boxShapeHint( aspect ), + boxBorderMetricsHint( aspect ), + boxBorderColorsHint( aspect ), + gradientHint( aspect ), + shadowMetricsHint( aspect ), + shadowColorHint( aspect ) + ); +} + +QskArcHints QskSkinnable::arcHints( QskAspect aspect ) const +{ + return QskArcHints( + arcMetricsHint( aspect ), + metric( aspect | QskAspect::Border ), + color( aspect | QskAspect::Border ), + gradientHint( aspect ) + ); } bool QskSkinnable::setArcMetricsHint( diff --git a/src/controls/QskSkinnable.h b/src/controls/QskSkinnable.h index a4772448..26160b97 100644 --- a/src/controls/QskSkinnable.h +++ b/src/controls/QskSkinnable.h @@ -22,6 +22,7 @@ class QDebug; class QSGNode; class QQuickItem; +class QskArcHints; class QskArcMetrics; class QskControl; class QskAnimationHint; @@ -226,6 +227,7 @@ class QSK_EXPORT QskSkinnable QColor shadowColorHint( QskAspect, QskSkinHintStatus* = nullptr ) const; QskBoxHints boxHints( QskAspect ) const; + QskArcHints arcHints( QskAspect ) const; bool setArcMetricsHint( QskAspect, const QskArcMetrics& ); bool resetArcMetricsHint( QskAspect ); diff --git a/src/nodes/QskArcNode.cpp b/src/nodes/QskArcNode.cpp index e048f3b7..af5ee1b1 100644 --- a/src/nodes/QskArcNode.cpp +++ b/src/nodes/QskArcNode.cpp @@ -4,11 +4,10 @@ *****************************************************************************/ #include "QskArcNode.h" -#include "QskArcMetrics.h" +#include "QskArcHints.h" #include "QskArcRenderNode.h" #include "QskArcRenderer.h" #include "QskMargins.h" -#include "QskGradient.h" #include "QskSGNode.h" #include "QskRgbValue.h" @@ -58,24 +57,21 @@ QskArcNode::~QskArcNode() { } -void QskArcNode::setArcData( const QRectF& rect, - const QskArcMetrics& arcMetrics, const QskGradient& gradient ) -{ - setArcData( rect, arcMetrics, 0.0, QColor(), gradient ); -} - -void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics, - const qreal borderWidth, const QColor& borderColor, const QskGradient& gradient ) +void QskArcNode::setArcData( const QRectF& rect, const QskArcHints& hints ) { using namespace QskSGNode; QskArcRenderNode* arcNode = nullptr; QskArcRenderNode* fillNode = nullptr; - if ( !( rect.isEmpty() || arcMetrics.isNull() ) ) + if ( !rect.isEmpty() && hints.isVisible() ) { + const auto& gradient = hints.gradient; + const auto borderWidth = hints.borderWidth; + const auto borderColor = hints.borderColor; + const bool radial = false; - const auto metricsArc = arcMetrics.toAbsolute( rect.size() ); + const auto metricsArc = hints.metrics.toAbsolute( rect.size() ); const auto hasFilling = gradient.isVisible(); const auto hasBorder = ( borderWidth > 0.0 ) && QskRgb::isVisible( borderColor ); diff --git a/src/nodes/QskArcNode.h b/src/nodes/QskArcNode.h index 59ca1190..3bfcb916 100644 --- a/src/nodes/QskArcNode.h +++ b/src/nodes/QskArcNode.h @@ -9,8 +9,7 @@ #include "QskGlobal.h" #include -class QskArcMetrics; -class QskGradient; +class QskArcHints; class QSK_EXPORT QskArcNode : public QSGNode { @@ -18,10 +17,7 @@ class QSK_EXPORT QskArcNode : public QSGNode QskArcNode(); ~QskArcNode() override; - void setArcData( const QRectF&, const QskArcMetrics&, const QskGradient& ); - - void setArcData( const QRectF&, const QskArcMetrics&, - qreal borderWidth, const QColor& borderColor, const QskGradient& ); + void setArcData( const QRectF&, const QskArcHints& ); }; #endif