btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_renderer_base.h
blob2dc3aa1ae1dfcc5f75c474db6ce0837e0a5c1ca7
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 //----------------------------------------------------------------------------
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"
26 namespace agg
29 //-----------------------------------------------------------renderer_base
30 template<class PixelFormat> class renderer_base
32 public:
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) :
40 m_ren(&ren),
41 m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
43 void attach(pixfmt_type& ren)
45 m_ren = &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);
61 cb.normalize();
62 if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
64 m_clip_box = cb;
65 return true;
67 m_clip_box.x1 = 1;
68 m_clip_box.y1 = 1;
69 m_clip_box.x2 = 0;
70 m_clip_box.y2 = 0;
71 return false;
74 //--------------------------------------------------------------------
75 void reset_clipping(bool visibility)
77 if(visibility)
79 m_clip_box.x1 = 0;
80 m_clip_box.y1 = 0;
81 m_clip_box.x2 = width() - 1;
82 m_clip_box.y2 = height() - 1;
84 else
86 m_clip_box.x1 = 1;
87 m_clip_box.y1 = 1;
88 m_clip_box.x2 = 0;
89 m_clip_box.y2 = 0;
93 //--------------------------------------------------------------------
94 void clip_box_naked(int x1, int y1, int x2, int y2)
96 m_clip_box.x1 = x1;
97 m_clip_box.y1 = y1;
98 m_clip_box.x2 = x2;
99 m_clip_box.y2 = 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)
126 unsigned y;
127 if(width())
129 for(y = 0; y < height(); y++)
131 m_ren->copy_hline(0, y, width(), c);
136 //--------------------------------------------------------------------
137 void fill(const color_type& c)
139 unsigned y;
140 if(width())
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)
152 if(inbox(x, y))
154 m_ren->copy_pixel(x, y, c);
158 //--------------------------------------------------------------------
159 void blend_pixel(int x, int y, const color_type& c, cover_type cover)
161 if(inbox(x, y))
163 m_ren->blend_pixel(x, y, c, cover);
167 //--------------------------------------------------------------------
168 color_type pixel(int x, int y) const
170 return inbox(x, y) ?
171 m_ren->pixel(x, y) :
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);
243 rc.normalize();
244 if(rc.clip(clip_box()))
246 int y;
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);
259 rc.normalize();
260 if(rc.clip(clip_box()))
262 int y;
263 for(y = rc.y1; y <= rc.y2; y++)
265 m_ren->blend_hline(rc.x1,
267 unsigned(rc.x2 - rc.x1 + 1),
269 cover);
274 //--------------------------------------------------------------------
275 void blend_solid_hspan(int x, int y, int len,
276 const color_type& c,
277 const cover_type* covers)
279 if(y > ymax()) return;
280 if(y < ymin()) return;
282 if(x < xmin())
284 len -= xmin() - x;
285 if(len <= 0) return;
286 covers += xmin() - x;
287 x = xmin();
289 if(x + len > xmax())
291 len = xmax() - x + 1;
292 if(len <= 0) return;
294 m_ren->blend_solid_hspan(x, y, len, c, covers);
297 //--------------------------------------------------------------------
298 void blend_solid_hspan_subpix(int x, int y, int len,
299 const color_type& c,
300 const cover_type* covers)
302 if(y > ymax()) return;
303 if(y < ymin()) return;
305 if(x < xmin())
307 len -= 3 * (xmin() - x);
308 if(len <= 0) return;
309 covers += 3 * (xmin() - x);
310 x = xmin();
312 if(x + len / 3 > xmax())
314 len = 3 * (xmax() - x + 1);
315 if(len <= 0) return;
317 m_ren->blend_solid_hspan_subpix(x, y, len, c, covers);
320 //--------------------------------------------------------------------
321 void blend_solid_vspan(int x, int y, int len,
322 const color_type& c,
323 const cover_type* covers)
325 if(x > xmax()) return;
326 if(x < xmin()) return;
328 if(y < ymin())
330 len -= ymin() - y;
331 if(len <= 0) return;
332 covers += ymin() - y;
333 y = ymin();
335 if(y + len > ymax())
337 len = ymax() - y + 1;
338 if(len <= 0) return;
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;
350 if(x < xmin())
352 int d = xmin() - x;
353 len -= d;
354 if(len <= 0) return;
355 colors += d;
356 x = xmin();
358 if(x + len > xmax())
360 len = xmax() - x + 1;
361 if(len <= 0) return;
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;
373 if(y < ymin())
375 int d = ymin() - y;
376 len -= d;
377 if(len <= 0) return;
378 colors += d;
379 y = ymin();
381 if(y + len > ymax())
383 len = ymax() - y + 1;
384 if(len <= 0) return;
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;
399 if(x < xmin())
401 int d = xmin() - x;
402 len -= d;
403 if(len <= 0) return;
404 if(covers) covers += d;
405 colors += d;
406 x = xmin();
408 if(x + len > xmax())
410 len = xmax() - x + 1;
411 if(len <= 0) return;
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;
425 if(y < ymin())
427 int d = ymin() - y;
428 len -= d;
429 if(len <= 0) return;
430 if(covers) covers += d;
431 colors += d;
432 y = ymin();
434 if(y + len > ymax())
436 len = ymax() - y + 1;
437 if(len <= 0) return;
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
445 rect_i rc(0,0,0,0);
446 rect_i cb = clip_box();
447 ++cb.x2;
448 ++cb.y2;
450 if(src.x1 < 0)
452 dst.x1 -= src.x1;
453 src.x1 = 0;
455 if(src.y1 < 0)
457 dst.y1 -= src.y1;
458 src.y1 = 0;
461 if(src.x2 > wsrc) src.x2 = wsrc;
462 if(src.y2 > hsrc) src.y2 = hsrc;
464 if(dst.x1 < cb.x1)
466 src.x1 += cb.x1 - dst.x1;
467 dst.x1 = cb.x1;
469 if(dst.y1 < cb.y1)
471 src.y1 += cb.y1 - dst.y1;
472 dst.y1 = cb.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;
483 return rc;
486 //--------------------------------------------------------------------
487 template<class RenBuf>
488 void copy_from(const RenBuf& src,
489 const rect_i* rect_src_ptr = 0,
490 int dx = 0,
491 int dy = 0)
493 rect_i rsrc(0, 0, src.width(), src.height());
494 if(rect_src_ptr)
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());
510 if(rc.x2 > 0)
512 int incy = 1;
513 if(rdst.y1 > rsrc.y1)
515 rsrc.y1 += rc.y2 - 1;
516 rdst.y1 += rc.y2 - 1;
517 incy = -1;
519 while(rc.y2 > 0)
521 m_ren->copy_from(src,
522 rdst.x1, rdst.y1,
523 rsrc.x1, rsrc.y1,
524 rc.x2);
525 rdst.y1 += incy;
526 rsrc.y1 += incy;
527 --rc.y2;
532 //--------------------------------------------------------------------
533 template<class SrcPixelFormatRenderer>
534 void blend_from(const SrcPixelFormatRenderer& src,
535 const rect_i* rect_src_ptr = 0,
536 int dx = 0,
537 int dy = 0,
538 cover_type cover = agg::cover_full)
540 rect_i rsrc(0, 0, src.width(), src.height());
541 if(rect_src_ptr)
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());
556 if(rc.x2 > 0)
558 int incy = 1;
559 if(rdst.y1 > rsrc.y1)
561 rsrc.y1 += rc.y2 - 1;
562 rdst.y1 += rc.y2 - 1;
563 incy = -1;
565 while(rc.y2 > 0)
567 typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
568 if(rw.ptr)
570 int x1src = rsrc.x1;
571 int x1dst = rdst.x1;
572 int len = rc.x2;
573 if(rw.x1 > x1src)
575 x1dst += rw.x1 - x1src;
576 len -= rw.x1 - x1src;
577 x1src = rw.x1;
579 if(len > 0)
581 if(x1src + len-1 > rw.x2)
583 len -= x1src + len - rw.x2 - 1;
585 if(len > 0)
587 m_ren->blend_from(src,
588 x1dst, rdst.y1,
589 x1src, rsrc.y1,
590 len,
591 cover);
595 rdst.y1 += incy;
596 rsrc.y1 += incy;
597 --rc.y2;
602 private:
603 pixfmt_type* m_ren;
604 rect_i m_clip_box;
610 #endif