Anti-Grain Geometry - AGG (libagg)
2.5
|
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