2017-07-21 18:21:34 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskGradient.h"
|
2017-10-17 17:34:00 +02:00
|
|
|
#include "QskRgbValue.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
#include <qhashfunctions.h>
|
2018-08-03 08:15:28 +02:00
|
|
|
#include <qvariant.h>
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
static void qskRegisterGradient()
|
|
|
|
{
|
|
|
|
qRegisterMetaType< QskGradient >();
|
2019-04-18 16:11:38 +02:00
|
|
|
qRegisterMetaType< QskGradientStop >();
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Q_CONSTRUCTOR_FUNCTION( qskRegisterGradient )
|
|
|
|
|
|
|
|
static inline bool qskIsGradientValid( const QVector< QskGradientStop >& stops )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
if ( stops.size() < 2 )
|
|
|
|
return false;
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( stops.first().position() != 0.0 || stops.last().position() != 1.0 )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !stops.first().color().isValid() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for ( int i = 1; i < stops.size(); i++ )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( stops[ i ].position() < stops[ i - 1 ].position() )
|
2017-07-21 18:21:34 +02:00
|
|
|
return false;
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( !stops[ i ].color().isValid() )
|
2017-07-21 18:21:34 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
static inline bool qskIsMonochrome( const QVector< QskGradientStop >& stops )
|
|
|
|
{
|
|
|
|
for ( int i = 1; i < stops.size(); i++ )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( stops[ i ].color() != stops[ 0 ].color() )
|
2017-10-17 17:34:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline QColor qskInterpolated(
|
|
|
|
const QskGradientStop& s1, const QskGradientStop& s2, qreal pos )
|
|
|
|
{
|
|
|
|
if ( s1.color() == s2.color() )
|
|
|
|
return s1.color();
|
|
|
|
|
|
|
|
const qreal ratio = ( pos - s1.position() ) / ( s2.position() - s1.position() );
|
|
|
|
return QskRgbValue::interpolated( s1.color(), s2.color(), ratio );
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool qskComparePositions(
|
|
|
|
const QVector< QskGradientStop >& s1, const QVector< QskGradientStop >& s2 )
|
|
|
|
{
|
|
|
|
if ( s1.count() != s2.count() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// the first is always at 0.0, the last at 1.0
|
|
|
|
for ( int i = 1; i < s1.count() - 1; i++ )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( s1[ i ].position() != s2[ i ].position() )
|
2017-10-17 17:34:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline QVector< QskGradientStop > qskExpandedStops(
|
|
|
|
const QVector< QskGradientStop >& s1, const QVector< QskGradientStop >& s2 )
|
|
|
|
{
|
|
|
|
// expand s1 by stops matching to the positions from s2
|
|
|
|
|
|
|
|
if ( qskComparePositions( s1, s2 ) )
|
|
|
|
return s1;
|
|
|
|
|
|
|
|
QVector< QskGradientStop > stops;
|
|
|
|
|
|
|
|
stops += s1.first();
|
|
|
|
|
|
|
|
int i = 1, j = 1;
|
2018-08-03 08:15:28 +02:00
|
|
|
while ( ( i < s1.count() - 1 ) || ( j < s2.count() - 1 ) )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( s1[ i ].position() < s2[ j ].position() )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
stops += s1[ i++ ];
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
const qreal pos = s2[ j++ ].position();
|
|
|
|
stops += QskGradientStop( pos, qskInterpolated( s1[ i - 1 ], s1[ i ], pos ) );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stops += s1.last();
|
|
|
|
|
|
|
|
return stops;
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskGradientStop::QskGradientStop()
|
|
|
|
: m_position( -1.0 )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskGradientStop::QskGradientStop( qreal position, const QColor& color )
|
|
|
|
: m_position( position )
|
|
|
|
, m_color( color )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradientStop::setPosition( qreal position )
|
|
|
|
{
|
|
|
|
m_position = position;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradientStop::resetPosition()
|
|
|
|
{
|
|
|
|
m_position = -1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradientStop::setColor( const QColor& color )
|
|
|
|
{
|
|
|
|
m_color = color;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradientStop::resetColor()
|
|
|
|
{
|
|
|
|
m_color = QColor();
|
|
|
|
}
|
|
|
|
|
2020-01-02 12:20:15 +01:00
|
|
|
void QskGradientStop::setStop( qreal position, const QColor& color )
|
|
|
|
{
|
|
|
|
m_position = position;
|
|
|
|
m_color = color;
|
|
|
|
}
|
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
uint QskGradientStop::hash( uint seed ) const
|
|
|
|
{
|
|
|
|
uint hash = qHashBits( &m_position, sizeof( m_position ), seed );
|
|
|
|
return qHashBits( &m_color, sizeof( m_color ), hash );
|
|
|
|
}
|
|
|
|
|
|
|
|
QColor QskGradientStop::interpolated(
|
|
|
|
const QskGradientStop& s1, const QskGradientStop& s2, qreal position )
|
|
|
|
{
|
|
|
|
if ( s1.color() == s2.color() )
|
|
|
|
return s1.color();
|
|
|
|
|
|
|
|
auto min = &s1;
|
|
|
|
auto max = &s2;
|
|
|
|
|
|
|
|
if ( min->position() > max->position() )
|
|
|
|
std::swap( min, max );
|
|
|
|
|
|
|
|
if ( position <= min->position() )
|
|
|
|
return min->color();
|
|
|
|
|
|
|
|
if ( position >= max->position() )
|
|
|
|
return max->color();
|
|
|
|
|
|
|
|
const qreal r = ( position - min->position() ) / ( max->position() - min->position() );
|
|
|
|
return QskRgbValue::interpolated( min->color(), max->color(), r );
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskGradient::QskGradient()
|
|
|
|
: m_orientation( Vertical )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskGradient::QskGradient( const QColor& color )
|
|
|
|
: m_orientation( Vertical )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
setColor( color );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskGradient::QskGradient( Orientation orientation,
|
2018-08-03 08:15:28 +02:00
|
|
|
const QColor& startColor, const QColor& stopColor )
|
|
|
|
: m_orientation( orientation )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
setColors( startColor, stopColor );
|
|
|
|
}
|
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
QskGradient::QskGradient( Orientation orientation,
|
2018-08-03 08:15:28 +02:00
|
|
|
const QVector< QskGradientStop >& stops )
|
|
|
|
: m_orientation( orientation )
|
|
|
|
, m_stops( stops )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QskGradient::~QskGradient()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskGradient::isValid() const
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
return qskIsGradientValid( m_stops );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradient::invalidate()
|
|
|
|
{
|
|
|
|
m_stops.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskGradient::isMonochrome() const
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
if ( !qskIsGradientValid( m_stops ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
return true;
|
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
return qskIsMonochrome( m_stops );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool QskGradient::isVisible() const
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
if ( isValid() )
|
|
|
|
{
|
|
|
|
for ( const auto& stop : m_stops )
|
|
|
|
{
|
|
|
|
const auto& c = stop.color();
|
|
|
|
if ( c.isValid() && c.alpha() > 0 )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradient::setOrientation( Orientation orientation )
|
|
|
|
{
|
|
|
|
m_orientation = orientation;
|
|
|
|
}
|
|
|
|
|
|
|
|
QskGradient::Orientation QskGradient::orientation() const
|
|
|
|
{
|
|
|
|
return m_orientation;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradient::setColor( const QColor& color )
|
|
|
|
{
|
|
|
|
setColors( color, color );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradient::setColors( const QColor& startColor, const QColor& stopColor )
|
|
|
|
{
|
|
|
|
m_stops.resize( 2 );
|
2018-08-03 08:15:28 +02:00
|
|
|
m_stops[ 0 ].setPosition( 0.0 );
|
|
|
|
m_stops[ 0 ].setColor( startColor );
|
|
|
|
m_stops[ 1 ].setPosition( 1.0 );
|
|
|
|
m_stops[ 1 ].setColor( stopColor );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradient::setStops( const QVector< QskGradientStop >& stops )
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
if ( !qskIsGradientValid( stops ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
qWarning( "Invalid gradient stops" );
|
|
|
|
invalidate();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_stops = stops;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVector< QskGradientStop > QskGradient::stops() const
|
|
|
|
{
|
|
|
|
return m_stops;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradient::setStopAt( int index, qreal stop )
|
|
|
|
{
|
|
|
|
if ( stop < 0.0 || stop > 1.0 )
|
|
|
|
{
|
|
|
|
qWarning( "Invalid gradient stop: %g, must be in the range [0,1]", stop );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( index >= m_stops.size() )
|
|
|
|
m_stops.resize( index + 1 );
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
m_stops[ index ].setPosition( stop );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskGradient::stopAt( int index ) const
|
|
|
|
{
|
|
|
|
if ( index >= m_stops.size() )
|
|
|
|
return -1.0;
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
return m_stops[ index ].position();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskGradient::setColorAt( int index, const QColor& color )
|
|
|
|
{
|
|
|
|
if ( !color.isValid() )
|
|
|
|
{
|
|
|
|
qWarning( "Invalid gradient color" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( index >= m_stops.size() )
|
|
|
|
m_stops.resize( index + 1 );
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
m_stops[ index ].setColor( color );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QColor QskGradient::colorAt( int index ) const
|
|
|
|
{
|
|
|
|
if ( index >= m_stops.size() )
|
|
|
|
return QColor();
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
return m_stops[ index ].color();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
void QskGradient::setAlpha( int alpha )
|
|
|
|
{
|
|
|
|
for ( auto& stop : m_stops )
|
|
|
|
{
|
|
|
|
QColor c = stop.color();
|
|
|
|
if ( c.isValid() && c.alpha() )
|
|
|
|
{
|
|
|
|
c.setAlpha( alpha );
|
|
|
|
stop.setColor( c );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskGradient::hasStopAt( qreal value ) const
|
|
|
|
{
|
|
|
|
// better use binary search TODO ...
|
|
|
|
for ( auto& stop : m_stops )
|
|
|
|
{
|
|
|
|
if ( stop.position() == value )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if ( stop.position() > value )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint QskGradient::hash( uint seed ) const
|
|
|
|
{
|
|
|
|
const int count = m_stops.size();
|
|
|
|
if ( count == 0 )
|
|
|
|
return seed;
|
|
|
|
|
|
|
|
uint hash = qHashBits( &m_orientation, sizeof( m_orientation ), seed );
|
|
|
|
for ( const auto& stop : m_stops )
|
|
|
|
hash = stop.hash( hash );
|
|
|
|
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
QskGradient QskGradient::interpolated(
|
|
|
|
const QskGradient& to, qreal value ) const
|
|
|
|
{
|
|
|
|
if ( !( isValid() && to.isValid() ) )
|
2018-12-22 16:12:45 +01:00
|
|
|
{
|
|
|
|
if ( !isValid() && !to.isValid() )
|
|
|
|
return to;
|
|
|
|
|
|
|
|
qreal progress;
|
|
|
|
const QskGradient* gradient;
|
|
|
|
|
|
|
|
if ( to.isValid() )
|
|
|
|
{
|
|
|
|
progress = value;
|
|
|
|
gradient = &to;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
progress = 1.0 - value;
|
|
|
|
gradient = this;
|
|
|
|
}
|
2019-01-04 13:42:16 +01:00
|
|
|
|
2018-12-22 16:12:45 +01:00
|
|
|
/*
|
|
|
|
We interpolate as if the invalid gradient would be
|
|
|
|
a transparent version of the valid gradient
|
|
|
|
*/
|
|
|
|
|
|
|
|
QVector< QskGradientStop > stops = gradient->m_stops;
|
|
|
|
for ( auto& stop : stops )
|
|
|
|
{
|
|
|
|
auto c = stop.color();
|
|
|
|
c.setAlpha( c.alpha() * progress );
|
|
|
|
|
|
|
|
stop.setColor( c );
|
|
|
|
}
|
|
|
|
|
|
|
|
return QskGradient( gradient->m_orientation, stops );
|
|
|
|
}
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
if ( qskIsMonochrome( m_stops ) )
|
|
|
|
{
|
|
|
|
// we can ignore our stops
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
const QColor c = m_stops[ 0 ].color();
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
QVector< QskGradientStop > s2 = to.m_stops;
|
|
|
|
for ( int i = 0; i < s2.count(); i++ )
|
|
|
|
{
|
|
|
|
const QColor c2 = QskRgbValue::interpolated(
|
2018-08-03 08:15:28 +02:00
|
|
|
c, s2[ i ].color(), value );
|
2017-10-17 17:34:00 +02:00
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
s2[ i ].setColor( c2 );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return QskGradient( to.m_orientation, s2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( qskIsMonochrome( to.m_stops ) )
|
|
|
|
{
|
|
|
|
// we can ignore the stops of to
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
const QColor c = to.m_stops[ 0 ].color();
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
QVector< QskGradientStop > s2 = m_stops;
|
|
|
|
for ( int i = 0; i < s2.count(); i++ )
|
|
|
|
{
|
|
|
|
const QColor c2 = QskRgbValue::interpolated(
|
2018-08-03 08:15:28 +02:00
|
|
|
s2[ i ].color(), c, value );
|
2017-10-17 17:34:00 +02:00
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
s2[ i ].setColor( c2 );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return QskGradient( m_orientation, s2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( m_orientation == to.m_orientation )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
we need to have the same number of stops
|
|
|
|
at the same positions
|
|
|
|
*/
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
const auto s1 = qskExpandedStops( m_stops, to.m_stops );
|
|
|
|
auto s2 = qskExpandedStops( to.m_stops, m_stops );
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
for ( int i = 0; i < s1.count(); i++ )
|
|
|
|
{
|
|
|
|
const QColor c2 = QskRgbValue::interpolated(
|
2018-08-03 08:15:28 +02:00
|
|
|
s1[ i ].color(), s2[ i ].color(), value );
|
2017-10-17 17:34:00 +02:00
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
s2[ i ].setColor( c2 );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return QskGradient( m_orientation, s2 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
The interpolation is devided into 2 steps. First we
|
2018-12-22 16:12:45 +01:00
|
|
|
interpolate into a monochrome gradient and then change
|
2017-10-17 17:34:00 +02:00
|
|
|
the orientation before we continue in direction of the
|
|
|
|
final gradient.
|
|
|
|
*/
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
const QColor c = m_stops[ 0 ].color();
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
if ( value <= 0.5 )
|
|
|
|
{
|
|
|
|
QVector< QskGradientStop > s2 = m_stops;
|
|
|
|
|
|
|
|
for ( int i = 0; i < s2.count(); i++ )
|
|
|
|
{
|
|
|
|
const QColor c2 = QskRgbValue::interpolated(
|
2018-08-03 08:15:28 +02:00
|
|
|
s2[ i ].color(), c, 2 * value );
|
2017-10-17 17:34:00 +02:00
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
s2[ i ].setColor( c2 );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return QskGradient( m_orientation, s2 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QVector< QskGradientStop > s2 = to.m_stops;
|
|
|
|
|
|
|
|
for ( int i = 0; i < s2.count(); i++ )
|
|
|
|
{
|
|
|
|
const QColor c2 = QskRgbValue::interpolated(
|
2018-08-03 08:15:28 +02:00
|
|
|
c, s2[ i ].color(), 2 * ( value - 0.5 ) );
|
2017-10-17 17:34:00 +02:00
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
s2[ i ].setColor( c2 );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return QskGradient( to.m_orientation, s2 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant QskGradient::interpolate(
|
|
|
|
const QskGradient& from, const QskGradient& to, qreal progress )
|
|
|
|
{
|
|
|
|
return QVariant::fromValue( from.interpolated( to, progress ) );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
#ifndef QT_NO_DEBUG_STREAM
|
|
|
|
|
2018-07-19 14:10:48 +02:00
|
|
|
#include <qdebug.h>
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QDebug operator<<( QDebug debug, const QskGradientStop& stop )
|
|
|
|
{
|
|
|
|
debug << "GR:" << stop.position() << stop.color();
|
|
|
|
return debug;
|
|
|
|
}
|
|
|
|
|
|
|
|
QDebug operator<<( QDebug debug, const QskGradient& gradient )
|
|
|
|
{
|
|
|
|
debug << "GR:" << gradient.orientation() << gradient.stops().count();
|
|
|
|
return debug;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "moc_QskGradient.cpp"
|