Anti-Grain Geometry Tutorial
agg_renderer_base.h
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_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 
29  //-----------------------------------------------------------renderer_base
30  template<class PixelFormat> class renderer_base
31  {
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;
36 
37  //--------------------------------------------------------------------
38  renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {}
39  explicit renderer_base(pixfmt_type& ren) :
40  m_ren(&ren),
41  m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
42  {}
43  void attach(pixfmt_type& ren)
44  {
45  m_ren = &ren;
46  m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1);
47  }
48 
49  //--------------------------------------------------------------------
50  const pixfmt_type& ren() const { return *m_ren; }
51  pixfmt_type& ren() { return *m_ren; }
52 
53  //--------------------------------------------------------------------
54  unsigned width() const { return m_ren->width(); }
55  unsigned height() const { return m_ren->height(); }
56 
57  //--------------------------------------------------------------------
58  bool clip_box(int x1, int y1, int x2, int y2)
59  {
60  rect_i cb(x1, y1, x2, y2);
61  cb.normalize();
62  if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
63  {
64  m_clip_box = cb;
65  return true;
66  }
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;
72  }
73 
74  //--------------------------------------------------------------------
75  void reset_clipping(bool visibility)
76  {
77  if(visibility)
78  {
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;
83  }
84  else
85  {
86  m_clip_box.x1 = 1;
87  m_clip_box.y1 = 1;
88  m_clip_box.x2 = 0;
89  m_clip_box.y2 = 0;
90  }
91  }
92 
93  //--------------------------------------------------------------------
94  void clip_box_naked(int x1, int y1, int x2, int y2)
95  {
96  m_clip_box.x1 = x1;
97  m_clip_box.y1 = y1;
98  m_clip_box.x2 = x2;
99  m_clip_box.y2 = y2;
100  }
101 
102  //--------------------------------------------------------------------
103  bool inbox(int x, int y) const
104  {
105  return x >= m_clip_box.x1 && y >= m_clip_box.y1 &&
106  x <= m_clip_box.x2 && y <= m_clip_box.y2;
107  }
108 
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; }
115 
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; }
122 
123  //--------------------------------------------------------------------
124  void clear(const color_type& c)
125  {
126  unsigned y;
127  if(width())
128  {
129  for(y = 0; y < height(); y++)
130  {
131  m_ren->copy_hline(0, y, width(), c);
132  }
133  }
134  }
135 
136 
137  //--------------------------------------------------------------------
138  void fill(const color_type& c)
139  {
140  unsigned y;
141  if(width())
142  {
143  for(y = 0; y < height(); y++)
144  {
145  m_ren->blend_hline(0, y, width(), c, cover_mask);
146  }
147  }
148  }
149 
150  //--------------------------------------------------------------------
151  void copy_pixel(int x, int y, const color_type& c)
152  {
153  if(inbox(x, y))
154  {
155  m_ren->copy_pixel(x, y, c);
156  }
157  }
158 
159  //--------------------------------------------------------------------
160  void blend_pixel(int x, int y, const color_type& c, cover_type cover)
161  {
162  if(inbox(x, y))
163  {
164  m_ren->blend_pixel(x, y, c, cover);
165  }
166  }
167 
168  //--------------------------------------------------------------------
169  color_type pixel(int x, int y) const
170  {
171  return inbox(x, y) ?
172  m_ren->pixel(x, y) :
173  color_type::no_color();
174  }
175 
176  //--------------------------------------------------------------------
177  void copy_hline(int x1, int y, int x2, const color_type& c)
178  {
179  if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
180  if(y > ymax()) return;
181  if(y < ymin()) return;
182  if(x1 > xmax()) return;
183  if(x2 < xmin()) return;
184 
185  if(x1 < xmin()) x1 = xmin();
186  if(x2 > xmax()) x2 = xmax();
187 
188  m_ren->copy_hline(x1, y, x2 - x1 + 1, c);
189  }
190 
191  //--------------------------------------------------------------------
192  void copy_vline(int x, int y1, int y2, const color_type& c)
193  {
194  if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
195  if(x > xmax()) return;
196  if(x < xmin()) return;
197  if(y1 > ymax()) return;
198  if(y2 < ymin()) return;
199 
200  if(y1 < ymin()) y1 = ymin();
201  if(y2 > ymax()) y2 = ymax();
202 
203  m_ren->copy_vline(x, y1, y2 - y1 + 1, c);
204  }
205 
206  //--------------------------------------------------------------------
207  void blend_hline(int x1, int y, int x2,
208  const color_type& c, cover_type cover)
209  {
210  if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
211  if(y > ymax()) return;
212  if(y < ymin()) return;
213  if(x1 > xmax()) return;
214  if(x2 < xmin()) return;
215 
216  if(x1 < xmin()) x1 = xmin();
217  if(x2 > xmax()) x2 = xmax();
218 
219  m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover);
220  }
221 
222  //--------------------------------------------------------------------
223  void blend_vline(int x, int y1, int y2,
224  const color_type& c, cover_type cover)
225  {
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;
231 
232  if(y1 < ymin()) y1 = ymin();
233  if(y2 > ymax()) y2 = ymax();
234 
235  m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover);
236  }
237 
238 
239  //--------------------------------------------------------------------
240  void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
241  {
242  rect_i rc(x1, y1, x2, y2);
243  rc.normalize();
244  if(rc.clip(clip_box()))
245  {
246  int y;
247  for(y = rc.y1; y <= rc.y2; y++)
248  {
249  m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c);
250  }
251  }
252  }
253 
254  //--------------------------------------------------------------------
255  void blend_bar(int x1, int y1, int x2, int y2,
256  const color_type& c, cover_type cover)
257  {
258  rect_i rc(x1, y1, x2, y2);
259  rc.normalize();
260  if(rc.clip(clip_box()))
261  {
262  int y;
263  for(y = rc.y1; y <= rc.y2; y++)
264  {
265  m_ren->blend_hline(rc.x1,
266  y,
267  unsigned(rc.x2 - rc.x1 + 1),
268  c,
269  cover);
270  }
271  }
272  }
273 
274  //--------------------------------------------------------------------
275  void blend_solid_hspan(int x, int y, int len,
276  const color_type& c,
277  const cover_type* covers)
278  {
279  if(y > ymax()) return;
280  if(y < ymin()) return;
281 
282  if(x < xmin())
283  {
284  len -= xmin() - x;
285  if(len <= 0) return;
286  covers += xmin() - x;
287  x = xmin();
288  }
289  if(x + len > xmax())
290  {
291  len = xmax() - x + 1;
292  if(len <= 0) return;
293  }
294  m_ren->blend_solid_hspan(x, y, len, c, covers);
295  }
296 
297  //--------------------------------------------------------------------
298  void blend_solid_vspan(int x, int y, int len,
299  const color_type& c,
300  const cover_type* covers)
301  {
302  if(x > xmax()) return;
303  if(x < xmin()) return;
304 
305  if(y < ymin())
306  {
307  len -= ymin() - y;
308  if(len <= 0) return;
309  covers += ymin() - y;
310  y = ymin();
311  }
312  if(y + len > ymax())
313  {
314  len = ymax() - y + 1;
315  if(len <= 0) return;
316  }
317  m_ren->blend_solid_vspan(x, y, len, c, covers);
318  }
319 
320 
321  //--------------------------------------------------------------------
322  void copy_color_hspan(int x, int y, int len, const color_type* colors)
323  {
324  if(y > ymax()) return;
325  if(y < ymin()) return;
326 
327  if(x < xmin())
328  {
329  int d = xmin() - x;
330  len -= d;
331  if(len <= 0) return;
332  colors += d;
333  x = xmin();
334  }
335  if(x + len > xmax())
336  {
337  len = xmax() - x + 1;
338  if(len <= 0) return;
339  }
340  m_ren->copy_color_hspan(x, y, len, colors);
341  }
342 
343 
344  //--------------------------------------------------------------------
345  void copy_color_vspan(int x, int y, int len, const color_type* colors)
346  {
347  if(x > xmax()) return;
348  if(x < xmin()) return;
349 
350  if(y < ymin())
351  {
352  int d = ymin() - y;
353  len -= d;
354  if(len <= 0) return;
355  colors += d;
356  y = ymin();
357  }
358  if(y + len > ymax())
359  {
360  len = ymax() - y + 1;
361  if(len <= 0) return;
362  }
363  m_ren->copy_color_vspan(x, y, len, colors);
364  }
365 
366 
367  //--------------------------------------------------------------------
368  void blend_color_hspan(int x, int y, int len,
369  const color_type* colors,
370  const cover_type* covers,
371  cover_type cover = agg::cover_full)
372  {
373  if(y > ymax()) return;
374  if(y < ymin()) return;
375 
376  if(x < xmin())
377  {
378  int d = xmin() - x;
379  len -= d;
380  if(len <= 0) return;
381  if(covers) covers += d;
382  colors += d;
383  x = xmin();
384  }
385  if(x + len > xmax())
386  {
387  len = xmax() - x + 1;
388  if(len <= 0) return;
389  }
390  m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
391  }
392 
393  //--------------------------------------------------------------------
394  void blend_color_vspan(int x, int y, int len,
395  const color_type* colors,
396  const cover_type* covers,
397  cover_type cover = agg::cover_full)
398  {
399  if(x > xmax()) return;
400  if(x < xmin()) return;
401 
402  if(y < ymin())
403  {
404  int d = ymin() - y;
405  len -= d;
406  if(len <= 0) return;
407  if(covers) covers += d;
408  colors += d;
409  y = ymin();
410  }
411  if(y + len > ymax())
412  {
413  len = ymax() - y + 1;
414  if(len <= 0) return;
415  }
416  m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
417  }
418 
419  //--------------------------------------------------------------------
420  rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const
421  {
422  rect_i rc(0,0,0,0);
423  rect_i cb = clip_box();
424  ++cb.x2;
425  ++cb.y2;
426 
427  if(src.x1 < 0)
428  {
429  dst.x1 -= src.x1;
430  src.x1 = 0;
431  }
432  if(src.y1 < 0)
433  {
434  dst.y1 -= src.y1;
435  src.y1 = 0;
436  }
437 
438  if(src.x2 > wsrc) src.x2 = wsrc;
439  if(src.y2 > hsrc) src.y2 = hsrc;
440 
441  if(dst.x1 < cb.x1)
442  {
443  src.x1 += cb.x1 - dst.x1;
444  dst.x1 = cb.x1;
445  }
446  if(dst.y1 < cb.y1)
447  {
448  src.y1 += cb.y1 - dst.y1;
449  dst.y1 = cb.y1;
450  }
451 
452  if(dst.x2 > cb.x2) dst.x2 = cb.x2;
453  if(dst.y2 > cb.y2) dst.y2 = cb.y2;
454 
455  rc.x2 = dst.x2 - dst.x1;
456  rc.y2 = dst.y2 - dst.y1;
457 
458  if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1;
459  if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1;
460  return rc;
461  }
462 
463  //--------------------------------------------------------------------
464  template<class RenBuf>
465  void copy_from(const RenBuf& src,
466  const rect_i* rect_src_ptr = 0,
467  int dx = 0,
468  int dy = 0)
469  {
470  rect_i rsrc(0, 0, src.width(), src.height());
471  if(rect_src_ptr)
472  {
473  rsrc.x1 = rect_src_ptr->x1;
474  rsrc.y1 = rect_src_ptr->y1;
475  rsrc.x2 = rect_src_ptr->x2 + 1;
476  rsrc.y2 = rect_src_ptr->y2 + 1;
477  }
478 
479  // Version with xdst, ydst (absolute positioning)
480  //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
481 
482  // Version with dx, dy (relative positioning)
483  rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
484 
485  rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
486 
487  if(rc.x2 > 0)
488  {
489  int incy = 1;
490  if(rdst.y1 > rsrc.y1)
491  {
492  rsrc.y1 += rc.y2 - 1;
493  rdst.y1 += rc.y2 - 1;
494  incy = -1;
495  }
496  while(rc.y2 > 0)
497  {
498  m_ren->copy_from(src,
499  rdst.x1, rdst.y1,
500  rsrc.x1, rsrc.y1,
501  rc.x2);
502  rdst.y1 += incy;
503  rsrc.y1 += incy;
504  --rc.y2;
505  }
506  }
507  }
508 
509  //--------------------------------------------------------------------
510  template<class SrcPixelFormatRenderer>
511  void blend_from(const SrcPixelFormatRenderer& src,
512  const rect_i* rect_src_ptr = 0,
513  int dx = 0,
514  int dy = 0,
515  cover_type cover = agg::cover_full)
516  {
517  rect_i rsrc(0, 0, src.width(), src.height());
518  if(rect_src_ptr)
519  {
520  rsrc.x1 = rect_src_ptr->x1;
521  rsrc.y1 = rect_src_ptr->y1;
522  rsrc.x2 = rect_src_ptr->x2 + 1;
523  rsrc.y2 = rect_src_ptr->y2 + 1;
524  }
525 
526  // Version with xdst, ydst (absolute positioning)
527  //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
528 
529  // Version with dx, dy (relative positioning)
530  rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
531  rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
532 
533  if(rc.x2 > 0)
534  {
535  int incy = 1;
536  if(rdst.y1 > rsrc.y1)
537  {
538  rsrc.y1 += rc.y2 - 1;
539  rdst.y1 += rc.y2 - 1;
540  incy = -1;
541  }
542  while(rc.y2 > 0)
543  {
544  typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
545  if(rw.ptr)
546  {
547  int x1src = rsrc.x1;
548  int x1dst = rdst.x1;
549  int len = rc.x2;
550  if(rw.x1 > x1src)
551  {
552  x1dst += rw.x1 - x1src;
553  len -= rw.x1 - x1src;
554  x1src = rw.x1;
555  }
556  if(len > 0)
557  {
558  if(x1src + len-1 > rw.x2)
559  {
560  len -= x1src + len - rw.x2 - 1;
561  }
562  if(len > 0)
563  {
564  m_ren->blend_from(src,
565  x1dst, rdst.y1,
566  x1src, rsrc.y1,
567  len,
568  cover);
569  }
570  }
571  }
572  rdst.y1 += incy;
573  rsrc.y1 += incy;
574  --rc.y2;
575  }
576  }
577  }
578 
579  //--------------------------------------------------------------------
580  template<class SrcPixelFormatRenderer>
581  void blend_from_color(const SrcPixelFormatRenderer& src,
582  const color_type& color,
583  const rect_i* rect_src_ptr = 0,
584  int dx = 0,
585  int dy = 0,
586  cover_type cover = agg::cover_full)
587  {
588  rect_i rsrc(0, 0, src.width(), src.height());
589  if(rect_src_ptr)
590  {
591  rsrc.x1 = rect_src_ptr->x1;
592  rsrc.y1 = rect_src_ptr->y1;
593  rsrc.x2 = rect_src_ptr->x2 + 1;
594  rsrc.y2 = rect_src_ptr->y2 + 1;
595  }
596 
597  // Version with xdst, ydst (absolute positioning)
598  //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
599 
600  // Version with dx, dy (relative positioning)
601  rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
602  rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
603 
604  if(rc.x2 > 0)
605  {
606  int incy = 1;
607  if(rdst.y1 > rsrc.y1)
608  {
609  rsrc.y1 += rc.y2 - 1;
610  rdst.y1 += rc.y2 - 1;
611  incy = -1;
612  }
613  while(rc.y2 > 0)
614  {
615  typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
616  if(rw.ptr)
617  {
618  int x1src = rsrc.x1;
619  int x1dst = rdst.x1;
620  int len = rc.x2;
621  if(rw.x1 > x1src)
622  {
623  x1dst += rw.x1 - x1src;
624  len -= rw.x1 - x1src;
625  x1src = rw.x1;
626  }
627  if(len > 0)
628  {
629  if(x1src + len-1 > rw.x2)
630  {
631  len -= x1src + len - rw.x2 - 1;
632  }
633  if(len > 0)
634  {
635  m_ren->blend_from_color(src,
636  color,
637  x1dst, rdst.y1,
638  x1src, rsrc.y1,
639  len,
640  cover);
641  }
642  }
643  }
644  rdst.y1 += incy;
645  rsrc.y1 += incy;
646  --rc.y2;
647  }
648  }
649  }
650 
651  //--------------------------------------------------------------------
652  template<class SrcPixelFormatRenderer>
653  void blend_from_lut(const SrcPixelFormatRenderer& src,
654  const color_type* color_lut,
655  const rect_i* rect_src_ptr = 0,
656  int dx = 0,
657  int dy = 0,
658  cover_type cover = agg::cover_full)
659  {
660  rect_i rsrc(0, 0, src.width(), src.height());
661  if(rect_src_ptr)
662  {
663  rsrc.x1 = rect_src_ptr->x1;
664  rsrc.y1 = rect_src_ptr->y1;
665  rsrc.x2 = rect_src_ptr->x2 + 1;
666  rsrc.y2 = rect_src_ptr->y2 + 1;
667  }
668 
669  // Version with xdst, ydst (absolute positioning)
670  //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
671 
672  // Version with dx, dy (relative positioning)
673  rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
674  rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
675 
676  if(rc.x2 > 0)
677  {
678  int incy = 1;
679  if(rdst.y1 > rsrc.y1)
680  {
681  rsrc.y1 += rc.y2 - 1;
682  rdst.y1 += rc.y2 - 1;
683  incy = -1;
684  }
685  while(rc.y2 > 0)
686  {
687  typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1);
688  if(rw.ptr)
689  {
690  int x1src = rsrc.x1;
691  int x1dst = rdst.x1;
692  int len = rc.x2;
693  if(rw.x1 > x1src)
694  {
695  x1dst += rw.x1 - x1src;
696  len -= rw.x1 - x1src;
697  x1src = rw.x1;
698  }
699  if(len > 0)
700  {
701  if(x1src + len-1 > rw.x2)
702  {
703  len -= x1src + len - rw.x2 - 1;
704  }
705  if(len > 0)
706  {
707  m_ren->blend_from_lut(src,
708  color_lut,
709  x1dst, rdst.y1,
710  x1src, rsrc.y1,
711  len,
712  cover);
713  }
714  }
715  }
716  rdst.y1 += incy;
717  rsrc.y1 += incy;
718  --rc.y2;
719  }
720  }
721  }
722 
723  private:
724  pixfmt_type* m_ren;
725  rect_i m_clip_box;
726  };
727 
728 
729 }
730 
731 #endif
Definition: agg_arc.cpp:24