1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
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
;
36 //--------------------------------------------------------------------
37 renderer_base(pixfmt_type
& _ren
) :
39 m_clip_box(0, 0, _ren
.width() - 1, _ren
.height() - 1)
43 //--------------------------------------------------------------------
44 const pixfmt_type
& ren() const { return *m_ren
; }
45 pixfmt_type
& ren() { return *m_ren
; }
47 //--------------------------------------------------------------------
48 unsigned width() const { return m_ren
->width(); }
49 unsigned height() const { return m_ren
->height(); }
51 //--------------------------------------------------------------------
52 bool clip_box(int x1
, int y1
, int x2
, int y2
)
54 rect
cb(x1
, y1
, x2
, y2
);
56 if(cb
.clip(rect(0, 0, width() - 1, height() - 1)))
68 //--------------------------------------------------------------------
69 void reset_clipping(bool visibility
)
75 m_clip_box
.x2
= width() - 1;
76 m_clip_box
.y2
= height() - 1;
87 //--------------------------------------------------------------------
88 void clip_box_naked(int x1
, int y1
, int x2
, int y2
)
96 //--------------------------------------------------------------------
97 bool inbox(int x
, int y
) const
99 return x
>= m_clip_box
.x1
&& y
>= m_clip_box
.y1
&&
100 x
<= m_clip_box
.x2
&& y
<= m_clip_box
.y2
;
103 //--------------------------------------------------------------------
104 void first_clip_box() {}
105 bool next_clip_box() { return false; }
107 //--------------------------------------------------------------------
108 const rect
& clip_box() const { return m_clip_box
; }
109 int xmin() const { return m_clip_box
.x1
; }
110 int ymin() const { return m_clip_box
.y1
; }
111 int xmax() const { return m_clip_box
.x2
; }
112 int ymax() const { return m_clip_box
.y2
; }
114 //--------------------------------------------------------------------
115 const rect
& bounding_clip_box() const { return m_clip_box
; }
116 int bounding_xmin() const { return m_clip_box
.x1
; }
117 int bounding_ymin() const { return m_clip_box
.y1
; }
118 int bounding_xmax() const { return m_clip_box
.x2
; }
119 int bounding_ymax() const { return m_clip_box
.y2
; }
121 //--------------------------------------------------------------------
122 void clear(const color_type
& c
)
127 for(y
= 0; y
< height(); y
++)
129 m_ren
->copy_hline(0, y
, width(), c
);
134 //--------------------------------------------------------------------
135 void copy_pixel(int x
, int y
, const color_type
& c
)
139 m_ren
->copy_pixel(x
, y
, c
);
143 //--------------------------------------------------------------------
144 void blend_pixel(int x
, int y
, const color_type
& c
, cover_type cover
)
148 m_ren
->blend_pixel(x
, y
, c
, cover
);
152 //--------------------------------------------------------------------
153 color_type
pixel(int x
, int y
) const
157 color_type::no_color();
160 //--------------------------------------------------------------------
161 void copy_hline(int x1
, int y
, int x2
, const color_type
& c
)
163 if(x1
> x2
) { int t
= x2
; x2
= x1
; x1
= t
; }
164 if(y
> ymax()) return;
165 if(y
< ymin()) return;
166 if(x1
> xmax()) return;
167 if(x2
< xmin()) return;
169 if(x1
< xmin()) x1
= xmin();
170 if(x2
> xmax()) x2
= xmax();
172 m_ren
->copy_hline(x1
, y
, x2
- x1
+ 1, c
);
175 //--------------------------------------------------------------------
176 void copy_vline(int x
, int y1
, int y2
, const color_type
& c
)
178 if(y1
> y2
) { int t
= y2
; y2
= y1
; y1
= t
; }
179 if(x
> xmax()) return;
180 if(x
< xmin()) return;
181 if(y1
> ymax()) return;
182 if(y2
< ymin()) return;
184 if(y1
< ymin()) y1
= ymin();
185 if(y2
> ymax()) y2
= ymax();
187 m_ren
->copy_vline(x
, y1
, y2
- y1
+ 1, c
);
190 //--------------------------------------------------------------------
191 void blend_hline(int x1
, int y
, int x2
,
192 const color_type
& c
, cover_type cover
)
194 if(x1
> x2
) { int t
= x2
; x2
= x1
; x1
= t
; }
195 if(y
> ymax()) return;
196 if(y
< ymin()) return;
197 if(x1
> xmax()) return;
198 if(x2
< xmin()) return;
200 if(x1
< xmin()) x1
= xmin();
201 if(x2
> xmax()) x2
= xmax();
203 m_ren
->blend_hline(x1
, y
, x2
- x1
+ 1, c
, cover
);
206 //--------------------------------------------------------------------
207 void blend_vline(int x
, int y1
, int y2
,
208 const color_type
& c
, cover_type cover
)
210 if(y1
> y2
) { int t
= y2
; y2
= y1
; y1
= t
; }
211 if(x
> xmax()) return;
212 if(x
< xmin()) return;
213 if(y1
> ymax()) return;
214 if(y2
< ymin()) return;
216 if(y1
< ymin()) y1
= ymin();
217 if(y2
> ymax()) y2
= ymax();
219 m_ren
->blend_vline(x
, y1
, y2
- y1
+ 1, c
, cover
);
223 //--------------------------------------------------------------------
224 void copy_bar(int x1
, int y1
, int x2
, int y2
, const color_type
& c
)
226 rect
rc(x1
, y1
, x2
, y2
);
228 if(rc
.clip(clip_box()))
231 for(y
= rc
.y1
; y
<= rc
.y2
; y
++)
233 m_ren
->copy_hline(rc
.x1
, y
, unsigned(rc
.x2
- rc
.x1
+ 1), c
);
238 //--------------------------------------------------------------------
239 void blend_bar(int x1
, int y1
, int x2
, int y2
,
240 const color_type
& c
, cover_type cover
)
242 rect
rc(x1
, y1
, x2
, y2
);
244 if(rc
.clip(clip_box()))
247 for(y
= rc
.y1
; y
<= rc
.y2
; y
++)
249 m_ren
->blend_hline(rc
.x1
,
251 unsigned(rc
.x2
- rc
.x1
+ 1),
259 //--------------------------------------------------------------------
260 void blend_solid_hspan(int x
, int y
, int len
,
262 const cover_type
* covers
)
264 if(y
> ymax()) return;
265 if(y
< ymin()) return;
271 covers
+= xmin() - x
;
276 len
= xmax() - x
+ 1;
279 m_ren
->blend_solid_hspan(x
, y
, len
, c
, covers
);
282 //--------------------------------------------------------------------
283 void blend_solid_vspan(int x
, int y
, int len
,
285 const cover_type
* covers
)
287 if(x
> xmax()) return;
288 if(x
< xmin()) return;
294 covers
+= ymin() - y
;
299 len
= ymax() - y
+ 1;
302 m_ren
->blend_solid_vspan(x
, y
, len
, c
, covers
);
305 //--------------------------------------------------------------------
306 void blend_color_hspan(int x
, int y
, int len
,
307 const color_type
* colors
,
308 const cover_type
* covers
,
309 cover_type cover
= cover_full
)
311 if(y
> ymax()) return;
312 if(y
< ymin()) return;
319 if(covers
) covers
+= d
;
325 len
= xmax() - x
+ 1;
328 m_ren
->blend_color_hspan(x
, y
, len
, colors
, covers
, cover
);
331 //--------------------------------------------------------------------
332 void blend_color_vspan(int x
, int y
, int len
,
333 const color_type
* colors
,
334 const cover_type
* covers
,
335 cover_type cover
= cover_full
)
337 if(x
> xmax()) return;
338 if(x
< xmin()) return;
345 if(covers
) covers
+= d
;
351 len
= ymax() - y
+ 1;
354 m_ren
->blend_color_vspan(x
, y
, len
, colors
, covers
, cover
);
358 //--------------------------------------------------------------------
359 void blend_opaque_color_hspan(int x
, int y
, int len
,
360 const color_type
* colors
,
361 const cover_type
* covers
,
362 cover_type cover
= cover_full
)
364 if(y
> ymax()) return;
365 if(y
< ymin()) return;
372 if(covers
) covers
+= d
;
378 len
= xmax() - x
+ 1;
381 m_ren
->blend_opaque_color_hspan(x
, y
, len
, colors
, covers
, cover
);
384 //--------------------------------------------------------------------
385 void blend_opaque_color_vspan(int x
, int y
, int len
,
386 const color_type
* colors
,
387 const cover_type
* covers
,
388 cover_type cover
= cover_full
)
390 if(x
> xmax()) return;
391 if(x
< xmin()) return;
398 if(covers
) covers
+= d
;
404 len
= ymax() - y
+ 1;
407 m_ren
->blend_opaque_color_vspan(x
, y
, len
, colors
, covers
, cover
);
411 //--------------------------------------------------------------------
412 void blend_color_hspan_no_clip(int x
, int y
, int len
,
413 const color_type
* colors
,
414 const cover_type
* covers
,
415 cover_type cover
= cover_full
)
417 m_ren
->blend_color_hspan(x
, y
, len
, colors
, covers
, cover
);
420 //--------------------------------------------------------------------
421 void blend_color_vspan_no_clip(int x
, int y
, int len
,
422 const color_type
* colors
,
423 const cover_type
* covers
,
424 cover_type cover
= cover_full
)
426 m_ren
->blend_color_vspan(x
, y
, len
, colors
, covers
, cover
);
429 //--------------------------------------------------------------------
430 void blend_opaque_color_hspan_no_clip(int x
, int y
, int len
,
431 const color_type
* colors
,
432 const cover_type
* covers
,
433 cover_type cover
= cover_full
)
435 m_ren
->blend_opaque_color_hspan(x
, y
, len
, colors
, covers
, cover
);
438 //--------------------------------------------------------------------
439 void blend_opaque_color_vspan_no_clip(int x
, int y
, int len
,
440 const color_type
* colors
,
441 const cover_type
* covers
,
442 cover_type cover
= cover_full
)
444 m_ren
->blend_opaque_color_vspan(x
, y
, len
, colors
, covers
, cover
);
447 //--------------------------------------------------------------------
448 rect
clip_rect_area(rect
& dst
, rect
& src
, int wsrc
, int hsrc
) const
451 rect cb
= clip_box();
466 if(src
.x2
> wsrc
) src
.x2
= wsrc
;
467 if(src
.y2
> hsrc
) src
.y2
= hsrc
;
471 src
.x1
+= cb
.x1
- dst
.x1
;
476 src
.y1
+= cb
.y1
- dst
.y1
;
480 if(dst
.x2
> cb
.x2
) dst
.x2
= cb
.x2
;
481 if(dst
.y2
> cb
.y2
) dst
.y2
= cb
.y2
;
483 rc
.x2
= dst
.x2
- dst
.x1
;
484 rc
.y2
= dst
.y2
- dst
.y1
;
486 if(rc
.x2
> src
.x2
- src
.x1
) rc
.x2
= src
.x2
- src
.x1
;
487 if(rc
.y2
> src
.y2
- src
.y1
) rc
.y2
= src
.y2
- src
.y1
;
492 //--------------------------------------------------------------------
493 void copy_from(const rendering_buffer
& src
,
494 const rect
* rect_src_ptr
= 0,
498 rect
rsrc(0, 0, src
.width(), src
.height());
501 rsrc
.x1
= rect_src_ptr
->x1
;
502 rsrc
.y1
= rect_src_ptr
->y1
;
503 rsrc
.x2
= rect_src_ptr
->x2
+ 1;
504 rsrc
.y2
= rect_src_ptr
->y2
+ 1;
507 // Version with xdst, ydst (absolute positioning)
508 //rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
510 // Version with dx, dy (relative positioning)
511 rect
rdst(rsrc
.x1
+ dx
, rsrc
.y1
+ dy
, rsrc
.x2
+ dx
, rsrc
.y2
+ dy
);
513 rect rc
= clip_rect_area(rdst
, rsrc
, src
.width(), src
.height());
518 if(rdst
.y1
> rsrc
.y1
)
520 rsrc
.y1
+= rc
.y2
- 1;
521 rdst
.y1
+= rc
.y2
- 1;
526 m_ren
->copy_from(src
,
539 //--------------------------------------------------------------------
540 template<class SrcPixelFormatRenderer
>
541 void blend_from(const SrcPixelFormatRenderer
& src
,
542 const rect
* rect_src_ptr
= 0,
546 rect
rsrc(0, 0, src
.width(), src
.height());
549 rsrc
.x1
= rect_src_ptr
->x1
;
550 rsrc
.y1
= rect_src_ptr
->y1
;
551 rsrc
.x2
= rect_src_ptr
->x2
+ 1;
552 rsrc
.y2
= rect_src_ptr
->y2
+ 1;
555 // Version with xdst, ydst (absolute positioning)
556 //rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
558 // Version with dx, dy (relative positioning)
559 rect
rdst(rsrc
.x1
+ dx
, rsrc
.y1
+ dy
, rsrc
.x2
+ dx
, rsrc
.y2
+ dy
);
561 rect rc
= clip_rect_area(rdst
, rsrc
, src
.width(), src
.height());
566 if(rdst
.y1
> rsrc
.y1
)
568 rsrc
.y1
+= rc
.y2
- 1;
569 rdst
.y1
+= rc
.y2
- 1;
574 typename
SrcPixelFormatRenderer::row_data span
= src
.span(rsrc
.x1
, rsrc
.y1
);
582 x1dst
+= span
.x1
- x1src
;
583 len
-= span
.x1
- x1src
;
588 if(x1src
+ len
-1 > span
.x2
)
590 len
-= x1src
+ len
- span
.x2
- 1;
594 m_ren
->blend_from(src
, span
.ptr
,