Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_gradient_lut.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 
00025 #ifndef AGG_GRADIENT_LUT_INCLUDED
00026 #define AGG_GRADIENT_LUT_INCLUDED
00027 
00028 #include "agg_array.h"
00029 #include "agg_dda_line.h"
00030 #include "agg_color_rgba.h"
00031 #include "agg_color_gray.h"
00032 
00033 namespace agg
00034 {
00035 
00036     //======================================================color_interpolator
00037     template<class ColorT> struct color_interpolator
00038     {
00039     public:
00040         typedef ColorT color_type;
00041 
00042         color_interpolator(const color_type& c1, 
00043                            const color_type& c2, 
00044                            unsigned len) :
00045             m_c1(c1),
00046             m_c2(c2),
00047             m_len(len),
00048             m_count(0)
00049         {}
00050 
00051         void operator ++ ()
00052         {
00053             ++m_count;
00054         }
00055 
00056         color_type color() const
00057         {
00058             return m_c1.gradient(m_c2, double(m_count) / m_len);
00059         }
00060 
00061     private:
00062         color_type m_c1;
00063         color_type m_c2;
00064         unsigned   m_len;
00065         unsigned   m_count;
00066     };
00067 
00068     //========================================================================
00069     // Fast specialization for rgba8
00070     template<> struct color_interpolator<rgba8>
00071     {
00072     public:
00073         typedef rgba8 color_type;
00074 
00075         color_interpolator(const color_type& c1, 
00076                            const color_type& c2, 
00077                            unsigned len) :
00078             r(c1.r, c2.r, len),
00079             g(c1.g, c2.g, len),
00080             b(c1.b, c2.b, len),
00081             a(c1.a, c2.a, len)
00082         {}
00083 
00084         void operator ++ ()
00085         {
00086             ++r; ++g; ++b; ++a;
00087         }
00088 
00089         color_type color() const
00090         {
00091             return color_type(r.y(), g.y(), b.y(), a.y());
00092         }
00093 
00094     private:
00095         agg::dda_line_interpolator<14> r, g, b, a;
00096     };
00097 
00098     //========================================================================
00099     // Fast specialization for gray8
00100     template<> struct color_interpolator<gray8>
00101     {
00102     public:
00103         typedef gray8 color_type;
00104 
00105         color_interpolator(const color_type& c1, 
00106                            const color_type& c2, 
00107                            unsigned len) :
00108             v(c1.v, c2.v, len),
00109             a(c1.a, c2.a, len)
00110         {}
00111 
00112         void operator ++ ()
00113         {
00114             ++v; ++a;
00115         }
00116 
00117         color_type color() const
00118         {
00119             return color_type(v.y(), a.y());
00120         }
00121 
00122     private:
00123         agg::dda_line_interpolator<14> v,a;
00124     };
00125 
00126     //============================================================gradient_lut
00127     template<class ColorInterpolator, 
00128              unsigned ColorLutSize=256> class gradient_lut
00129     {
00130     public:
00131         typedef ColorInterpolator interpolator_type;
00132         typedef typename interpolator_type::color_type color_type;
00133         enum { color_lut_size = ColorLutSize };
00134 
00135         //--------------------------------------------------------------------
00136         gradient_lut() : m_color_lut(color_lut_size) {}
00137 
00138         // Build Gradient Lut
00139         // First, call remove_all(), then add_color() at least twice, 
00140         // then build_lut(). Argument "offset" in add_color must be 
00141         // in range [0...1] and defines a color stop as it is described 
00142         // in SVG specification, section Gradients and Patterns. 
00143         // The simplest linear gradient is:
00144         //    gradient_lut.add_color(0.0, start_color);
00145         //    gradient_lut.add_color(1.0, end_color);
00146         //--------------------------------------------------------------------
00147         void remove_all();
00148         void add_color(double offset, const color_type& color);
00149         void build_lut();
00150 
00151         // Size-index Interface. This class can be used directly as the 
00152         // ColorF in span_gradient. All it needs is two access methods 
00153         // size() and operator [].
00154         //--------------------------------------------------------------------
00155         static unsigned size() 
00156         { 
00157             return color_lut_size; 
00158         }
00159         const color_type& operator [] (unsigned i) const 
00160         { 
00161             return m_color_lut[i]; 
00162         }
00163 
00164     private:
00165         //--------------------------------------------------------------------
00166         struct color_point
00167         {
00168             double     offset;
00169             color_type color;
00170 
00171             color_point() {}
00172             color_point(double off, const color_type& c) : 
00173                 offset(off), color(c)
00174             {
00175                 if(offset < 0.0) offset = 0.0;
00176                 if(offset > 1.0) offset = 1.0;
00177             }
00178         };
00179         typedef agg::pod_bvector<color_point, 4> color_profile_type;
00180         typedef agg::pod_array<color_type>       color_lut_type;
00181 
00182         static bool offset_less(const color_point& a, const color_point& b)
00183         {
00184             return a.offset < b.offset;
00185         }
00186         static bool offset_equal(const color_point& a, const color_point& b)
00187         {
00188             return a.offset == b.offset;
00189         }
00190 
00191         //--------------------------------------------------------------------
00192         color_profile_type  m_color_profile;
00193         color_lut_type      m_color_lut;
00194     };
00195 
00196 
00197 
00198     //------------------------------------------------------------------------
00199     template<class T, unsigned S>
00200     void gradient_lut<T,S>::remove_all()
00201     { 
00202         m_color_profile.remove_all(); 
00203     }
00204 
00205     //------------------------------------------------------------------------
00206     template<class T, unsigned S>
00207     void gradient_lut<T,S>::add_color(double offset, const color_type& color)
00208     {
00209         m_color_profile.add(color_point(offset, color));
00210     }
00211 
00212     //------------------------------------------------------------------------
00213     template<class T, unsigned S>
00214     void gradient_lut<T,S>::build_lut()
00215     {
00216         quick_sort(m_color_profile, offset_less);
00217         m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
00218         if(m_color_profile.size() >= 2)
00219         {
00220             unsigned i;
00221             unsigned start = uround(m_color_profile[0].offset * color_lut_size);
00222             unsigned end;
00223             color_type c = m_color_profile[0].color;
00224             for(i = 0; i < start; i++) 
00225             {
00226                 m_color_lut[i] = c;
00227             }
00228             for(i = 1; i < m_color_profile.size(); i++)
00229             {
00230                 end  = uround(m_color_profile[i].offset * color_lut_size);
00231                 interpolator_type ci(m_color_profile[i-1].color, 
00232                                      m_color_profile[i  ].color, 
00233                                      end - start + 1);
00234                 while(start < end)
00235                 {
00236                     m_color_lut[start] = ci.color();
00237                     ++ci;
00238                     ++start;
00239                 }
00240             }
00241             c = m_color_profile.last().color;
00242             for(; end < m_color_lut.size(); end++)
00243             {
00244                 m_color_lut[end] = c;
00245             }
00246         }
00247     }
00248 }
00249 
00250 
00251 
00252 
00253 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines