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 // Adaptation for high precision colors has been sponsored by
17 // Liberty Technology Systems, Inc., visit http://lib-sys.com
18 //
19 // Liberty Technology Systems, Inc. is the provider of
20 // PostScript and PDF technology for software developers.
21 //
22 //----------------------------------------------------------------------------
23 //
24 // color types gray8, gray16
25 //
26 //----------------------------------------------------------------------------
27 
28 #ifndef AGG_COLOR_GRAY_INCLUDED
29 #define AGG_COLOR_GRAY_INCLUDED
30 
31 #include "agg_basics.h"
32 #include "agg_color_rgba.h"
33 
34 namespace agg
35 {
36 
37     //===================================================================gray8
38     template<class Colorspace>
39     struct gray8T
40     {
41         typedef int8u  value_type;
42         typedef int32u calc_type;
43         typedef int32  long_type;
44         enum base_scale_e
45         {
46             base_shift = 8,
47             base_scale = 1 << base_shift,
48             base_mask  = base_scale - 1,
49             base_MSB = 1 << (base_shift - 1)
50         };
51         typedef gray8T self_type;
52 
53         value_type v;
54         value_type a;
55 
luminancegray8T56         static value_type luminance(const rgba& c)
57         {
58             // Calculate grayscale value as per ITU-R BT.709.
59             return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask));
60         }
61 
luminancegray8T62         static value_type luminance(const rgba8& c)
63         {
64             // Calculate grayscale value as per ITU-R BT.709.
65             return value_type((55u * c.r + 184u * c.g + 18u * c.b) >> 8);
66         }
67 
convertgray8T68         static void convert(gray8T<linear>& dst, const gray8T<sRGB>& src)
69         {
70             dst.v = sRGB_conv<value_type>::rgb_from_sRGB(src.v);
71             dst.a = src.a;
72         }
73 
convertgray8T74         static void convert(gray8T<sRGB>& dst, const gray8T<linear>& src)
75         {
76             dst.v = sRGB_conv<value_type>::rgb_to_sRGB(src.v);
77             dst.a = src.a;
78         }
79 
convertgray8T80         static void convert(gray8T<linear>& dst, const rgba8& src)
81         {
82             dst.v = luminance(src);
83             dst.a = src.a;
84         }
85 
convertgray8T86         static void convert(gray8T<linear>& dst, const srgba8& src)
87         {
88             // The RGB weights are only valid for linear values.
89             convert(dst, rgba8(src));
90         }
91 
convertgray8T92         static void convert(gray8T<sRGB>& dst, const rgba8& src)
93         {
94             dst.v = sRGB_conv<value_type>::rgb_to_sRGB(luminance(src));
95             dst.a = src.a;
96         }
97 
convertgray8T98         static void convert(gray8T<sRGB>& dst, const srgba8& src)
99         {
100             // The RGB weights are only valid for linear values.
101             convert(dst, rgba8(src));
102         }
103 
104         //--------------------------------------------------------------------
gray8Tgray8T105         gray8T() {}
106 
107         //--------------------------------------------------------------------
108         explicit gray8T(unsigned v_, unsigned a_ = base_mask) :
vgray8T109             v(int8u(v_)), a(int8u(a_)) {}
110 
111         //--------------------------------------------------------------------
gray8Tgray8T112         gray8T(const self_type& c, unsigned a_) :
113             v(c.v), a(value_type(a_)) {}
114 
115         //--------------------------------------------------------------------
gray8Tgray8T116         gray8T(const rgba& c) :
117             v(luminance(c)),
118             a(value_type(uround(c.a * base_mask))) {}
119 
120         //--------------------------------------------------------------------
121         template<class T>
gray8Tgray8T122         gray8T(const gray8T<T>& c)
123         {
124             convert(*this, c);
125         }
126 
127         //--------------------------------------------------------------------
128         template<class T>
gray8Tgray8T129         gray8T(const rgba8T<T>& c)
130         {
131             convert(*this, c);
132         }
133 
134         //--------------------------------------------------------------------
135         template<class T>
convert_from_sRGBgray8T136         T convert_from_sRGB() const
137         {
138             typename T::value_type y = sRGB_conv<typename T::value_type>::rgb_from_sRGB(v);
139             return T(y, y, y, sRGB_conv<typename T::value_type>::alpha_from_sRGB(a));
140         }
141 
142         template<class T>
convert_to_sRGBgray8T143         T convert_to_sRGB() const
144         {
145             typename T::value_type y = sRGB_conv<typename T::value_type>::rgb_to_sRGB(v);
146             return T(y, y, y, sRGB_conv<typename T::value_type>::alpha_to_sRGB(a));
147         }
148 
149         //--------------------------------------------------------------------
make_rgba8gray8T150         rgba8 make_rgba8(const linear&) const
151         {
152             return rgba8(v, v, v, a);
153         }
154 
make_rgba8gray8T155         rgba8 make_rgba8(const sRGB&) const
156         {
157             return convert_from_sRGB<srgba8>();
158         }
159 
rgba8gray8T160         operator rgba8() const
161         {
162             return make_rgba8(Colorspace());
163         }
164 
165         //--------------------------------------------------------------------
make_srgba8gray8T166         srgba8 make_srgba8(const linear&) const
167         {
168             return convert_to_sRGB<rgba8>();
169         }
170 
make_srgba8gray8T171         srgba8 make_srgba8(const sRGB&) const
172         {
173             return srgba8(v, v, v, a);
174         }
175 
srgba8gray8T176         operator srgba8() const
177         {
178             return make_rgba8(Colorspace());
179         }
180 
181         //--------------------------------------------------------------------
make_rgba16gray8T182         rgba16 make_rgba16(const linear&) const
183         {
184             rgba16::value_type rgb = (v << 8) | v;
185             return rgba16(rgb, rgb, rgb, (a << 8) | a);
186         }
187 
make_rgba16gray8T188         rgba16 make_rgba16(const sRGB&) const
189         {
190             return convert_from_sRGB<rgba16>();
191         }
192 
rgba16gray8T193         operator rgba16() const
194         {
195             return make_rgba16(Colorspace());
196         }
197 
198         //--------------------------------------------------------------------
make_rgba32gray8T199         rgba32 make_rgba32(const linear&) const
200         {
201             rgba32::value_type v32 = v / 255.0f;
202             return rgba32(v32, v32, v32, a / 255.0f);
203         }
204 
make_rgba32gray8T205         rgba32 make_rgba32(const sRGB&) const
206         {
207             return convert_from_sRGB<rgba32>();
208         }
209 
rgba32gray8T210         operator rgba32() const
211         {
212             return make_rgba32(Colorspace());
213         }
214 
215         //--------------------------------------------------------------------
to_doublegray8T216         static AGG_INLINE double to_double(value_type a)
217         {
218             return double(a) / base_mask;
219         }
220 
221         //--------------------------------------------------------------------
from_doublegray8T222         static AGG_INLINE value_type from_double(double a)
223         {
224             return value_type(uround(a * base_mask));
225         }
226 
227         //--------------------------------------------------------------------
empty_valuegray8T228         static AGG_INLINE value_type empty_value()
229         {
230             return 0;
231         }
232 
233         //--------------------------------------------------------------------
full_valuegray8T234         static AGG_INLINE value_type full_value()
235         {
236             return base_mask;
237         }
238 
239         //--------------------------------------------------------------------
is_transparentgray8T240         AGG_INLINE bool is_transparent() const
241         {
242             return a == 0;
243         }
244 
245         //--------------------------------------------------------------------
is_opaquegray8T246         AGG_INLINE bool is_opaque() const
247         {
248             return a == base_mask;
249         }
250 
251         //--------------------------------------------------------------------
252         // Fixed-point multiply, exact over int8u.
multiplygray8T253         static AGG_INLINE value_type multiply(value_type a, value_type b)
254         {
255             calc_type t = a * b + base_MSB;
256             return value_type(((t >> base_shift) + t) >> base_shift);
257         }
258 
259         //--------------------------------------------------------------------
demultiplygray8T260         static AGG_INLINE value_type demultiply(value_type a, value_type b)
261         {
262             if (a * b == 0)
263             {
264                 return 0;
265             }
266             else if (a >= b)
267             {
268                 return base_mask;
269             }
270             else return value_type((a * base_mask + (b >> 1)) / b);
271         }
272 
273         //--------------------------------------------------------------------
274         template<typename T>
downscalegray8T275         static AGG_INLINE T downscale(T a)
276         {
277             return a >> base_shift;
278         }
279 
280         //--------------------------------------------------------------------
281         template<typename T>
downshiftgray8T282         static AGG_INLINE T downshift(T a, unsigned n)
283         {
284             return a >> n;
285         }
286 
287         //--------------------------------------------------------------------
288         // Fixed-point multiply, exact over int8u.
289         // Specifically for multiplying a color component by a cover.
mult_covergray8T290         static AGG_INLINE value_type mult_cover(value_type a, value_type b)
291         {
292             return multiply(a, b);
293         }
294 
295         //--------------------------------------------------------------------
scale_covergray8T296         static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
297         {
298             return multiply(b, a);
299         }
300 
301         //--------------------------------------------------------------------
302         // Interpolate p to q by a, assuming q is premultiplied by a.
prelerpgray8T303         static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
304         {
305             return p + q - multiply(p, a);
306         }
307 
308         //--------------------------------------------------------------------
309         // Interpolate p to q by a.
lerpgray8T310         static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
311         {
312             int t = (q - p) * a + base_MSB - (p > q);
313             return value_type(p + (((t >> base_shift) + t) >> base_shift));
314         }
315 
316         //--------------------------------------------------------------------
cleargray8T317         self_type& clear()
318         {
319             v = a = 0;
320 			return *this;
321         }
322 
323         //--------------------------------------------------------------------
transparentgray8T324         self_type& transparent()
325         {
326             a = 0;
327             return *this;
328         }
329 
330         //--------------------------------------------------------------------
opacitygray8T331         self_type& opacity(double a_)
332         {
333             if (a_ < 0) a = 0;
334             else if (a_ > 1) a = 1;
335             else a = (value_type)uround(a_ * double(base_mask));
336 			return *this;
337         }
338 
339         //--------------------------------------------------------------------
opacitygray8T340         double opacity() const
341         {
342             return double(a) / double(base_mask);
343         }
344 
345         //--------------------------------------------------------------------
premultiplygray8T346         self_type& premultiply()
347         {
348             if (a < base_mask)
349             {
350                 if (a == 0) v = 0;
351                 else v = multiply(v, a);
352             }
353             return *this;
354         }
355 
356         //--------------------------------------------------------------------
demultiplygray8T357         self_type& demultiply()
358         {
359             if (a < base_mask)
360             {
361                 if (a == 0)
362                 {
363                     v = 0;
364                 }
365                 else
366                 {
367                     calc_type v_ = (calc_type(v) * base_mask) / a;
368                     v = value_type((v_ > base_mask) ? (value_type)base_mask : v_);
369                 }
370             }
371             return *this;
372         }
373 
374         //--------------------------------------------------------------------
gradientgray8T375         self_type gradient(self_type c, double k) const
376         {
377             self_type ret;
378             calc_type ik = uround(k * base_scale);
379             ret.v = lerp(v, c.v, ik);
380             ret.a = lerp(a, c.a, ik);
381             return ret;
382         }
383 
384         //--------------------------------------------------------------------
addgray8T385         AGG_INLINE void add(const self_type& c, unsigned cover)
386         {
387             calc_type cv, ca;
388             if (cover == cover_mask)
389             {
390                 if (c.a == base_mask)
391                 {
392                     *this = c;
393                     return;
394                 }
395                 else
396                 {
397                     cv = v + c.v;
398                     ca = a + c.a;
399                 }
400             }
401             else
402             {
403                 cv = v + mult_cover(c.v, cover);
404                 ca = a + mult_cover(c.a, cover);
405             }
406             v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv);
407             a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
408         }
409 
410         //--------------------------------------------------------------------
no_colorgray8T411         static self_type no_color() { return self_type(0,0); }
412     };
413 
414     typedef gray8T<linear> gray8;
415     typedef gray8T<sRGB> sgray8;
416 
417 
418     //==================================================================gray16
419     struct gray16
420     {
421         typedef int16u value_type;
422         typedef int32u calc_type;
423         typedef int64  long_type;
424         enum base_scale_e
425         {
426             base_shift = 16,
427             base_scale = 1 << base_shift,
428             base_mask  = base_scale - 1,
429             base_MSB = 1 << (base_shift - 1)
430         };
431         typedef gray16 self_type;
432 
433         value_type v;
434         value_type a;
435 
luminancegray16436         static value_type luminance(const rgba& c)
437         {
438             // Calculate grayscale value as per ITU-R BT.709.
439             return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask));
440         }
441 
luminancegray16442         static value_type luminance(const rgba16& c)
443         {
444             // Calculate grayscale value as per ITU-R BT.709.
445             return value_type((13933u * c.r + 46872u * c.g + 4732u * c.b) >> 16);
446         }
447 
luminancegray16448         static value_type luminance(const rgba8& c)
449         {
450             return luminance(rgba16(c));
451         }
452 
luminancegray16453         static value_type luminance(const srgba8& c)
454         {
455             return luminance(rgba16(c));
456         }
457 
luminancegray16458         static value_type luminance(const rgba32& c)
459         {
460             return luminance(rgba(c));
461         }
462 
463         //--------------------------------------------------------------------
gray16gray16464         gray16() {}
465 
466         //--------------------------------------------------------------------
467         explicit gray16(unsigned v_, unsigned a_ = base_mask) :
vgray16468             v(int16u(v_)), a(int16u(a_)) {}
469 
470         //--------------------------------------------------------------------
gray16gray16471         gray16(const self_type& c, unsigned a_) :
472             v(c.v), a(value_type(a_)) {}
473 
474         //--------------------------------------------------------------------
gray16gray16475         gray16(const rgba& c) :
476             v(luminance(c)),
477             a((value_type)uround(c.a * double(base_mask))) {}
478 
479         //--------------------------------------------------------------------
gray16gray16480         gray16(const rgba8& c) :
481             v(luminance(c)),
482             a((value_type(c.a) << 8) | c.a) {}
483 
484         //--------------------------------------------------------------------
gray16gray16485         gray16(const srgba8& c) :
486             v(luminance(c)),
487             a((value_type(c.a) << 8) | c.a) {}
488 
489         //--------------------------------------------------------------------
gray16gray16490         gray16(const rgba16& c) :
491             v(luminance(c)),
492             a(c.a) {}
493 
494         //--------------------------------------------------------------------
gray16gray16495         gray16(const gray8& c) :
496             v((value_type(c.v) << 8) | c.v),
497             a((value_type(c.a) << 8) | c.a) {}
498 
499         //--------------------------------------------------------------------
gray16gray16500         gray16(const sgray8& c) :
501             v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)),
502             a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
503 
504         //--------------------------------------------------------------------
rgba8gray16505         operator rgba8() const
506         {
507             return rgba8(v >> 8, v >> 8, v >> 8, a >> 8);
508         }
509 
510         //--------------------------------------------------------------------
srgba8gray16511         operator srgba8() const
512         {
513             value_type y = sRGB_conv<value_type>::rgb_to_sRGB(v);
514             return srgba8(y, y, y, sRGB_conv<value_type>::alpha_to_sRGB(a));
515         }
516 
517         //--------------------------------------------------------------------
rgba16gray16518         operator rgba16() const
519         {
520             return rgba16(v, v, v, a);
521         }
522 
523 		//--------------------------------------------------------------------
rgba32gray16524 		operator rgba32() const
525 		{
526 			rgba32::value_type v32 = v / 65535.0f;
527 			return rgba32(v32, v32, v32, a / 65535.0f);
528 		}
529 
530 		//--------------------------------------------------------------------
gray8gray16531         operator gray8() const
532         {
533             return gray8(v >> 8, a >> 8);
534         }
535 
536         //--------------------------------------------------------------------
sgray8gray16537         operator sgray8() const
538         {
539             return sgray8(
540                 sRGB_conv<value_type>::rgb_to_sRGB(v),
541                 sRGB_conv<value_type>::alpha_to_sRGB(a));
542         }
543 
544         //--------------------------------------------------------------------
to_doublegray16545         static AGG_INLINE double to_double(value_type a)
546         {
547             return double(a) / base_mask;
548         }
549 
550         //--------------------------------------------------------------------
from_doublegray16551         static AGG_INLINE value_type from_double(double a)
552         {
553             return value_type(uround(a * base_mask));
554         }
555 
556         //--------------------------------------------------------------------
empty_valuegray16557         static AGG_INLINE value_type empty_value()
558         {
559             return 0;
560         }
561 
562         //--------------------------------------------------------------------
full_valuegray16563         static AGG_INLINE value_type full_value()
564         {
565             return base_mask;
566         }
567 
568         //--------------------------------------------------------------------
is_transparentgray16569         AGG_INLINE bool is_transparent() const
570         {
571             return a == 0;
572         }
573 
574         //--------------------------------------------------------------------
is_opaquegray16575         AGG_INLINE bool is_opaque() const
576         {
577             return a == base_mask;
578         }
579 
580         //--------------------------------------------------------------------
581         // Fixed-point multiply, exact over int16u.
multiplygray16582         static AGG_INLINE value_type multiply(value_type a, value_type b)
583         {
584             calc_type t = a * b + base_MSB;
585             return value_type(((t >> base_shift) + t) >> base_shift);
586         }
587 
588         //--------------------------------------------------------------------
demultiplygray16589         static AGG_INLINE value_type demultiply(value_type a, value_type b)
590         {
591             if (a * b == 0)
592             {
593                 return 0;
594             }
595             else if (a >= b)
596             {
597                 return base_mask;
598             }
599             else return value_type((a * base_mask + (b >> 1)) / b);
600         }
601 
602         //--------------------------------------------------------------------
603         template<typename T>
downscalegray16604         static AGG_INLINE T downscale(T a)
605         {
606             return a >> base_shift;
607         }
608 
609         //--------------------------------------------------------------------
610         template<typename T>
downshiftgray16611         static AGG_INLINE T downshift(T a, unsigned n)
612         {
613             return a >> n;
614         }
615 
616         //--------------------------------------------------------------------
617         // Fixed-point multiply, almost exact over int16u.
618         // Specifically for multiplying a color component by a cover.
mult_covergray16619         static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
620         {
621             return multiply(a, b << 8 | b);
622         }
623 
624         //--------------------------------------------------------------------
scale_covergray16625         static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
626         {
627             return mult_cover(b, a) >> 8;
628         }
629 
630         //--------------------------------------------------------------------
631         // Interpolate p to q by a, assuming q is premultiplied by a.
prelerpgray16632         static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
633         {
634             return p + q - multiply(p, a);
635         }
636 
637         //--------------------------------------------------------------------
638         // Interpolate p to q by a.
lerpgray16639         static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
640         {
641             int t = (q - p) * a + base_MSB - (p > q);
642             return value_type(p + (((t >> base_shift) + t) >> base_shift));
643         }
644 
645         //--------------------------------------------------------------------
cleargray16646         self_type& clear()
647         {
648             v = a = 0;
649 			return *this;
650         }
651 
652         //--------------------------------------------------------------------
transparentgray16653         self_type& transparent()
654         {
655             a = 0;
656             return *this;
657         }
658 
659         //--------------------------------------------------------------------
opacitygray16660         self_type& opacity(double a_)
661         {
662             if (a_ < 0) a = 0;
663             else if(a_ > 1) a = 1;
664             else a = (value_type)uround(a_ * double(base_mask));
665 			return *this;
666         }
667 
668         //--------------------------------------------------------------------
opacitygray16669         double opacity() const
670         {
671             return double(a) / double(base_mask);
672         }
673 
674 
675         //--------------------------------------------------------------------
premultiplygray16676         self_type& premultiply()
677         {
678             if (a < base_mask)
679             {
680                 if(a == 0) v = 0;
681                 else v = multiply(v, a);
682             }
683             return *this;
684         }
685 
686         //--------------------------------------------------------------------
demultiplygray16687         self_type& demultiply()
688         {
689             if (a < base_mask)
690             {
691                 if (a == 0)
692                 {
693                     v = 0;
694                 }
695                 else
696                 {
697                     calc_type v_ = (calc_type(v) * base_mask) / a;
698 					v = (v_ > base_mask) ? value_type(base_mask) : value_type(v_);
699                 }
700             }
701             return *this;
702         }
703 
704         //--------------------------------------------------------------------
gradientgray16705         self_type gradient(self_type c, double k) const
706         {
707             self_type ret;
708             calc_type ik = uround(k * base_scale);
709             ret.v = lerp(v, c.v, ik);
710             ret.a = lerp(a, c.a, ik);
711             return ret;
712         }
713 
714         //--------------------------------------------------------------------
addgray16715         AGG_INLINE void add(const self_type& c, unsigned cover)
716         {
717             calc_type cv, ca;
718             if (cover == cover_mask)
719             {
720                 if (c.a == base_mask)
721                 {
722                     *this = c;
723                     return;
724                 }
725                 else
726                 {
727                     cv = v + c.v;
728                     ca = a + c.a;
729                 }
730             }
731             else
732             {
733                 cv = v + mult_cover(c.v, cover);
734                 ca = a + mult_cover(c.a, cover);
735             }
736             v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv);
737             a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
738         }
739 
740         //--------------------------------------------------------------------
no_colorgray16741         static self_type no_color() { return self_type(0,0); }
742     };
743 
744 
745     //===================================================================gray32
746     struct gray32
747     {
748         typedef float value_type;
749         typedef double calc_type;
750         typedef double long_type;
751         typedef gray32 self_type;
752 
753         value_type v;
754         value_type a;
755 
756         // Calculate grayscale value as per ITU-R BT.709.
luminancegray32757         static value_type luminance(double r, double g, double b)
758         {
759             return value_type(0.2126 * r + 0.7152 * g + 0.0722 * b);
760         }
761 
luminancegray32762         static value_type luminance(const rgba& c)
763         {
764             return luminance(c.r, c.g, c.b);
765         }
766 
luminancegray32767         static value_type luminance(const rgba32& c)
768         {
769             return luminance(c.r, c.g, c.b);
770         }
771 
luminancegray32772         static value_type luminance(const rgba8& c)
773         {
774             return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0);
775         }
776 
luminancegray32777         static value_type luminance(const rgba16& c)
778         {
779             return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0);
780         }
781 
782         //--------------------------------------------------------------------
gray32gray32783         gray32() {}
784 
785         //--------------------------------------------------------------------
786         explicit gray32(value_type v_, value_type a_ = 1) :
vgray32787             v(v_), a(a_) {}
788 
789         //--------------------------------------------------------------------
gray32gray32790         gray32(const self_type& c, value_type a_) :
791             v(c.v), a(a_) {}
792 
793         //--------------------------------------------------------------------
gray32gray32794         gray32(const rgba& c) :
795             v(luminance(c)),
796             a(value_type(c.a)) {}
797 
798         //--------------------------------------------------------------------
gray32gray32799         gray32(const rgba8& c) :
800             v(luminance(c)),
801             a(value_type(c.a / 255.0)) {}
802 
803         //--------------------------------------------------------------------
gray32gray32804         gray32(const srgba8& c) :
805             v(luminance(rgba32(c))),
806             a(value_type(c.a / 255.0)) {}
807 
808         //--------------------------------------------------------------------
gray32gray32809         gray32(const rgba16& c) :
810             v(luminance(c)),
811             a(value_type(c.a / 65535.0)) {}
812 
813         //--------------------------------------------------------------------
gray32gray32814         gray32(const rgba32& c) :
815             v(luminance(c)),
816             a(value_type(c.a)) {}
817 
818         //--------------------------------------------------------------------
gray32gray32819         gray32(const gray8& c) :
820             v(value_type(c.v / 255.0)),
821             a(value_type(c.a / 255.0)) {}
822 
823         //--------------------------------------------------------------------
gray32gray32824         gray32(const sgray8& c) :
825             v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)),
826             a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
827 
828         //--------------------------------------------------------------------
gray32gray32829         gray32(const gray16& c) :
830             v(value_type(c.v / 65535.0)),
831             a(value_type(c.a / 65535.0)) {}
832 
833         //--------------------------------------------------------------------
rgbagray32834         operator rgba() const
835         {
836             return rgba(v, v, v, a);
837         }
838 
839         //--------------------------------------------------------------------
gray8gray32840         operator gray8() const
841         {
842             return gray8(uround(v * 255.0), uround(a * 255.0));
843         }
844 
845         //--------------------------------------------------------------------
sgray8gray32846         operator sgray8() const
847         {
848             // Return (non-premultiplied) sRGB values.
849             return sgray8(
850                 sRGB_conv<value_type>::rgb_to_sRGB(v),
851                 sRGB_conv<value_type>::alpha_to_sRGB(a));
852         }
853 
854         //--------------------------------------------------------------------
gray16gray32855         operator gray16() const
856         {
857             return gray16(uround(v * 65535.0), uround(a * 65535.0));
858         }
859 
860         //--------------------------------------------------------------------
rgba8gray32861         operator rgba8() const
862         {
863             rgba8::value_type y = uround(v * 255.0);
864             return rgba8(y, y, y, uround(a * 255.0));
865         }
866 
867         //--------------------------------------------------------------------
srgba8gray32868         operator srgba8() const
869         {
870             srgba8::value_type y = sRGB_conv<value_type>::rgb_to_sRGB(v);
871             return srgba8(y, y, y, sRGB_conv<value_type>::alpha_to_sRGB(a));
872         }
873 
874 		//--------------------------------------------------------------------
rgba16gray32875 		operator rgba16() const
876 		{
877 			rgba16::value_type y = uround(v * 65535.0);
878 			return rgba16(y, y, y, uround(a * 65535.0));
879 		}
880 
881 		//--------------------------------------------------------------------
rgba32gray32882 		operator rgba32() const
883 		{
884             return rgba32(v, v, v, a);
885 		}
886 
887 		//--------------------------------------------------------------------
to_doublegray32888         static AGG_INLINE double to_double(value_type a)
889         {
890             return a;
891         }
892 
893         //--------------------------------------------------------------------
from_doublegray32894         static AGG_INLINE value_type from_double(double a)
895         {
896             return value_type(a);
897         }
898 
899         //--------------------------------------------------------------------
empty_valuegray32900         static AGG_INLINE value_type empty_value()
901         {
902             return 0;
903         }
904 
905         //--------------------------------------------------------------------
full_valuegray32906         static AGG_INLINE value_type full_value()
907         {
908             return 1;
909         }
910 
911         //--------------------------------------------------------------------
is_transparentgray32912         AGG_INLINE bool is_transparent() const
913         {
914             return a <= 0;
915         }
916 
917         //--------------------------------------------------------------------
is_opaquegray32918         AGG_INLINE bool is_opaque() const
919         {
920             return a >= 1;
921         }
922 
923         //--------------------------------------------------------------------
invertgray32924         static AGG_INLINE value_type invert(value_type x)
925         {
926             return 1 - x;
927         }
928 
929         //--------------------------------------------------------------------
multiplygray32930         static AGG_INLINE value_type multiply(value_type a, value_type b)
931         {
932             return value_type(a * b);
933         }
934 
935         //--------------------------------------------------------------------
demultiplygray32936         static AGG_INLINE value_type demultiply(value_type a, value_type b)
937         {
938             return (b == 0) ? 0 : value_type(a / b);
939         }
940 
941         //--------------------------------------------------------------------
942         template<typename T>
downscalegray32943         static AGG_INLINE T downscale(T a)
944         {
945             return a;
946         }
947 
948         //--------------------------------------------------------------------
949         template<typename T>
downshiftgray32950         static AGG_INLINE T downshift(T a, unsigned n)
951         {
952             return n > 0 ? a / (1 << n) : a;
953         }
954 
955         //--------------------------------------------------------------------
mult_covergray32956         static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
957         {
958             return value_type(a * b / cover_mask);
959         }
960 
961         //--------------------------------------------------------------------
scale_covergray32962         static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
963         {
964             return cover_type(uround(a * b));
965         }
966 
967         //--------------------------------------------------------------------
968         // Interpolate p to q by a, assuming q is premultiplied by a.
prelerpgray32969         static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
970         {
971             return (1 - a) * p + q; // more accurate than "p + q - p * a"
972         }
973 
974         //--------------------------------------------------------------------
975         // Interpolate p to q by a.
lerpgray32976         static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
977         {
978 			// The form "p + a * (q - p)" avoids a multiplication, but may produce an
979 			// inaccurate result. For example, "p + (q - p)" may not be exactly equal
980 			// to q. Therefore, stick to the basic expression, which at least produces
981 			// the correct result at either extreme.
982 			return (1 - a) * p + a * q;
983         }
984 
985         //--------------------------------------------------------------------
cleargray32986         self_type& clear()
987         {
988             v = a = 0;
989 			return *this;
990         }
991 
992         //--------------------------------------------------------------------
transparentgray32993         self_type& transparent()
994         {
995             a = 0;
996             return *this;
997         }
998 
999         //--------------------------------------------------------------------
opacitygray321000         self_type& opacity(double a_)
1001         {
1002             if (a_ < 0) a = 0;
1003             else if (a_ > 1) a = 1;
1004             else a = value_type(a_);
1005 			return *this;
1006         }
1007 
1008         //--------------------------------------------------------------------
opacitygray321009         double opacity() const
1010         {
1011             return a;
1012         }
1013 
1014 
1015         //--------------------------------------------------------------------
premultiplygray321016         self_type& premultiply()
1017         {
1018             if (a < 0) v = 0;
1019             else if(a < 1) v *= a;
1020             return *this;
1021         }
1022 
1023         //--------------------------------------------------------------------
demultiplygray321024         self_type& demultiply()
1025         {
1026             if (a < 0) v = 0;
1027             else if (a < 1) v /= a;
1028             return *this;
1029         }
1030 
1031         //--------------------------------------------------------------------
gradientgray321032         self_type gradient(self_type c, double k) const
1033         {
1034             return self_type(
1035                 value_type(v + (c.v - v) * k),
1036                 value_type(a + (c.a - a) * k));
1037         }
1038 
1039         //--------------------------------------------------------------------
no_colorgray321040         static self_type no_color() { return self_type(0,0); }
1041     };
1042 }
1043 
1044 
1045 
1046 
1047 #endif
1048