allowing gradient stops that do not start/end with 0.0/1.0 ( like

QGradient )
This commit is contained in:
Uwe Rathmann 2022-10-24 17:29:39 +02:00
parent 1f28eec9de
commit e67b0b385a
6 changed files with 124 additions and 31 deletions

View File

@ -31,10 +31,10 @@ static inline QskGradient::Orientation qskOrientation( Qt::Orientation o )
static inline bool qskIsGradientValid( const QskGradientStops& stops )
{
if ( stops.size() < 2 )
if ( stops.isEmpty() )
return false;
if ( stops.first().position() != 0.0 || stops.last().position() != 1.0 )
if ( stops.first().position() < 0.0 || stops.last().position() > 1.0 )
return false;
if ( !stops.first().color().isValid() )
@ -200,9 +200,20 @@ void QskGradient::setStops( const QskGradientStops& stops )
m_isDirty = true;
}
int QskGradient::stopCount() const noexcept
int QskGradient::stepCount() const noexcept
{
return m_stops.count();
if ( !isValid() )
return 0;
int steps = m_stops.count() - 1;
if ( m_stops.first().position() > 0.0 )
steps++;
if ( m_stops.last().position() < 1.0 )
steps++;
return steps;
}
qreal QskGradient::stopAt( int index ) const noexcept

View File

@ -100,7 +100,7 @@ class QSK_EXPORT QskGradient
Q_INVOKABLE qreal stopAt( int index ) const noexcept;
Q_INVOKABLE QColor colorAt( int index ) const noexcept;
Q_INVOKABLE int stopCount() const noexcept;
int stepCount() const noexcept;
private:
void updateStatusBits() const;

View File

@ -88,7 +88,6 @@ void QskBoxNode::setBoxData( const QRectF& rect,
}
#endif
#if 1
const auto metricsHash = qskMetricsHash( shape, borderMetrics );
const auto colorsHash = qskColorsHash( borderColors, fillGradient );
@ -104,7 +103,6 @@ void QskBoxNode::setBoxData( const QRectF& rect,
markDirty( QSGNode::DirtyMaterial );
markDirty( QSGNode::DirtyGeometry );
#endif
if ( rect.isEmpty() )
{
@ -112,7 +110,7 @@ void QskBoxNode::setBoxData( const QRectF& rect,
return;
}
bool hasFill = fillGradient.isValid();
bool hasFill = fillGradient.isVisible();
bool hasBorder = !borderMetrics.isNull();
if ( hasBorder )

View File

@ -153,16 +153,25 @@ namespace QskVertex
, m_value2( value2 )
, m_stops( stops )
{
Q_ASSERT( stops.size() > 2 );
if ( stops.first().position() > 0.0 )
{
m_color1 = m_color2 = stops[ 0 ].color();
m_index = 0;
}
else
{
m_color1 = stops[ 0 ].color();
m_color2 = stops[ 1 ].color();
m_index = 1;
}
m_color1 = stops[ 0 ].color();
m_color2 = stops[ 1 ].color();
m_finalIndex = m_stops.count() - 1;
if ( stops.last().position() < 1.0 )
m_finalIndex++;
m_valueStep1 = value1;
m_valueStep2 = valueAt( stops[ 1 ].position() );
m_valueStep2 = valueAt( stops[ m_index ].position() );
m_stepSize = m_valueStep2 - m_valueStep1;
m_index = 1;
}
inline qreal value() const
@ -183,13 +192,24 @@ namespace QskVertex
inline bool advance()
{
const auto& stop = m_stops[ ++m_index ];
m_index++;
m_color1 = m_color2;
m_color2 = stop.color();
m_valueStep1 = m_valueStep2;
m_valueStep2 = valueAt( stop.position() );
if ( m_index >= m_stops.count() )
{
m_color2 = m_color1;
m_valueStep2 = valueAt( 1.0 );
}
else
{
const auto& stop = m_stops[ m_index ];
m_color2 = stop.color();
m_valueStep2 = valueAt( stop.position() );
}
m_stepSize = m_valueStep2 - m_valueStep1;
return !isDone();
@ -197,7 +217,7 @@ namespace QskVertex
inline bool isDone() const
{
return m_index >= m_stops.count() - 1;
return m_index >= m_finalIndex;
}
private:
@ -209,7 +229,7 @@ namespace QskVertex
const qreal m_value1, m_value2;
const QskGradientStops m_stops;
int m_index;
int m_index, m_finalIndex;
qreal m_valueStep1, m_valueStep2, m_stepSize;
Color m_color1, m_color2;
};
@ -237,7 +257,7 @@ namespace QskVertex
ColoredLine* fillOrdered( ContourIterator& contourIt,
qreal value1, qreal value2, const QskGradient& gradient, ColoredLine* line )
{
if ( gradient.stops().size() == 2 )
if ( gradient.stepCount() == 1 )
{
if ( value2 == 1.0 && value1 == 0.0 )
{

View File

@ -100,7 +100,7 @@ namespace
int additionalGradientStops( const QskGradient& gradient )
{
return qMax( 0, gradient.stops().count() - 2 );
return qMax( 0, gradient.stepCount() - 1 );
}
}
@ -575,10 +575,26 @@ namespace
auto line = lines + additionalGradientStops( gradient );
{
const auto &stop = stops.first();
if ( stop.position() > 0.0 )
setAdditionalLine( x11, y11, x12, y12, dx1, dy1, dx2, dy2, stop, line-- );
}
for( int i = 1; i < stops.count() - 1; i++ )
{
setAdditionalLine( x11, y11, x12, y12, dx1, dy1, dx2, dy2, stops[i], line-- );
}
{
const auto &stop = stops.last();
if ( stop.position() < 1.0 )
{
setAdditionalLine( x11, y11, x12, y12, dx1, dy1, dx2, dy2, stop, line-- );
}
}
}
template< class BorderMap, class FillMap >
@ -931,7 +947,7 @@ static inline int qskFillLineCount(
// adding vertexes for the stops - beside the first/last
if ( !gradient.isMonochrome() )
lineCount += gradient.stops().size() - 2;
lineCount += gradient.stepCount() - 1;
return lineCount;
}
@ -1339,7 +1355,7 @@ void QskBoxRenderer::renderRectellipse( const QRectF& rect,
{
// degenerated to a rectangle
fillLineCount = gradient.stops().count();
fillLineCount = gradient.stepCount() + 1;
#if 1
// code copied from QskBoxRendererRect.cpp TODO ...
@ -1411,7 +1427,7 @@ void QskBoxRenderer::renderRectellipse( const QRectF& rect,
}
else if ( !gradient.isMonochrome() )
{
if ( gradient.stops().count() > 2 ||
if ( gradient.stepCount() > 1 ||
gradient.orientation() == QskGradient::Diagonal )
{
fillRandom = false;

View File

@ -430,6 +430,12 @@ static inline void qskCreateBorder(
{
const auto stops = colors.bottom().stops();
if ( stops.first().position() > 0.0 )
{
( line++ )->setLine( in.right, in.bottom,
out.right, out.bottom, stops.first().color() );
}
for( const auto& stop : stops )
{
const qreal x1 = in.right - stop.position() * dx1;
@ -437,11 +443,23 @@ static inline void qskCreateBorder(
( line++ )->setLine( x1, in.bottom, x2, out.bottom, stop.color() );
}
if ( stops.last().position() < 1.0 )
{
( line++ )->setLine( in.left, in.bottom,
out.left, out.bottom, stops.last().color() );
}
}
{
const auto stops = colors.left().stops();
if ( stops.first().position() > 0.0 )
{
( line++ )->setLine( in.left, in.bottom,
out.left, out.bottom, stops.first().color() );
}
for( const auto& stop : stops )
{
const qreal y1 = in.bottom + stop.position() * dy1;
@ -449,11 +467,23 @@ static inline void qskCreateBorder(
( line++ )->setLine( in.left, y1, out.left, y2, stop.color() );
}
if ( stops.last().position() < 1.0 )
{
( line++ )->setLine( in.left, in.top,
out.left, out.top, stops.last().color() );
}
}
{
const auto stops = colors.top().stops();
if ( stops.first().position() > 0.0 )
{
( line++ )->setLine( in.left, in.top,
out.left, out.top, stops.first().color() );
}
for( const auto& stop : stops )
{
const qreal x1 = in.left + stop.position() * dx1;
@ -461,11 +491,23 @@ static inline void qskCreateBorder(
( line++ )->setLine( x1, in.top, x2, out.top, stop.color() );
}
if ( stops.last().position() < 1.0 )
{
( line++ )->setLine( in.right, in.top,
out.right, out.top, stops.last().color() );
}
}
{
const auto stops = colors.right().stops();
if ( stops.first().position() > 0.0 )
{
( line++ )->setLine( in.right, in.top,
out.right, out.top, stops.first().color() );
}
for( const auto& stop : stops )
{
const qreal y1 = in.bottom + ( 1 - stop.position() ) * dy1;
@ -473,6 +515,12 @@ static inline void qskCreateBorder(
( line++ )->setLine( in.right, y1, out.right, y2, stop.color() );
}
if ( stops.last().position() < 1.0 )
{
( line++ )->setLine( in.right, in.bottom,
out.right, out.bottom, stops.last().color() );
}
}
}
@ -528,7 +576,7 @@ void QskBoxRenderer::renderRect(
int fillLineCount = 0;
if ( gradient.isVisible() && !in.isEmpty() )
{
fillLineCount = gradient.stops().count();
fillLineCount = gradient.stepCount() + 1;
if ( gradient.orientation() == QskGradient::Diagonal )
{
@ -566,10 +614,10 @@ void QskBoxRenderer::renderRect(
// ### As an optimization we could check orientation and colors
// to test whether colors are the same
const int additionalLines = -1
+ bc.left().stops().count() - 1
+ bc.top().stops().count() - 1
+ bc.right().stops().count() - 1
+ bc.bottom().stops().count() - 1;
+ bc.left().stepCount()
+ bc.top().stepCount()
+ bc.right().stepCount()
+ bc.bottom().stepCount();
borderLineCount += qMax( additionalLines, 0 );
}
@ -589,7 +637,7 @@ void QskBoxRenderer::renderRect(
}
else
{
bool fillRandom = gd.stops().count() <= 2;
bool fillRandom = gd.stepCount() <= 1;
if ( fillRandom )
{
/*