diff --git a/examples/boxes/Box.cpp b/examples/boxes/Box.cpp index b42028ec..1849edf1 100644 --- a/examples/boxes/Box.cpp +++ b/examples/boxes/Box.cpp @@ -205,11 +205,11 @@ void Box::setGradient( { const QskHctColor hctColor( base ); - QVector< QRgb > rgb; - rgb.reserve( 10 ); + QVector< QRgb > colors; + colors.reserve( 10 ); for ( int i = 0; i < 10; i++ ) - rgb += hctColor.toned( 90 - i * 7 ).rgb(); + colors += hctColor.toned( 90 - i * 7 ).rgb(); - setGradient( QskGradient( orientation, QskGradient::colorStops( rgb, true ) ) ); + setGradient( QskGradient( orientation, qskBuildGradientStops( colors, true ) ) ); } diff --git a/examples/gallery/progressbar/ProgressBarPage.cpp b/examples/gallery/progressbar/ProgressBarPage.cpp index e3e0146b..4a5b5ae9 100644 --- a/examples/gallery/progressbar/ProgressBarPage.cpp +++ b/examples/gallery/progressbar/ProgressBarPage.cpp @@ -29,15 +29,14 @@ namespace { const QskHctColor hctColor( base ); - QVector< QRgb > rgb; - rgb += hctColor.toned( 75 ).rgb(); - rgb += hctColor.toned( 60 ).rgb(); - rgb += hctColor.toned( 45 ).rgb(); - rgb += hctColor.toned( 30 ).rgb(); + QVector< QRgb > colors; + colors += hctColor.toned( 75 ).rgb(); + colors += hctColor.toned( 60 ).rgb(); + colors += hctColor.toned( 45 ).rgb(); + colors += hctColor.toned( 30 ).rgb(); - const auto stops = QskGradient::colorStops( rgb, true ); - - setBarGradient( QskGradient( orientation(), stops ) ); + setBarGradient( QskGradient( orientation(), + qskBuildGradientStops( colors, true ) ) ); } }; } diff --git a/src/common/QskGradient.cpp b/src/common/QskGradient.cpp index 129ea200..50e675a1 100644 --- a/src/common/QskGradient.cpp +++ b/src/common/QskGradient.cpp @@ -9,8 +9,6 @@ #include #include -#include - static void qskRegisterGradient() { qRegisterMetaType< QskGradient >(); @@ -37,9 +35,7 @@ static inline bool qskIsGradientValid( const QskGradientStops& stops ) return false; if ( stops.first().position() != 0.0 || stops.last().position() != 1.0 ) - { return false; - } if ( !stops.first().color().isValid() ) return false; @@ -56,29 +52,6 @@ static inline bool qskIsGradientValid( const QskGradientStops& stops ) return true; } -static inline bool qskIsMonochrome( const QskGradientStops& stops ) -{ - for ( int i = 1; i < stops.size(); i++ ) - { - if ( stops[ i ].color() != stops[ 0 ].color() ) - return false; - } - - return true; -} - -static inline bool qskIsVisible( const QskGradientStops& stops ) -{ - for ( const auto& stop : stops ) - { - const auto& c = stop.color(); - if ( c.isValid() && c.alpha() > 0 ) - return true; - } - - return false; -} - static inline QColor qskInterpolated( const QskGradientStop& s1, const QskGradientStop& s2, qreal pos ) { @@ -183,53 +156,6 @@ static inline QskGradientStops qskExtractedStops( return extracted; } -static inline QskGradientStops qskGradientStops( const QGradientStops& qtStops ) -{ - QskGradientStops stops; - stops.reserve( qtStops.count() ); - - for ( const auto& s : qtStops ) - stops += QskGradientStop( s.first, s.second ); - - return stops; -} - -static inline QskGradientStops qskColorStops( - const QRgb* rgb, int count, bool discrete ) -{ - QskGradientStops stops; - - if ( discrete ) - stops.reserve( 2 * count - 2 ); - else - stops.reserve( count ); - - stops += QskGradientStop( 0.0, rgb[0] ); - - if ( discrete ) - { - const auto step = 1.0 / count; - - for ( int i = 1; i < count; i++ ) - { - const qreal pos = i * step; - stops += QskGradientStop( pos, rgb[i - 1] ); - stops += QskGradientStop( pos, rgb[i] ); - } - } - else - { - const auto step = 1.0 / ( count - 1 ); - - for ( int i = 1; i < count - 1; i++ ) - stops += QskGradientStop( i * step, rgb[i] ); - } - - stops += QskGradientStop( 1.0, rgb[count - 1] ); - - return stops; -} - QskGradient::QskGradient( Orientation orientation ) noexcept : m_orientation( orientation ) , m_isDirty( false ) @@ -277,7 +203,7 @@ QskGradient::QskGradient( Qt::Orientation orientation, QGradient::Preset preset QskGradient::QskGradient( Orientation orientation, QGradient::Preset preset ) : QskGradient( orientation ) { - setStops( qskGradientStops( QGradient( preset ).stops() ) ); + setStops( qskBuildGradientStops( QGradient( preset ).stops() ) ); } QskGradient::~QskGradient() @@ -380,20 +306,35 @@ void QskGradient::setStops( const QskGradientStops& stops ) m_isDirty = true; } -int QskGradient::stopCount() const +int QskGradient::stopCount() const noexcept { return m_stops.count(); } -qreal QskGradient::stopAt( int index ) const +qreal QskGradient::stopAt( int index ) const noexcept { - if ( index >= m_stops.size() ) + if ( index < 0 || index >= m_stops.size() ) return -1.0; return m_stops[ index ].position(); } -QColor QskGradient::colorAt( int index ) const +bool QskGradient::hasStopAt( qreal value ) const noexcept +{ + // better use binary search TODO ... + for ( auto& stop : m_stops ) + { + if ( stop.position() == value ) + return true; + + if ( stop.position() > value ) + break; + } + + return false; +} + +QColor QskGradient::colorAt( int index ) const noexcept { if ( index >= m_stops.size() ) return QColor(); @@ -416,21 +357,6 @@ void QskGradient::setAlpha( int alpha ) m_isDirty = true; } -bool QskGradient::hasStopAt( qreal value ) const noexcept -{ - // better use binary search TODO ... - for ( auto& stop : m_stops ) - { - if ( stop.position() == value ) - return true; - - if ( stop.position() > value ) - break; - } - - return false; -} - void QskGradient::reverse() { if ( isMonochrome() ) @@ -611,39 +537,6 @@ QVariant QskGradient::interpolate( return QVariant::fromValue( from.interpolated( to, progress ) ); } -QskGradientStops QskGradient::colorStops( - const QVector< QRgb >& rgb, bool discrete ) -{ - const int count = rgb.count(); - - if ( count == 0 ) - return QskGradientStops(); - - if ( count == 1 ) - { - QskGradientStops stops; - stops.reserve( 2 ); - - stops += QskGradientStop( 0.0, rgb[0] ); - stops += QskGradientStop( 1.0, rgb[0] ); - - return stops; - } - - return qskColorStops( rgb.constData(), count, discrete ); -} - -QGradientStops QskGradient::qtStops() const -{ - QGradientStops qstops; - qstops.reserve( m_stops.count() ); - - for ( const auto& stop : m_stops ) - qstops += { stop.position(), stop.color() }; - - return qstops; -} - void QskGradient::clearStops() { if ( !m_stops.isEmpty() ) @@ -655,9 +548,6 @@ void QskGradient::clearStops() QskHashValue QskGradient::hash( QskHashValue seed ) const { - if ( m_stops.isEmpty() ) - return seed; - const auto o = orientation(); auto hash = qHashBits( &o, sizeof( o ), seed ); @@ -667,7 +557,6 @@ QskHashValue QskGradient::hash( QskHashValue seed ) const return hash; } - #ifndef QT_NO_DEBUG_STREAM #include @@ -704,13 +593,13 @@ QDebug operator<<( QDebug debug, const QskGradient& gradient ) } else { - const auto& s = gradient.stops(); - for ( int i = 0; i < s.count(); i++ ) + const auto& stops = gradient.stops(); + for ( int i = 0; i < stops.count(); i++ ) { if ( i != 0 ) debug << ", "; - debug << s[i]; + debug << stops[i]; } } } diff --git a/src/common/QskGradient.h b/src/common/QskGradient.h index 305d3ac8..76120a81 100644 --- a/src/common/QskGradient.h +++ b/src/common/QskGradient.h @@ -98,15 +98,10 @@ class QSK_EXPORT QskGradient QskHashValue hash( QskHashValue seed ) const; - Q_INVOKABLE qreal stopAt( int index ) const; - Q_INVOKABLE QColor colorAt( int index ) const; + Q_INVOKABLE qreal stopAt( int index ) const noexcept; + Q_INVOKABLE QColor colorAt( int index ) const noexcept; - Q_INVOKABLE int stopCount() const; - - QGradientStops qtStops() const; - - static QskGradientStops colorStops( - const QVector< QRgb >&, bool discrete = false ); + Q_INVOKABLE int stopCount() const noexcept; private: void updateStatusBits() const; diff --git a/src/common/QskGradientStop.cpp b/src/common/QskGradientStop.cpp index 48dbdac2..348b4077 100644 --- a/src/common/QskGradientStop.cpp +++ b/src/common/QskGradientStop.cpp @@ -8,6 +8,7 @@ #include #include +#include #include @@ -94,3 +95,128 @@ QDebug operator<<( QDebug debug, const QskGradientStop& stop ) #endif #include "moc_QskGradientStop.cpp" + +// some helper functions around QskGradientStops + +bool qskIsVisible( const QskGradientStops& stops ) noexcept +{ + for ( const auto& stop : stops ) + { + const auto& c = stop.color(); + if ( c.isValid() && c.alpha() > 0 ) + return true; + } + + return false; +} + +bool qskIsMonochrome( const QskGradientStops& stops ) noexcept +{ + for ( int i = 1; i < stops.size(); i++ ) + { + if ( stops[ i ].color() != stops[ 0 ].color() ) + return false; + } + + return true; +} + +QskGradientStops qskTransparentGradientStops( const QskGradientStops& stops, qreal ratio ) +{ + auto newStops = stops; + + for ( auto& stop : newStops ) + { + auto c = stop.color(); + c.setAlpha( c.alpha() * ratio ); + + stop.setColor( c ); + } + + return newStops; +} + +QVector< QskGradientStop > qskBuildGradientStops( const QGradientStops& qtStops ) +{ + QVector< QskGradientStop > stops; + stops.reserve( qtStops.count() ); + + for ( const auto& s : qtStops ) + stops += QskGradientStop( s.first, s.second ); + + return stops; +} + +template< typename T > +static inline QVector< QskGradientStop > qskCreateStops( + const QVector< T > colors, bool discrete ) +{ + QVector< QskGradientStop > stops; + + const auto count = colors.count(); + if ( count == 0 ) + return stops; + + if ( count == 1 ) + { + stops.reserve( 2 ); + + stops += QskGradientStop( 0.0, colors[0] ); + stops += QskGradientStop( 1.0, colors[0] ); + + return stops; + } + + if ( discrete ) + { + const auto step = 1.0 / count; + stops.reserve( 2 * count - 2 ); + + stops += QskGradientStop( 0.0, colors[0] ); + + for ( int i = 1; i < count; i++ ) + { + const qreal pos = i * step; + stops += QskGradientStop( pos, colors[i - 1] ); + stops += QskGradientStop( pos, colors[i] ); + } + + stops += QskGradientStop( 1.0, colors[count - 1] ); + } + else + { + const auto step = 1.0 / ( count - 1 ); + stops.reserve( count ); + + stops += QskGradientStop( 0.0, colors[0] ); + + for ( int i = 1; i < count - 1; i++ ) + stops += QskGradientStop( i * step, colors[i] ); + + stops += QskGradientStop( 1.0, colors[count - 1] ); + } + + return stops; +} + +QskGradientStops qskBuildGradientStops( const QVector< QRgb >& colors, bool discrete ) +{ + return qskCreateStops( colors, discrete ); +} + +QskGradientStops qskBuildGradientStops( const QVector< QColor >& colors, bool discrete ) +{ + return qskCreateStops( colors, discrete ); +} + +QGradientStops qskToQGradientStops( const QskGradientStops& stops ) +{ + QGradientStops qstops; + qstops.reserve( stops.count() ); + + for ( const auto& stop : stops ) + qstops += { stop.position(), stop.color() }; + + return qstops; +} + diff --git a/src/common/QskGradientStop.h b/src/common/QskGradientStop.h index 9776de2d..8133f957 100644 --- a/src/common/QskGradientStop.h +++ b/src/common/QskGradientStop.h @@ -12,6 +12,8 @@ #include #include +typedef QPair< qreal, QColor > QGradientStop; + class QSK_EXPORT QskGradientStop { Q_GADGET @@ -22,6 +24,7 @@ class QSK_EXPORT QskGradientStop public: constexpr QskGradientStop() noexcept; constexpr QskGradientStop( qreal position, const QColor& ) noexcept; + constexpr QskGradientStop( const QGradientStop& ) noexcept; QskGradientStop( qreal position, Qt::GlobalColor ) noexcept; QskGradientStop( qreal position, QRgb ) noexcept; @@ -57,8 +60,6 @@ class QSK_EXPORT QskGradientStop Q_DECLARE_METATYPE( QskGradientStop ) -typedef QVector< QskGradientStop > QskGradientStops; - inline constexpr QskGradientStop::QskGradientStop() noexcept : m_position( -1.0 ) { @@ -83,6 +84,11 @@ inline QskGradientStop::QskGradientStop( { } +inline constexpr QskGradientStop::QskGradientStop( const QGradientStop& qtStop ) noexcept + : QskGradientStop( qtStop.first, qtStop.second ) +{ +} + inline constexpr qreal QskGradientStop::position() const noexcept { return m_position; @@ -116,4 +122,18 @@ QSK_EXPORT QDebug operator<<( QDebug, const QskGradientStop& ); #endif +typedef QVector< QskGradientStop > QskGradientStops; + +QSK_EXPORT bool qskIsMonochrome( const QskGradientStops& ) noexcept; +QSK_EXPORT bool qskIsVisible( const QskGradientStops& ) noexcept; + +QSK_EXPORT QskGradientStops qskBuildGradientStops( + const QVector< QRgb >&, bool discrete = false ); + +QSK_EXPORT QskGradientStops qskBuildGradientStops( + const QVector< QColor >&, bool discrete = false ); + +QSK_EXPORT QskGradientStops qskBuildGradientStops( const QVector< QGradientStop >& ); +QSK_EXPORT QVector< QGradientStop > qskToQGradientStops( const QVector< QskGradientStop >& ); + #endif diff --git a/src/nodes/QskArcRenderer.cpp b/src/nodes/QskArcRenderer.cpp index 72f5576c..0a9f0ad2 100644 --- a/src/nodes/QskArcRenderer.cpp +++ b/src/nodes/QskArcRenderer.cpp @@ -23,17 +23,19 @@ void QskArcRenderer::renderArc(const QRectF& rect, QBrush brush; + const auto qStops = qskToQGradientStops( gradient.stops() ); + if( gradient.orientation() == QskGradient::Vertical ) { QRadialGradient radial( rect.center(), qMin( rect.width(), rect.height() ) ); - radial.setStops( gradient.qtStops() ); + radial.setStops( qStops ); brush = radial; } else { QConicalGradient conical( rect.center(), metrics.startAngle() ); - conical.setStops( gradient.qtStops() ); + conical.setStops( qStops ); brush = conical; }