31feeff9aa
expection are reflect/repeat spreading. Code has been reimplemented or cleaned up significantly
225 lines
5.7 KiB
C++
225 lines
5.7 KiB
C++
/******************************************************************************
|
|
* 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>
|
|
#include <QskGradientDirection.h>
|
|
#include <QskVertex.h>
|
|
|
|
namespace QskBox
|
|
{
|
|
class ColorMap
|
|
{
|
|
public:
|
|
inline ColorMap()
|
|
: ColorMap( QskGradient() )
|
|
{
|
|
}
|
|
|
|
inline ColorMap( const QskGradient& gradient )
|
|
: m_isTransparent( !gradient.isVisible() )
|
|
, m_isMonochrome( gradient.isMonochrome() )
|
|
, m_color1( gradient.rgbStart() )
|
|
, m_color2( gradient.rgbEnd() )
|
|
{
|
|
if ( !m_isMonochrome )
|
|
{
|
|
const auto dir = gradient.linearDirection();
|
|
|
|
m_x = dir.x1();
|
|
m_y = dir.y1();
|
|
m_dx = dir.x2() - dir.x1();
|
|
m_dy = dir.y2() - dir.y1();
|
|
m_dot = m_dx * m_dx + m_dy * m_dy;
|
|
}
|
|
}
|
|
|
|
inline void setLine( qreal x1, qreal y1, qreal x2, qreal y2,
|
|
QskVertex::ColoredLine* line ) const
|
|
{
|
|
if ( m_isMonochrome )
|
|
{
|
|
line->setLine( x1, y1, x2, y2, m_color1 );
|
|
}
|
|
else
|
|
{
|
|
const auto c1 = colorAt( x1, y1 );
|
|
const auto c2 = colorAt( x2, y2 );
|
|
|
|
line->setLine( x1, y1, c1, x2, y2, c2 );
|
|
}
|
|
}
|
|
|
|
inline bool isMonochrome() const { return m_isMonochrome; }
|
|
inline bool isTransparent() const { return m_isTransparent; }
|
|
|
|
static inline bool isGradientSupported(
|
|
const QskGradient& gradient, const QRectF& rect )
|
|
{
|
|
if ( gradient.isMonochrome() )
|
|
return true;
|
|
|
|
switch( gradient.stepCount() )
|
|
{
|
|
case 0:
|
|
return true;
|
|
|
|
case 1:
|
|
{
|
|
Q_ASSERT( gradient.stretchMode() != QskGradient::StretchToSize );
|
|
return gradient.linearDirection().contains( rect );
|
|
}
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private:
|
|
inline QskVertex::Color colorAt( qreal x, qreal y ) const
|
|
{
|
|
return m_color1.interpolatedTo( m_color2, valueAt( x, y ) );
|
|
}
|
|
|
|
inline qreal valueAt( qreal x, qreal y ) const
|
|
{
|
|
const qreal dx = x - m_x;
|
|
const qreal dy = y - m_y;
|
|
|
|
return ( dx * m_dx + dy * m_dy ) / m_dot;
|
|
}
|
|
|
|
const bool m_isTransparent;
|
|
const bool m_isMonochrome;
|
|
|
|
qreal m_x, m_y, m_dx, m_dy, m_dot;
|
|
|
|
const QskVertex::Color m_color1;
|
|
const QskVertex::Color m_color2;
|
|
};
|
|
|
|
class GradientIterator
|
|
{
|
|
public:
|
|
GradientIterator() = default;
|
|
|
|
inline GradientIterator( const QskVertex::Color color )
|
|
: m_color1( color )
|
|
, m_color2( color )
|
|
{
|
|
}
|
|
|
|
inline GradientIterator(
|
|
const QskVertex::Color& color1, const QskVertex::Color& color2 )
|
|
: m_color1( color1 )
|
|
, m_color2( color2 )
|
|
{
|
|
}
|
|
|
|
inline GradientIterator( const QskGradientStops& stops )
|
|
: m_stops( stops )
|
|
, m_color1( stops.first().rgb() )
|
|
, m_color2( m_color1 )
|
|
, m_pos1( stops.first().position() )
|
|
, m_pos2( m_pos1 )
|
|
, m_index( 0 )
|
|
{
|
|
}
|
|
|
|
inline void reset( const QskVertex::Color color )
|
|
{
|
|
m_index = -1;
|
|
m_color1 = m_color2 = color;
|
|
}
|
|
|
|
inline void reset( const QskVertex::Color& color1,
|
|
const QskVertex::Color& color2 )
|
|
{
|
|
m_index = -1;
|
|
m_color1 = color1;
|
|
m_color2 = color2;
|
|
}
|
|
|
|
inline void reset( const QskGradientStops& stops )
|
|
{
|
|
m_stops = stops;
|
|
|
|
m_index = 0;
|
|
m_color1 = m_color2 = stops.first().rgb();
|
|
m_pos1 = m_pos2 = stops.first().position();
|
|
}
|
|
|
|
inline qreal position() const
|
|
{
|
|
return m_pos2;
|
|
}
|
|
|
|
inline QskVertex::Color color() const
|
|
{
|
|
return m_color2;
|
|
}
|
|
|
|
inline QskVertex::Color colorAt( qreal pos ) const
|
|
{
|
|
if ( m_color1 == m_color2 )
|
|
return m_color1;
|
|
|
|
if ( m_index < 0 )
|
|
{
|
|
return m_color1.interpolatedTo( m_color2, pos );
|
|
}
|
|
else
|
|
{
|
|
if ( m_pos2 == m_pos1 )
|
|
return m_color1;
|
|
|
|
const auto r = ( pos - m_pos1 ) / ( m_pos2 - m_pos1 );
|
|
return m_color1.interpolatedTo( m_color2, r );
|
|
}
|
|
}
|
|
|
|
inline bool advance()
|
|
{
|
|
if ( m_index < 0 )
|
|
return true;
|
|
|
|
m_pos1 = m_pos2;
|
|
m_color1 = m_color2;
|
|
|
|
if ( ++m_index < m_stops.size() )
|
|
{
|
|
const auto& s = m_stops[ m_index ];
|
|
|
|
m_pos2 = s.position();
|
|
m_color2 = s.rgb();
|
|
}
|
|
|
|
return !isDone();
|
|
}
|
|
|
|
inline bool isDone() const
|
|
{
|
|
if ( m_index < 0 )
|
|
return true;
|
|
|
|
return m_index >= m_stops.size();
|
|
}
|
|
|
|
private:
|
|
QskGradientStops m_stops;
|
|
|
|
QskVertex::Color m_color1, m_color2;
|
|
|
|
qreal m_pos1 = 0.0;
|
|
qreal m_pos2 = 1.0;
|
|
|
|
int m_index = -1;
|
|
};
|
|
}
|
|
|
|
#endif
|