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#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
17#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
18
19
20#include <string.h>
21#include "agg_array.h"
22#include "agg_rendering_buffer.h"
23
24
25namespace agg
26{
27    //==================================================pixfmt_amask_adaptor
28    template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor
29    {
30    public:
31        typedef PixFmt pixfmt_type;
32        typedef typename pixfmt_type::color_type color_type;
33        typedef typename pixfmt_type::row_data row_data;
34        typedef AlphaMask amask_type;
35        typedef typename amask_type::cover_type cover_type;
36
37    private:
38        enum span_extra_tail_e { span_extra_tail = 256 };
39
40        void realloc_span(unsigned len)
41        {
42            if(len > m_span.size())
43            {
44                m_span.resize(len + span_extra_tail);
45            }
46        }
47
48        void init_span(unsigned len)
49        {
50            realloc_span(len);
51            memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
52        }
53
54        void init_span(unsigned len, const cover_type* covers)
55        {
56            realloc_span(len);
57            memcpy(&m_span[0], covers, len * sizeof(cover_type));
58        }
59
60
61    public:
62        pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
63            m_pixf(&pixf), m_mask(&mask), m_span()
64        {}
65
66        void attach_pixfmt(pixfmt_type& pixf)          { m_pixf = &pixf; }
67        void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
68
69        //--------------------------------------------------------------------
70        template<class PixFmt_>
71        bool attach_pixfmt(PixFmt_& pixf, int x1, int y1, int x2, int y2)
72        {
73            return m_pixf->attach(pixf, x1, y1, x2, y2);
74        }
75
76        //--------------------------------------------------------------------
77        unsigned width()  const { return m_pixf->width();  }
78        unsigned height() const { return m_pixf->height(); }
79
80        //--------------------------------------------------------------------
81        color_type pixel(int x, int y)
82        {
83            return m_pixf->pixel(x, y);
84        }
85
86        //--------------------------------------------------------------------
87        void copy_pixel(int x, int y, const color_type& c)
88        {
89            m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y));
90        }
91
92        //--------------------------------------------------------------------
93        void blend_pixel(int x, int y, const color_type& c, cover_type cover)
94        {
95            m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
96        }
97
98        //--------------------------------------------------------------------
99        void copy_hline(int x, int y,
100                        unsigned len,
101                        const color_type& c)
102        {
103            realloc_span(len);
104            m_mask->fill_hspan(x, y, &m_span[0], len);
105            m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
106        }
107
108        //--------------------------------------------------------------------
109        void blend_hline(int x, int y,
110                         unsigned len,
111                         const color_type& c,
112                         cover_type cover)
113        {
114            init_span(len);
115            m_mask->combine_hspan(x, y, &m_span[0], len);
116            m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
117        }
118
119        //--------------------------------------------------------------------
120        void copy_vline(int x, int y,
121                        unsigned len,
122                        const color_type& c)
123        {
124            realloc_span(len);
125            m_mask->fill_vspan(x, y, &m_span[0], len);
126            m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
127        }
128
129        //--------------------------------------------------------------------
130        void blend_vline(int x, int y,
131                         unsigned len,
132                         const color_type& c,
133                         cover_type cover)
134        {
135            init_span(len);
136            m_mask->combine_vspan(x, y, &m_span[0], len);
137            m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
138        }
139
140        //--------------------------------------------------------------------
141        void copy_from(const rendering_buffer& from,
142                       int xdst, int ydst,
143                       int xsrc, int ysrc,
144                       unsigned len)
145        {
146            m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
147        }
148
149
150        //--------------------------------------------------------------------
151        void blend_solid_hspan(int x, int y,
152                               unsigned len,
153                               const color_type& c,
154                               const cover_type* covers)
155        {
156            init_span(len, covers);
157            m_mask->combine_hspan(x, y, &m_span[0], len);
158            m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
159        }
160
161
162        //--------------------------------------------------------------------
163        void blend_solid_vspan(int x, int y,
164                               unsigned len,
165                               const color_type& c,
166                               const cover_type* covers)
167        {
168            init_span(len, covers);
169            m_mask->combine_vspan(x, y, &m_span[0], len);
170            m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
171        }
172
173
174        //--------------------------------------------------------------------
175        void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
176        {
177            realloc_span(len);
178            m_mask->fill_hspan(x, y, &m_span[0], len);
179            m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
180        }
181
182        //--------------------------------------------------------------------
183        void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
184        {
185            realloc_span(len);
186            m_mask->fill_vspan(x, y, &m_span[0], len);
187            m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
188        }
189
190        //--------------------------------------------------------------------
191        void blend_color_hspan(int x, int y,
192                               unsigned len,
193                               const color_type* colors,
194                               const cover_type* covers,
195                               cover_type cover = cover_full)
196        {
197            if(covers)
198            {
199                init_span(len, covers);
200                m_mask->combine_hspan(x, y, &m_span[0], len);
201            }
202            else
203            {
204                realloc_span(len);
205                m_mask->fill_hspan(x, y, &m_span[0], len);
206            }
207            m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
208        }
209
210
211        //--------------------------------------------------------------------
212        void blend_color_vspan(int x, int y,
213                               unsigned len,
214                               const color_type* colors,
215                               const cover_type* covers,
216                               cover_type cover = cover_full)
217        {
218            if(covers)
219            {
220                init_span(len, covers);
221                m_mask->combine_vspan(x, y, &m_span[0], len);
222            }
223            else
224            {
225                realloc_span(len);
226                m_mask->fill_vspan(x, y, &m_span[0], len);
227            }
228            m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
229        }
230
231    private:
232        pixfmt_type*          m_pixf;
233        const amask_type*     m_mask;
234        pod_array<cover_type> m_span;
235    };
236
237}
238
239#endif
240
241