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#ifndef AGG_PIXFMT_RGB_PACKED_INCLUDED
25#define AGG_PIXFMT_RGB_PACKED_INCLUDED
26
27#include <string.h>
28#include "agg_basics.h"
29#include "agg_color_rgba.h"
30#include "agg_rendering_buffer.h"
31
32namespace agg
33{
34    //=========================================================blender_rgb555
35    struct blender_rgb555
36    {
37        typedef rgba8 color_type;
38        typedef color_type::value_type value_type;
39        typedef color_type::calc_type calc_type;
40        typedef int16u pixel_type;
41
42        static AGG_INLINE void blend_pix(pixel_type* p,
43                                         unsigned cr, unsigned cg, unsigned cb,
44                                         unsigned alpha,
45                                         unsigned)
46        {
47            pixel_type rgb = *p;
48            calc_type r = (rgb >> 7) & 0xF8;
49            calc_type g = (rgb >> 2) & 0xF8;
50            calc_type b = (rgb << 3) & 0xF8;
51            *p = (pixel_type)
52               (((((cr - r) * alpha + (r << 8)) >> 1)  & 0x7C00) |
53                ((((cg - g) * alpha + (g << 8)) >> 6)  & 0x03E0) |
54                 (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000);
55        }
56
57        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
58        {
59            return (pixel_type)(((r & 0xF8) << 7) |
60                                ((g & 0xF8) << 2) |
61                                 (b >> 3) | 0x8000);
62        }
63
64        static AGG_INLINE color_type make_color(pixel_type p)
65        {
66            return color_type((p >> 7) & 0xF8,
67                              (p >> 2) & 0xF8,
68                              (p << 3) & 0xF8);
69        }
70    };
71
72
73    //=====================================================blender_rgb555_pre
74    struct blender_rgb555_pre
75    {
76        typedef rgba8 color_type;
77        typedef color_type::value_type value_type;
78        typedef color_type::calc_type calc_type;
79        typedef int16u pixel_type;
80
81        static AGG_INLINE void blend_pix(pixel_type* p,
82                                         unsigned cr, unsigned cg, unsigned cb,
83                                         unsigned alpha,
84                                         unsigned cover)
85        {
86            alpha = color_type::base_mask - alpha;
87            pixel_type rgb = *p;
88            calc_type r = (rgb >> 7) & 0xF8;
89            calc_type g = (rgb >> 2) & 0xF8;
90            calc_type b = (rgb << 3) & 0xF8;
91            *p = (pixel_type)
92               ((((r * alpha + cr * cover) >> 1)  & 0x7C00) |
93                (((g * alpha + cg * cover) >> 6)  & 0x03E0) |
94                 ((b * alpha + cb * cover) >> 11) | 0x8000);
95        }
96
97        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
98        {
99            return (pixel_type)(((r & 0xF8) << 7) |
100                                ((g & 0xF8) << 2) |
101                                 (b >> 3) | 0x8000);
102        }
103
104        static AGG_INLINE color_type make_color(pixel_type p)
105        {
106            return color_type((p >> 7) & 0xF8,
107                              (p >> 2) & 0xF8,
108                              (p << 3) & 0xF8);
109        }
110    };
111
112
113
114
115    //=====================================================blender_rgb555_gamma
116    template<class Gamma> class blender_rgb555_gamma
117    {
118    public:
119        typedef rgba8 color_type;
120        typedef color_type::value_type value_type;
121        typedef color_type::calc_type calc_type;
122        typedef int16u pixel_type;
123        typedef Gamma gamma_type;
124
125        blender_rgb555_gamma() : m_gamma(0) {}
126        void gamma(const gamma_type& g) { m_gamma = &g; }
127
128        AGG_INLINE void blend_pix(pixel_type* p,
129                                  unsigned cr, unsigned cg, unsigned cb,
130                                  unsigned alpha,
131                                  unsigned)
132        {
133            pixel_type rgb = *p;
134            calc_type r = m_gamma->dir((rgb >> 7) & 0xF8);
135            calc_type g = m_gamma->dir((rgb >> 2) & 0xF8);
136            calc_type b = m_gamma->dir((rgb << 3) & 0xF8);
137            *p = (pixel_type)
138               (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) |
139                ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) |
140                 (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000);
141        }
142
143        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
144        {
145            return (pixel_type)(((r & 0xF8) << 7) |
146                                ((g & 0xF8) << 2) |
147                                 (b >> 3) | 0x8000);
148        }
149
150        static AGG_INLINE color_type make_color(pixel_type p)
151        {
152            return color_type((p >> 7) & 0xF8,
153                              (p >> 2) & 0xF8,
154                              (p << 3) & 0xF8);
155        }
156
157    private:
158        const Gamma* m_gamma;
159    };
160
161
162
163
164
165    //=========================================================blender_rgb565
166    struct blender_rgb565
167    {
168        typedef rgba8 color_type;
169        typedef color_type::value_type value_type;
170        typedef color_type::calc_type calc_type;
171        typedef int16u pixel_type;
172
173        static AGG_INLINE void blend_pix(pixel_type* p,
174                                         unsigned cr, unsigned cg, unsigned cb,
175                                         unsigned alpha,
176                                         unsigned)
177        {
178            pixel_type rgb = *p;
179            calc_type r = (rgb >> 8) & 0xF8;
180            calc_type g = (rgb >> 3) & 0xFC;
181            calc_type b = (rgb << 3) & 0xF8;
182            *p = (pixel_type)
183               (((((cr - r) * alpha + (r << 8))     ) & 0xF800) |
184                ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) |
185                 (((cb - b) * alpha + (b << 8)) >> 11));
186        }
187
188        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
189        {
190            return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
191        }
192
193        static AGG_INLINE color_type make_color(pixel_type p)
194        {
195            return color_type((p >> 8) & 0xF8,
196                              (p >> 3) & 0xFC,
197                              (p << 3) & 0xF8);
198        }
199    };
200
201
202
203    //=====================================================blender_rgb565_pre
204    struct blender_rgb565_pre
205    {
206        typedef rgba8 color_type;
207        typedef color_type::value_type value_type;
208        typedef color_type::calc_type calc_type;
209        typedef int16u pixel_type;
210
211        static AGG_INLINE void blend_pix(pixel_type* p,
212                                         unsigned cr, unsigned cg, unsigned cb,
213                                         unsigned alpha,
214                                         unsigned cover)
215        {
216            alpha = color_type::base_mask - alpha;
217            pixel_type rgb = *p;
218            calc_type r = (rgb >> 8) & 0xF8;
219            calc_type g = (rgb >> 3) & 0xFC;
220            calc_type b = (rgb << 3) & 0xF8;
221            *p = (pixel_type)
222               ((((r * alpha + cr * cover)      ) & 0xF800) |
223                (((g * alpha + cg * cover) >> 5 ) & 0x07E0) |
224                 ((b * alpha + cb * cover) >> 11));
225        }
226
227        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
228        {
229            return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
230        }
231
232        static AGG_INLINE color_type make_color(pixel_type p)
233        {
234            return color_type((p >> 8) & 0xF8,
235                              (p >> 3) & 0xFC,
236                              (p << 3) & 0xF8);
237        }
238    };
239
240
241
242    //=====================================================blender_rgb565_gamma
243    template<class Gamma> class blender_rgb565_gamma
244    {
245    public:
246        typedef rgba8 color_type;
247        typedef color_type::value_type value_type;
248        typedef color_type::calc_type calc_type;
249        typedef int16u pixel_type;
250        typedef Gamma gamma_type;
251
252        blender_rgb565_gamma() : m_gamma(0) {}
253        void gamma(const gamma_type& g) { m_gamma = &g; }
254
255        AGG_INLINE void blend_pix(pixel_type* p,
256                                  unsigned cr, unsigned cg, unsigned cb,
257                                  unsigned alpha,
258                                  unsigned)
259        {
260            pixel_type rgb = *p;
261            calc_type r = m_gamma->dir((rgb >> 8) & 0xF8);
262            calc_type g = m_gamma->dir((rgb >> 3) & 0xFC);
263            calc_type b = m_gamma->dir((rgb << 3) & 0xF8);
264            *p = (pixel_type)
265               (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) |
266                ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) |
267                 (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3));
268        }
269
270        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
271        {
272            return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
273        }
274
275        static AGG_INLINE color_type make_color(pixel_type p)
276        {
277            return color_type((p >> 8) & 0xF8,
278                              (p >> 3) & 0xFC,
279                              (p << 3) & 0xF8);
280        }
281
282    private:
283        const Gamma* m_gamma;
284    };
285
286
287
288    //=====================================================blender_rgbAAA
289    struct blender_rgbAAA
290    {
291        typedef rgba16 color_type;
292        typedef color_type::value_type value_type;
293        typedef color_type::calc_type calc_type;
294        typedef int32u pixel_type;
295
296        static AGG_INLINE void blend_pix(pixel_type* p,
297                                         unsigned cr, unsigned cg, unsigned cb,
298                                         unsigned alpha,
299                                         unsigned)
300        {
301            pixel_type rgb = *p;
302            calc_type r = (rgb >> 14) & 0xFFC0;
303            calc_type g = (rgb >> 4)  & 0xFFC0;
304            calc_type b = (rgb << 6)  & 0xFFC0;
305            *p = (pixel_type)
306               (((((cr - r) * alpha + (r << 16)) >> 2)  & 0x3FF00000) |
307                ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) |
308                 (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000);
309        }
310
311        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
312        {
313            return (pixel_type)(((r & 0xFFC0) << 14) |
314                                ((g & 0xFFC0) << 4) |
315                                 (b >> 6) | 0xC0000000);
316        }
317
318        static AGG_INLINE color_type make_color(pixel_type p)
319        {
320            return color_type((p >> 14) & 0xFFC0,
321                              (p >> 4)  & 0xFFC0,
322                              (p << 6)  & 0xFFC0);
323        }
324    };
325
326
327
328    //==================================================blender_rgbAAA_pre
329    struct blender_rgbAAA_pre
330    {
331        typedef rgba16 color_type;
332        typedef color_type::value_type value_type;
333        typedef color_type::calc_type calc_type;
334        typedef int32u pixel_type;
335
336        static AGG_INLINE void blend_pix(pixel_type* p,
337                                         unsigned cr, unsigned cg, unsigned cb,
338                                         unsigned alpha,
339                                         unsigned cover)
340        {
341            alpha = color_type::base_mask - alpha;
342            cover = (cover + 1) << (color_type::base_shift - 8);
343            pixel_type rgb = *p;
344            calc_type r = (rgb >> 14) & 0xFFC0;
345            calc_type g = (rgb >> 4)  & 0xFFC0;
346            calc_type b = (rgb << 6)  & 0xFFC0;
347            *p = (pixel_type)
348               ((((r * alpha + cr * cover) >> 2)  & 0x3FF00000) |
349                (((g * alpha + cg * cover) >> 12) & 0x000FFC00) |
350                 ((b * alpha + cb * cover) >> 22) | 0xC0000000);
351        }
352
353        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
354        {
355            return (pixel_type)(((r & 0xFFC0) << 14) |
356                                ((g & 0xFFC0) << 4) |
357                                 (b >> 6) | 0xC0000000);
358        }
359
360        static AGG_INLINE color_type make_color(pixel_type p)
361        {
362            return color_type((p >> 14) & 0xFFC0,
363                              (p >> 4)  & 0xFFC0,
364                              (p << 6)  & 0xFFC0);
365        }
366    };
367
368
369
370    //=================================================blender_rgbAAA_gamma
371    template<class Gamma> class blender_rgbAAA_gamma
372    {
373    public:
374        typedef rgba16 color_type;
375        typedef color_type::value_type value_type;
376        typedef color_type::calc_type calc_type;
377        typedef int32u pixel_type;
378        typedef Gamma gamma_type;
379
380        blender_rgbAAA_gamma() : m_gamma(0) {}
381        void gamma(const gamma_type& g) { m_gamma = &g; }
382
383        AGG_INLINE void blend_pix(pixel_type* p,
384                                  unsigned cr, unsigned cg, unsigned cb,
385                                  unsigned alpha,
386                                  unsigned)
387        {
388            pixel_type rgb = *p;
389            calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0);
390            calc_type g = m_gamma->dir((rgb >> 4)  & 0xFFC0);
391            calc_type b = m_gamma->dir((rgb << 6)  & 0xFFC0);
392            *p = (pixel_type)
393               (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) |
394                ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) |
395                 (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000);
396        }
397
398        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
399        {
400            return (pixel_type)(((r & 0xFFC0) << 14) |
401                                ((g & 0xFFC0) << 4) |
402                                 (b >> 6) | 0xC0000000);
403        }
404
405        static AGG_INLINE color_type make_color(pixel_type p)
406        {
407            return color_type((p >> 14) & 0xFFC0,
408                              (p >> 4)  & 0xFFC0,
409                              (p << 6)  & 0xFFC0);
410        }
411    private:
412        const Gamma* m_gamma;
413    };
414
415
416    //=====================================================blender_bgrAAA
417    struct blender_bgrAAA
418    {
419        typedef rgba16 color_type;
420        typedef color_type::value_type value_type;
421        typedef color_type::calc_type calc_type;
422        typedef int32u pixel_type;
423
424        static AGG_INLINE void blend_pix(pixel_type* p,
425                                         unsigned cr, unsigned cg, unsigned cb,
426                                         unsigned alpha,
427                                         unsigned)
428        {
429            pixel_type bgr = *p;
430            calc_type b = (bgr >> 14) & 0xFFC0;
431            calc_type g = (bgr >> 4)  & 0xFFC0;
432            calc_type r = (bgr << 6)  & 0xFFC0;
433            *p = (pixel_type)
434               (((((cb - b) * alpha + (b << 16)) >> 2)  & 0x3FF00000) |
435                ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) |
436                 (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000);
437        }
438
439        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
440        {
441            return (pixel_type)(((b & 0xFFC0) << 14) |
442                                ((g & 0xFFC0) << 4) |
443                                 (r >> 6) | 0xC0000000);
444        }
445
446        static AGG_INLINE color_type make_color(pixel_type p)
447        {
448            return color_type((p << 6)  & 0xFFC0,
449                              (p >> 4)  & 0xFFC0,
450                              (p >> 14) & 0xFFC0);
451        }
452    };
453
454
455
456    //=================================================blender_bgrAAA_pre
457    struct blender_bgrAAA_pre
458    {
459        typedef rgba16 color_type;
460        typedef color_type::value_type value_type;
461        typedef color_type::calc_type calc_type;
462        typedef int32u pixel_type;
463
464        static AGG_INLINE void blend_pix(pixel_type* p,
465                                         unsigned cr, unsigned cg, unsigned cb,
466                                         unsigned alpha,
467                                         unsigned cover)
468        {
469            alpha = color_type::base_mask - alpha;
470            cover = (cover + 1) << (color_type::base_shift - 8);
471            pixel_type bgr = *p;
472            calc_type b = (bgr >> 14) & 0xFFC0;
473            calc_type g = (bgr >> 4)  & 0xFFC0;
474            calc_type r = (bgr << 6)  & 0xFFC0;
475            *p = (pixel_type)
476               ((((b * alpha + cb * cover) >> 2)  & 0x3FF00000) |
477                (((g * alpha + cg * cover) >> 12) & 0x000FFC00) |
478                 ((r * alpha + cr * cover) >> 22) | 0xC0000000);
479        }
480
481        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
482        {
483            return (pixel_type)(((b & 0xFFC0) << 14) |
484                                ((g & 0xFFC0) << 4) |
485                                 (r >> 6) | 0xC0000000);
486        }
487
488        static AGG_INLINE color_type make_color(pixel_type p)
489        {
490            return color_type((p << 6)  & 0xFFC0,
491                              (p >> 4)  & 0xFFC0,
492                              (p >> 14) & 0xFFC0);
493        }
494    };
495
496
497
498    //=================================================blender_bgrAAA_gamma
499    template<class Gamma> class blender_bgrAAA_gamma
500    {
501    public:
502        typedef rgba16 color_type;
503        typedef color_type::value_type value_type;
504        typedef color_type::calc_type calc_type;
505        typedef int32u pixel_type;
506        typedef Gamma gamma_type;
507
508        blender_bgrAAA_gamma() : m_gamma(0) {}
509        void gamma(const gamma_type& g) { m_gamma = &g; }
510
511        AGG_INLINE void blend_pix(pixel_type* p,
512                                  unsigned cr, unsigned cg, unsigned cb,
513                                  unsigned alpha,
514                                  unsigned)
515        {
516            pixel_type bgr = *p;
517            calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0);
518            calc_type g = m_gamma->dir((bgr >> 4)  & 0xFFC0);
519            calc_type r = m_gamma->dir((bgr << 6)  & 0xFFC0);
520            *p = (pixel_type)
521               (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) |
522                ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) |
523                 (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000);
524        }
525
526        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
527        {
528            return (pixel_type)(((b & 0xFFC0) << 14) |
529                                ((g & 0xFFC0) << 4) |
530                                 (r >> 6) | 0xC0000000);
531        }
532
533        static AGG_INLINE color_type make_color(pixel_type p)
534        {
535            return color_type((p << 6)  & 0xFFC0,
536                              (p >> 4)  & 0xFFC0,
537                              (p >> 14) & 0xFFC0);
538        }
539
540    private:
541        const Gamma* m_gamma;
542    };
543
544
545
546    //=====================================================blender_rgbBBA
547    struct blender_rgbBBA
548    {
549        typedef rgba16 color_type;
550        typedef color_type::value_type value_type;
551        typedef color_type::calc_type calc_type;
552        typedef int32u pixel_type;
553
554        static AGG_INLINE void blend_pix(pixel_type* p,
555                                         unsigned cr, unsigned cg, unsigned cb,
556                                         unsigned alpha,
557                                         unsigned)
558        {
559            pixel_type rgb = *p;
560            calc_type r = (rgb >> 16) & 0xFFE0;
561            calc_type g = (rgb >> 5)  & 0xFFE0;
562            calc_type b = (rgb << 6)  & 0xFFC0;
563            *p = (pixel_type)
564               (((((cr - r) * alpha + (r << 16))      ) & 0xFFE00000) |
565                ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) |
566                 (((cb - b) * alpha + (b << 16)) >> 22));
567        }
568
569        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
570        {
571            return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
572        }
573
574        static AGG_INLINE color_type make_color(pixel_type p)
575        {
576            return color_type((p >> 16) & 0xFFE0,
577                              (p >> 5)  & 0xFFE0,
578                              (p << 6)  & 0xFFC0);
579        }
580    };
581
582
583    //=================================================blender_rgbBBA_pre
584    struct blender_rgbBBA_pre
585    {
586        typedef rgba16 color_type;
587        typedef color_type::value_type value_type;
588        typedef color_type::calc_type calc_type;
589        typedef int32u pixel_type;
590
591        static AGG_INLINE void blend_pix(pixel_type* p,
592                                         unsigned cr, unsigned cg, unsigned cb,
593                                         unsigned alpha,
594                                         unsigned cover)
595        {
596            alpha = color_type::base_mask - alpha;
597            cover = (cover + 1) << (color_type::base_shift - 8);
598            pixel_type rgb = *p;
599            calc_type r = (rgb >> 16) & 0xFFE0;
600            calc_type g = (rgb >> 5)  & 0xFFE0;
601            calc_type b = (rgb << 6)  & 0xFFC0;
602            *p = (pixel_type)
603               ((((r * alpha + cr * cover)      ) & 0xFFE00000) |
604                (((g * alpha + cg * cover) >> 11) & 0x001FFC00) |
605                 ((b * alpha + cb * cover) >> 22));
606        }
607
608        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
609        {
610            return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
611        }
612
613        static AGG_INLINE color_type make_color(pixel_type p)
614        {
615            return color_type((p >> 16) & 0xFFE0,
616                              (p >> 5)  & 0xFFE0,
617                              (p << 6)  & 0xFFC0);
618        }
619    };
620
621
622
623    //=================================================blender_rgbBBA_gamma
624    template<class Gamma> class blender_rgbBBA_gamma
625    {
626    public:
627        typedef rgba16 color_type;
628        typedef color_type::value_type value_type;
629        typedef color_type::calc_type calc_type;
630        typedef int32u pixel_type;
631        typedef Gamma gamma_type;
632
633        blender_rgbBBA_gamma() : m_gamma(0) {}
634        void gamma(const gamma_type& g) { m_gamma = &g; }
635
636        AGG_INLINE void blend_pix(pixel_type* p,
637                                  unsigned cr, unsigned cg, unsigned cb,
638                                  unsigned alpha,
639                                  unsigned)
640        {
641            pixel_type rgb = *p;
642            calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0);
643            calc_type g = m_gamma->dir((rgb >> 5)  & 0xFFE0);
644            calc_type b = m_gamma->dir((rgb << 6)  & 0xFFC0);
645            *p = (pixel_type)
646               (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) |
647                ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) |
648                 (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ));
649        }
650
651        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
652        {
653            return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6));
654        }
655
656        static AGG_INLINE color_type make_color(pixel_type p)
657        {
658            return color_type((p >> 16) & 0xFFE0,
659                              (p >> 5)  & 0xFFE0,
660                              (p << 6)  & 0xFFC0);
661        }
662
663    private:
664        const Gamma* m_gamma;
665    };
666
667
668    //=====================================================blender_bgrABB
669    struct blender_bgrABB
670    {
671        typedef rgba16 color_type;
672        typedef color_type::value_type value_type;
673        typedef color_type::calc_type calc_type;
674        typedef int32u pixel_type;
675
676        static AGG_INLINE void blend_pix(pixel_type* p,
677                                         unsigned cr, unsigned cg, unsigned cb,
678                                         unsigned alpha,
679                                         unsigned)
680        {
681            pixel_type bgr = *p;
682            calc_type b = (bgr >> 16) & 0xFFC0;
683            calc_type g = (bgr >> 6)  & 0xFFE0;
684            calc_type r = (bgr << 5)  & 0xFFE0;
685            *p = (pixel_type)
686               (((((cb - b) * alpha + (b << 16))      ) & 0xFFC00000) |
687                ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) |
688                 (((cr - r) * alpha + (r << 16)) >> 21));
689        }
690
691        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
692        {
693            return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
694        }
695
696        static AGG_INLINE color_type make_color(pixel_type p)
697        {
698            return color_type((p << 5)  & 0xFFE0,
699                              (p >> 6)  & 0xFFE0,
700                              (p >> 16) & 0xFFC0);
701        }
702    };
703
704
705    //=================================================blender_bgrABB_pre
706    struct blender_bgrABB_pre
707    {
708        typedef rgba16 color_type;
709        typedef color_type::value_type value_type;
710        typedef color_type::calc_type calc_type;
711        typedef int32u pixel_type;
712
713        static AGG_INLINE void blend_pix(pixel_type* p,
714                                         unsigned cr, unsigned cg, unsigned cb,
715                                         unsigned alpha,
716                                         unsigned cover)
717        {
718            alpha = color_type::base_mask - alpha;
719            cover = (cover + 1) << (color_type::base_shift - 8);
720            pixel_type bgr = *p;
721            calc_type b = (bgr >> 16) & 0xFFC0;
722            calc_type g = (bgr >> 6)  & 0xFFE0;
723            calc_type r = (bgr << 5)  & 0xFFE0;
724            *p = (pixel_type)
725               ((((b * alpha + cb * cover)      ) & 0xFFC00000) |
726                (((g * alpha + cg * cover) >> 10) & 0x003FF800) |
727                 ((r * alpha + cr * cover) >> 21));
728        }
729
730        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
731        {
732            return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
733        }
734
735        static AGG_INLINE color_type make_color(pixel_type p)
736        {
737            return color_type((p << 5)  & 0xFFE0,
738                              (p >> 6)  & 0xFFE0,
739                              (p >> 16) & 0xFFC0);
740        }
741    };
742
743
744
745    //=================================================blender_bgrABB_gamma
746    template<class Gamma> class blender_bgrABB_gamma
747    {
748    public:
749        typedef rgba16 color_type;
750        typedef color_type::value_type value_type;
751        typedef color_type::calc_type calc_type;
752        typedef int32u pixel_type;
753        typedef Gamma gamma_type;
754
755        blender_bgrABB_gamma() : m_gamma(0) {}
756        void gamma(const gamma_type& g) { m_gamma = &g; }
757
758        AGG_INLINE void blend_pix(pixel_type* p,
759                                  unsigned cr, unsigned cg, unsigned cb,
760                                  unsigned alpha,
761                                  unsigned)
762        {
763            pixel_type bgr = *p;
764            calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0);
765            calc_type g = m_gamma->dir((bgr >> 6)  & 0xFFE0);
766            calc_type r = m_gamma->dir((bgr << 5)  & 0xFFE0);
767            *p = (pixel_type)
768               (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) |
769                ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) |
770                 (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 ));
771        }
772
773        static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
774        {
775            return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5));
776        }
777
778        static AGG_INLINE color_type make_color(pixel_type p)
779        {
780            return color_type((p << 5)  & 0xFFE0,
781                              (p >> 6)  & 0xFFE0,
782                              (p >> 16) & 0xFFC0);
783        }
784
785    private:
786        const Gamma* m_gamma;
787    };
788
789
790
791    //===========================================pixfmt_alpha_blend_rgb_packed
792    template<class Blender,  class RenBuf> class pixfmt_alpha_blend_rgb_packed
793    {
794    public:
795        typedef RenBuf   rbuf_type;
796        typedef typename rbuf_type::row_data row_data;
797        typedef Blender  blender_type;
798        typedef typename blender_type::color_type color_type;
799        typedef typename blender_type::pixel_type pixel_type;
800        typedef int                               order_type; // A fake one
801        typedef typename color_type::value_type   value_type;
802        typedef typename color_type::calc_type    calc_type;
803        enum base_scale_e
804        {
805            base_shift = color_type::base_shift,
806            base_scale = color_type::base_scale,
807            base_mask  = color_type::base_mask,
808            pix_width  = sizeof(pixel_type)
809        };
810
811    private:
812        //--------------------------------------------------------------------
813        AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
814        {
815            if (c.a)
816            {
817                calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
818                if(alpha == base_mask)
819                {
820                    *p = m_blender.make_pix(c.r, c.g, c.b);
821                }
822                else
823                {
824                    m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
825                }
826            }
827        }
828
829    public:
830        //--------------------------------------------------------------------
831        pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {}
832        void attach(rbuf_type& rb) { m_rbuf = &rb; }
833
834        //--------------------------------------------------------------------
835        template<class PixFmt>
836        bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
837        {
838            rect_i r(x1, y1, x2, y2);
839            if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
840            {
841                int stride = pixf.stride();
842                m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
843                               (r.x2 - r.x1) + 1,
844                               (r.y2 - r.y1) + 1,
845                               stride);
846                return true;
847            }
848            return false;
849        }
850
851        Blender& blender() { return m_blender; }
852
853        //--------------------------------------------------------------------
854        AGG_INLINE unsigned width()  const { return m_rbuf->width();  }
855        AGG_INLINE unsigned height() const { return m_rbuf->height(); }
856        AGG_INLINE int      stride() const { return m_rbuf->stride(); }
857
858        //--------------------------------------------------------------------
859        AGG_INLINE       int8u* row_ptr(int y)       { return m_rbuf->row_ptr(y); }
860        AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
861        AGG_INLINE row_data     row(int y)     const { return m_rbuf->row(y); }
862
863        //--------------------------------------------------------------------
864        AGG_INLINE int8u* pix_ptr(int x, int y)
865        {
866            return m_rbuf->row_ptr(y) + x * pix_width;
867        }
868
869        AGG_INLINE const int8u* pix_ptr(int x, int y) const
870        {
871            return m_rbuf->row_ptr(y) + x * pix_width;
872        }
873
874        //--------------------------------------------------------------------
875        AGG_INLINE void make_pix(int8u* p, const color_type& c)
876        {
877            *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b);
878        }
879
880        //--------------------------------------------------------------------
881        AGG_INLINE color_type pixel(int x, int y) const
882        {
883            return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]);
884        }
885
886        //--------------------------------------------------------------------
887        AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
888        {
889            ((pixel_type*)
890                m_rbuf->row_ptr(x, y, 1))[x] =
891                    m_blender.make_pix(c.r, c.g, c.b);
892        }
893
894        //--------------------------------------------------------------------
895        AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
896        {
897            copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover);
898        }
899
900        //--------------------------------------------------------------------
901        AGG_INLINE void copy_hline(int x, int y,
902                                   unsigned len,
903                                   const color_type& c)
904        {
905            pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
906            pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
907            do
908            {
909                *p++ = v;
910            }
911            while(--len);
912        }
913
914        //--------------------------------------------------------------------
915        AGG_INLINE void copy_vline(int x, int y,
916                                   unsigned len,
917                                   const color_type& c)
918        {
919            pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
920            do
921            {
922                pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x;
923                *p = v;
924            }
925            while(--len);
926        }
927
928        //--------------------------------------------------------------------
929        void blend_hline(int x, int y,
930                         unsigned len,
931                         const color_type& c,
932                         int8u cover)
933        {
934            if (c.a)
935            {
936                pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
937                calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
938                if(alpha == base_mask)
939                {
940                    pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
941                    do
942                    {
943                        *p++ = v;
944                    }
945                    while(--len);
946                }
947                else
948                {
949                    do
950                    {
951                        m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
952                        ++p;
953                    }
954                    while(--len);
955                }
956            }
957        }
958
959        //--------------------------------------------------------------------
960        void blend_vline(int x, int y,
961                         unsigned len,
962                         const color_type& c,
963                         int8u cover)
964        {
965            if (c.a)
966            {
967                calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
968                if(alpha == base_mask)
969                {
970                    pixel_type v = m_blender.make_pix(c.r, c.g, c.b);
971                    do
972                    {
973                        ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v;
974                    }
975                    while(--len);
976                }
977                else
978                {
979                    do
980                    {
981                        m_blender.blend_pix(
982                            (pixel_type*)m_rbuf->row_ptr(x, y++, 1),
983                            c.r, c.g, c.b, alpha, cover);
984                    }
985                    while(--len);
986                }
987            }
988        }
989
990        //--------------------------------------------------------------------
991        void blend_solid_hspan(int x, int y,
992                               unsigned len,
993                               const color_type& c,
994                               const int8u* covers)
995        {
996            pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
997            do
998            {
999                copy_or_blend_pix(p, c, *covers++);
1000                ++p;
1001            }
1002            while(--len);
1003        }
1004
1005        //--------------------------------------------------------------------
1006        void blend_solid_vspan(int x, int y,
1007                               unsigned len,
1008                               const color_type& c,
1009                               const int8u* covers)
1010        {
1011            do
1012            {
1013                copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x,
1014                                  c, *covers++);
1015            }
1016            while(--len);
1017        }
1018
1019        //--------------------------------------------------------------------
1020        void copy_color_hspan(int x, int y,
1021                              unsigned len,
1022                              const color_type* colors)
1023        {
1024            pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
1025            do
1026            {
1027                *p++ = m_blender.make_pix(colors->r, colors->g, colors->b);
1028                ++colors;
1029            }
1030            while(--len);
1031        }
1032
1033        //--------------------------------------------------------------------
1034        void copy_color_vspan(int x, int y,
1035                              unsigned len,
1036                              const color_type* colors)
1037        {
1038            do
1039            {
1040                pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x;
1041                *p = m_blender.make_pix(colors->r, colors->g, colors->b);
1042                ++colors;
1043            }
1044            while(--len);
1045        }
1046
1047        //--------------------------------------------------------------------
1048        void blend_color_hspan(int x, int y,
1049                               unsigned len,
1050                               const color_type* colors,
1051                               const int8u* covers,
1052                               int8u cover)
1053        {
1054            pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x;
1055            do
1056            {
1057                copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover);
1058            }
1059            while(--len);
1060        }
1061
1062        //--------------------------------------------------------------------
1063        void blend_color_vspan(int x, int y,
1064                               unsigned len,
1065                               const color_type* colors,
1066                               const int8u* covers,
1067                               int8u cover)
1068        {
1069            do
1070            {
1071                copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x,
1072                                  *colors++, covers ? *covers++ : cover);
1073            }
1074            while(--len);
1075        }
1076
1077        //--------------------------------------------------------------------
1078        template<class RenBuf2>
1079        void copy_from(const RenBuf2& from,
1080                       int xdst, int ydst,
1081                       int xsrc, int ysrc,
1082                       unsigned len)
1083        {
1084            const int8u* p = from.row_ptr(ysrc);
1085            if(p)
1086            {
1087                memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
1088                        p + xsrc * pix_width,
1089                        len * pix_width);
1090            }
1091        }
1092
1093        //--------------------------------------------------------------------
1094        template<class SrcPixelFormatRenderer>
1095        void blend_from(const SrcPixelFormatRenderer& from,
1096                        int xdst, int ydst,
1097                        int xsrc, int ysrc,
1098                        unsigned len,
1099                        int8u cover)
1100        {
1101            typedef typename SrcPixelFormatRenderer::order_type src_order;
1102
1103            const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
1104            if(psrc)
1105            {
1106                psrc += xsrc * 4;
1107                pixel_type* pdst =
1108                    (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
1109                do
1110                {
1111                    value_type alpha = psrc[src_order::A];
1112                    if(alpha)
1113                    {
1114                        if(alpha == base_mask && cover == 255)
1115                        {
1116                            *pdst = m_blender.make_pix(psrc[src_order::R],
1117                                                       psrc[src_order::G],
1118                                                       psrc[src_order::B]);
1119                        }
1120                        else
1121                        {
1122                            m_blender.blend_pix(pdst,
1123                                                psrc[src_order::R],
1124                                                psrc[src_order::G],
1125                                                psrc[src_order::B],
1126                                                alpha,
1127                                                cover);
1128                        }
1129                    }
1130                    psrc += 4;
1131                    ++pdst;
1132                }
1133                while(--len);
1134            }
1135        }
1136
1137    private:
1138        rbuf_type* m_rbuf;
1139        Blender    m_blender;
1140    };
1141
1142    typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555, rendering_buffer> pixfmt_rgb555; //----pixfmt_rgb555
1143    typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565, rendering_buffer> pixfmt_rgb565; //----pixfmt_rgb565
1144
1145    typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555_pre, rendering_buffer> pixfmt_rgb555_pre; //----pixfmt_rgb555_pre
1146    typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565_pre, rendering_buffer> pixfmt_rgb565_pre; //----pixfmt_rgb565_pre
1147
1148    typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA, rendering_buffer> pixfmt_rgbAAA; //----pixfmt_rgbAAA
1149    typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA, rendering_buffer> pixfmt_bgrAAA; //----pixfmt_bgrAAA
1150    typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA, rendering_buffer> pixfmt_rgbBBA; //----pixfmt_rgbBBA
1151    typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB, rendering_buffer> pixfmt_bgrABB; //----pixfmt_bgrABB
1152
1153    typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_pre, rendering_buffer> pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre
1154    typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_pre, rendering_buffer> pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre
1155    typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_pre, rendering_buffer> pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre
1156    typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB_pre, rendering_buffer> pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre
1157
1158
1159    //-----------------------------------------------------pixfmt_rgb555_gamma
1160    template<class Gamma> class pixfmt_rgb555_gamma :
1161    public pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>,
1162                                         rendering_buffer>
1163    {
1164    public:
1165        pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) :
1166            pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>,
1167                                          rendering_buffer>(rb)
1168        {
1169            this->blender().gamma(g);
1170        }
1171    };
1172
1173
1174    //-----------------------------------------------------pixfmt_rgb565_gamma
1175    template<class Gamma> class pixfmt_rgb565_gamma :
1176    public pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>
1177    {
1178    public:
1179        pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) :
1180            pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>(rb)
1181        {
1182            this->blender().gamma(g);
1183        }
1184    };
1185
1186
1187    //-----------------------------------------------------pixfmt_rgbAAA_gamma
1188    template<class Gamma> class pixfmt_rgbAAA_gamma :
1189    public pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>,
1190                                         rendering_buffer>
1191    {
1192    public:
1193        pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) :
1194            pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>,
1195                                          rendering_buffer>(rb)
1196        {
1197            this->blender().gamma(g);
1198        }
1199    };
1200
1201
1202    //-----------------------------------------------------pixfmt_bgrAAA_gamma
1203    template<class Gamma> class pixfmt_bgrAAA_gamma :
1204    public pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>,
1205                                         rendering_buffer>
1206    {
1207    public:
1208        pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) :
1209            pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>,
1210                                          rendering_buffer>(rb)
1211        {
1212            this->blender().gamma(g);
1213        }
1214    };
1215
1216
1217    //-----------------------------------------------------pixfmt_rgbBBA_gamma
1218    template<class Gamma> class pixfmt_rgbBBA_gamma :
1219    public pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>,
1220                                         rendering_buffer>
1221    {
1222    public:
1223        pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) :
1224            pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>,
1225                                          rendering_buffer>(rb)
1226        {
1227            this->blender().gamma(g);
1228        }
1229    };
1230
1231
1232    //-----------------------------------------------------pixfmt_bgrABB_gamma
1233    template<class Gamma> class pixfmt_bgrABB_gamma :
1234    public pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>,
1235                                         rendering_buffer>
1236    {
1237    public:
1238        pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) :
1239            pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>,
1240                                          rendering_buffer>(rb)
1241        {
1242            this->blender().gamma(g);
1243        }
1244    };
1245
1246
1247}
1248
1249#endif
1250
1251