Anti-Grain Geometry Tutorial
agg_color_rgba.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 //
12 // Adaptation for high precision colors has been sponsored by
13 // Liberty Technology Systems, Inc., visit http://lib-sys.com
14 //
15 // Liberty Technology Systems, Inc. is the provider of
16 // PostScript and PDF technology for software developers.
17 //
18 //----------------------------------------------------------------------------
19 // Contact: mcseem@antigrain.com
20 // mcseemagg@yahoo.com
21 // http://www.antigrain.com
22 //----------------------------------------------------------------------------
23 
24 #ifndef AGG_COLOR_RGBA_INCLUDED
25 #define AGG_COLOR_RGBA_INCLUDED
26 
27 #include <cmath>
28 #include "agg_basics.h"
29 #include "agg_gamma_lut.h"
30 
31 namespace agg
32 {
33  // Supported component orders for RGB and RGBA pixel formats
34  //=======================================================================
35  struct order_rgb { enum rgb_e { R=0, G=1, B=2, N=3 }; };
36  struct order_bgr { enum bgr_e { B=0, G=1, R=2, N=3 }; };
37  struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, N=4 }; };
38  struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, N=4 }; };
39  struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, N=4 }; };
40  struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, N=4 }; };
41 
42  // Colorspace tag types.
43  struct linear {};
44  struct sRGB {};
45 
46  //====================================================================rgba
47  struct rgba
48  {
49  typedef double value_type;
50 
51  double r;
52  double g;
53  double b;
54  double a;
55 
56  //--------------------------------------------------------------------
57  rgba() {}
58 
59  //--------------------------------------------------------------------
60  rgba(double r_, double g_, double b_, double a_=1.0) :
61  r(r_), g(g_), b(b_), a(a_) {}
62 
63  //--------------------------------------------------------------------
64  rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
65 
66  //--------------------------------------------------------------------
67  rgba& clear()
68  {
69  r = g = b = a = 0;
70  return *this;
71  }
72 
73  //--------------------------------------------------------------------
74  rgba& transparent()
75  {
76  a = 0;
77  return *this;
78  }
79 
80  //--------------------------------------------------------------------
81  rgba& opacity(double a_)
82  {
83  if (a_ < 0) a = 0;
84  else if (a_ > 1) a = 1;
85  else a = a_;
86  return *this;
87  }
88 
89  //--------------------------------------------------------------------
90  double opacity() const
91  {
92  return a;
93  }
94 
95  //--------------------------------------------------------------------
96  rgba& premultiply()
97  {
98  r *= a;
99  g *= a;
100  b *= a;
101  return *this;
102  }
103 
104  //--------------------------------------------------------------------
105  rgba& premultiply(double a_)
106  {
107  if (a <= 0 || a_ <= 0)
108  {
109  r = g = b = a = 0;
110  }
111  else
112  {
113  a_ /= a;
114  r *= a_;
115  g *= a_;
116  b *= a_;
117  a = a_;
118  }
119  return *this;
120  }
121 
122  //--------------------------------------------------------------------
123  rgba& demultiply()
124  {
125  if (a == 0)
126  {
127  r = g = b = 0;
128  }
129  else
130  {
131  double a_ = 1.0 / a;
132  r *= a_;
133  g *= a_;
134  b *= a_;
135  }
136  return *this;
137  }
138 
139 
140  //--------------------------------------------------------------------
141  rgba gradient(rgba c, double k) const
142  {
143  rgba ret;
144  ret.r = r + (c.r - r) * k;
145  ret.g = g + (c.g - g) * k;
146  ret.b = b + (c.b - b) * k;
147  ret.a = a + (c.a - a) * k;
148  return ret;
149  }
150 
151  rgba& operator+=(const rgba& c)
152  {
153  r += c.r;
154  g += c.g;
155  b += c.b;
156  a += c.a;
157  return *this;
158  }
159 
160  rgba& operator*=(double k)
161  {
162  r *= k;
163  g *= k;
164  b *= k;
165  a *= k;
166  return *this;
167  }
168 
169  //--------------------------------------------------------------------
170  static rgba no_color() { return rgba(0,0,0,0); }
171 
172  //--------------------------------------------------------------------
173  static rgba from_wavelength(double wl, double gamma = 1.0);
174 
175  //--------------------------------------------------------------------
176  explicit rgba(double wavelen, double gamma=1.0)
177  {
178  *this = from_wavelength(wavelen, gamma);
179  }
180 
181  };
182 
183  inline rgba operator+(const rgba& a, const rgba& b)
184  {
185  return rgba(a) += b;
186  }
187 
188  inline rgba operator*(const rgba& a, double b)
189  {
190  return rgba(a) *= b;
191  }
192 
193  //------------------------------------------------------------------------
194  inline rgba rgba::from_wavelength(double wl, double gamma)
195  {
196  rgba t(0.0, 0.0, 0.0);
197 
198  if (wl >= 380.0 && wl <= 440.0)
199  {
200  t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
201  t.b = 1.0;
202  }
203  else if (wl >= 440.0 && wl <= 490.0)
204  {
205  t.g = (wl - 440.0) / (490.0 - 440.0);
206  t.b = 1.0;
207  }
208  else if (wl >= 490.0 && wl <= 510.0)
209  {
210  t.g = 1.0;
211  t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
212  }
213  else if (wl >= 510.0 && wl <= 580.0)
214  {
215  t.r = (wl - 510.0) / (580.0 - 510.0);
216  t.g = 1.0;
217  }
218  else if (wl >= 580.0 && wl <= 645.0)
219  {
220  t.r = 1.0;
221  t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
222  }
223  else if (wl >= 645.0 && wl <= 780.0)
224  {
225  t.r = 1.0;
226  }
227 
228  double s = 1.0;
229  if (wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
230  else if (wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
231 
232  t.r = std::pow(t.r * s, gamma);
233  t.g = std::pow(t.g * s, gamma);
234  t.b = std::pow(t.b * s, gamma);
235  return t;
236  }
237 
238  inline rgba rgba_pre(double r, double g, double b, double a)
239  {
240  return rgba(r, g, b, a).premultiply();
241  }
242 
243 
244  //===================================================================rgba8
245  template<class Colorspace>
246  struct rgba8T
247  {
248  typedef int8u value_type;
249  typedef int32u calc_type;
250  typedef int32 long_type;
251  enum base_scale_e
252  {
253  base_shift = 8,
254  base_scale = 1 << base_shift,
255  base_mask = base_scale - 1,
256  base_MSB = 1 << (base_shift - 1)
257  };
258  typedef rgba8T self_type;
259 
260 
261  value_type r;
262  value_type g;
263  value_type b;
264  value_type a;
265 
266  static void convert(rgba8T<linear>& dst, const rgba8T<sRGB>& src)
267  {
271  dst.a = src.a;
272  }
273 
274  static void convert(rgba8T<sRGB>& dst, const rgba8T<linear>& src)
275  {
276  dst.r = sRGB_conv<value_type>::rgb_to_sRGB(src.r);
277  dst.g = sRGB_conv<value_type>::rgb_to_sRGB(src.g);
278  dst.b = sRGB_conv<value_type>::rgb_to_sRGB(src.b);
279  dst.a = src.a;
280  }
281 
282  static void convert(rgba8T<linear>& dst, const rgba& src)
283  {
284  dst.r = value_type(uround(src.r * base_mask));
285  dst.g = value_type(uround(src.g * base_mask));
286  dst.b = value_type(uround(src.b * base_mask));
287  dst.a = value_type(uround(src.a * base_mask));
288  }
289 
290  static void convert(rgba8T<sRGB>& dst, const rgba& src)
291  {
292  // Use the "float" table.
293  dst.r = sRGB_conv<float>::rgb_to_sRGB(float(src.r));
294  dst.g = sRGB_conv<float>::rgb_to_sRGB(float(src.g));
295  dst.b = sRGB_conv<float>::rgb_to_sRGB(float(src.b));
296  dst.a = sRGB_conv<float>::alpha_to_sRGB(float(src.a));
297  }
298 
299  static void convert(rgba& dst, const rgba8T<linear>& src)
300  {
301  dst.r = src.r / 255.0;
302  dst.g = src.g / 255.0;
303  dst.b = src.b / 255.0;
304  dst.a = src.a / 255.0;
305  }
306 
307  static void convert(rgba& dst, const rgba8T<sRGB>& src)
308  {
309  // Use the "float" table.
310  dst.r = sRGB_conv<float>::rgb_from_sRGB(src.r);
311  dst.g = sRGB_conv<float>::rgb_from_sRGB(src.g);
312  dst.b = sRGB_conv<float>::rgb_from_sRGB(src.b);
313  dst.a = sRGB_conv<float>::alpha_from_sRGB(src.a);
314  }
315 
316  //--------------------------------------------------------------------
317  rgba8T() {}
318 
319  //--------------------------------------------------------------------
320  rgba8T(unsigned r_, unsigned g_, unsigned b_, unsigned a_ = base_mask) :
321  r(value_type(r_)),
322  g(value_type(g_)),
323  b(value_type(b_)),
324  a(value_type(a_)) {}
325 
326  //--------------------------------------------------------------------
327  rgba8T(const rgba& c)
328  {
329  convert(*this, c);
330  }
331 
332  //--------------------------------------------------------------------
333  rgba8T(const self_type& c, unsigned a_) :
334  r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
335 
336  //--------------------------------------------------------------------
337  template<class T>
338  rgba8T(const rgba8T<T>& c)
339  {
340  convert(*this, c);
341  }
342 
343  //--------------------------------------------------------------------
344  operator rgba() const
345  {
346  rgba c;
347  convert(c, *this);
348  return c;
349  }
350 
351  //--------------------------------------------------------------------
352  static AGG_INLINE double to_double(value_type a)
353  {
354  return double(a) / base_mask;
355  }
356 
357  //--------------------------------------------------------------------
358  static AGG_INLINE value_type from_double(double a)
359  {
360  return value_type(uround(a * base_mask));
361  }
362 
363  //--------------------------------------------------------------------
364  static AGG_INLINE value_type empty_value()
365  {
366  return 0;
367  }
368 
369  //--------------------------------------------------------------------
370  static AGG_INLINE value_type full_value()
371  {
372  return base_mask;
373  }
374 
375  //--------------------------------------------------------------------
376  AGG_INLINE bool is_transparent() const
377  {
378  return a == 0;
379  }
380 
381  //--------------------------------------------------------------------
382  AGG_INLINE bool is_opaque() const
383  {
384  return a == base_mask;
385  }
386 
387  //--------------------------------------------------------------------
388  static AGG_INLINE value_type invert(value_type x)
389  {
390  return base_mask - x;
391  }
392 
393  //--------------------------------------------------------------------
394  // Fixed-point multiply, exact over int8u.
395  static AGG_INLINE value_type multiply(value_type a, value_type b)
396  {
397  calc_type t = a * b + base_MSB;
398  return value_type(((t >> base_shift) + t) >> base_shift);
399  }
400 
401  //--------------------------------------------------------------------
402  static AGG_INLINE value_type demultiply(value_type a, value_type b)
403  {
404  if (a * b == 0)
405  {
406  return 0;
407  }
408  else if (a >= b)
409  {
410  return base_mask;
411  }
412  else return value_type((a * base_mask + (b >> 1)) / b);
413  }
414 
415  //--------------------------------------------------------------------
416  template<typename T>
417  static AGG_INLINE T downscale(T a)
418  {
419  return a >> base_shift;
420  }
421 
422  //--------------------------------------------------------------------
423  template<typename T>
424  static AGG_INLINE T downshift(T a, unsigned n)
425  {
426  return a >> n;
427  }
428 
429  //--------------------------------------------------------------------
430  // Fixed-point multiply, exact over int8u.
431  // Specifically for multiplying a color component by a cover.
432  static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
433  {
434  return multiply(a, b);
435  }
436 
437  //--------------------------------------------------------------------
438  static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
439  {
440  return multiply(b, a);
441  }
442 
443  //--------------------------------------------------------------------
444  // Interpolate p to q by a, assuming q is premultiplied by a.
445  static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
446  {
447  return p + q - multiply(p, a);
448  }
449 
450  //--------------------------------------------------------------------
451  // Interpolate p to q by a.
452  static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
453  {
454  int t = (q - p) * a + base_MSB - (p > q);
455  return value_type(p + (((t >> base_shift) + t) >> base_shift));
456  }
457 
458  //--------------------------------------------------------------------
459  self_type& clear()
460  {
461  r = g = b = a = 0;
462  return *this;
463  }
464 
465  //--------------------------------------------------------------------
466  self_type& transparent()
467  {
468  a = 0;
469  return *this;
470  }
471 
472  //--------------------------------------------------------------------
473  self_type& opacity(double a_)
474  {
475  if (a_ < 0) a = 0;
476  else if (a_ > 1) a = 1;
477  else a = (value_type)uround(a_ * double(base_mask));
478  return *this;
479  }
480 
481  //--------------------------------------------------------------------
482  double opacity() const
483  {
484  return double(a) / double(base_mask);
485  }
486 
487  //--------------------------------------------------------------------
488  AGG_INLINE self_type& premultiply()
489  {
490  if (a != base_mask)
491  {
492  if (a == 0)
493  {
494  r = g = b = 0;
495  }
496  else
497  {
498  r = multiply(r, a);
499  g = multiply(g, a);
500  b = multiply(b, a);
501  }
502  }
503  return *this;
504  }
505 
506  //--------------------------------------------------------------------
507  AGG_INLINE self_type& premultiply(unsigned a_)
508  {
509  if (a != base_mask || a_ < base_mask)
510  {
511  if (a == 0 || a_ == 0)
512  {
513  r = g = b = a = 0;
514  }
515  else
516  {
517  calc_type r_ = (calc_type(r) * a_) / a;
518  calc_type g_ = (calc_type(g) * a_) / a;
519  calc_type b_ = (calc_type(b) * a_) / a;
520  r = value_type((r_ > a_) ? a_ : r_);
521  g = value_type((g_ > a_) ? a_ : g_);
522  b = value_type((b_ > a_) ? a_ : b_);
523  a = value_type(a_);
524  }
525  }
526  return *this;
527  }
528 
529  //--------------------------------------------------------------------
530  AGG_INLINE self_type& demultiply()
531  {
532  if (a < base_mask)
533  {
534  if (a == 0)
535  {
536  r = g = b = 0;
537  }
538  else
539  {
540  calc_type r_ = (calc_type(r) * base_mask) / a;
541  calc_type g_ = (calc_type(g) * base_mask) / a;
542  calc_type b_ = (calc_type(b) * base_mask) / a;
543  r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
544  g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
545  b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
546  }
547  }
548  return *this;
549  }
550 
551  //--------------------------------------------------------------------
552  AGG_INLINE self_type gradient(const self_type& c, double k) const
553  {
554  self_type ret;
555  calc_type ik = uround(k * base_mask);
556  ret.r = lerp(r, c.r, ik);
557  ret.g = lerp(g, c.g, ik);
558  ret.b = lerp(b, c.b, ik);
559  ret.a = lerp(a, c.a, ik);
560  return ret;
561  }
562 
563  //--------------------------------------------------------------------
564  AGG_INLINE void add(const self_type& c, unsigned cover)
565  {
566  calc_type cr, cg, cb, ca;
567  if (cover == cover_mask)
568  {
569  if (c.a == base_mask)
570  {
571  *this = c;
572  return;
573  }
574  else
575  {
576  cr = r + c.r;
577  cg = g + c.g;
578  cb = b + c.b;
579  ca = a + c.a;
580  }
581  }
582  else
583  {
584  cr = r + mult_cover(c.r, cover);
585  cg = g + mult_cover(c.g, cover);
586  cb = b + mult_cover(c.b, cover);
587  ca = a + mult_cover(c.a, cover);
588  }
589  r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr);
590  g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg);
591  b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb);
592  a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
593  }
594 
595  //--------------------------------------------------------------------
596  template<class GammaLUT>
597  AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
598  {
599  r = gamma.dir(r);
600  g = gamma.dir(g);
601  b = gamma.dir(b);
602  }
603 
604  //--------------------------------------------------------------------
605  template<class GammaLUT>
606  AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
607  {
608  r = gamma.inv(r);
609  g = gamma.inv(g);
610  b = gamma.inv(b);
611  }
612 
613  //--------------------------------------------------------------------
614  static self_type no_color() { return self_type(0,0,0,0); }
615 
616  //--------------------------------------------------------------------
617  static self_type from_wavelength(double wl, double gamma = 1.0)
618  {
619  return self_type(rgba::from_wavelength(wl, gamma));
620  }
621  };
622 
623  typedef rgba8T<linear> rgba8;
624  typedef rgba8T<sRGB> srgba8;
625 
626 
627  //-------------------------------------------------------------rgb8_packed
628  inline rgba8 rgb8_packed(unsigned v)
629  {
630  return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
631  }
632 
633  //-------------------------------------------------------------bgr8_packed
634  inline rgba8 bgr8_packed(unsigned v)
635  {
636  return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
637  }
638 
639  //------------------------------------------------------------argb8_packed
640  inline rgba8 argb8_packed(unsigned v)
641  {
642  return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
643  }
644 
645  //---------------------------------------------------------rgba8_gamma_dir
646  template<class GammaLUT>
647  rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma)
648  {
649  return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
650  }
651 
652  //---------------------------------------------------------rgba8_gamma_inv
653  template<class GammaLUT>
654  rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma)
655  {
656  return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
657  }
658 
659 
660 
661  //==================================================================rgba16
662  struct rgba16
663  {
664  typedef int16u value_type;
665  typedef int32u calc_type;
666  typedef int64 long_type;
667  enum base_scale_e
668  {
669  base_shift = 16,
670  base_scale = 1 << base_shift,
671  base_mask = base_scale - 1,
672  base_MSB = 1 << (base_shift - 1)
673  };
674  typedef rgba16 self_type;
675 
676  value_type r;
677  value_type g;
678  value_type b;
679  value_type a;
680 
681  //--------------------------------------------------------------------
682  rgba16() {}
683 
684  //--------------------------------------------------------------------
685  rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
686  r(value_type(r_)),
687  g(value_type(g_)),
688  b(value_type(b_)),
689  a(value_type(a_)) {}
690 
691  //--------------------------------------------------------------------
692  rgba16(const self_type& c, unsigned a_) :
693  r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
694 
695  //--------------------------------------------------------------------
696  rgba16(const rgba& c) :
697  r((value_type)uround(c.r * double(base_mask))),
698  g((value_type)uround(c.g * double(base_mask))),
699  b((value_type)uround(c.b * double(base_mask))),
700  a((value_type)uround(c.a * double(base_mask))) {}
701 
702  //--------------------------------------------------------------------
703  rgba16(const rgba8& c) :
704  r(value_type((value_type(c.r) << 8) | c.r)),
705  g(value_type((value_type(c.g) << 8) | c.g)),
706  b(value_type((value_type(c.b) << 8) | c.b)),
707  a(value_type((value_type(c.a) << 8) | c.a)) {}
708 
709  //--------------------------------------------------------------------
710  rgba16(const srgba8& c) :
715 
716  //--------------------------------------------------------------------
717  operator rgba() const
718  {
719  return rgba(
720  r / 65535.0,
721  g / 65535.0,
722  b / 65535.0,
723  a / 65535.0);
724  }
725 
726  //--------------------------------------------------------------------
727  operator rgba8() const
728  {
729  return rgba8(r >> 8, g >> 8, b >> 8, a >> 8);
730  }
731 
732  //--------------------------------------------------------------------
733  operator srgba8() const
734  {
735  // Return (non-premultiplied) sRGB values.
736  return srgba8(
741  }
742 
743  //--------------------------------------------------------------------
744  static AGG_INLINE double to_double(value_type a)
745  {
746  return double(a) / base_mask;
747  }
748 
749  //--------------------------------------------------------------------
750  static AGG_INLINE value_type from_double(double a)
751  {
752  return value_type(uround(a * base_mask));
753  }
754 
755  //--------------------------------------------------------------------
756  static AGG_INLINE value_type empty_value()
757  {
758  return 0;
759  }
760 
761  //--------------------------------------------------------------------
762  static AGG_INLINE value_type full_value()
763  {
764  return base_mask;
765  }
766 
767  //--------------------------------------------------------------------
768  AGG_INLINE bool is_transparent() const
769  {
770  return a == 0;
771  }
772 
773  //--------------------------------------------------------------------
774  AGG_INLINE bool is_opaque() const
775  {
776  return a == base_mask;
777  }
778 
779  //--------------------------------------------------------------------
780  static AGG_INLINE value_type invert(value_type x)
781  {
782  return base_mask - x;
783  }
784 
785  //--------------------------------------------------------------------
786  // Fixed-point multiply, exact over int16u.
787  static AGG_INLINE value_type multiply(value_type a, value_type b)
788  {
789  calc_type t = a * b + base_MSB;
790  return value_type(((t >> base_shift) + t) >> base_shift);
791  }
792 
793  //--------------------------------------------------------------------
794  static AGG_INLINE value_type demultiply(value_type a, value_type b)
795  {
796  if (a * b == 0)
797  {
798  return 0;
799  }
800  else if (a >= b)
801  {
802  return base_mask;
803  }
804  else return value_type((a * base_mask + (b >> 1)) / b);
805  }
806 
807  //--------------------------------------------------------------------
808  template<typename T>
809  static AGG_INLINE T downscale(T a)
810  {
811  return a >> base_shift;
812  }
813 
814  //--------------------------------------------------------------------
815  template<typename T>
816  static AGG_INLINE T downshift(T a, unsigned n)
817  {
818  return a >> n;
819  }
820 
821  //--------------------------------------------------------------------
822  // Fixed-point multiply, almost exact over int16u.
823  // Specifically for multiplying a color component by a cover.
824  static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
825  {
826  return multiply(a, (b << 8) | b);
827  }
828 
829  //--------------------------------------------------------------------
830  static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
831  {
832  return multiply((a << 8) | a, b) >> 8;
833  }
834 
835  //--------------------------------------------------------------------
836  // Interpolate p to q by a, assuming q is premultiplied by a.
837  static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
838  {
839  return p + q - multiply(p, a);
840  }
841 
842  //--------------------------------------------------------------------
843  // Interpolate p to q by a.
844  static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
845  {
846  int t = (q - p) * a + base_MSB - (p > q);
847  return value_type(p + (((t >> base_shift) + t) >> base_shift));
848  }
849 
850  //--------------------------------------------------------------------
851  self_type& clear()
852  {
853  r = g = b = a = 0;
854  return *this;
855  }
856 
857  //--------------------------------------------------------------------
858  self_type& transparent()
859  {
860  a = 0;
861  return *this;
862  }
863 
864  //--------------------------------------------------------------------
865  AGG_INLINE self_type& opacity(double a_)
866  {
867  if (a_ < 0) a = 0;
868  if (a_ > 1) a = 1;
869  a = value_type(uround(a_ * double(base_mask)));
870  return *this;
871  }
872 
873  //--------------------------------------------------------------------
874  double opacity() const
875  {
876  return double(a) / double(base_mask);
877  }
878 
879  //--------------------------------------------------------------------
880  AGG_INLINE self_type& premultiply()
881  {
882  if (a != base_mask)
883  {
884  if (a == 0)
885  {
886  r = g = b = 0;
887  }
888  else
889  {
890  r = multiply(r, a);
891  g = multiply(g, a);
892  b = multiply(b, a);
893  }
894  }
895  return *this;
896  }
897 
898  //--------------------------------------------------------------------
899  AGG_INLINE self_type& premultiply(unsigned a_)
900  {
901  if (a < base_mask || a_ < base_mask)
902  {
903  if (a == 0 || a_ == 0)
904  {
905  r = g = b = a = 0;
906  }
907  else
908  {
909  calc_type r_ = (calc_type(r) * a_) / a;
910  calc_type g_ = (calc_type(g) * a_) / a;
911  calc_type b_ = (calc_type(b) * a_) / a;
912  r = value_type((r_ > a_) ? a_ : r_);
913  g = value_type((g_ > a_) ? a_ : g_);
914  b = value_type((b_ > a_) ? a_ : b_);
915  a = value_type(a_);
916  }
917  }
918  return *this;
919  }
920 
921  //--------------------------------------------------------------------
922  AGG_INLINE self_type& demultiply()
923  {
924  if (a < base_mask)
925  {
926  if (a == 0)
927  {
928  r = g = b = 0;
929  }
930  else
931  {
932  calc_type r_ = (calc_type(r) * base_mask) / a;
933  calc_type g_ = (calc_type(g) * base_mask) / a;
934  calc_type b_ = (calc_type(b) * base_mask) / a;
935  r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
936  g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
937  b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
938  }
939  }
940  return *this;
941  }
942 
943  //--------------------------------------------------------------------
944  AGG_INLINE self_type gradient(const self_type& c, double k) const
945  {
946  self_type ret;
947  calc_type ik = uround(k * base_mask);
948  ret.r = lerp(r, c.r, ik);
949  ret.g = lerp(g, c.g, ik);
950  ret.b = lerp(b, c.b, ik);
951  ret.a = lerp(a, c.a, ik);
952  return ret;
953  }
954 
955  //--------------------------------------------------------------------
956  AGG_INLINE void add(const self_type& c, unsigned cover)
957  {
958  calc_type cr, cg, cb, ca;
959  if (cover == cover_mask)
960  {
961  if (c.a == base_mask)
962  {
963  *this = c;
964  return;
965  }
966  else
967  {
968  cr = r + c.r;
969  cg = g + c.g;
970  cb = b + c.b;
971  ca = a + c.a;
972  }
973  }
974  else
975  {
976  cr = r + mult_cover(c.r, cover);
977  cg = g + mult_cover(c.g, cover);
978  cb = b + mult_cover(c.b, cover);
979  ca = a + mult_cover(c.a, cover);
980  }
981  r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr);
982  g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg);
983  b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb);
984  a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
985  }
986 
987  //--------------------------------------------------------------------
988  template<class GammaLUT>
989  AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
990  {
991  r = gamma.dir(r);
992  g = gamma.dir(g);
993  b = gamma.dir(b);
994  }
995 
996  //--------------------------------------------------------------------
997  template<class GammaLUT>
998  AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
999  {
1000  r = gamma.inv(r);
1001  g = gamma.inv(g);
1002  b = gamma.inv(b);
1003  }
1004 
1005  //--------------------------------------------------------------------
1006  static self_type no_color() { return self_type(0,0,0,0); }
1007 
1008  //--------------------------------------------------------------------
1009  static self_type from_wavelength(double wl, double gamma = 1.0)
1010  {
1011  return self_type(rgba::from_wavelength(wl, gamma));
1012  }
1013  };
1014 
1015 
1016  //------------------------------------------------------rgba16_gamma_dir
1017  template<class GammaLUT>
1018  rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma)
1019  {
1020  return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
1021  }
1022 
1023  //------------------------------------------------------rgba16_gamma_inv
1024  template<class GammaLUT>
1025  rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma)
1026  {
1027  return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
1028  }
1029 
1030  //====================================================================rgba32
1031  struct rgba32
1032  {
1033  typedef float value_type;
1034  typedef double calc_type;
1035  typedef double long_type;
1036  typedef rgba32 self_type;
1037 
1038  value_type r;
1039  value_type g;
1040  value_type b;
1041  value_type a;
1042 
1043  //--------------------------------------------------------------------
1044  rgba32() {}
1045 
1046  //--------------------------------------------------------------------
1047  rgba32(value_type r_, value_type g_, value_type b_, value_type a_= 1) :
1048  r(r_), g(g_), b(b_), a(a_) {}
1049 
1050  //--------------------------------------------------------------------
1051  rgba32(const self_type& c, float a_) :
1052  r(c.r), g(c.g), b(c.b), a(a_) {}
1053 
1054  //--------------------------------------------------------------------
1055  rgba32(const rgba& c) :
1056  r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {}
1057 
1058  //--------------------------------------------------------------------
1059  rgba32(const rgba8& c) :
1060  r(value_type(c.r / 255.0)),
1061  g(value_type(c.g / 255.0)),
1062  b(value_type(c.b / 255.0)),
1063  a(value_type(c.a / 255.0)) {}
1064 
1065  //--------------------------------------------------------------------
1066  rgba32(const srgba8& c) :
1071 
1072  //--------------------------------------------------------------------
1073  rgba32(const rgba16& c) :
1074  r(value_type(c.r / 65535.0)),
1075  g(value_type(c.g / 65535.0)),
1076  b(value_type(c.b / 65535.0)),
1077  a(value_type(c.a / 65535.0)) {}
1078 
1079  //--------------------------------------------------------------------
1080  operator rgba() const
1081  {
1082  return rgba(r, g, b, a);
1083  }
1084 
1085  //--------------------------------------------------------------------
1086  operator rgba8() const
1087  {
1088  return rgba8(
1089  uround(r * 255.0),
1090  uround(g * 255.0),
1091  uround(b * 255.0),
1092  uround(a * 255.0));
1093  }
1094 
1095  //--------------------------------------------------------------------
1096  operator srgba8() const
1097  {
1098  return srgba8(
1103  }
1104 
1105  //--------------------------------------------------------------------
1106  operator rgba16() const
1107  {
1108  return rgba8(
1109  uround(r * 65535.0),
1110  uround(g * 65535.0),
1111  uround(b * 65535.0),
1112  uround(a * 65535.0));
1113  }
1114 
1115  //--------------------------------------------------------------------
1116  static AGG_INLINE double to_double(value_type a)
1117  {
1118  return a;
1119  }
1120 
1121  //--------------------------------------------------------------------
1122  static AGG_INLINE value_type from_double(double a)
1123  {
1124  return value_type(a);
1125  }
1126 
1127  //--------------------------------------------------------------------
1128  static AGG_INLINE value_type empty_value()
1129  {
1130  return 0;
1131  }
1132 
1133  //--------------------------------------------------------------------
1134  static AGG_INLINE value_type full_value()
1135  {
1136  return 1;
1137  }
1138 
1139  //--------------------------------------------------------------------
1140  AGG_INLINE bool is_transparent() const
1141  {
1142  return a <= 0;
1143  }
1144 
1145  //--------------------------------------------------------------------
1146  AGG_INLINE bool is_opaque() const
1147  {
1148  return a >= 1;
1149  }
1150 
1151  //--------------------------------------------------------------------
1152  static AGG_INLINE value_type invert(value_type x)
1153  {
1154  return 1 - x;
1155  }
1156 
1157  //--------------------------------------------------------------------
1158  static AGG_INLINE value_type multiply(value_type a, value_type b)
1159  {
1160  return value_type(a * b);
1161  }
1162 
1163  //--------------------------------------------------------------------
1164  static AGG_INLINE value_type demultiply(value_type a, value_type b)
1165  {
1166  return (b == 0) ? 0 : value_type(a / b);
1167  }
1168 
1169  //--------------------------------------------------------------------
1170  template<typename T>
1171  static AGG_INLINE T downscale(T a)
1172  {
1173  return a;
1174  }
1175 
1176  //--------------------------------------------------------------------
1177  template<typename T>
1178  static AGG_INLINE T downshift(T a, unsigned n)
1179  {
1180  return n > 0 ? a / (1 << n) : a;
1181  }
1182 
1183  //--------------------------------------------------------------------
1184  static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
1185  {
1186  return value_type(a * b / cover_mask);
1187  }
1188 
1189  //--------------------------------------------------------------------
1190  static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
1191  {
1192  return cover_type(uround(a * b));
1193  }
1194 
1195  //--------------------------------------------------------------------
1196  // Interpolate p to q by a, assuming q is premultiplied by a.
1197  static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
1198  {
1199  return (1 - a) * p + q; // more accurate than "p + q - p * a"
1200  }
1201 
1202  //--------------------------------------------------------------------
1203  // Interpolate p to q by a.
1204  static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
1205  {
1206  // The form "p + a * (q - p)" avoids a multiplication, but may produce an
1207  // inaccurate result. For example, "p + (q - p)" may not be exactly equal
1208  // to q. Therefore, stick to the basic expression, which at least produces
1209  // the correct result at either extreme.
1210  return (1 - a) * p + a * q;
1211  }
1212 
1213  //--------------------------------------------------------------------
1214  self_type& clear()
1215  {
1216  r = g = b = a = 0;
1217  return *this;
1218  }
1219 
1220  //--------------------------------------------------------------------
1221  self_type& transparent()
1222  {
1223  a = 0;
1224  return *this;
1225  }
1226 
1227  //--------------------------------------------------------------------
1228  AGG_INLINE self_type& opacity(double a_)
1229  {
1230  if (a_ < 0) a = 0;
1231  else if (a_ > 1) a = 1;
1232  else a = value_type(a_);
1233  return *this;
1234  }
1235 
1236  //--------------------------------------------------------------------
1237  double opacity() const
1238  {
1239  return a;
1240  }
1241 
1242  //--------------------------------------------------------------------
1243  AGG_INLINE self_type& premultiply()
1244  {
1245  if (a < 1)
1246  {
1247  if (a <= 0)
1248  {
1249  r = g = b = 0;
1250  }
1251  else
1252  {
1253  r *= a;
1254  g *= a;
1255  b *= a;
1256  }
1257  }
1258  return *this;
1259  }
1260 
1261  //--------------------------------------------------------------------
1262  AGG_INLINE self_type& demultiply()
1263  {
1264  if (a < 1)
1265  {
1266  if (a <= 0)
1267  {
1268  r = g = b = 0;
1269  }
1270  else
1271  {
1272  r /= a;
1273  g /= a;
1274  b /= a;
1275  }
1276  }
1277  return *this;
1278  }
1279 
1280  //--------------------------------------------------------------------
1281  AGG_INLINE self_type gradient(const self_type& c, double k) const
1282  {
1283  self_type ret;
1284  ret.r = value_type(r + (c.r - r) * k);
1285  ret.g = value_type(g + (c.g - g) * k);
1286  ret.b = value_type(b + (c.b - b) * k);
1287  ret.a = value_type(a + (c.a - a) * k);
1288  return ret;
1289  }
1290 
1291  //--------------------------------------------------------------------
1292  AGG_INLINE void add(const self_type& c, unsigned cover)
1293  {
1294  if (cover == cover_mask)
1295  {
1296  if (c.is_opaque())
1297  {
1298  *this = c;
1299  return;
1300  }
1301  else
1302  {
1303  r += c.r;
1304  g += c.g;
1305  b += c.b;
1306  a += c.a;
1307  }
1308  }
1309  else
1310  {
1311  r += mult_cover(c.r, cover);
1312  g += mult_cover(c.g, cover);
1313  b += mult_cover(c.b, cover);
1314  a += mult_cover(c.a, cover);
1315  }
1316  if (a > 1) a = 1;
1317  if (r > a) r = a;
1318  if (g > a) g = a;
1319  if (b > a) b = a;
1320  }
1321 
1322  //--------------------------------------------------------------------
1323  template<class GammaLUT>
1324  AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
1325  {
1326  r = gamma.dir(r);
1327  g = gamma.dir(g);
1328  b = gamma.dir(b);
1329  }
1330 
1331  //--------------------------------------------------------------------
1332  template<class GammaLUT>
1333  AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
1334  {
1335  r = gamma.inv(r);
1336  g = gamma.inv(g);
1337  b = gamma.inv(b);
1338  }
1339 
1340  //--------------------------------------------------------------------
1341  static self_type no_color() { return self_type(0,0,0,0); }
1342 
1343  //--------------------------------------------------------------------
1344  static self_type from_wavelength(double wl, double gamma = 1)
1345  {
1346  return self_type(rgba::from_wavelength(wl, gamma));
1347  }
1348  };
1349 }
1350 
1351 
1352 
1353 #endif
Definition: agg_arc.cpp:24