246 lines
7.4 KiB
C++
246 lines
7.4 KiB
C++
//----------------------------------------------------------------------------
|
|
// Anti-Grain Geometry - Version 2.4
|
|
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
|
//
|
|
// Permission to copy, use, modify, sell and distribute this software
|
|
// is granted provided this copyright notice appears in all copies.
|
|
// This software is provided "as is" without express or implied
|
|
// warranty, and with no claim as to its suitability for any purpose.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
// Contact: mcseem@antigrain.com
|
|
// mcseemagg@yahoo.com
|
|
// http://www.antigrain.com
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef AGG_GRADIENT_LUT_INCLUDED
|
|
#define AGG_GRADIENT_LUT_INCLUDED
|
|
|
|
#include "agg_array.h"
|
|
#include "agg_dda_line.h"
|
|
#include "agg_color_rgba.h"
|
|
#include "agg_color_gray.h"
|
|
|
|
namespace agg
|
|
{
|
|
|
|
//======================================================color_interpolator
|
|
template<class ColorT> struct color_interpolator
|
|
{
|
|
public:
|
|
typedef ColorT color_type;
|
|
|
|
color_interpolator(const color_type& c1,
|
|
const color_type& c2,
|
|
unsigned len) :
|
|
m_c1(c1),
|
|
m_c2(c2),
|
|
m_len(len),
|
|
m_count(0)
|
|
{}
|
|
|
|
void operator ++ ()
|
|
{
|
|
++m_count;
|
|
}
|
|
|
|
color_type color() const
|
|
{
|
|
return m_c1.gradient(m_c2, double(m_count) / m_len);
|
|
}
|
|
|
|
private:
|
|
color_type m_c1;
|
|
color_type m_c2;
|
|
unsigned m_len;
|
|
unsigned m_count;
|
|
};
|
|
|
|
//========================================================================
|
|
// Fast specialization for rgba8
|
|
template<> struct color_interpolator<rgba8>
|
|
{
|
|
public:
|
|
typedef rgba8 color_type;
|
|
|
|
color_interpolator(const color_type& c1,
|
|
const color_type& c2,
|
|
unsigned len) :
|
|
r(c1.r, c2.r, len),
|
|
g(c1.g, c2.g, len),
|
|
b(c1.b, c2.b, len),
|
|
a(c1.a, c2.a, len)
|
|
{}
|
|
|
|
void operator ++ ()
|
|
{
|
|
++r; ++g; ++b; ++a;
|
|
}
|
|
|
|
color_type color() const
|
|
{
|
|
return color_type(r.y(), g.y(), b.y(), a.y());
|
|
}
|
|
|
|
private:
|
|
agg::dda_line_interpolator<14> r, g, b, a;
|
|
};
|
|
|
|
//========================================================================
|
|
// Fast specialization for gray8
|
|
template<> struct color_interpolator<gray8>
|
|
{
|
|
public:
|
|
typedef gray8 color_type;
|
|
|
|
color_interpolator(const color_type& c1,
|
|
const color_type& c2,
|
|
unsigned len) :
|
|
v(c1.v, c2.v, len),
|
|
a(c1.a, c2.a, len)
|
|
{}
|
|
|
|
void operator ++ ()
|
|
{
|
|
++v; ++a;
|
|
}
|
|
|
|
color_type color() const
|
|
{
|
|
return color_type(v.y(), a.y());
|
|
}
|
|
|
|
private:
|
|
agg::dda_line_interpolator<14> v,a;
|
|
};
|
|
|
|
//============================================================gradient_lut
|
|
template<class ColorInterpolator,
|
|
unsigned ColorLutSize=256> class gradient_lut
|
|
{
|
|
public:
|
|
typedef ColorInterpolator interpolator_type;
|
|
typedef typename interpolator_type::color_type color_type;
|
|
enum { color_lut_size = ColorLutSize };
|
|
|
|
//--------------------------------------------------------------------
|
|
gradient_lut() : m_color_lut(color_lut_size) {}
|
|
|
|
// Build Gradient Lut
|
|
// First, call remove_all(), then add_color() at least twice,
|
|
// then build_lut(). Argument "offset" in add_color must be
|
|
// in range [0...1] and defines a color stop as it is described
|
|
// in SVG specification, section Gradients and Patterns.
|
|
// The simplest linear gradient is:
|
|
// gradient_lut.add_color(0.0, start_color);
|
|
// gradient_lut.add_color(1.0, end_color);
|
|
//--------------------------------------------------------------------
|
|
void remove_all();
|
|
void add_color(double offset, const color_type& color);
|
|
bool build_lut();
|
|
|
|
// Size-index Interface. This class can be used directly as the
|
|
// ColorF in span_gradient. All it needs is two access methods
|
|
// size() and operator [].
|
|
//--------------------------------------------------------------------
|
|
static unsigned size()
|
|
{
|
|
return color_lut_size;
|
|
}
|
|
const color_type& operator [] (unsigned i) const
|
|
{
|
|
return m_color_lut[i];
|
|
}
|
|
|
|
private:
|
|
//--------------------------------------------------------------------
|
|
struct color_point
|
|
{
|
|
double offset;
|
|
color_type color;
|
|
|
|
color_point() {}
|
|
color_point(double off, const color_type& c) :
|
|
offset(off), color(c)
|
|
{
|
|
if(offset < 0.0) offset = 0.0;
|
|
if(offset > 1.0) offset = 1.0;
|
|
}
|
|
};
|
|
typedef agg::pod_bvector<color_point, 4> color_profile_type;
|
|
typedef agg::pod_array<color_type> color_lut_type;
|
|
|
|
static bool offset_less(const color_point& a, const color_point& b)
|
|
{
|
|
return a.offset < b.offset;
|
|
}
|
|
static bool offset_equal(const color_point& a, const color_point& b)
|
|
{
|
|
return a.offset == b.offset;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
color_profile_type m_color_profile;
|
|
color_lut_type m_color_lut;
|
|
};
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class T, unsigned S>
|
|
void gradient_lut<T,S>::remove_all()
|
|
{
|
|
m_color_profile.remove_all();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class T, unsigned S>
|
|
void gradient_lut<T,S>::add_color(double offset, const color_type& color)
|
|
{
|
|
m_color_profile.add(color_point(offset, color));
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class T, unsigned S>
|
|
bool gradient_lut<T,S>::build_lut()
|
|
{
|
|
quick_sort(m_color_profile, offset_less);
|
|
m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
|
|
if(m_color_profile.size() >= 2)
|
|
{
|
|
unsigned i;
|
|
unsigned start = uround(m_color_profile[0].offset * color_lut_size);
|
|
unsigned end = 0;
|
|
color_type c = m_color_profile[0].color;
|
|
for(i = 0; i < start; i++)
|
|
{
|
|
m_color_lut[i] = c;
|
|
}
|
|
for(i = 1; i < m_color_profile.size(); i++)
|
|
{
|
|
end = uround(m_color_profile[i].offset * color_lut_size);
|
|
interpolator_type ci(m_color_profile[i-1].color,
|
|
m_color_profile[i ].color,
|
|
end - start + 1);
|
|
while(start < end)
|
|
{
|
|
m_color_lut[start] = ci.color();
|
|
++ci;
|
|
++start;
|
|
}
|
|
}
|
|
c = m_color_profile.last().color;
|
|
for(; end < m_color_lut.size(); end++)
|
|
{
|
|
m_color_lut[end] = c;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|