QskGradientStops code internally reorganized for planned new features

This commit is contained in:
Uwe Rathmann 2025-05-06 16:21:52 +02:00
parent dd5c97a077
commit 8f89e38ec3
2 changed files with 67 additions and 52 deletions

View File

@ -23,6 +23,31 @@ static void qskRegisterGradientStop()
Q_CONSTRUCTOR_FUNCTION( qskRegisterGradientStop ) Q_CONSTRUCTOR_FUNCTION( qskRegisterGradientStop )
static inline qreal qskBoundedStopPos( qreal pos )
{
if ( ( pos < 0.0 ) || qFuzzyIsNull( pos ) )
return 0.0;
if ( ( pos > 1.0 ) || qFuzzyCompare( pos, 1.0 ) )
return 1.0;
return pos;
}
static inline QVector< QskGradientStop >
qskNormalizedStops( const QVector< QskGradientStop >& stops )
{
auto s = stops;
if ( s.first().position() > 0.0 )
s.prepend( QskGradientStop( 0.0, s.first().color() ) );
if ( s.last().position() < 1.0 )
s.append( QskGradientStop( 1.0, s.last().color() ) );
return s;
}
void QskGradientStop::setPosition( qreal position ) noexcept void QskGradientStop::setPosition( qreal position ) noexcept
{ {
m_position = position; m_position = position;
@ -90,30 +115,15 @@ QDebug operator<<( QDebug debug, const QskGradientStop& stop )
// some helper functions around QskGradientStops // some helper functions around QskGradientStops
static inline QColor qskInterpolatedColor( static inline QColor qskColorAtPosition(
const QskGradientStops& stops, int index1, int index2, qreal position ) const QskGradientStop& s1, const QskGradientStop& s2, qreal pos )
{ {
{ const auto dp = s2.position() - s1.position();
const auto max = static_cast< int >( stops.count() ) - 1; if ( qFuzzyIsNull( dp ) )
index1 = qBound( 0, index1, max );
index2 = qBound( 0, index2, max );
}
const auto& s1 = stops[ index1 ];
const auto& s2 = stops[ index2 ];
if ( s1.color() == s2.color() )
return s1.color(); return s1.color();
if ( position <= s1.position() ) return QskRgb::interpolated(
return s1.color(); s1.color(), s2.color(), ( pos - s1.position() ) / dp );
if ( position >= s2.position() )
return s2.color();
const qreal r = ( position - s1.position() ) / ( s2.position() - s1.position() );
return QskRgb::interpolated( s1.color(), s2.color(), r );
} }
bool qskIsVisible( const QskGradientStops& stops ) noexcept bool qskIsVisible( const QskGradientStops& stops ) noexcept
@ -284,43 +294,48 @@ QColor qskInterpolatedColorAt( const QskGradientStops& stops, qreal pos ) noexce
if ( stops.isEmpty() ) if ( stops.isEmpty() )
return QColor(); return QColor();
pos = qBound( 0.0, pos, 1.0 );
if ( pos <= stops.first().position() ) if ( pos <= stops.first().position() )
return stops.first().color(); return stops.first().color();
for ( int i = 1; i < stops.count(); i++ ) for ( int i = 1; i < stops.count(); i++ )
{ {
if ( pos <= stops[i].position() ) if ( pos <= stops[ i ].position() )
return qskInterpolatedColor( stops, i - 1, i, pos ); return qskColorAtPosition( stops[ i - 1 ], stops[ i ], pos );
} }
return stops.last().color(); return stops.last().color();
} }
QskGradientStops qskExtractedGradientStops( QskGradientStops qskExtractedGradientStops(
const QskGradientStops& gradientStops, qreal from, qreal to ) const QskGradientStops& stops, qreal from, qreal to )
{ {
if ( ( from > to ) || ( from > 1.0 ) || gradientStops.isEmpty() ) if ( ( from > to ) || ( to > 1.0 ) || ( from < 0.0 ) || stops.isEmpty() )
return QskGradientStops(); return QskGradientStops();
if ( ( from <= 0.0 ) && ( to >= 1.0 ) ) from = qskBoundedStopPos( from );
return gradientStops; to = qskBoundedStopPos( to );
from = qMax( from, 0.0 ); if ( ( from == 0.0 ) && ( to == 1.0 ) )
to = qMin( to, 1.0 ); return stops;
QVector< QskGradientStop > stops1 = gradientStops; if ( from == to )
{
const auto color = qskInterpolatedColorAt( stops, from );
#if 1 QVector< QskGradientStop > s;
// not the most efficient implementation - maybe later TODO ... s.reserve( 2 );
s += QskGradientStop( 0.0, color );
s += QskGradientStop( 1.0, color );
if ( stops1.first().position() > 0.0 ) return s;
stops1.prepend( QskGradientStop( 0.0, stops1.first().color() ) ); }
if ( stops1.last().position() < 1.0 ) /*
stops1.append( QskGradientStop( 1.0, stops1.last().color() ) ); For situations where we have no stops at 0.0 and 1.0 we insert them
#endif manually. Not the most efficient implementation, but we avoid having
to deal with these situations for the moment. TODO ...
*/
const auto stops1 = qskNormalizedStops( stops );
QVector< QskGradientStop > stops2; QVector< QskGradientStop > stops2;
stops2.reserve( stops1.count() ); stops2.reserve( stops1.count() );
@ -337,26 +352,26 @@ QskGradientStops qskExtractedGradientStops(
{ {
int i = 0; int i = 0;
for ( ; i < stops1.count(); i++ ) if ( from == 0.0 )
{ {
if ( stops1[i].position() > from ) stops2 += stops1[i++];
break; }
else
{
while( stops1[++i].position() <= from ); // skip leading stops
stops2 += QskGradientStop( 0.0,
qskColorAtPosition( stops1[i - 1], stops1[ i ], from ) );
} }
stops2 += QskGradientStop( 0.0, while ( stops1[i].position() < to )
qskInterpolatedColor( stops1, i - 1, i, from ) );
for ( ; i < stops1.count(); i++ )
{ {
if ( stops1[i].position() >= to )
break;
const auto pos = ( stops1[i].position() - from ) / ( to - from ); const auto pos = ( stops1[i].position() - from ) / ( to - from );
stops2 += QskGradientStop( pos, stops1[i].color() ); stops2 += QskGradientStop( pos, stops1[i++].color() );
} }
stops2 += QskGradientStop( 1.0, stops2 += QskGradientStop( 1.0,
qskInterpolatedColor( stops1, i, i + 1, to ) ); qskColorAtPosition( stops1[i - 1], stops1[ i ], to ) );
} }
return stops2; return stops2;

View File

@ -143,7 +143,7 @@ QSK_EXPORT QskGradientStops qskInterpolatedGradientStops(
QSK_EXPORT QskGradientStops qskTransparentGradientStops( QSK_EXPORT QskGradientStops qskTransparentGradientStops(
const QskGradientStops&, qreal ratio ); const QskGradientStops&, qreal ratio );
// extracting the colors of [from, to ] and stretching them to [0.0, 1.0] // extracting the colors of [from, to ] and stretching them to [0.0, 1.0]
QSK_EXPORT QskGradientStops qskExtractedGradientStops( QSK_EXPORT QskGradientStops qskExtractedGradientStops(
const QskGradientStops&, qreal from, qreal to ); const QskGradientStops&, qreal from, qreal to );