123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- //----------------------------------------------------------------------------
- // 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);
- void 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>
- void 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;
- 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;
- }
- }
- }
- }
- #endif
|