1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 // class renderer_base
18 //----------------------------------------------------------------------------
20 #ifndef AGG_RENDERER_BASE_INCLUDED
21 #define AGG_RENDERER_BASE_INCLUDED
23 #include "agg_basics.h"
24 #include "agg_rendering_buffer.h"
29 //-----------------------------------------------------------renderer_base
30 template<class PixelFormat
> class renderer_base
33 typedef PixelFormat pixfmt_type
;
34 typedef typename
pixfmt_type::color_type color_type
;
35 typedef typename
pixfmt_type::row_data row_data
;
37 //--------------------------------------------------------------------
38 renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {}
39 renderer_base(pixfmt_type
& ren
) :
41 m_clip_box(0, 0, ren
.width() - 1, ren
.height() - 1)
43 void attach(pixfmt_type
& ren
)
46 m_clip_box
= rect_i(0, 0, ren
.width() - 1, ren
.height() - 1);
49 //--------------------------------------------------------------------
50 const pixfmt_type
& ren() const { return *m_ren
; }
51 pixfmt_type
& ren() { return *m_ren
; }
53 //--------------------------------------------------------------------
54 unsigned width() const { return m_ren
->width(); }
55 unsigned height() const { return m_ren
->height(); }
57 //--------------------------------------------------------------------
58 bool clip_box(int x1
, int y1
, int x2
, int y2
)
60 rect_i
cb(x1
, y1
, x2
, y2
);
62 if(cb
.clip(rect_i(0, 0, width() - 1, height() - 1)))
74 //--------------------------------------------------------------------
75 void reset_clipping(bool visibility
)
81 m_clip_box
.x2
= width() - 1;
82 m_clip_box
.y2
= height() - 1;
93 //--------------------------------------------------------------------
94 void clip_box_naked(int x1
, int y1
, int x2
, int y2
)
102 //--------------------------------------------------------------------
103 bool inbox(int x
, int y
) const
105 return x
>= m_clip_box
.x1
&& y
>= m_clip_box
.y1
&&
106 x
<= m_clip_box
.x2
&& y
<= m_clip_box
.y2
;
109 //--------------------------------------------------------------------
110 const rect_i
& clip_box() const { return m_clip_box
; }
111 int xmin() const { return m_clip_box
.x1
; }
112 int ymin() const { return m_clip_box
.y1
; }
113 int xmax() const { return m_clip_box
.x2
; }
114 int ymax() const { return m_clip_box
.y2
; }
116 //--------------------------------------------------------------------
117 const rect_i
& bounding_clip_box() const { return m_clip_box
; }
118 int bounding_xmin() const { return m_clip_box
.x1
; }
119 int bounding_ymin() const { return m_clip_box
.y1
; }
120 int bounding_xmax() const { return m_clip_box
.x2
; }
121 int bounding_ymax() const { return m_clip_box
.y2
; }
123 //--------------------------------------------------------------------
124 void clear(const color_type
& c
)
129 for(y
= 0; y
< height(); y
++)
131 m_ren
->copy_hline(0, y
, width(), c
);
136 //--------------------------------------------------------------------
137 void fill(const color_type
& c
)
142 for(y
= 0; y
< height(); y
++)
144 m_ren
->blend_hline(0, y
, width(), c
, cover_mask
);
149 //--------------------------------------------------------------------
150 void copy_pixel(int x
, int y
, const color_type
& c
)
154 m_ren
->copy_pixel(x
, y
, c
);
158 //--------------------------------------------------------------------
159 void blend_pixel(int x
, int y
, const color_type
& c
, cover_type cover
)
163 m_ren
->blend_pixel(x
, y
, c
, cover
);
167 //--------------------------------------------------------------------
168 color_type
pixel(int x
, int y
) const
172 color_type::no_color();
175 //--------------------------------------------------------------------
176 void copy_hline(int x1
, int y
, int x2
, const color_type
& c
)
178 if(x1
> x2
) { int t
= x2
; x2
= x1
; x1
= t
; }
179 if(y
> ymax()) return;
180 if(y
< ymin()) return;
181 if(x1
> xmax()) return;
182 if(x2
< xmin()) return;
184 if(x1
< xmin()) x1
= xmin();
185 if(x2
> xmax()) x2
= xmax();
187 m_ren
->copy_hline(x1
, y
, x2
- x1
+ 1, c
);
190 //--------------------------------------------------------------------
191 void copy_vline(int x
, int y1
, int y2
, const color_type
& c
)
193 if(y1
> y2
) { int t
= y2
; y2
= y1
; y1
= t
; }
194 if(x
> xmax()) return;
195 if(x
< xmin()) return;
196 if(y1
> ymax()) return;
197 if(y2
< ymin()) return;
199 if(y1
< ymin()) y1
= ymin();
200 if(y2
> ymax()) y2
= ymax();
202 m_ren
->copy_vline(x
, y1
, y2
- y1
+ 1, c
);
205 //--------------------------------------------------------------------
206 void blend_hline(int x1
, int y
, int x2
,
207 const color_type
& c
, cover_type cover
)
209 if(x1
> x2
) { int t
= x2
; x2
= x1
; x1
= t
; }
210 if(y
> ymax()) return;
211 if(y
< ymin()) return;
212 if(x1
> xmax()) return;
213 if(x2
< xmin()) return;
215 if(x1
< xmin()) x1
= xmin();
216 if(x2
> xmax()) x2
= xmax();
218 m_ren
->blend_hline(x1
, y
, x2
- x1
+ 1, c
, cover
);
222 //--------------------------------------------------------------------
223 void blend_vline(int x
, int y1
, int y2
,
224 const color_type
& c
, cover_type cover
)
226 if(y1
> y2
) { int t
= y2
; y2
= y1
; y1
= t
; }
227 if(x
> xmax()) return;
228 if(x
< xmin()) return;
229 if(y1
> ymax()) return;
230 if(y2
< ymin()) return;
232 if(y1
< ymin()) y1
= ymin();
233 if(y2
> ymax()) y2
= ymax();
235 m_ren
->blend_vline(x
, y1
, y2
- y1
+ 1, c
, cover
);
239 //--------------------------------------------------------------------
240 void copy_bar(int x1
, int y1
, int x2
, int y2
, const color_type
& c
)
242 rect_i
rc(x1
, y1
, x2
, y2
);
244 if(rc
.clip(clip_box()))
247 for(y
= rc
.y1
; y
<= rc
.y2
; y
++)
249 m_ren
->copy_hline(rc
.x1
, y
, unsigned(rc
.x2
- rc
.x1
+ 1), c
);
254 //--------------------------------------------------------------------
255 void blend_bar(int x1
, int y1
, int x2
, int y2
,
256 const color_type
& c
, cover_type cover
)
258 rect_i
rc(x1
, y1
, x2
, y2
);
260 if(rc
.clip(clip_box()))
263 for(y
= rc
.y1
; y
<= rc
.y2
; y
++)
265 m_ren
->blend_hline(rc
.x1
,
267 unsigned(rc
.x2
- rc
.x1
+ 1),
274 //--------------------------------------------------------------------
275 void blend_solid_hspan(int x
, int y
, int len
,
277 const cover_type
* covers
)
279 if(y
> ymax()) return;
280 if(y
< ymin()) return;
286 covers
+= xmin() - x
;
291 len
= xmax() - x
+ 1;
294 m_ren
->blend_solid_hspan(x
, y
, len
, c
, covers
);
297 //--------------------------------------------------------------------
298 void blend_solid_hspan_subpix(int x
, int y
, int len
,
300 const cover_type
* covers
)
302 if(y
> ymax()) return;
303 if(y
< ymin()) return;
307 len
-= 3 * (xmin() - x
);
309 covers
+= 3 * (xmin() - x
);
312 if(x
+ len
/ 3 > xmax())
314 len
= 3 * (xmax() - x
+ 1);
317 m_ren
->blend_solid_hspan_subpix(x
, y
, len
, c
, covers
);
320 //--------------------------------------------------------------------
321 void blend_solid_vspan(int x
, int y
, int len
,
323 const cover_type
* covers
)
325 if(x
> xmax()) return;
326 if(x
< xmin()) return;
332 covers
+= ymin() - y
;
337 len
= ymax() - y
+ 1;
340 m_ren
->blend_solid_vspan(x
, y
, len
, c
, covers
);
344 //--------------------------------------------------------------------
345 void copy_color_hspan(int x
, int y
, int len
, const color_type
* colors
)
347 if(y
> ymax()) return;
348 if(y
< ymin()) return;
360 len
= xmax() - x
+ 1;
363 m_ren
->copy_color_hspan(x
, y
, len
, colors
);
367 //--------------------------------------------------------------------
368 void copy_color_vspan(int x
, int y
, int len
, const color_type
* colors
)
370 if(x
> xmax()) return;
371 if(x
< xmin()) return;
383 len
= ymax() - y
+ 1;
386 m_ren
->copy_color_vspan(x
, y
, len
, colors
);
390 //--------------------------------------------------------------------
391 void blend_color_hspan(int x
, int y
, int len
,
392 const color_type
* colors
,
393 const cover_type
* covers
,
394 cover_type cover
= agg::cover_full
)
396 if(y
> ymax()) return;
397 if(y
< ymin()) return;
404 if(covers
) covers
+= d
;
410 len
= xmax() - x
+ 1;
413 m_ren
->blend_color_hspan(x
, y
, len
, colors
, covers
, cover
);
416 //--------------------------------------------------------------------
417 void blend_color_vspan(int x
, int y
, int len
,
418 const color_type
* colors
,
419 const cover_type
* covers
,
420 cover_type cover
= agg::cover_full
)
422 if(x
> xmax()) return;
423 if(x
< xmin()) return;
430 if(covers
) covers
+= d
;
436 len
= ymax() - y
+ 1;
439 m_ren
->blend_color_vspan(x
, y
, len
, colors
, covers
, cover
);
442 //--------------------------------------------------------------------
443 rect_i
clip_rect_area(rect_i
& dst
, rect_i
& src
, int wsrc
, int hsrc
) const
446 rect_i cb
= clip_box();
461 if(src
.x2
> wsrc
) src
.x2
= wsrc
;
462 if(src
.y2
> hsrc
) src
.y2
= hsrc
;
466 src
.x1
+= cb
.x1
- dst
.x1
;
471 src
.y1
+= cb
.y1
- dst
.y1
;
475 if(dst
.x2
> cb
.x2
) dst
.x2
= cb
.x2
;
476 if(dst
.y2
> cb
.y2
) dst
.y2
= cb
.y2
;
478 rc
.x2
= dst
.x2
- dst
.x1
;
479 rc
.y2
= dst
.y2
- dst
.y1
;
481 if(rc
.x2
> src
.x2
- src
.x1
) rc
.x2
= src
.x2
- src
.x1
;
482 if(rc
.y2
> src
.y2
- src
.y1
) rc
.y2
= src
.y2
- src
.y1
;
486 //--------------------------------------------------------------------
487 template<class RenBuf
>
488 void copy_from(const RenBuf
& src
,
489 const rect_i
* rect_src_ptr
= 0,
493 rect_i
rsrc(0, 0, src
.width(), src
.height());
496 rsrc
.x1
= rect_src_ptr
->x1
;
497 rsrc
.y1
= rect_src_ptr
->y1
;
498 rsrc
.x2
= rect_src_ptr
->x2
+ 1;
499 rsrc
.y2
= rect_src_ptr
->y2
+ 1;
502 // Version with xdst, ydst (absolute positioning)
503 //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
505 // Version with dx, dy (relative positioning)
506 rect_i
rdst(rsrc
.x1
+ dx
, rsrc
.y1
+ dy
, rsrc
.x2
+ dx
, rsrc
.y2
+ dy
);
508 rect_i rc
= clip_rect_area(rdst
, rsrc
, src
.width(), src
.height());
513 if(rdst
.y1
> rsrc
.y1
)
515 rsrc
.y1
+= rc
.y2
- 1;
516 rdst
.y1
+= rc
.y2
- 1;
521 m_ren
->copy_from(src
,
532 //--------------------------------------------------------------------
533 template<class SrcPixelFormatRenderer
>
534 void blend_from(const SrcPixelFormatRenderer
& src
,
535 const rect_i
* rect_src_ptr
= 0,
538 cover_type cover
= agg::cover_full
)
540 rect_i
rsrc(0, 0, src
.width(), src
.height());
543 rsrc
.x1
= rect_src_ptr
->x1
;
544 rsrc
.y1
= rect_src_ptr
->y1
;
545 rsrc
.x2
= rect_src_ptr
->x2
+ 1;
546 rsrc
.y2
= rect_src_ptr
->y2
+ 1;
549 // Version with xdst, ydst (absolute positioning)
550 //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
552 // Version with dx, dy (relative positioning)
553 rect_i
rdst(rsrc
.x1
+ dx
, rsrc
.y1
+ dy
, rsrc
.x2
+ dx
, rsrc
.y2
+ dy
);
554 rect_i rc
= clip_rect_area(rdst
, rsrc
, src
.width(), src
.height());
559 if(rdst
.y1
> rsrc
.y1
)
561 rsrc
.y1
+= rc
.y2
- 1;
562 rdst
.y1
+= rc
.y2
- 1;
567 typename
SrcPixelFormatRenderer::row_data rw
= src
.row(rsrc
.y1
);
575 x1dst
+= rw
.x1
- x1src
;
576 len
-= rw
.x1
- x1src
;
581 if(x1src
+ len
-1 > rw
.x2
)
583 len
-= x1src
+ len
- rw
.x2
- 1;
587 m_ren
->blend_from(src
,