agg_span_gradient.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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_SPAN_GRADIENT_INCLUDED
  16. #define AGG_SPAN_GRADIENT_INCLUDED
  17. #include <math.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "agg_basics.h"
  21. #include "agg_math.h"
  22. #include "agg_array.h"
  23. namespace agg
  24. {
  25. enum gradient_subpixel_scale_e
  26. {
  27. gradient_subpixel_shift = 4, //-----gradient_subpixel_shift
  28. gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale
  29. gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask
  30. };
  31. //==========================================================span_gradient
  32. template<class ColorT,
  33. class Interpolator,
  34. class GradientF,
  35. class ColorF>
  36. class span_gradient
  37. {
  38. public:
  39. typedef Interpolator interpolator_type;
  40. typedef ColorT color_type;
  41. enum downscale_shift_e
  42. {
  43. downscale_shift = interpolator_type::subpixel_shift -
  44. gradient_subpixel_shift
  45. };
  46. //--------------------------------------------------------------------
  47. span_gradient() {}
  48. //--------------------------------------------------------------------
  49. span_gradient(interpolator_type& inter,
  50. GradientF& gradient_function,
  51. ColorF& color_function,
  52. double d1, double d2) :
  53. m_interpolator(&inter),
  54. m_gradient_function(&gradient_function),
  55. m_color_function(&color_function),
  56. m_d1(iround(d1 * gradient_subpixel_scale)),
  57. m_d2(iround(d2 * gradient_subpixel_scale))
  58. {}
  59. //--------------------------------------------------------------------
  60. interpolator_type& interpolator() { return *m_interpolator; }
  61. const GradientF& gradient_function() const { return *m_gradient_function; }
  62. const ColorF& color_function() const { return *m_color_function; }
  63. double d1() const { return double(m_d1) / gradient_subpixel_scale; }
  64. double d2() const { return double(m_d2) / gradient_subpixel_scale; }
  65. //--------------------------------------------------------------------
  66. void interpolator(interpolator_type& i) { m_interpolator = &i; }
  67. void gradient_function(GradientF& gf) { m_gradient_function = &gf; }
  68. void color_function(ColorF& cf) { m_color_function = &cf; }
  69. void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
  70. void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
  71. //--------------------------------------------------------------------
  72. void prepare() {}
  73. //--------------------------------------------------------------------
  74. void generate(color_type* span, int x, int y, unsigned len)
  75. {
  76. int dd = m_d2 - m_d1;
  77. if(dd < 1) dd = 1;
  78. m_interpolator->begin(x+0.5, y+0.5, len);
  79. do
  80. {
  81. m_interpolator->coordinates(&x, &y);
  82. int d = m_gradient_function->calculate(x >> downscale_shift,
  83. y >> downscale_shift, m_d2);
  84. d = ((d - m_d1) * (int)m_color_function->size()) / dd;
  85. if(d < 0) d = 0;
  86. if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1;
  87. *span++ = (*m_color_function)[d];
  88. ++(*m_interpolator);
  89. }
  90. while(--len);
  91. }
  92. private:
  93. interpolator_type* m_interpolator;
  94. GradientF* m_gradient_function;
  95. ColorF* m_color_function;
  96. int m_d1;
  97. int m_d2;
  98. };
  99. //=====================================================gradient_linear_color
  100. template<class ColorT>
  101. struct gradient_linear_color
  102. {
  103. typedef ColorT color_type;
  104. gradient_linear_color() {}
  105. gradient_linear_color(const color_type& c1, const color_type& c2,
  106. unsigned size = 256) :
  107. m_c1(c1), m_c2(c2), m_size(size)
  108. // VFALCO 4/28/09
  109. ,m_mult(1/(double(size)-1))
  110. // VFALCO
  111. {}
  112. unsigned size() const { return m_size; }
  113. color_type operator [] (unsigned v) const
  114. {
  115. // VFALCO 4/28/09
  116. //return m_c1.gradient(m_c2, double(v) / double(m_size - 1));
  117. return m_c1.gradient(m_c2, double(v) * m_mult );
  118. // VFALCO
  119. }
  120. void colors(const color_type& c1, const color_type& c2, unsigned size = 256)
  121. {
  122. m_c1 = c1;
  123. m_c2 = c2;
  124. m_size = size;
  125. // VFALCO 4/28/09
  126. m_mult=1/(double(size)-1);
  127. // VFALCO
  128. }
  129. color_type m_c1;
  130. color_type m_c2;
  131. unsigned m_size;
  132. // VFALCO 4/28/09
  133. double m_mult;
  134. // VFALCO
  135. };
  136. //==========================================================gradient_circle
  137. class gradient_circle
  138. {
  139. // Actually the same as radial. Just for compatibility
  140. public:
  141. static AGG_INLINE int calculate(int x, int y, int)
  142. {
  143. return int(fast_sqrt(x*x + y*y));
  144. }
  145. };
  146. //==========================================================gradient_radial
  147. class gradient_radial
  148. {
  149. public:
  150. static AGG_INLINE int calculate(int x, int y, int)
  151. {
  152. return int(fast_sqrt(x*x + y*y));
  153. }
  154. };
  155. //========================================================gradient_radial_d
  156. class gradient_radial_d
  157. {
  158. public:
  159. static AGG_INLINE int calculate(int x, int y, int)
  160. {
  161. return uround(sqrt(double(x)*double(x) + double(y)*double(y)));
  162. }
  163. };
  164. //====================================================gradient_radial_focus
  165. class gradient_radial_focus
  166. {
  167. public:
  168. //---------------------------------------------------------------------
  169. gradient_radial_focus() :
  170. m_r(100 * gradient_subpixel_scale),
  171. m_fx(0),
  172. m_fy(0)
  173. {
  174. update_values();
  175. }
  176. //---------------------------------------------------------------------
  177. gradient_radial_focus(double r, double fx, double fy) :
  178. m_r (iround(r * gradient_subpixel_scale)),
  179. m_fx(iround(fx * gradient_subpixel_scale)),
  180. m_fy(iround(fy * gradient_subpixel_scale))
  181. {
  182. update_values();
  183. }
  184. //---------------------------------------------------------------------
  185. void init(double r, double fx, double fy)
  186. {
  187. m_r = iround(r * gradient_subpixel_scale);
  188. m_fx = iround(fx * gradient_subpixel_scale);
  189. m_fy = iround(fy * gradient_subpixel_scale);
  190. update_values();
  191. }
  192. //---------------------------------------------------------------------
  193. double radius() const { return double(m_r) / gradient_subpixel_scale; }
  194. double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
  195. double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
  196. //---------------------------------------------------------------------
  197. int calculate(int x, int y, int) const
  198. {
  199. double dx = x - m_fx;
  200. double dy = y - m_fy;
  201. double d2 = dx * m_fy - dy * m_fx;
  202. double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
  203. return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul);
  204. }
  205. private:
  206. //---------------------------------------------------------------------
  207. void update_values()
  208. {
  209. // Calculate the invariant values. In case the focal center
  210. // lies exactly on the gradient circle the divisor degenerates
  211. // into zero. In this case we just move the focal center by
  212. // one subpixel unit possibly in the direction to the origin (0,0)
  213. // and calculate the values again.
  214. //-------------------------
  215. m_r2 = double(m_r) * double(m_r);
  216. m_fx2 = double(m_fx) * double(m_fx);
  217. m_fy2 = double(m_fy) * double(m_fy);
  218. double d = (m_r2 - (m_fx2 + m_fy2));
  219. if(d == 0)
  220. {
  221. if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; }
  222. if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; }
  223. m_fx2 = double(m_fx) * double(m_fx);
  224. m_fy2 = double(m_fy) * double(m_fy);
  225. d = (m_r2 - (m_fx2 + m_fy2));
  226. }
  227. m_mul = m_r / d;
  228. }
  229. int m_r;
  230. int m_fx;
  231. int m_fy;
  232. double m_r2;
  233. double m_fx2;
  234. double m_fy2;
  235. double m_mul;
  236. };
  237. //==============================================================gradient_x
  238. class gradient_x
  239. {
  240. public:
  241. static int calculate(int x, int, int) { return x; }
  242. };
  243. //==============================================================gradient_y
  244. class gradient_y
  245. {
  246. public:
  247. static int calculate(int, int y, int) { return y; }
  248. };
  249. //========================================================gradient_diamond
  250. class gradient_diamond
  251. {
  252. public:
  253. static AGG_INLINE int calculate(int x, int y, int)
  254. {
  255. int ax = abs(x);
  256. int ay = abs(y);
  257. return ax > ay ? ax : ay;
  258. }
  259. };
  260. //=============================================================gradient_xy
  261. class gradient_xy
  262. {
  263. public:
  264. static AGG_INLINE int calculate(int x, int y, int d)
  265. {
  266. return abs(x) * abs(y) / d;
  267. }
  268. };
  269. //========================================================gradient_sqrt_xy
  270. class gradient_sqrt_xy
  271. {
  272. public:
  273. static AGG_INLINE int calculate(int x, int y, int)
  274. {
  275. return fast_sqrt(abs(x) * abs(y));
  276. }
  277. };
  278. //==========================================================gradient_conic
  279. class gradient_conic
  280. {
  281. public:
  282. static AGG_INLINE int calculate(int x, int y, int d)
  283. {
  284. return uround(fabs(atan2(double(y), double(x))) * double(d) / pi);
  285. }
  286. };
  287. //=================================================gradient_repeat_adaptor
  288. template<class GradientF> class gradient_repeat_adaptor
  289. {
  290. public:
  291. gradient_repeat_adaptor(const GradientF& gradient) :
  292. m_gradient(&gradient) {}
  293. AGG_INLINE int calculate(int x, int y, int d) const
  294. {
  295. int ret = m_gradient->calculate(x, y, d) % d;
  296. if(ret < 0) ret += d;
  297. return ret;
  298. }
  299. private:
  300. const GradientF* m_gradient;
  301. };
  302. //================================================gradient_reflect_adaptor
  303. template<class GradientF> class gradient_reflect_adaptor
  304. {
  305. public:
  306. gradient_reflect_adaptor(const GradientF& gradient) :
  307. m_gradient(&gradient) {}
  308. AGG_INLINE int calculate(int x, int y, int d) const
  309. {
  310. int d2 = d << 1;
  311. int ret = m_gradient->calculate(x, y, d) % d2;
  312. if(ret < 0) ret += d2;
  313. if(ret >= d) ret = d2 - ret;
  314. return ret;
  315. }
  316. private:
  317. const GradientF* m_gradient;
  318. };
  319. }
  320. #endif