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// scanline_u8 class
17//
18//----------------------------------------------------------------------------
19#ifndef AGG_ALPHA_MASK_U8_INCLUDED
20#define AGG_ALPHA_MASK_U8_INCLUDED
21
22#include <string.h>
23#include "agg_basics.h"
24#include "agg_rendering_buffer.h"
25
26namespace agg
27{
28    //===================================================one_component_mask_u8
29    struct one_component_mask_u8
30    {
31        static unsigned calculate(const int8u* p) { return *p; }
32    };
33
34
35    //=====================================================rgb_to_gray_mask_u8
36    template<unsigned R, unsigned G, unsigned B>
37    struct rgb_to_gray_mask_u8
38    {
39        static unsigned calculate(const int8u* p)
40        {
41            return (p[R]*77 + p[G]*150 + p[B]*29) >> 8;
42        }
43    };
44
45    //==========================================================alpha_mask_u8
46    template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
47    class alpha_mask_u8
48    {
49    public:
50        typedef int8u cover_type;
51        typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
52        enum cover_scale_e
53        {
54            cover_shift = 8,
55            cover_none  = 0,
56            cover_full  = 255
57        };
58
59        alpha_mask_u8() : m_rbuf(0) {}
60        alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
61
62        void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
63
64        MaskF& mask_function() { return m_mask_function; }
65        const MaskF& mask_function() const { return m_mask_function; }
66
67
68        //--------------------------------------------------------------------
69        cover_type pixel(int x, int y) const
70        {
71            if(x >= 0 && y >= 0 &&
72               x < (int)m_rbuf->width() &&
73               y < (int)m_rbuf->height())
74            {
75                return (cover_type)m_mask_function.calculate(
76                                        m_rbuf->row_ptr(y) + x * Step + Offset);
77            }
78            return 0;
79        }
80
81        //--------------------------------------------------------------------
82        cover_type combine_pixel(int x, int y, cover_type val) const
83        {
84            if(x >= 0 && y >= 0 &&
85               x < (int)m_rbuf->width() &&
86               y < (int)m_rbuf->height())
87            {
88                return (cover_type)((cover_full + val *
89                                     m_mask_function.calculate(
90                                        m_rbuf->row_ptr(y) + x * Step + Offset)) >>
91                                     cover_shift);
92            }
93            return 0;
94        }
95
96
97        //--------------------------------------------------------------------
98        void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
99        {
100            int xmax = m_rbuf->width() - 1;
101            int ymax = m_rbuf->height() - 1;
102
103            int count = num_pix;
104            cover_type* covers = dst;
105
106            if(y < 0 || y > ymax)
107            {
108                memset(dst, 0, num_pix * sizeof(cover_type));
109                return;
110            }
111
112            if(x < 0)
113            {
114                count += x;
115                if(count <= 0)
116                {
117                    memset(dst, 0, num_pix * sizeof(cover_type));
118                    return;
119                }
120                memset(covers, 0, -x * sizeof(cover_type));
121                covers -= x;
122                x = 0;
123            }
124
125            if(x + count > xmax)
126            {
127                int rest = x + count - xmax - 1;
128                count -= rest;
129                if(count <= 0)
130                {
131                    memset(dst, 0, num_pix * sizeof(cover_type));
132                    return;
133                }
134                memset(covers + count, 0, rest * sizeof(cover_type));
135            }
136
137            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
138            do
139            {
140                *covers++ = (cover_type)m_mask_function.calculate(mask);
141                mask += Step;
142            }
143            while(--count);
144        }
145
146
147        //--------------------------------------------------------------------
148        void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
149        {
150            int xmax = m_rbuf->width() - 1;
151            int ymax = m_rbuf->height() - 1;
152
153            int count = num_pix;
154            cover_type* covers = dst;
155
156            if(y < 0 || y > ymax)
157            {
158                memset(dst, 0, num_pix * sizeof(cover_type));
159                return;
160            }
161
162            if(x < 0)
163            {
164                count += x;
165                if(count <= 0)
166                {
167                    memset(dst, 0, num_pix * sizeof(cover_type));
168                    return;
169                }
170                memset(covers, 0, -x * sizeof(cover_type));
171                covers -= x;
172                x = 0;
173            }
174
175            if(x + count > xmax)
176            {
177                int rest = x + count - xmax - 1;
178                count -= rest;
179                if(count <= 0)
180                {
181                    memset(dst, 0, num_pix * sizeof(cover_type));
182                    return;
183                }
184                memset(covers + count, 0, rest * sizeof(cover_type));
185            }
186
187            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
188            do
189            {
190                *covers = (cover_type)((cover_full + (*covers) *
191                                       m_mask_function.calculate(mask)) >>
192                                       cover_shift);
193                ++covers;
194                mask += Step;
195            }
196            while(--count);
197        }
198
199        //--------------------------------------------------------------------
200        void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
201        {
202            int xmax = m_rbuf->width() - 1;
203            int ymax = m_rbuf->height() - 1;
204
205            int count = num_pix;
206            cover_type* covers = dst;
207
208            if(x < 0 || x > xmax)
209            {
210                memset(dst, 0, num_pix * sizeof(cover_type));
211                return;
212            }
213
214            if(y < 0)
215            {
216                count += y;
217                if(count <= 0)
218                {
219                    memset(dst, 0, num_pix * sizeof(cover_type));
220                    return;
221                }
222                memset(covers, 0, -y * sizeof(cover_type));
223                covers -= y;
224                y = 0;
225            }
226
227            if(y + count > ymax)
228            {
229                int rest = y + count - ymax - 1;
230                count -= rest;
231                if(count <= 0)
232                {
233                    memset(dst, 0, num_pix * sizeof(cover_type));
234                    return;
235                }
236                memset(covers + count, 0, rest * sizeof(cover_type));
237            }
238
239            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
240            do
241            {
242                *covers++ = (cover_type)m_mask_function.calculate(mask);
243                mask += m_rbuf->stride();
244            }
245            while(--count);
246        }
247
248        //--------------------------------------------------------------------
249        void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
250        {
251            int xmax = m_rbuf->width() - 1;
252            int ymax = m_rbuf->height() - 1;
253
254            int count = num_pix;
255            cover_type* covers = dst;
256
257            if(x < 0 || x > xmax)
258            {
259                memset(dst, 0, num_pix * sizeof(cover_type));
260                return;
261            }
262
263            if(y < 0)
264            {
265                count += y;
266                if(count <= 0)
267                {
268                    memset(dst, 0, num_pix * sizeof(cover_type));
269                    return;
270                }
271                memset(covers, 0, -y * sizeof(cover_type));
272                covers -= y;
273                y = 0;
274            }
275
276            if(y + count > ymax)
277            {
278                int rest = y + count - ymax - 1;
279                count -= rest;
280                if(count <= 0)
281                {
282                    memset(dst, 0, num_pix * sizeof(cover_type));
283                    return;
284                }
285                memset(covers + count, 0, rest * sizeof(cover_type));
286            }
287
288            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
289            do
290            {
291                *covers = (cover_type)((cover_full + (*covers) *
292                                       m_mask_function.calculate(mask)) >>
293                                       cover_shift);
294                ++covers;
295                mask += m_rbuf->stride();
296            }
297            while(--count);
298        }
299
300
301    private:
302        alpha_mask_u8(const self_type&);
303        const self_type& operator = (const self_type&);
304
305        rendering_buffer* m_rbuf;
306        MaskF             m_mask_function;
307    };
308
309
310    typedef alpha_mask_u8<1, 0> alpha_mask_gray8;   //----alpha_mask_gray8
311
312    typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r;  //----alpha_mask_rgb24r
313    typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g;  //----alpha_mask_rgb24g
314    typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b;  //----alpha_mask_rgb24b
315
316    typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r;  //----alpha_mask_bgr24r
317    typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g;  //----alpha_mask_bgr24g
318    typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b;  //----alpha_mask_bgr24b
319
320    typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
321    typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
322    typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
323    typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
324
325    typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
326    typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
327    typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
328    typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
329
330    typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
331    typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
332    typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
333    typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
334
335    typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
336    typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
337    typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
338    typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
339
340    typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray;  //----alpha_mask_rgb24gray
341    typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray;  //----alpha_mask_bgr24gray
342    typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
343    typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
344    typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
345    typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
346
347
348
349    //==========================================================amask_no_clip_u8
350    template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
351    class amask_no_clip_u8
352    {
353    public:
354        typedef int8u cover_type;
355        typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
356        enum cover_scale_e
357        {
358            cover_shift = 8,
359            cover_none  = 0,
360            cover_full  = 255
361        };
362
363        amask_no_clip_u8() : m_rbuf(0) {}
364        amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
365
366        void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
367
368        MaskF& mask_function() { return m_mask_function; }
369        const MaskF& mask_function() const { return m_mask_function; }
370
371
372        //--------------------------------------------------------------------
373        cover_type pixel(int x, int y) const
374        {
375            return (cover_type)m_mask_function.calculate(
376                                   m_rbuf->row_ptr(y) + x * Step + Offset);
377        }
378
379
380        //--------------------------------------------------------------------
381        cover_type combine_pixel(int x, int y, cover_type val) const
382        {
383            return (cover_type)((cover_full + val *
384                                 m_mask_function.calculate(
385                                    m_rbuf->row_ptr(y) + x * Step + Offset)) >>
386                                 cover_shift);
387        }
388
389
390        //--------------------------------------------------------------------
391        void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
392        {
393            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
394            do
395            {
396                *dst++ = (cover_type)m_mask_function.calculate(mask);
397                mask += Step;
398            }
399            while(--num_pix);
400        }
401
402
403
404        //--------------------------------------------------------------------
405        void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
406        {
407            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
408            do
409            {
410                *dst = (cover_type)((cover_full + (*dst) *
411                                    m_mask_function.calculate(mask)) >>
412                                    cover_shift);
413                ++dst;
414                mask += Step;
415            }
416            while(--num_pix);
417        }
418
419
420        //--------------------------------------------------------------------
421        void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
422        {
423            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
424            do
425            {
426                *dst++ = (cover_type)m_mask_function.calculate(mask);
427                mask += m_rbuf->stride();
428            }
429            while(--num_pix);
430        }
431
432
433        //--------------------------------------------------------------------
434        void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
435        {
436            const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
437            do
438            {
439                *dst = (cover_type)((cover_full + (*dst) *
440                                    m_mask_function.calculate(mask)) >>
441                                    cover_shift);
442                ++dst;
443                mask += m_rbuf->stride();
444            }
445            while(--num_pix);
446        }
447
448    private:
449        amask_no_clip_u8(const self_type&);
450        const self_type& operator = (const self_type&);
451
452        rendering_buffer* m_rbuf;
453        MaskF             m_mask_function;
454    };
455
456
457    typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8;   //----amask_no_clip_gray8
458
459    typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r;  //----amask_no_clip_rgb24r
460    typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g;  //----amask_no_clip_rgb24g
461    typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b;  //----amask_no_clip_rgb24b
462
463    typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r;  //----amask_no_clip_bgr24r
464    typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g;  //----amask_no_clip_bgr24g
465    typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b;  //----amask_no_clip_bgr24b
466
467    typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
468    typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
469    typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
470    typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
471
472    typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
473    typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
474    typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
475    typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
476
477    typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
478    typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
479    typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
480    typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
481
482    typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
483    typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
484    typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
485    typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
486
487    typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray;  //----amask_no_clip_rgb24gray
488    typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray;  //----amask_no_clip_bgr24gray
489    typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
490    typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
491    typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
492    typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
493
494
495}
496
497
498
499#endif
500