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 // class renderer_mclip
17 //
18 //----------------------------------------------------------------------------
19 
20 #ifndef AGG_RENDERER_MCLIP_INCLUDED
21 #define AGG_RENDERER_MCLIP_INCLUDED
22 
23 #include "agg_basics.h"
24 #include "agg_array.h"
25 #include "agg_renderer_base.h"
26 
27 namespace agg
28 {
29 
30     //----------------------------------------------------------renderer_mclip
31     template<class PixelFormat> class renderer_mclip
usage()32     {
33     public:
34         typedef PixelFormat pixfmt_type;
35         typedef typename pixfmt_type::color_type color_type;
36         typedef typename pixfmt_type::row_data row_data;
37         typedef renderer_base<pixfmt_type> base_ren_type;
38 
39         //--------------------------------------------------------------------
40         explicit renderer_mclip(pixfmt_type& pixf) :
41             m_ren(pixf),
42             m_curr_cb(0),
43             m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
44         {}
45         void attach(pixfmt_type& pixf)
46         {
47             m_ren.attach(pixf);
48             reset_clipping(true);
49         }
50 
51         //--------------------------------------------------------------------
52         const pixfmt_type& ren() const { return m_ren.ren();  }
53         pixfmt_type& ren() { return m_ren.ren();  }
54 
55         //--------------------------------------------------------------------
56         unsigned width()  const { return m_ren.width();  }
57         unsigned height() const { return m_ren.height(); }
58 
59         //--------------------------------------------------------------------
60         const rect_i& clip_box() const { return m_ren.clip_box(); }
61         int           xmin()     const { return m_ren.xmin(); }
62         int           ymin()     const { return m_ren.ymin(); }
63         int           xmax()     const { return m_ren.xmax(); }
64         int           ymax()     const { return m_ren.ymax(); }
65 
66         //--------------------------------------------------------------------
67         const rect_i& bounding_clip_box() const { return m_bounds;    }
68         int           bounding_xmin()     const { return m_bounds.x1; }
69         int           bounding_ymin()     const { return m_bounds.y1; }
70         int           bounding_xmax()     const { return m_bounds.x2; }
71         int           bounding_ymax()     const { return m_bounds.y2; }
72 
73         //--------------------------------------------------------------------
74         void first_clip_box()
75         {
76             m_curr_cb = 0;
77             if(m_clip.size())
78             {
79                 const rect_i& cb = m_clip[0];
80                 m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
81             }
82         }
83 
84         //--------------------------------------------------------------------
85         bool next_clip_box()
86         {
87             if(++m_curr_cb < m_clip.size())
88             {
89                 const rect_i& cb = m_clip[m_curr_cb];
90                 m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
91                 return true;
92             }
93             return false;
94         }
95 
96         //--------------------------------------------------------------------
97         void reset_clipping(bool visibility)
98         {
99             m_ren.reset_clipping(visibility);
100             m_clip.remove_all();
101             m_curr_cb = 0;
102             m_bounds = m_ren.clip_box();
103         }
104 
105         //--------------------------------------------------------------------
106         void add_clip_box(int x1, int y1, int x2, int y2)
107         {
108             rect_i cb(x1, y1, x2, y2);
109             cb.normalize();
110             if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
111             {
112                 m_clip.add(cb);
113                 if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1;
114                 if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1;
115                 if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2;
116                 if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2;
117             }
118         }
119 
120         //--------------------------------------------------------------------
121         void clear(const color_type& c)
122         {
123             m_ren.clear(c);
124         }
125 
126         //--------------------------------------------------------------------
127         void copy_pixel(int x, int y, const color_type& c)
128         {
129             first_clip_box();
130             do
131             {
132                 if(m_ren.inbox(x, y))
133                 {
134                     m_ren.ren().copy_pixel(x, y, c);
135                     break;
136                 }
137             }
138             while(next_clip_box());
139         }
140 
141         //--------------------------------------------------------------------
142         void blend_pixel(int x, int y, const color_type& c, cover_type cover)
143         {
144             first_clip_box();
145             do
146             {
147                 if(m_ren.inbox(x, y))
148                 {
149                     m_ren.ren().blend_pixel(x, y, c, cover);
150                     break;
151                 }
152             }
153             while(next_clip_box());
154         }
155 
156         //--------------------------------------------------------------------
157         color_type pixel(int x, int y) const
158         {
159             first_clip_box();
160             do
161             {
162                 if(m_ren.inbox(x, y))
163                 {
164                     return m_ren.ren().pixel(x, y);
165                 }
166             }
167             while(next_clip_box());
168             return color_type::no_color();
169         }
170 
171         //--------------------------------------------------------------------
172         void copy_hline(int x1, int y, int x2, const color_type& c)
173         {
174             first_clip_box();
175             do
176             {
177                 m_ren.copy_hline(x1, y, x2, c);
178             }
179             while(next_clip_box());
180         }
181 
182         //--------------------------------------------------------------------
183         void copy_vline(int x, int y1, int y2, const color_type& c)
184         {
185             first_clip_box();
186             do
187             {
188                 m_ren.copy_vline(x, y1, y2, c);
189             }
190             while(next_clip_box());
191         }
192 
193         //--------------------------------------------------------------------
194         void blend_hline(int x1, int y, int x2,
195                          const color_type& c, cover_type cover)
196         {
197             first_clip_box();
198             do
199             {
200                 m_ren.blend_hline(x1, y, x2, c, cover);
201             }
202             while(next_clip_box());
203         }
204 
205         //--------------------------------------------------------------------
206         void blend_vline(int x, int y1, int y2,
207                          const color_type& c, cover_type cover)
208         {
209             first_clip_box();
210             do
211             {
212                 m_ren.blend_vline(x, y1, y2, c, cover);
213             }
214             while(next_clip_box());
215         }
216 
217         //--------------------------------------------------------------------
218         void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
219         {
220             first_clip_box();
221             do
222             {
223                 m_ren.copy_bar(x1, y1, x2, y2, c);
224             }
225             while(next_clip_box());
226         }
227 
228         //--------------------------------------------------------------------
229         void blend_bar(int x1, int y1, int x2, int y2,
230                        const color_type& c, cover_type cover)
231         {
232             first_clip_box();
233             do
234             {
235                 m_ren.blend_bar(x1, y1, x2, y2, c, cover);
236             }
237             while(next_clip_box());
238         }
239 
240         //--------------------------------------------------------------------
241         void blend_solid_hspan(int x, int y, int len,
242                                const color_type& c, const cover_type* covers)
243         {
244             first_clip_box();
245             do
246             {
247                 m_ren.blend_solid_hspan(x, y, len, c, covers);
248             }
249             while(next_clip_box());
250         }
251 
252         //--------------------------------------------------------------------
253         void blend_solid_vspan(int x, int y, int len,
254                                const color_type& c, const cover_type* covers)
255         {
256             first_clip_box();
257             do
258             {
259                 m_ren.blend_solid_vspan(x, y, len, c, covers);
260             }
261             while(next_clip_box());
262         }
263 
264 
265         //--------------------------------------------------------------------
266         void copy_color_hspan(int x, int y, int len, const color_type* colors)
267         {
268             first_clip_box();
269             do
270             {
271                 m_ren.copy_color_hspan(x, y, len, colors);
272             }
273             while(next_clip_box());
274         }
275 
276         //--------------------------------------------------------------------
277         void blend_color_hspan(int x, int y, int len,
278                                const color_type* colors,
279                                const cover_type* covers,
280                                cover_type cover = cover_full)
281         {
282             first_clip_box();
283             do
284             {
285                 m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
286             }
287             while(next_clip_box());
288         }
289 
290         //--------------------------------------------------------------------
291         void blend_color_vspan(int x, int y, int len,
292                                const color_type* colors,
293                                const cover_type* covers,
294                                cover_type cover = cover_full)
295         {
296             first_clip_box();
297             do
298             {
299                 m_ren.blend_color_vspan(x, y, len, colors, covers, cover);
300             }
301             while(next_clip_box());
302         }
303 
304         //--------------------------------------------------------------------
305         void copy_from(const rendering_buffer& from,
306                        const rect_i* rc=0,
307                        int x_to=0,
308                        int y_to=0)
309         {
310             first_clip_box();
311             do
312             {
313                 m_ren.copy_from(from, rc, x_to, y_to);
314             }
315             while(next_clip_box());
316         }
317 
318         //--------------------------------------------------------------------
319         template<class SrcPixelFormatRenderer>
320         void blend_from(const SrcPixelFormatRenderer& src,
321                         const rect_i* rect_src_ptr = 0,
322                         int dx = 0,
323                         int dy = 0,
324                         cover_type cover = cover_full)
325         {
326             first_clip_box();
327             do
328             {
329                 m_ren.blend_from(src, rect_src_ptr, dx, dy, cover);
330             }
331             while(next_clip_box());
332         }
333 
334 
335     private:
336         renderer_mclip(const renderer_mclip<PixelFormat>&);
337         const renderer_mclip<PixelFormat>&
338             operator = (const renderer_mclip<PixelFormat>&);
339 
340         base_ren_type          m_ren;
341         pod_bvector<rect_i, 4> m_clip;
342         unsigned               m_curr_cb;
343         rect_i                 m_bounds;
344     };
345 
346 
347 }
348 
349 #endif
350