agg_gradient_lut.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. #ifndef AGG_GRADIENT_LUT_INCLUDED
  16. #define AGG_GRADIENT_LUT_INCLUDED
  17. #include "agg_array.h"
  18. #include "agg_dda_line.h"
  19. #include "agg_color_rgba.h"
  20. #include "agg_color_gray.h"
  21. namespace agg
  22. {
  23. //======================================================color_interpolator
  24. template<class ColorT> struct color_interpolator
  25. {
  26. public:
  27. typedef ColorT color_type;
  28. color_interpolator(const color_type& c1,
  29. const color_type& c2,
  30. unsigned len) :
  31. m_c1(c1),
  32. m_c2(c2),
  33. m_len(len),
  34. m_count(0)
  35. {}
  36. void operator ++ ()
  37. {
  38. ++m_count;
  39. }
  40. color_type color() const
  41. {
  42. return m_c1.gradient(m_c2, double(m_count) / m_len);
  43. }
  44. private:
  45. color_type m_c1;
  46. color_type m_c2;
  47. unsigned m_len;
  48. unsigned m_count;
  49. };
  50. //========================================================================
  51. // Fast specialization for rgba8
  52. template<> struct color_interpolator<rgba8>
  53. {
  54. public:
  55. typedef rgba8 color_type;
  56. color_interpolator(const color_type& c1,
  57. const color_type& c2,
  58. unsigned len) :
  59. r(c1.r, c2.r, len),
  60. g(c1.g, c2.g, len),
  61. b(c1.b, c2.b, len),
  62. a(c1.a, c2.a, len)
  63. {}
  64. void operator ++ ()
  65. {
  66. ++r; ++g; ++b; ++a;
  67. }
  68. color_type color() const
  69. {
  70. return color_type(r.y(), g.y(), b.y(), a.y());
  71. }
  72. private:
  73. agg::dda_line_interpolator<14> r, g, b, a;
  74. };
  75. //========================================================================
  76. // Fast specialization for gray8
  77. template<> struct color_interpolator<gray8>
  78. {
  79. public:
  80. typedef gray8 color_type;
  81. color_interpolator(const color_type& c1,
  82. const color_type& c2,
  83. unsigned len) :
  84. v(c1.v, c2.v, len),
  85. a(c1.a, c2.a, len)
  86. {}
  87. void operator ++ ()
  88. {
  89. ++v; ++a;
  90. }
  91. color_type color() const
  92. {
  93. return color_type(v.y(), a.y());
  94. }
  95. private:
  96. agg::dda_line_interpolator<14> v,a;
  97. };
  98. //============================================================gradient_lut
  99. template<class ColorInterpolator,
  100. unsigned ColorLutSize=256> class gradient_lut
  101. {
  102. public:
  103. typedef ColorInterpolator interpolator_type;
  104. typedef typename interpolator_type::color_type color_type;
  105. enum { color_lut_size = ColorLutSize };
  106. //--------------------------------------------------------------------
  107. gradient_lut() : m_color_lut(color_lut_size) {}
  108. // Build Gradient Lut
  109. // First, call remove_all(), then add_color() at least twice,
  110. // then build_lut(). Argument "offset" in add_color must be
  111. // in range [0...1] and defines a color stop as it is described
  112. // in SVG specification, section Gradients and Patterns.
  113. // The simplest linear gradient is:
  114. // gradient_lut.add_color(0.0, start_color);
  115. // gradient_lut.add_color(1.0, end_color);
  116. //--------------------------------------------------------------------
  117. void remove_all();
  118. void add_color(double offset, const color_type& color);
  119. void build_lut();
  120. // Size-index Interface. This class can be used directly as the
  121. // ColorF in span_gradient. All it needs is two access methods
  122. // size() and operator [].
  123. //--------------------------------------------------------------------
  124. static unsigned size()
  125. {
  126. return color_lut_size;
  127. }
  128. const color_type& operator [] (unsigned i) const
  129. {
  130. return m_color_lut[i];
  131. }
  132. private:
  133. //--------------------------------------------------------------------
  134. struct color_point
  135. {
  136. double offset;
  137. color_type color;
  138. color_point() {}
  139. color_point(double off, const color_type& c) :
  140. offset(off), color(c)
  141. {
  142. if(offset < 0.0) offset = 0.0;
  143. if(offset > 1.0) offset = 1.0;
  144. }
  145. };
  146. typedef agg::pod_bvector<color_point, 4> color_profile_type;
  147. typedef agg::pod_array<color_type> color_lut_type;
  148. static bool offset_less(const color_point& a, const color_point& b)
  149. {
  150. return a.offset < b.offset;
  151. }
  152. static bool offset_equal(const color_point& a, const color_point& b)
  153. {
  154. return a.offset == b.offset;
  155. }
  156. //--------------------------------------------------------------------
  157. color_profile_type m_color_profile;
  158. color_lut_type m_color_lut;
  159. };
  160. //------------------------------------------------------------------------
  161. template<class T, unsigned S>
  162. void gradient_lut<T,S>::remove_all()
  163. {
  164. m_color_profile.remove_all();
  165. }
  166. //------------------------------------------------------------------------
  167. template<class T, unsigned S>
  168. void gradient_lut<T,S>::add_color(double offset, const color_type& color)
  169. {
  170. m_color_profile.add(color_point(offset, color));
  171. }
  172. //------------------------------------------------------------------------
  173. template<class T, unsigned S>
  174. void gradient_lut<T,S>::build_lut()
  175. {
  176. quick_sort(m_color_profile, offset_less);
  177. m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
  178. if(m_color_profile.size() >= 2)
  179. {
  180. unsigned i;
  181. unsigned start = uround(m_color_profile[0].offset * color_lut_size);
  182. unsigned end;
  183. color_type c = m_color_profile[0].color;
  184. for(i = 0; i < start; i++)
  185. {
  186. m_color_lut[i] = c;
  187. }
  188. for(i = 1; i < m_color_profile.size(); i++)
  189. {
  190. end = uround(m_color_profile[i].offset * color_lut_size);
  191. interpolator_type ci(m_color_profile[i-1].color,
  192. m_color_profile[i ].color,
  193. end - start + 1);
  194. while(start < end)
  195. {
  196. m_color_lut[start] = ci.color();
  197. ++ci;
  198. ++start;
  199. }
  200. }
  201. c = m_color_profile.last().color;
  202. for(; end < m_color_lut.size(); end++)
  203. {
  204. m_color_lut[end] = c;
  205. }
  206. }
  207. }
  208. }
  209. #endif