qskinny/src/nodes/QskBoxRendererColorMap.h

250 lines
6.0 KiB
C
Raw Normal View History

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_BOX_RENDERER_COLOR_MAP_H
#define QSK_BOX_RENDERER_COLOR_MAP_H
#include <QskGradient.h>
2018-08-03 06:15:28 +00:00
#include <QskVertex.h>
#include <cassert>
class QskBoxShapeMetrics;
namespace QskVertex
{
class ColorMapNone
{
2018-08-03 06:15:28 +00:00
public:
constexpr inline Color colorAt( qreal ) const
{
return Color();
}
};
class ColorMapSolid
{
2018-08-03 06:15:28 +00:00
public:
2022-11-16 13:23:47 +00:00
constexpr inline ColorMapSolid() = default;
inline ColorMapSolid( const QskGradient& gradient )
: m_color( gradient.rgbStart() )
{
}
inline Color colorAt( qreal ) const
{
return m_color;
}
2018-08-03 06:15:28 +00:00
private:
const Color m_color;
};
class ColorMapGradient
{
2018-08-03 06:15:28 +00:00
public:
2022-11-16 13:23:47 +00:00
inline ColorMapGradient( const QskGradient& gradient )
: m_color1( gradient.rgbStart() )
, m_color2( gradient.rgbEnd() )
{
}
inline Color colorAt( qreal value ) const
{
return m_color1.interpolatedTo( m_color2, value );
}
2018-08-03 06:15:28 +00:00
private:
const Color m_color1;
const Color m_color2;
};
class ColorIterator
{
2018-08-03 06:15:28 +00:00
public:
static inline bool advance()
{
return false;
}
inline qreal value() const
{
assert( false );
return 0.0;
}
inline Color color() const
{
assert( false );
return Color();
}
static inline bool isDone()
{
return true;
}
};
2022-12-29 07:20:29 +00:00
class SimpleColorIterator : public ColorIterator
{
public:
inline SimpleColorIterator( const QColor& color )
: m_color1( color )
, m_color2( color )
, m_isMonochrome( true )
{
}
inline SimpleColorIterator( const QColor& color1, const QColor& color2 )
: m_color1( color1 )
, m_color2( color2 )
, m_isMonochrome( false )
{
}
inline Color colorAt( qreal value ) const
{
/*
When having only 1 color or 2 colors at 0.0/1.0 only we do not
need gradient lines. So all what this iterator has to provide is
an implementation of colorAt to colourize the contour lines.
*/
if ( m_isMonochrome )
return m_color1;
return m_color1.interpolatedTo( m_color2, value );
}
private:
const Color m_color1, m_color2;
const bool m_isMonochrome;
};
class GradientColorIterator : public ColorIterator
{
2018-08-03 06:15:28 +00:00
public:
inline GradientColorIterator( const QskGradientStops& stops )
: m_stops( stops )
2018-08-03 06:15:28 +00:00
{
if ( stops.first().position() > 0.0 )
{
2022-11-14 08:01:07 +00:00
m_color1 = m_color2 = stops[ 0 ].rgb();
m_index = 0;
}
else
{
2022-11-14 08:01:07 +00:00
m_color1 = stops[ 0 ].rgb();
m_color2 = stops[ 1 ].rgb();
m_index = 1;
}
2018-08-03 06:15:28 +00:00
m_finalIndex = m_stops.count() - 1;
if ( stops.last().position() < 1.0 )
m_finalIndex++;
2018-08-03 06:15:28 +00:00
m_valueStep1 = 0.0;
m_valueStep2 = stops[ m_index ].position();
m_stepSize = m_valueStep2 - m_valueStep1;
2018-08-03 06:15:28 +00:00
}
inline qreal value() const
{
return m_valueStep2;
2018-08-03 06:15:28 +00:00
}
inline Color color() const
{
return m_color2;
2018-08-03 06:15:28 +00:00
}
inline Color colorAt( qreal value ) const
{
const qreal r = ( value - m_valueStep1 ) / m_stepSize;
return m_color1.interpolatedTo( m_color2, r );
2018-08-03 06:15:28 +00:00
}
inline bool advance()
{
m_index++;
2018-08-03 06:15:28 +00:00
m_color1 = m_color2;
m_valueStep1 = m_valueStep2;
if ( m_index >= m_stops.count() )
{
m_color2 = m_color1;
m_valueStep2 = 1.0;
}
else
{
const auto& stop = m_stops[ m_index ];
2022-11-14 08:01:07 +00:00
m_color2 = stop.rgb();
m_valueStep2 = stop.position();
}
m_stepSize = m_valueStep2 - m_valueStep1;
2018-08-03 06:15:28 +00:00
return !isDone();
2018-08-03 06:15:28 +00:00
}
inline bool isDone() const
{
return m_index >= m_finalIndex;
2018-08-03 06:15:28 +00:00
}
private:
2021-09-17 11:35:11 +00:00
const QskGradientStops m_stops;
2018-08-03 06:15:28 +00:00
int m_index, m_finalIndex;
qreal m_valueStep1, m_valueStep2, m_stepSize;
Color m_color1, m_color2;
2018-08-03 06:15:28 +00:00
};
template< class ContourIterator, class ColorIterator >
ColoredLine* fillOrdered( ContourIterator& contourIt,
2018-08-03 06:15:28 +00:00
ColorIterator& colorIt, ColoredLine* line )
{
do
{
while ( !colorIt.isDone() && ( colorIt.value() < contourIt.value() ) )
{
if ( contourIt.setGradientLine( colorIt.value(), colorIt.color(), line ) )
line++;
colorIt.advance();
}
const auto color = colorIt.colorAt( contourIt.value() );
contourIt.setContourLine( color, line++ );
} while ( contourIt.advance() );
return line;
}
template< class ContourIterator >
ColoredLine* fillOrdered( ContourIterator& contourIt,
const QskGradient& gradient, ColoredLine* line )
{
if ( gradient.stepCount() == 1 )
{
2022-12-29 07:20:29 +00:00
SimpleColorIterator colorIt( gradient.rgbStart(), gradient.rgbEnd() );
line = fillOrdered( contourIt, colorIt, line );
}
else
{
GradientColorIterator colorIt( gradient.stops() );
line = fillOrdered( contourIt, colorIt, line );
}
return line;
}
}
#endif