xref: /haiku/headers/libs/agg/agg_alpha_mask_u8.h (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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 
26 namespace 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