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 <math.h>
28#include "agg_basics.h"
29
30namespace agg
31{
32    // Supported byte orders for RGB and RGBA pixel formats
33    //=======================================================================
34    struct order_rgb  { enum rgb_e  { R=0, G=1, B=2, rgb_tag }; };       //----order_rgb
35    struct order_bgr  { enum bgr_e  { B=0, G=1, R=2, rgb_tag }; };       //----order_bgr
36    struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba
37    struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb
38    struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr
39    struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra
40
41    //====================================================================rgba
42    struct rgba
43    {
44        typedef double value_type;
45
46        double r;
47        double g;
48        double b;
49        double a;
50
51        //--------------------------------------------------------------------
52        rgba() {}
53
54        //--------------------------------------------------------------------
55        rgba(double r_, double g_, double b_, double a_=1.0) :
56            r(r_), g(g_), b(b_), a(a_) {}
57
58        //--------------------------------------------------------------------
59        rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
60
61        //--------------------------------------------------------------------
62        void clear()
63        {
64            r = g = b = a = 0;
65        }
66
67        //--------------------------------------------------------------------
68        const rgba& transparent()
69        {
70            a = 0.0;
71            return *this;
72        }
73
74        //--------------------------------------------------------------------
75        const rgba& opacity(double a_)
76        {
77            if(a_ < 0.0) a_ = 0.0;
78            if(a_ > 1.0) a_ = 1.0;
79            a = a_;
80            return *this;
81        }
82
83        //--------------------------------------------------------------------
84        double opacity() const
85        {
86            return a;
87        }
88
89        //--------------------------------------------------------------------
90        const rgba& premultiply()
91        {
92            r *= a;
93            g *= a;
94            b *= a;
95            return *this;
96        }
97
98        //--------------------------------------------------------------------
99        const rgba& premultiply(double a_)
100        {
101            if(a <= 0.0 || a_ <= 0.0)
102            {
103                r = g = b = a = 0.0;
104                return *this;
105            }
106            a_ /= a;
107            r *= a_;
108            g *= a_;
109            b *= a_;
110            a  = a_;
111            return *this;
112        }
113
114        //--------------------------------------------------------------------
115        const rgba& demultiply()
116        {
117            if(a == 0)
118            {
119                r = g = b = 0;
120                return *this;
121            }
122            double a_ = 1.0 / a;
123            r *= a_;
124            g *= a_;
125            b *= a_;
126            return *this;
127        }
128
129
130        //--------------------------------------------------------------------
131        rgba gradient(rgba c, double k) const
132        {
133            rgba ret;
134            ret.r = r + (c.r - r) * k;
135            ret.g = g + (c.g - g) * k;
136            ret.b = b + (c.b - b) * k;
137            ret.a = a + (c.a - a) * k;
138            return ret;
139        }
140
141        //--------------------------------------------------------------------
142        static rgba no_color() { return rgba(0,0,0,0); }
143
144        //--------------------------------------------------------------------
145        static rgba from_wavelength(double wl, double gamma = 1.0);
146
147        //--------------------------------------------------------------------
148        explicit rgba(double wavelen, double gamma=1.0)
149        {
150            *this = from_wavelength(wavelen, gamma);
151        }
152
153    };
154
155    //----------------------------------------------------------------rgba_pre
156    inline rgba rgba_pre(double r, double g, double b, double a=1.0)
157    {
158        return rgba(r, g, b, a).premultiply();
159    }
160    inline rgba rgba_pre(const rgba& c)
161    {
162        return rgba(c).premultiply();
163    }
164    inline rgba rgba_pre(const rgba& c, double a)
165    {
166        return rgba(c, a).premultiply();
167    }
168
169    //------------------------------------------------------------------------
170    inline rgba rgba::from_wavelength(double wl, double gamma)
171    {
172        rgba t(0.0, 0.0, 0.0);
173
174        if(wl >= 380.0 && wl <= 440.0)
175        {
176            t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
177            t.b = 1.0;
178        }
179        else
180        if(wl >= 440.0 && wl <= 490.0)
181        {
182            t.g = (wl - 440.0) / (490.0 - 440.0);
183            t.b = 1.0;
184        }
185        else
186        if(wl >= 490.0 && wl <= 510.0)
187        {
188            t.g = 1.0;
189            t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
190        }
191        else
192        if(wl >= 510.0 && wl <= 580.0)
193        {
194            t.r = (wl - 510.0) / (580.0 - 510.0);
195            t.g = 1.0;
196        }
197        else
198        if(wl >= 580.0 && wl <= 645.0)
199        {
200            t.r = 1.0;
201            t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
202        }
203        else
204        if(wl >= 645.0 && wl <= 780.0)
205        {
206            t.r = 1.0;
207        }
208
209        double s = 1.0;
210        if(wl > 700.0)       s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
211        else if(wl <  420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
212
213        t.r = pow(t.r * s, gamma);
214        t.g = pow(t.g * s, gamma);
215        t.b = pow(t.b * s, gamma);
216        return t;
217    }
218
219
220
221
222    //===================================================================rgba8
223    struct rgba8
224    {
225        typedef int8u  value_type;
226        typedef int32u calc_type;
227        typedef int32  long_type;
228        enum base_scale_e
229        {
230            base_shift = 8,
231            base_scale = 1 << base_shift,
232            base_mask  = base_scale - 1
233        };
234        typedef rgba8 self_type;
235
236
237        value_type r;
238        value_type g;
239        value_type b;
240        value_type a;
241
242        //--------------------------------------------------------------------
243        rgba8() {}
244
245        //--------------------------------------------------------------------
246        rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
247            r(value_type(r_)),
248            g(value_type(g_)),
249            b(value_type(b_)),
250            a(value_type(a_)) {}
251
252        //--------------------------------------------------------------------
253        rgba8(const rgba& c, double a_) :
254            r((value_type)uround(c.r * double(base_mask))),
255            g((value_type)uround(c.g * double(base_mask))),
256            b((value_type)uround(c.b * double(base_mask))),
257            a((value_type)uround(a_  * double(base_mask))) {}
258
259        //--------------------------------------------------------------------
260        rgba8(const self_type& c, unsigned a_) :
261            r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
262
263        //--------------------------------------------------------------------
264        rgba8(const rgba& c) :
265            r((value_type)uround(c.r * double(base_mask))),
266            g((value_type)uround(c.g * double(base_mask))),
267            b((value_type)uround(c.b * double(base_mask))),
268            a((value_type)uround(c.a * double(base_mask))) {}
269
270        //--------------------------------------------------------------------
271        void clear()
272        {
273            r = g = b = a = 0;
274        }
275
276        //--------------------------------------------------------------------
277        const self_type& transparent()
278        {
279            a = 0;
280            return *this;
281        }
282
283        //--------------------------------------------------------------------
284        const self_type& opacity(double a_)
285        {
286            if(a_ < 0.0) a_ = 0.0;
287            if(a_ > 1.0) a_ = 1.0;
288            a = (value_type)uround(a_ * double(base_mask));
289            return *this;
290        }
291
292        //--------------------------------------------------------------------
293        double opacity() const
294        {
295            return double(a) / double(base_mask);
296        }
297
298        //--------------------------------------------------------------------
299        AGG_INLINE const self_type& premultiply()
300        {
301            if(a == base_mask) return *this;
302            if(a == 0)
303            {
304                r = g = b = 0;
305                return *this;
306            }
307            r = value_type((calc_type(r) * a) >> base_shift);
308            g = value_type((calc_type(g) * a) >> base_shift);
309            b = value_type((calc_type(b) * a) >> base_shift);
310            return *this;
311        }
312
313        //--------------------------------------------------------------------
314        AGG_INLINE const self_type& premultiply(unsigned a_)
315        {
316            if(a == base_mask && a_ >= base_mask) return *this;
317            if(a == 0 || a_ == 0)
318            {
319                r = g = b = a = 0;
320                return *this;
321            }
322            calc_type r_ = (calc_type(r) * a_) / a;
323            calc_type g_ = (calc_type(g) * a_) / a;
324            calc_type b_ = (calc_type(b) * a_) / a;
325            r = value_type((r_ > a_) ? a_ : r_);
326            g = value_type((g_ > a_) ? a_ : g_);
327            b = value_type((b_ > a_) ? a_ : b_);
328            a = value_type(a_);
329            return *this;
330        }
331
332        //--------------------------------------------------------------------
333        AGG_INLINE const self_type& demultiply()
334        {
335            if(a == base_mask) return *this;
336            if(a == 0)
337            {
338                r = g = b = 0;
339                return *this;
340            }
341            calc_type r_ = (calc_type(r) * base_mask) / a;
342            calc_type g_ = (calc_type(g) * base_mask) / a;
343            calc_type b_ = (calc_type(b) * base_mask) / a;
344            r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
345            g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
346            b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
347            return *this;
348        }
349
350        //--------------------------------------------------------------------
351        AGG_INLINE self_type gradient(const self_type& c, double k) const
352        {
353            self_type ret;
354            calc_type ik = uround(k * base_scale);
355            ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
356            ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
357            ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
358            ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
359            return ret;
360        }
361
362        //--------------------------------------------------------------------
363        AGG_INLINE void add(const self_type& c, unsigned cover)
364        {
365            calc_type cr, cg, cb, ca;
366            if(cover == cover_mask)
367            {
368                if(c.a == base_mask)
369                {
370                    *this = c;
371                }
372                else
373                {
374                    cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
375                    cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
376                    cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
377                    ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
378                }
379            }
380            else
381            {
382                cr = r + ((c.r * cover + cover_mask/2) >> cover_shift);
383                cg = g + ((c.g * cover + cover_mask/2) >> cover_shift);
384                cb = b + ((c.b * cover + cover_mask/2) >> cover_shift);
385                ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
386                r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
387                g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
388                b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
389                a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
390            }
391        }
392
393        //--------------------------------------------------------------------
394        template<class GammaLUT>
395        AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
396        {
397            r = gamma.dir(r);
398            g = gamma.dir(g);
399            b = gamma.dir(b);
400        }
401
402        //--------------------------------------------------------------------
403        template<class GammaLUT>
404        AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
405        {
406            r = gamma.inv(r);
407            g = gamma.inv(g);
408            b = gamma.inv(b);
409        }
410
411        //--------------------------------------------------------------------
412        static self_type no_color() { return self_type(0,0,0,0); }
413
414        //--------------------------------------------------------------------
415        static self_type from_wavelength(double wl, double gamma = 1.0)
416        {
417            return self_type(rgba::from_wavelength(wl, gamma));
418        }
419    };
420
421
422    //-------------------------------------------------------------rgba8_pre
423    inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b,
424                           unsigned a = rgba8::base_mask)
425    {
426        return rgba8(r,g,b,a).premultiply();
427    }
428    inline rgba8 rgba8_pre(const rgba8& c)
429    {
430        return rgba8(c).premultiply();
431    }
432    inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
433    {
434        return rgba8(c,a).premultiply();
435    }
436    inline rgba8 rgba8_pre(const rgba& c)
437    {
438        return rgba8(c).premultiply();
439    }
440    inline rgba8 rgba8_pre(const rgba& c, double a)
441    {
442        return rgba8(c,a).premultiply();
443    }
444
445
446    //-----------------------------------------------------------rgb8_packed
447    inline rgba8 rgb8_packed(unsigned v)
448    {
449        return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
450    }
451
452    //-----------------------------------------------------------bgr8_packed
453    inline rgba8 bgr8_packed(unsigned v)
454    {
455        return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
456    }
457
458    //----------------------------------------------------------argb8_packed
459    inline rgba8 argb8_packed(unsigned v)
460    {
461        return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
462    }
463
464
465
466
467
468
469
470
471    //=================================================================rgba16
472    struct rgba16
473    {
474        typedef int16u value_type;
475        typedef int32u calc_type;
476        typedef int64  long_type;
477        enum base_scale_e
478        {
479            base_shift = 16,
480            base_scale = 1 << base_shift,
481            base_mask  = base_scale - 1
482        };
483        typedef rgba16 self_type;
484
485        value_type r;
486        value_type g;
487        value_type b;
488        value_type a;
489
490        //--------------------------------------------------------------------
491        rgba16() {}
492
493        //--------------------------------------------------------------------
494        rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
495            r(value_type(r_)),
496            g(value_type(g_)),
497            b(value_type(b_)),
498            a(value_type(a_)) {}
499
500        //--------------------------------------------------------------------
501        rgba16(const self_type& c, unsigned a_) :
502            r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
503
504        //--------------------------------------------------------------------
505        rgba16(const rgba& c) :
506            r((value_type)uround(c.r * double(base_mask))),
507            g((value_type)uround(c.g * double(base_mask))),
508            b((value_type)uround(c.b * double(base_mask))),
509            a((value_type)uround(c.a * double(base_mask))) {}
510
511        //--------------------------------------------------------------------
512        rgba16(const rgba& c, double a_) :
513            r((value_type)uround(c.r * double(base_mask))),
514            g((value_type)uround(c.g * double(base_mask))),
515            b((value_type)uround(c.b * double(base_mask))),
516            a((value_type)uround(a_  * double(base_mask))) {}
517
518        //--------------------------------------------------------------------
519        rgba16(const rgba8& c) :
520            r(value_type((value_type(c.r) << 8) | c.r)),
521            g(value_type((value_type(c.g) << 8) | c.g)),
522            b(value_type((value_type(c.b) << 8) | c.b)),
523            a(value_type((value_type(c.a) << 8) | c.a)) {}
524
525        //--------------------------------------------------------------------
526        rgba16(const rgba8& c, unsigned a_) :
527            r(value_type((value_type(c.r) << 8) | c.r)),
528            g(value_type((value_type(c.g) << 8) | c.g)),
529            b(value_type((value_type(c.b) << 8) | c.b)),
530            a(value_type((             a_ << 8) | c.a)) {}
531
532        //--------------------------------------------------------------------
533        void clear()
534        {
535            r = g = b = a = 0;
536        }
537
538        //--------------------------------------------------------------------
539        const self_type& transparent()
540        {
541            a = 0;
542            return *this;
543        }
544
545        //--------------------------------------------------------------------
546        AGG_INLINE const self_type& opacity(double a_)
547        {
548            if(a_ < 0.0) a_ = 0.0;
549            if(a_ > 1.0) a_ = 1.0;
550            a = (value_type)uround(a_ * double(base_mask));
551            return *this;
552        }
553
554        //--------------------------------------------------------------------
555        double opacity() const
556        {
557            return double(a) / double(base_mask);
558        }
559
560        //--------------------------------------------------------------------
561        AGG_INLINE const self_type& premultiply()
562        {
563            if(a == base_mask) return *this;
564            if(a == 0)
565            {
566                r = g = b = 0;
567                return *this;
568            }
569            r = value_type((calc_type(r) * a) >> base_shift);
570            g = value_type((calc_type(g) * a) >> base_shift);
571            b = value_type((calc_type(b) * a) >> base_shift);
572            return *this;
573        }
574
575        //--------------------------------------------------------------------
576        AGG_INLINE const self_type& premultiply(unsigned a_)
577        {
578            if(a == base_mask && a_ >= base_mask) return *this;
579            if(a == 0 || a_ == 0)
580            {
581                r = g = b = a = 0;
582                return *this;
583            }
584            calc_type r_ = (calc_type(r) * a_) / a;
585            calc_type g_ = (calc_type(g) * a_) / a;
586            calc_type b_ = (calc_type(b) * a_) / a;
587            r = value_type((r_ > a_) ? a_ : r_);
588            g = value_type((g_ > a_) ? a_ : g_);
589            b = value_type((b_ > a_) ? a_ : b_);
590            a = value_type(a_);
591            return *this;
592        }
593
594        //--------------------------------------------------------------------
595        AGG_INLINE const self_type& demultiply()
596        {
597            if(a == base_mask) return *this;
598            if(a == 0)
599            {
600                r = g = b = 0;
601                return *this;
602            }
603            calc_type r_ = (calc_type(r) * base_mask) / a;
604            calc_type g_ = (calc_type(g) * base_mask) / a;
605            calc_type b_ = (calc_type(b) * base_mask) / a;
606            r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
607            g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
608            b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
609            return *this;
610        }
611
612        //--------------------------------------------------------------------
613        AGG_INLINE self_type gradient(const self_type& c, double k) const
614        {
615            self_type ret;
616            calc_type ik = uround(k * base_scale);
617            ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
618            ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
619            ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
620            ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
621            return ret;
622        }
623
624        //--------------------------------------------------------------------
625        AGG_INLINE void add(const self_type& c, unsigned cover)
626        {
627            calc_type cr, cg, cb, ca;
628            if(cover == cover_mask)
629            {
630                if(c.a == base_mask)
631                {
632                    *this = c;
633                }
634                else
635                {
636                    cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
637                    cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
638                    cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
639                    ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
640                }
641            }
642            else
643            {
644                cr = r + ((c.r * cover + cover_mask) >> cover_shift);
645                cg = g + ((c.g * cover + cover_mask) >> cover_shift);
646                cb = b + ((c.b * cover + cover_mask) >> cover_shift);
647                ca = a + ((c.a * cover + cover_mask) >> cover_shift);
648                r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
649                g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
650                b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
651                a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
652            }
653        }
654
655        //--------------------------------------------------------------------
656        template<class GammaLUT>
657        AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
658        {
659            r = gamma.dir(r);
660            g = gamma.dir(g);
661            b = gamma.dir(b);
662        }
663
664        //--------------------------------------------------------------------
665        template<class GammaLUT>
666        AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
667        {
668            r = gamma.inv(r);
669            g = gamma.inv(g);
670            b = gamma.inv(b);
671        }
672
673        //--------------------------------------------------------------------
674        static self_type no_color() { return self_type(0,0,0,0); }
675
676        //--------------------------------------------------------------------
677        static self_type from_wavelength(double wl, double gamma = 1.0)
678        {
679            return self_type(rgba::from_wavelength(wl, gamma));
680        }
681    };
682
683
684
685    //--------------------------------------------------------------rgba16_pre
686    inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b,
687                             unsigned a = rgba16::base_mask)
688    {
689        return rgba16(r,g,b,a).premultiply();
690    }
691    inline rgba16 rgba16_pre(const rgba16& c, unsigned a)
692    {
693        return rgba16(c,a).premultiply();
694    }
695    inline rgba16 rgba16_pre(const rgba& c)
696    {
697        return rgba16(c).premultiply();
698    }
699    inline rgba16 rgba16_pre(const rgba& c, double a)
700    {
701        return rgba16(c,a).premultiply();
702    }
703    inline rgba16 rgba16_pre(const rgba8& c)
704    {
705        return rgba16(c).premultiply();
706    }
707    inline rgba16 rgba16_pre(const rgba8& c, unsigned a)
708    {
709        return rgba16(c,a).premultiply();
710    }
711
712}
713
714
715
716#endif
717