diff --git a/src/common/QskGradient.cpp b/src/common/QskGradient.cpp index a27fb931..9eef5732 100644 --- a/src/common/QskGradient.cpp +++ b/src/common/QskGradient.cpp @@ -9,6 +9,8 @@ #include #include +#include + static void qskRegisterGradient() { qRegisterMetaType< QskGradient >(); @@ -17,6 +19,12 @@ static void qskRegisterGradient() Q_CONSTRUCTOR_FUNCTION( qskRegisterGradient ) +static inline QskGradient::Orientation qskOrientation( Qt::Orientation o ) +{ + return ( o == Qt::Vertical ) + ? QskGradient::Vertical : QskGradient::Horizontal; +} + static inline bool qskIsGradientValid( const QVector< QskGradientStop >& stops ) { if ( stops.size() < 2 ) @@ -110,6 +118,53 @@ static inline QVector< QskGradientStop > qskExpandedStops( return stops; } +static inline QVector< QskGradientStop > qskExtractedStops( + const QVector< QskGradientStop >& stops, qreal from, qreal to ) +{ + QVector< QskGradientStop > extracted; + + if ( from == to ) + extracted.reserve( 2 ); + else + extracted.reserve( stops.size() ); + + int i = 0; + + if ( from == 0.0 ) + { + extracted += QskGradientStop( 0.0, stops[i].color() ); + } + else + { + for ( ; i < stops.count(); i++ ) + { + if ( stops[i].position() >= from ) + break; + } + + const auto color = + QskGradientStop::interpolated( stops[i-1], stops[i], from ); + + extracted += QskGradientStop( 0.0, color ); + } + + for ( i = i + 1 ; i < stops.count(); i++ ) + { + const auto& s = stops[i]; + + if ( s.position() >= to ) + break; + + const auto pos = ( s.position() - from ) / ( to - from ); + extracted += QskGradientStop( pos, s.color() ); + } + + const auto color = QskGradientStop::interpolated( stops[i-1], stops[i], to ); + extracted += QskGradientStop( 1.0, color ); + + return extracted; +} + void QskGradientStop::setPosition( qreal position ) { m_position = position; @@ -175,6 +230,12 @@ QskGradient::QskGradient( const QColor& color ) setColor( color ); } +QskGradient::QskGradient( Qt::Orientation orientation, + const QColor& startColor, const QColor& stopColor ) + : QskGradient( qskOrientation( orientation ), startColor, stopColor ) +{ +} + QskGradient::QskGradient( Orientation orientation, const QColor& startColor, const QColor& stopColor ) : m_orientation( orientation ) @@ -182,6 +243,12 @@ QskGradient::QskGradient( Orientation orientation, setColors( startColor, stopColor ); } +QskGradient::QskGradient( Qt::Orientation orientation, + const QVector< QskGradientStop >& stops ) + : QskGradient( qskOrientation( orientation ), stops ) +{ +} + QskGradient::QskGradient( Orientation orientation, const QVector< QskGradientStop >& stops ) : m_orientation( orientation ) @@ -226,6 +293,11 @@ bool QskGradient::isVisible() const return false; } +void QskGradient::setOrientation( Qt::Orientation orientation ) +{ + setOrientation( qskOrientation( orientation ) ); +} + void QskGradient::setOrientation( Orientation orientation ) { m_orientation = orientation; @@ -354,6 +426,39 @@ uint QskGradient::hash( uint seed ) const return hash; } +void QskGradient::reverse() +{ + if ( isMonochrome() ) + return; + + std::reverse( m_stops.begin(), m_stops.end() ); + for( auto& stop : m_stops ) + stop.setPosition( 1.0 - stop.position() ); +} + +QskGradient QskGradient::reversed() const +{ + auto gradient = *this; + gradient.reverse(); + + return gradient; +} + +QskGradient QskGradient::extracted( qreal from, qreal to ) const +{ + if ( from > to ) + return QskGradient( m_orientation ); + + if ( isMonochrome() || ( from <= 0.0 && to >= 1.0 ) ) + return *this; + + from = qMax( from, 0.0 ); + to = qMin( to, 1.0 ); + + const auto stops = qskExtractedStops( m_stops, from, to ); + return QskGradient( m_orientation, stops ); +} + QskGradient QskGradient::interpolated( const QskGradient& to, qreal value ) const { diff --git a/src/common/QskGradient.h b/src/common/QskGradient.h index e66d169f..cdee174c 100644 --- a/src/common/QskGradient.h +++ b/src/common/QskGradient.h @@ -76,16 +76,20 @@ class QSK_EXPORT QskGradient QskGradient( QRgb ); QskGradient( const QColor& ); + QskGradient( Qt::Orientation, const QVector< QskGradientStop >& ); + QskGradient( Qt::Orientation, const QColor&, const QColor& ); + QskGradient( Orientation, const QVector< QskGradientStop >& ); QskGradient( Orientation, const QColor&, const QColor& ); ~QskGradient(); + void setOrientation( Qt::Orientation ); void setOrientation( Orientation ); Orientation orientation() const; bool isValid() const; - void invalidate(); + Q_INVOKABLE void invalidate(); bool operator==( const QskGradient& ) const; bool operator!=( const QskGradient& ) const; @@ -93,20 +97,25 @@ class QSK_EXPORT QskGradient void setColor( const QColor& ); void setColors( const QColor&, const QColor& ); - QColor startColor() const; - QColor endColor() const; + Q_INVOKABLE QColor startColor() const; + Q_INVOKABLE QColor endColor() const; - void setStops( const QVector< QskGradientStop >& ); - QVector< QskGradientStop > stops() const; + Q_INVOKABLE void setStops( const QVector< QskGradientStop >& ); + Q_INVOKABLE QVector< QskGradientStop > stops() const; - bool hasStopAt( qreal value ) const; + Q_INVOKABLE bool hasStopAt( qreal value ) const; void setAlpha( int alpha ); bool isMonochrome() const; bool isVisible() const; - QskGradient expanded( const QVector< QskGradientStop >& ); + void reverse(); + QskGradient reversed() const; + + // all stops between [from, to] with positions streched into [0,1] + QskGradient extracted( qreal from, qreal start ) const; + QskGradient interpolated( const QskGradient&, qreal value ) const; static QVariant interpolate( const QskGradient&, @@ -114,8 +123,8 @@ class QSK_EXPORT QskGradient uint hash( uint seed ) const; - qreal stopAt( int index ) const; - QColor colorAt( int index ) const; + Q_INVOKABLE qreal stopAt( int index ) const; + Q_INVOKABLE QColor colorAt( int index ) const; private: void setStopAt( int index, qreal stop );