xref: /haiku/headers/libs/agg/agg_renderer_base.h (revision 39241fe22890fb958b6ba32d6ab9526da98be187)
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.2
3 // Copyright (C) 2002-2004 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_base
17 //
18 //----------------------------------------------------------------------------
19 
20 #ifndef AGG_RENDERER_BASE_INCLUDED
21 #define AGG_RENDERER_BASE_INCLUDED
22 
23 #include "agg_basics.h"
24 #include "agg_rendering_buffer.h"
25 
26 namespace agg
27 {
28     //-----------------------------------------------------------renderer_base
29     template<class PixelFormat> class renderer_base
30     {
31     public:
32         typedef PixelFormat pixfmt_type;
33         typedef typename pixfmt_type::color_type color_type;
34 
35         //--------------------------------------------------------------------
36         renderer_base(pixfmt_type& ren) :
37             m_ren(&ren),
38             m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
39         {
40         }
41 
42         //--------------------------------------------------------------------
43         const pixfmt_type& ren() const { return *m_ren;  }
44         pixfmt_type& ren() { return *m_ren;  }
45 
46         //--------------------------------------------------------------------
47         unsigned width()  const { return m_ren->width();  }
48         unsigned height() const { return m_ren->height(); }
49 
50         //--------------------------------------------------------------------
51         bool clip_box(int x1, int y1, int x2, int y2)
52         {
53             rect cb(x1, y1, x2, y2);
54             cb.normalize();
55             if(cb.clip(rect(0, 0, width() - 1, height() - 1)))
56             {
57                 m_clip_box = cb;
58                 return true;
59             }
60             m_clip_box.x1 = 1;
61             m_clip_box.y1 = 1;
62             m_clip_box.x2 = 0;
63             m_clip_box.y2 = 0;
64             return false;
65         }
66 
67         //--------------------------------------------------------------------
68         void reset_clipping(bool visibility)
69         {
70             if(visibility)
71             {
72                 m_clip_box.x1 = 0;
73                 m_clip_box.y1 = 0;
74                 m_clip_box.x2 = width() - 1;
75                 m_clip_box.y2 = height() - 1;
76             }
77             else
78             {
79                 m_clip_box.x1 = 1;
80                 m_clip_box.y1 = 1;
81                 m_clip_box.x2 = 0;
82                 m_clip_box.y2 = 0;
83             }
84         }
85 
86         //--------------------------------------------------------------------
87         void clip_box_naked(int x1, int y1, int x2, int y2)
88         {
89             m_clip_box.x1 = x1;
90             m_clip_box.y1 = y1;
91             m_clip_box.x2 = x2;
92             m_clip_box.y2 = y2;
93         }
94 
95         //--------------------------------------------------------------------
96         bool inbox(int x, int y) const
97         {
98             return x >= m_clip_box.x1 && y >= m_clip_box.y1 &&
99                    x <= m_clip_box.x2 && y <= m_clip_box.y2;
100         }
101 
102         //--------------------------------------------------------------------
103         void first_clip_box() {}
104         bool next_clip_box() { return false; }
105 
106         //--------------------------------------------------------------------
107         const rect& clip_box() const { return m_clip_box;    }
108         int         xmin()     const { return m_clip_box.x1; }
109         int         ymin()     const { return m_clip_box.y1; }
110         int         xmax()     const { return m_clip_box.x2; }
111         int         ymax()     const { return m_clip_box.y2; }
112 
113         //--------------------------------------------------------------------
114         const rect& bounding_clip_box() const { return m_clip_box;    }
115         int         bounding_xmin()     const { return m_clip_box.x1; }
116         int         bounding_ymin()     const { return m_clip_box.y1; }
117         int         bounding_xmax()     const { return m_clip_box.x2; }
118         int         bounding_ymax()     const { return m_clip_box.y2; }
119 
120         //--------------------------------------------------------------------
121         void clear(const color_type& c)
122         {
123             unsigned y;
124             if(width())
125             {
126                 for(y = 0; y < height(); y++)
127                 {
128                     m_ren->copy_hline(0, y, width(), c);
129                 }
130             }
131         }
132 
133         //--------------------------------------------------------------------
134         void copy_pixel(int x, int y, const color_type& c)
135         {
136             if(inbox(x, y))
137             {
138                 m_ren->copy_pixel(x, y, c);
139             }
140         }
141 
142         //--------------------------------------------------------------------
143         void blend_pixel(int x, int y, const color_type& c, cover_type cover)
144         {
145             if(inbox(x, y))
146             {
147                 m_ren->blend_pixel(x, y, c, cover);
148             }
149         }
150 
151         //--------------------------------------------------------------------
152         color_type pixel(int x, int y) const
153         {
154             return inbox(x, y) ?
155                    m_ren->pixel(x, y) :
156                    color_type::no_color();
157         }
158 
159         //--------------------------------------------------------------------
160         void copy_hline(int x1, int y, int x2, const color_type& c)
161         {
162             if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
163             if(y  > ymax()) return;
164             if(y  < ymin()) return;
165             if(x1 > xmax()) return;
166             if(x2 < xmin()) return;
167 
168             if(x1 < xmin()) x1 = xmin();
169             if(x2 > xmax()) x2 = xmax();
170 
171             m_ren->copy_hline(x1, y, x2 - x1 + 1, c);
172         }
173 
174         //--------------------------------------------------------------------
175         void copy_vline(int x, int y1, int y2, const color_type& c)
176         {
177             if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
178             if(x  > xmax()) return;
179             if(x  < xmin()) return;
180             if(y1 > ymax()) return;
181             if(y2 < ymin()) return;
182 
183             if(y1 < ymin()) y1 = ymin();
184             if(y2 > ymax()) y2 = ymax();
185 
186             m_ren->copy_vline(x, y1, y2 - y1 + 1, c);
187         }
188 
189         //--------------------------------------------------------------------
190         void blend_hline(int x1, int y, int x2,
191                          const color_type& c, cover_type cover)
192         {
193             if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
194             if(y  > ymax()) return;
195             if(y  < ymin()) return;
196             if(x1 > xmax()) return;
197             if(x2 < xmin()) return;
198 
199             if(x1 < xmin()) x1 = xmin();
200             if(x2 > xmax()) x2 = xmax();
201 
202             m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover);
203         }
204 
205         //--------------------------------------------------------------------
206         void blend_vline(int x, int y1, int y2,
207                          const color_type& c, cover_type cover)
208         {
209             if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
210             if(x  > xmax()) return;
211             if(x  < xmin()) return;
212             if(y1 > ymax()) return;
213             if(y2 < ymin()) return;
214 
215             if(y1 < ymin()) y1 = ymin();
216             if(y2 > ymax()) y2 = ymax();
217 
218             m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover);
219         }
220 
221 
222         //--------------------------------------------------------------------
223         void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
224         {
225             rect rc(x1, y1, x2, y2);
226             rc.normalize();
227             if(rc.clip(clip_box()))
228             {
229                 int y;
230                 for(y = rc.y1; y <= rc.y2; y++)
231                 {
232                     m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c);
233                 }
234             }
235         }
236 
237         //--------------------------------------------------------------------
238         void blend_bar(int x1, int y1, int x2, int y2,
239                        const color_type& c, cover_type cover)
240         {
241             rect rc(x1, y1, x2, y2);
242             rc.normalize();
243             if(rc.clip(clip_box()))
244             {
245                 int y;
246                 for(y = rc.y1; y <= rc.y2; y++)
247                 {
248                     m_ren->blend_hline(rc.x1,
249                                        y,
250                                        unsigned(rc.x2 - rc.x1 + 1),
251                                        c,
252                                        cover);
253                 }
254             }
255         }
256 
257 
258         //--------------------------------------------------------------------
259         void blend_solid_hspan(int x, int y, int len,
260                                const color_type& c,
261                                const cover_type* covers)
262         {
263             if(y > ymax()) return;
264             if(y < ymin()) return;
265 
266             if(x < xmin())
267             {
268                 len -= xmin() - x;
269                 if(len <= 0) return;
270                 covers += xmin() - x;
271                 x = xmin();
272             }
273             if(x + len > xmax())
274             {
275                 len = xmax() - x + 1;
276                 if(len <= 0) return;
277             }
278             m_ren->blend_solid_hspan(x, y, len, c, covers);
279         }
280 
281         //--------------------------------------------------------------------
282         void blend_solid_vspan(int x, int y, int len,
283                                const color_type& c,
284                                const cover_type* covers)
285         {
286             if(x > xmax()) return;
287             if(x < xmin()) return;
288 
289             if(y < ymin())
290             {
291                 len -= ymin() - y;
292                 if(len <= 0) return;
293                 covers += ymin() - y;
294                 y = ymin();
295             }
296             if(y + len > ymax())
297             {
298                 len = ymax() - y + 1;
299                 if(len <= 0) return;
300             }
301             m_ren->blend_solid_vspan(x, y, len, c, covers);
302         }
303 
304         //--------------------------------------------------------------------
305         void blend_color_hspan(int x, int y, int len,
306                                const color_type* colors,
307                                const cover_type* covers,
308                                cover_type cover = cover_full)
309         {
310             if(y > ymax()) return;
311             if(y < ymin()) return;
312 
313             if(x < xmin())
314             {
315                 int d = xmin() - x;
316                 len -= d;
317                 if(len <= 0) return;
318                 if(covers) covers += d;
319                 colors += d;
320                 x = xmin();
321             }
322             if(x + len > xmax())
323             {
324                 len = xmax() - x + 1;
325                 if(len <= 0) return;
326             }
327             m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
328         }
329 
330         //--------------------------------------------------------------------
331         void blend_color_vspan(int x, int y, int len,
332                                const color_type* colors,
333                                const cover_type* covers,
334                                cover_type cover = cover_full)
335         {
336             if(x > xmax()) return;
337             if(x < xmin()) return;
338 
339             if(y < ymin())
340             {
341                 int d = ymin() - y;
342                 len -= d;
343                 if(len <= 0) return;
344                 if(covers) covers += d;
345                 colors += d;
346                 y = ymin();
347             }
348             if(y + len > ymax())
349             {
350                 len = ymax() - y + 1;
351                 if(len <= 0) return;
352             }
353             m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
354         }
355 
356         //--------------------------------------------------------------------
357         void blend_color_hspan_no_clip(int x, int y, int len,
358                                        const color_type* colors,
359                                        const cover_type* covers,
360                                        cover_type cover = cover_full)
361         {
362             m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
363         }
364 
365         //--------------------------------------------------------------------
366         void blend_color_vspan_no_clip(int x, int y, int len,
367                                        const color_type* colors,
368                                        const cover_type* covers,
369                                        cover_type cover = cover_full)
370         {
371             m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
372         }
373 
374         //--------------------------------------------------------------------
375         void copy_from(const rendering_buffer& from,
376                        const rect* rc=0,
377                        int x_to=0,
378                        int y_to=0)
379         {
380             rect tmp_rect(0, 0, from.width(), from.height());
381             if(rc == 0)
382             {
383                 rc = &tmp_rect;
384             }
385 
386             rect rc2(*rc);
387             rc2.normalize();
388             if(rc2.clip(rect(0, 0, from.width() - 1, from.height() - 1)))
389             {
390                 rect rc3(x_to + rc2.x1 - rc->x1,
391                          y_to + rc2.y1 - rc->y1,
392                          x_to + rc2.x2 - rc->x1,
393                          y_to + rc2.y2 - rc->y1);
394                 rc3.normalize();
395 
396                 if(rc3.clip(clip_box()))
397                 {
398                     while(rc3.y1 <= rc3.y2)
399                     {
400                         m_ren->copy_from(from,
401                                          rc3.x1, rc3.y1,
402                                          rc2.x1, rc2.y1,
403                                          rc3.x2 - rc3.x1 + 1);
404                         ++rc2.y1;
405                         ++rc3.y1;
406                     }
407                 }
408             }
409         }
410 
411 
412     private:
413         pixfmt_type* m_ren;
414         rect         m_clip_box;
415     };
416 
417 
418 }
419 
420 #endif
421