Anti-Grain Geometry Tutorial
agg_gradient_lut.h
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 
16 #ifndef AGG_GRADIENT_LUT_INCLUDED
17 #define AGG_GRADIENT_LUT_INCLUDED
18 
19 #include "agg_array.h"
20 #include "agg_dda_line.h"
21 #include "agg_color_rgba.h"
22 #include "agg_color_gray.h"
23 
24 namespace agg
25 {
26 
27  //======================================================color_interpolator
28  template<class ColorT> struct color_interpolator
29  {
30  public:
31  typedef ColorT color_type;
32 
33  color_interpolator(const color_type& c1,
34  const color_type& c2,
35  unsigned len) :
36  m_c1(c1),
37  m_c2(c2),
38  m_len(len),
39  m_count(0)
40  {}
41 
42  void operator ++ ()
43  {
44  ++m_count;
45  }
46 
47  color_type color() const
48  {
49  return m_c1.gradient(m_c2, double(m_count) / m_len);
50  }
51 
52  private:
53  color_type m_c1;
54  color_type m_c2;
55  unsigned m_len;
56  unsigned m_count;
57  };
58 
59  //========================================================================
60  // Fast specialization for rgba8
61  template<> struct color_interpolator<rgba8>
62  {
63  public:
64  typedef rgba8 color_type;
65 
66  color_interpolator(const color_type& c1,
67  const color_type& c2,
68  unsigned len) :
69  r(c1.r, c2.r, len),
70  g(c1.g, c2.g, len),
71  b(c1.b, c2.b, len),
72  a(c1.a, c2.a, len)
73  {}
74 
75  void operator ++ ()
76  {
77  ++r; ++g; ++b; ++a;
78  }
79 
80  color_type color() const
81  {
82  return color_type(r.y(), g.y(), b.y(), a.y());
83  }
84 
85  private:
87  };
88 
89  //========================================================================
90  // Fast specialization for gray8
91  template<> struct color_interpolator<gray8>
92  {
93  public:
94  typedef gray8 color_type;
95 
96  color_interpolator(const color_type& c1,
97  const color_type& c2,
98  unsigned len) :
99  v(c1.v, c2.v, len),
100  a(c1.a, c2.a, len)
101  {}
102 
103  void operator ++ ()
104  {
105  ++v; ++a;
106  }
107 
108  color_type color() const
109  {
110  return color_type(v.y(), a.y());
111  }
112 
113  private:
115  };
116 
117  //============================================================gradient_lut
118  template<class ColorInterpolator,
119  unsigned ColorLutSize=256> class gradient_lut
120  {
121  public:
122  typedef ColorInterpolator interpolator_type;
123  typedef typename interpolator_type::color_type color_type;
124  enum { color_lut_size = ColorLutSize };
125 
126  //--------------------------------------------------------------------
127  gradient_lut() : m_color_lut(color_lut_size) {}
128 
129  // Build Gradient Lut
130  // First, call remove_all(), then add_color() at least twice,
131  // then build_lut(). Argument "offset" in add_color must be
132  // in range [0...1] and defines a color stop as it is described
133  // in SVG specification, section Gradients and Patterns.
134  // The simplest linear gradient is:
135  // gradient_lut.add_color(0.0, start_color);
136  // gradient_lut.add_color(1.0, end_color);
137  //--------------------------------------------------------------------
138  void remove_all();
139  void add_color(double offset, const color_type& color);
140  void build_lut();
141 
142  // Size-index Interface. This class can be used directly as the
143  // ColorF in span_gradient. All it needs is two access methods
144  // size() and operator [].
145  //--------------------------------------------------------------------
146  static unsigned size()
147  {
148  return color_lut_size;
149  }
150  const color_type& operator [] (unsigned i) const
151  {
152  return m_color_lut[i];
153  }
154 
155  private:
156  //--------------------------------------------------------------------
157  struct color_point
158  {
159  double offset;
160  color_type color;
161 
162  color_point() {}
163  color_point(double off, const color_type& c) :
164  offset(off), color(c)
165  {
166  if(offset < 0.0) offset = 0.0;
167  if(offset > 1.0) offset = 1.0;
168  }
169  };
172 
173  static bool offset_less(const color_point& a, const color_point& b)
174  {
175  return a.offset < b.offset;
176  }
177  static bool offset_equal(const color_point& a, const color_point& b)
178  {
179  return a.offset == b.offset;
180  }
181 
182  //--------------------------------------------------------------------
183  color_profile_type m_color_profile;
184  color_lut_type m_color_lut;
185  };
186 
187 
188 
189  //------------------------------------------------------------------------
190  template<class T, unsigned S>
192  {
193  m_color_profile.remove_all();
194  }
195 
196  //------------------------------------------------------------------------
197  template<class T, unsigned S>
198  void gradient_lut<T,S>::add_color(double offset, const color_type& color)
199  {
200  m_color_profile.add(color_point(offset, color));
201  }
202 
203  //------------------------------------------------------------------------
204  template<class T, unsigned S>
206  {
207  quick_sort(m_color_profile, offset_less);
208  m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
209  if(m_color_profile.size() >= 2)
210  {
211  unsigned i;
212  unsigned start = uround(m_color_profile[0].offset * color_lut_size);
213  unsigned end;
214  color_type c = m_color_profile[0].color;
215  for(i = 0; i < start; i++)
216  {
217  m_color_lut[i] = c;
218  }
219  for(i = 1; i < m_color_profile.size(); i++)
220  {
221  end = uround(m_color_profile[i].offset * color_lut_size);
222  interpolator_type ci(m_color_profile[i-1].color,
223  m_color_profile[i ].color,
224  end - start + 1);
225  while(start < end)
226  {
227  m_color_lut[start] = ci.color();
228  ++ci;
229  ++start;
230  }
231  }
232  c = m_color_profile.last().color;
233  for(; end < m_color_lut.size(); end++)
234  {
235  m_color_lut[end] = c;
236  }
237  }
238  }
239 }
240 
241 
242 
243 
244 #endif
Definition: agg_arc.cpp:24