update dev300-m58
[ooovba.git] / agg / inc / agg_renderer_outline_aa.h
blobc93c23de3fffea3773eb2f45f6a858dfdff7ca7c
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
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 #ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED
16 #define AGG_RENDERER_OUTLINE_AA_INCLUDED
18 #include "agg_basics.h"
19 #include "agg_math.h"
20 #include "agg_line_aa_basics.h"
21 #include "agg_dda_line.h"
22 #include "agg_ellipse_bresenham.h"
23 #include "agg_renderer_base.h"
24 #include "agg_gamma_functions.h"
26 namespace agg
29 //===================================================distance_interpolator0
30 class distance_interpolator0
32 public:
33 //---------------------------------------------------------------------
34 distance_interpolator0() {}
35 distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) :
36 m_dx(line_mr(x2) - line_mr(x1)),
37 m_dy(line_mr(y2) - line_mr(y1)),
38 m_dist((line_mr(x + line_subpixel_size/2) - line_mr(x2)) * m_dy -
39 (line_mr(y + line_subpixel_size/2) - line_mr(y2)) * m_dx)
41 m_dx <<= line_mr_subpixel_shift;
42 m_dy <<= line_mr_subpixel_shift;
45 //---------------------------------------------------------------------
46 void inc_x() { m_dist += m_dy; }
47 void dec_x() { m_dist -= m_dy; }
48 void inc_y() { m_dist -= m_dx; }
49 void dec_y() { m_dist += m_dx; }
51 //---------------------------------------------------------------------
52 void inc_x(int _dy)
54 m_dist += m_dy;
55 if(_dy > 0) m_dist -= m_dx;
56 if(_dy < 0) m_dist += m_dx;
59 //---------------------------------------------------------------------
60 void dec_x(int _dy)
62 m_dist -= m_dy;
63 if(_dy > 0) m_dist -= m_dx;
64 if(_dy < 0) m_dist += m_dx;
67 //---------------------------------------------------------------------
68 void inc_y(int _dx)
70 m_dist -= m_dx;
71 if(_dx > 0) m_dist += m_dy;
72 if(_dx < 0) m_dist -= m_dy;
75 void dec_y(int _dx)
76 //---------------------------------------------------------------------
78 m_dist += m_dx;
79 if(_dx > 0) m_dist += m_dy;
80 if(_dx < 0) m_dist -= m_dy;
83 //---------------------------------------------------------------------
84 int dist() const { return m_dist; }
85 int dx() const { return m_dx; }
86 int dy() const { return m_dy; }
88 private:
89 //---------------------------------------------------------------------
90 int m_dx;
91 int m_dy;
92 int m_dist;
97 //===================================================distance_interpolator1
98 class distance_interpolator1
100 public:
101 //---------------------------------------------------------------------
102 distance_interpolator1() {}
103 distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) :
104 m_dx(x2 - x1),
105 m_dy(y2 - y1),
106 m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) -
107 double(y + line_subpixel_size/2 - y2) * double(m_dx)))
109 m_dx <<= line_subpixel_shift;
110 m_dy <<= line_subpixel_shift;
113 //---------------------------------------------------------------------
114 void inc_x() { m_dist += m_dy; }
115 void dec_x() { m_dist -= m_dy; }
116 void inc_y() { m_dist -= m_dx; }
117 void dec_y() { m_dist += m_dx; }
119 //---------------------------------------------------------------------
120 void inc_x(int _dy)
122 m_dist += m_dy;
123 if(_dy > 0) m_dist -= m_dx;
124 if(_dy < 0) m_dist += m_dx;
127 //---------------------------------------------------------------------
128 void dec_x(int _dy)
130 m_dist -= m_dy;
131 if(_dy > 0) m_dist -= m_dx;
132 if(_dy < 0) m_dist += m_dx;
135 //---------------------------------------------------------------------
136 void inc_y(int _dx)
138 m_dist -= m_dx;
139 if(_dx > 0) m_dist += m_dy;
140 if(_dx < 0) m_dist -= m_dy;
143 void dec_y(int _dx)
144 //---------------------------------------------------------------------
146 m_dist += m_dx;
147 if(_dx > 0) m_dist += m_dy;
148 if(_dx < 0) m_dist -= m_dy;
151 //---------------------------------------------------------------------
152 int dist() const { return m_dist; }
153 int dx() const { return m_dx; }
154 int dy() const { return m_dy; }
156 private:
157 //---------------------------------------------------------------------
158 int m_dx;
159 int m_dy;
160 int m_dist;
167 //===================================================distance_interpolator2
168 class distance_interpolator2
170 public:
171 //---------------------------------------------------------------------
172 distance_interpolator2() {}
173 distance_interpolator2(int x1, int y1, int x2, int y2,
174 int sx, int sy, int x, int y) :
175 m_dx(x2 - x1),
176 m_dy(y2 - y1),
177 m_dx_start(line_mr(sx) - line_mr(x1)),
178 m_dy_start(line_mr(sy) - line_mr(y1)),
180 m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) -
181 double(y + line_subpixel_size/2 - y2) * double(m_dx))),
183 m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start -
184 (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start)
186 m_dx <<= line_subpixel_shift;
187 m_dy <<= line_subpixel_shift;
188 m_dx_start <<= line_mr_subpixel_shift;
189 m_dy_start <<= line_mr_subpixel_shift;
192 distance_interpolator2(int x1, int y1, int x2, int y2,
193 int ex, int ey, int x, int y, int) :
194 m_dx(x2 - x1),
195 m_dy(y2 - y1),
196 m_dx_start(line_mr(ex) - line_mr(x2)),
197 m_dy_start(line_mr(ey) - line_mr(y2)),
199 m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) -
200 double(y + line_subpixel_size/2 - y2) * double(m_dx))),
202 m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_start -
203 (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_start)
205 m_dx <<= line_subpixel_shift;
206 m_dy <<= line_subpixel_shift;
207 m_dx_start <<= line_mr_subpixel_shift;
208 m_dy_start <<= line_mr_subpixel_shift;
212 //---------------------------------------------------------------------
213 void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; }
214 void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; }
215 void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; }
216 void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; }
218 //---------------------------------------------------------------------
219 void inc_x(int _dy)
221 m_dist += m_dy;
222 m_dist_start += m_dy_start;
223 if(_dy > 0)
225 m_dist -= m_dx;
226 m_dist_start -= m_dx_start;
228 if(_dy < 0)
230 m_dist += m_dx;
231 m_dist_start += m_dx_start;
235 //---------------------------------------------------------------------
236 void dec_x(int _dy)
238 m_dist -= m_dy;
239 m_dist_start -= m_dy_start;
240 if(_dy > 0)
242 m_dist -= m_dx;
243 m_dist_start -= m_dx_start;
245 if(_dy < 0)
247 m_dist += m_dx;
248 m_dist_start += m_dx_start;
252 //---------------------------------------------------------------------
253 void inc_y(int _dx)
255 m_dist -= m_dx;
256 m_dist_start -= m_dx_start;
257 if(_dx > 0)
259 m_dist += m_dy;
260 m_dist_start += m_dy_start;
262 if(_dx < 0)
264 m_dist -= m_dy;
265 m_dist_start -= m_dy_start;
269 //---------------------------------------------------------------------
270 void dec_y(int _dx)
272 m_dist += m_dx;
273 m_dist_start += m_dx_start;
274 if(_dx > 0)
276 m_dist += m_dy;
277 m_dist_start += m_dy_start;
279 if(_dx < 0)
281 m_dist -= m_dy;
282 m_dist_start -= m_dy_start;
286 //---------------------------------------------------------------------
287 int dist() const { return m_dist; }
288 int dist_start() const { return m_dist_start; }
289 int dist_end() const { return m_dist_start; }
291 //---------------------------------------------------------------------
292 int dx() const { return m_dx; }
293 int dy() const { return m_dy; }
294 int dx_start() const { return m_dx_start; }
295 int dy_start() const { return m_dy_start; }
296 int dx_end() const { return m_dx_start; }
297 int dy_end() const { return m_dy_start; }
299 private:
300 //---------------------------------------------------------------------
301 int m_dx;
302 int m_dy;
303 int m_dx_start;
304 int m_dy_start;
306 int m_dist;
307 int m_dist_start;
314 //===================================================distance_interpolator3
315 class distance_interpolator3
317 public:
318 //---------------------------------------------------------------------
319 distance_interpolator3() {}
320 distance_interpolator3(int x1, int y1, int x2, int y2,
321 int sx, int sy, int ex, int ey,
322 int x, int y) :
323 m_dx(x2 - x1),
324 m_dy(y2 - y1),
325 m_dx_start(line_mr(sx) - line_mr(x1)),
326 m_dy_start(line_mr(sy) - line_mr(y1)),
327 m_dx_end(line_mr(ex) - line_mr(x2)),
328 m_dy_end(line_mr(ey) - line_mr(y2)),
330 m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) -
331 double(y + line_subpixel_size/2 - y2) * double(m_dx))),
333 m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start -
334 (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start),
336 m_dist_end((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_end -
337 (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_end)
339 m_dx <<= line_subpixel_shift;
340 m_dy <<= line_subpixel_shift;
341 m_dx_start <<= line_mr_subpixel_shift;
342 m_dy_start <<= line_mr_subpixel_shift;
343 m_dx_end <<= line_mr_subpixel_shift;
344 m_dy_end <<= line_mr_subpixel_shift;
347 //---------------------------------------------------------------------
348 void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; }
349 void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; }
350 void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; }
351 void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; }
353 //---------------------------------------------------------------------
354 void inc_x(int _dy)
356 m_dist += m_dy;
357 m_dist_start += m_dy_start;
358 m_dist_end += m_dy_end;
359 if(_dy > 0)
361 m_dist -= m_dx;
362 m_dist_start -= m_dx_start;
363 m_dist_end -= m_dx_end;
365 if(_dy < 0)
367 m_dist += m_dx;
368 m_dist_start += m_dx_start;
369 m_dist_end += m_dx_end;
373 //---------------------------------------------------------------------
374 void dec_x(int _dy)
376 m_dist -= m_dy;
377 m_dist_start -= m_dy_start;
378 m_dist_end -= m_dy_end;
379 if(_dy > 0)
381 m_dist -= m_dx;
382 m_dist_start -= m_dx_start;
383 m_dist_end -= m_dx_end;
385 if(_dy < 0)
387 m_dist += m_dx;
388 m_dist_start += m_dx_start;
389 m_dist_end += m_dx_end;
393 //---------------------------------------------------------------------
394 void inc_y(int _dx)
396 m_dist -= m_dx;
397 m_dist_start -= m_dx_start;
398 m_dist_end -= m_dx_end;
399 if(_dx > 0)
401 m_dist += m_dy;
402 m_dist_start += m_dy_start;
403 m_dist_end += m_dy_end;
405 if(_dx < 0)
407 m_dist -= m_dy;
408 m_dist_start -= m_dy_start;
409 m_dist_end -= m_dy_end;
413 //---------------------------------------------------------------------
414 void dec_y(int _dx)
416 m_dist += m_dx;
417 m_dist_start += m_dx_start;
418 m_dist_end += m_dx_end;
419 if(_dx > 0)
421 m_dist += m_dy;
422 m_dist_start += m_dy_start;
423 m_dist_end += m_dy_end;
425 if(_dx < 0)
427 m_dist -= m_dy;
428 m_dist_start -= m_dy_start;
429 m_dist_end -= m_dy_end;
433 //---------------------------------------------------------------------
434 int dist() const { return m_dist; }
435 int dist_start() const { return m_dist_start; }
436 int dist_end() const { return m_dist_end; }
438 //---------------------------------------------------------------------
439 int dx() const { return m_dx; }
440 int dy() const { return m_dy; }
441 int dx_start() const { return m_dx_start; }
442 int dy_start() const { return m_dy_start; }
443 int dx_end() const { return m_dx_end; }
444 int dy_end() const { return m_dy_end; }
446 private:
447 //---------------------------------------------------------------------
448 int m_dx;
449 int m_dy;
450 int m_dx_start;
451 int m_dy_start;
452 int m_dx_end;
453 int m_dy_end;
455 int m_dist;
456 int m_dist_start;
457 int m_dist_end;
464 //================================================line_interpolator_aa_base
465 template<class Renderer> class line_interpolator_aa_base
467 public:
468 typedef Renderer renderer_type;
469 typedef typename Renderer::color_type color_type;
471 //---------------------------------------------------------------------
472 enum
474 max_half_width = 64
477 //---------------------------------------------------------------------
478 line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) :
479 m_lp(&lp),
480 m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
481 line_dbl_hr(lp.y2 - lp.y1),
482 lp.vertical ? abs(lp.y2 - lp.y1) :
483 abs(lp.x2 - lp.x1) + 1),
484 m_ren(ren),
485 m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len),
486 m_x(lp.x1 >> line_subpixel_shift),
487 m_y(lp.y1 >> line_subpixel_shift),
488 m_old_x(m_x),
489 m_old_y(m_y),
490 m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
491 abs((lp.x2 >> line_subpixel_shift) - m_x))),
492 m_width(ren.subpixel_width()),
493 m_max_extent(m_width >> (line_subpixel_shift - 2)),
494 m_step(0)
496 agg::dda2_line_interpolator li(0, lp.vertical ?
497 (lp.dy << agg::line_subpixel_shift) :
498 (lp.dx << agg::line_subpixel_shift),
499 lp.len);
501 unsigned i;
502 int stop = m_width + line_subpixel_size * 2;
503 for(i = 0; i < max_half_width; ++i)
505 m_dist[i] = li.y();
506 if(m_dist[i] >= stop) break;
507 ++li;
509 m_dist[i++] = 0x7FFF0000;
512 //---------------------------------------------------------------------
513 template<class DI> int step_hor_base(DI& di)
515 ++m_li;
516 m_x += m_lp->inc;
517 m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift;
519 if(m_lp->inc > 0) di.inc_x(m_y - m_old_y);
520 else di.dec_x(m_y - m_old_y);
522 m_old_y = m_y;
524 return di.dist() / m_len;
527 //---------------------------------------------------------------------
528 template<class DI> int step_ver_base(DI& di)
530 ++m_li;
531 m_y += m_lp->inc;
532 m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift;
534 if(m_lp->inc > 0) di.inc_y(m_x - m_old_x);
535 else di.dec_y(m_x - m_old_x);
537 m_old_x = m_x;
539 return di.dist() / m_len;
542 //---------------------------------------------------------------------
543 bool vertical() const { return m_lp->vertical; }
544 int width() const { return m_width; }
545 int count() const { return m_count; }
547 private:
548 line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&);
549 const line_interpolator_aa_base<Renderer>&
550 operator = (const line_interpolator_aa_base<Renderer>&);
552 protected:
553 const line_parameters* m_lp;
554 dda2_line_interpolator m_li;
555 renderer_type& m_ren;
556 int m_len;
557 int m_x;
558 int m_y;
559 int m_old_x;
560 int m_old_y;
561 int m_count;
562 int m_width;
563 int m_max_extent;
564 int m_step;
565 int m_dist[max_half_width + 1];
566 cover_type m_covers[max_half_width * 2 + 4];
575 //====================================================line_interpolator_aa0
576 template<class Renderer> class line_interpolator_aa0 :
577 public line_interpolator_aa_base<Renderer>
579 public:
580 typedef Renderer renderer_type;
581 typedef typename Renderer::color_type color_type;
582 typedef line_interpolator_aa_base<Renderer> base_type;
584 //---------------------------------------------------------------------
585 line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) :
586 line_interpolator_aa_base<Renderer>(ren, lp),
587 m_di(lp.x1, lp.y1, lp.x2, lp.y2,
588 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
590 base_type::m_li.adjust_forward();
593 //---------------------------------------------------------------------
594 bool step_hor()
596 int dist;
597 int dy;
598 int s1 = base_type::step_hor_base(m_di);
599 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
600 cover_type* p1 = p0;
602 *p1++ = (cover_type)base_type::m_ren.cover(s1);
604 dy = 1;
605 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
607 *p1++ = (cover_type)base_type::m_ren.cover(dist);
608 ++dy;
611 dy = 1;
612 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
614 *--p0 = (cover_type)base_type::m_ren.cover(dist);
615 ++dy;
617 base_type::m_ren.blend_solid_vspan(base_type::m_x,
618 base_type::m_y - dy + 1,
619 unsigned(p1 - p0),
620 p0);
621 return ++base_type::m_step < base_type::m_count;
624 //---------------------------------------------------------------------
625 bool step_ver()
627 int dist;
628 int dx;
629 int s1 = base_type::step_ver_base(m_di);
630 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
631 cover_type* p1 = p0;
633 *p1++ = (cover_type)base_type::m_ren.cover(s1);
635 dx = 1;
636 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
638 *p1++ = (cover_type)base_type::m_ren.cover(dist);
639 ++dx;
642 dx = 1;
643 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
645 *--p0 = (cover_type)base_type::m_ren.cover(dist);
646 ++dx;
648 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
649 base_type::m_y,
650 unsigned(p1 - p0),
651 p0);
652 return ++base_type::m_step < base_type::m_count;
655 private:
656 line_interpolator_aa0(const line_interpolator_aa0<Renderer>&);
657 const line_interpolator_aa0<Renderer>&
658 operator = (const line_interpolator_aa0<Renderer>&);
660 //---------------------------------------------------------------------
661 distance_interpolator1 m_di;
669 //====================================================line_interpolator_aa1
670 template<class Renderer> class line_interpolator_aa1 :
671 public line_interpolator_aa_base<Renderer>
673 public:
674 typedef Renderer renderer_type;
675 typedef typename Renderer::color_type color_type;
676 typedef line_interpolator_aa_base<Renderer> base_type;
678 //---------------------------------------------------------------------
679 line_interpolator_aa1(renderer_type& ren, const line_parameters& lp,
680 int sx, int sy) :
681 line_interpolator_aa_base<Renderer>(ren, lp),
682 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy,
683 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
685 int dist1_start;
686 int dist2_start;
688 int npix = 1;
690 if(lp.vertical)
694 --base_type::m_li;
695 base_type::m_y -= lp.inc;
696 base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
698 if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
699 else m_di.inc_y(base_type::m_x - base_type::m_old_x);
701 base_type::m_old_x = base_type::m_x;
703 dist1_start = dist2_start = m_di.dist_start();
705 int dx = 0;
706 if(dist1_start < 0) ++npix;
709 dist1_start += m_di.dy_start();
710 dist2_start -= m_di.dy_start();
711 if(dist1_start < 0) ++npix;
712 if(dist2_start < 0) ++npix;
713 ++dx;
715 while(base_type::m_dist[dx] <= base_type::m_width);
716 --base_type::m_step;
717 if(npix == 0) break;
718 npix = 0;
720 while(base_type::m_step >= -base_type::m_max_extent);
722 else
726 --base_type::m_li;
727 base_type::m_x -= lp.inc;
728 base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
730 if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
731 else m_di.inc_x(base_type::m_y - base_type::m_old_y);
733 base_type::m_old_y = base_type::m_y;
735 dist1_start = dist2_start = m_di.dist_start();
737 int dy = 0;
738 if(dist1_start < 0) ++npix;
741 dist1_start -= m_di.dx_start();
742 dist2_start += m_di.dx_start();
743 if(dist1_start < 0) ++npix;
744 if(dist2_start < 0) ++npix;
745 ++dy;
747 while(base_type::m_dist[dy] <= base_type::m_width);
748 --base_type::m_step;
749 if(npix == 0) break;
750 npix = 0;
752 while(base_type::m_step >= -base_type::m_max_extent);
754 base_type::m_li.adjust_forward();
757 //---------------------------------------------------------------------
758 bool step_hor()
760 int dist_start;
761 int dist;
762 int dy;
763 int s1 = base_type::step_hor_base(m_di);
765 dist_start = m_di.dist_start();
766 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
767 cover_type* p1 = p0;
769 *p1 = 0;
770 if(dist_start <= 0)
772 *p1 = (cover_type)base_type::m_ren.cover(s1);
774 ++p1;
776 dy = 1;
777 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
779 dist_start -= m_di.dx_start();
780 *p1 = 0;
781 if(dist_start <= 0)
783 *p1 = (cover_type)base_type::m_ren.cover(dist);
785 ++p1;
786 ++dy;
789 dy = 1;
790 dist_start = m_di.dist_start();
791 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
793 dist_start += m_di.dx_start();
794 *--p0 = 0;
795 if(dist_start <= 0)
797 *p0 = (cover_type)base_type::m_ren.cover(dist);
799 ++dy;
802 base_type::m_ren.blend_solid_vspan(base_type::m_x,
803 base_type::m_y - dy + 1,
804 unsigned(p1 - p0),
805 p0);
806 return ++base_type::m_step < base_type::m_count;
809 //---------------------------------------------------------------------
810 bool step_ver()
812 int dist_start;
813 int dist;
814 int dx;
815 int s1 = base_type::step_ver_base(m_di);
816 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
817 cover_type* p1 = p0;
819 dist_start = m_di.dist_start();
821 *p1 = 0;
822 if(dist_start <= 0)
824 *p1 = (cover_type)base_type::m_ren.cover(s1);
826 ++p1;
828 dx = 1;
829 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
831 dist_start += m_di.dy_start();
832 *p1 = 0;
833 if(dist_start <= 0)
835 *p1 = (cover_type)base_type::m_ren.cover(dist);
837 ++p1;
838 ++dx;
841 dx = 1;
842 dist_start = m_di.dist_start();
843 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
845 dist_start -= m_di.dy_start();
846 *--p0 = 0;
847 if(dist_start <= 0)
849 *p0 = (cover_type)base_type::m_ren.cover(dist);
851 ++dx;
853 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
854 base_type::m_y,
855 unsigned(p1 - p0),
856 p0);
857 return ++base_type::m_step < base_type::m_count;
860 private:
861 line_interpolator_aa1(const line_interpolator_aa1<Renderer>&);
862 const line_interpolator_aa1<Renderer>&
863 operator = (const line_interpolator_aa1<Renderer>&);
865 //---------------------------------------------------------------------
866 distance_interpolator2 m_di;
880 //====================================================line_interpolator_aa2
881 template<class Renderer> class line_interpolator_aa2 :
882 public line_interpolator_aa_base<Renderer>
884 public:
885 typedef Renderer renderer_type;
886 typedef typename Renderer::color_type color_type;
887 typedef line_interpolator_aa_base<Renderer> base_type;
889 //---------------------------------------------------------------------
890 line_interpolator_aa2(renderer_type& ren, const line_parameters& lp,
891 int ex, int ey) :
892 line_interpolator_aa_base<Renderer>(ren, lp),
893 m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey,
894 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask,
897 base_type::m_li.adjust_forward();
898 base_type::m_step -= base_type::m_max_extent;
901 //---------------------------------------------------------------------
902 bool step_hor()
904 int dist_end;
905 int dist;
906 int dy;
907 int s1 = base_type::step_hor_base(m_di);
908 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
909 cover_type* p1 = p0;
911 dist_end = m_di.dist_end();
913 int npix = 0;
914 *p1 = 0;
915 if(dist_end > 0)
917 *p1 = (cover_type)base_type::m_ren.cover(s1);
918 ++npix;
920 ++p1;
922 dy = 1;
923 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
925 dist_end -= m_di.dx_end();
926 *p1 = 0;
927 if(dist_end > 0)
929 *p1 = (cover_type)base_type::m_ren.cover(dist);
930 ++npix;
932 ++p1;
933 ++dy;
936 dy = 1;
937 dist_end = m_di.dist_end();
938 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
940 dist_end += m_di.dx_end();
941 *--p0 = 0;
942 if(dist_end > 0)
944 *p0 = (cover_type)base_type::m_ren.cover(dist);
945 ++npix;
947 ++dy;
949 base_type::m_ren.blend_solid_vspan(base_type::m_x,
950 base_type::m_y - dy + 1,
951 unsigned(p1 - p0),
952 p0);
953 return npix && ++base_type::m_step < base_type::m_count;
956 //---------------------------------------------------------------------
957 bool step_ver()
959 int dist_end;
960 int dist;
961 int dx;
962 int s1 = base_type::step_ver_base(m_di);
963 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
964 cover_type* p1 = p0;
966 dist_end = m_di.dist_end();
968 int npix = 0;
969 *p1 = 0;
970 if(dist_end > 0)
972 *p1 = (cover_type)base_type::m_ren.cover(s1);
973 ++npix;
975 ++p1;
977 dx = 1;
978 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
980 dist_end += m_di.dy_end();
981 *p1 = 0;
982 if(dist_end > 0)
984 *p1 = (cover_type)base_type::m_ren.cover(dist);
985 ++npix;
987 ++p1;
988 ++dx;
991 dx = 1;
992 dist_end = m_di.dist_end();
993 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
995 dist_end -= m_di.dy_end();
996 *--p0 = 0;
997 if(dist_end > 0)
999 *p0 = (cover_type)base_type::m_ren.cover(dist);
1000 ++npix;
1002 ++dx;
1004 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
1005 base_type::m_y,
1006 unsigned(p1 - p0),
1007 p0);
1008 return npix && ++base_type::m_step < base_type::m_count;
1011 private:
1012 line_interpolator_aa2(const line_interpolator_aa2<Renderer>&);
1013 const line_interpolator_aa2<Renderer>&
1014 operator = (const line_interpolator_aa2<Renderer>&);
1016 //---------------------------------------------------------------------
1017 distance_interpolator2 m_di;
1029 //====================================================line_interpolator_aa3
1030 template<class Renderer> class line_interpolator_aa3 :
1031 public line_interpolator_aa_base<Renderer>
1033 public:
1034 typedef Renderer renderer_type;
1035 typedef typename Renderer::color_type color_type;
1036 typedef line_interpolator_aa_base<Renderer> base_type;
1038 //---------------------------------------------------------------------
1039 line_interpolator_aa3(renderer_type& ren, const line_parameters& lp,
1040 int sx, int sy, int ex, int ey) :
1041 line_interpolator_aa_base<Renderer>(ren, lp),
1042 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey,
1043 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
1045 int dist1_start;
1046 int dist2_start;
1047 int npix = 1;
1048 if(lp.vertical)
1052 --base_type::m_li;
1053 base_type::m_y -= lp.inc;
1054 base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
1056 if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
1057 else m_di.inc_y(base_type::m_x - base_type::m_old_x);
1059 base_type::m_old_x = base_type::m_x;
1061 dist1_start = dist2_start = m_di.dist_start();
1063 int dx = 0;
1064 if(dist1_start < 0) ++npix;
1067 dist1_start += m_di.dy_start();
1068 dist2_start -= m_di.dy_start();
1069 if(dist1_start < 0) ++npix;
1070 if(dist2_start < 0) ++npix;
1071 ++dx;
1073 while(base_type::m_dist[dx] <= base_type::m_width);
1074 if(npix == 0) break;
1075 npix = 0;
1077 while(--base_type::m_step >= -base_type::m_max_extent);
1079 else
1083 --base_type::m_li;
1084 base_type::m_x -= lp.inc;
1085 base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
1087 if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
1088 else m_di.inc_x(base_type::m_y - base_type::m_old_y);
1090 base_type::m_old_y = base_type::m_y;
1092 dist1_start = dist2_start = m_di.dist_start();
1094 int dy = 0;
1095 if(dist1_start < 0) ++npix;
1098 dist1_start -= m_di.dx_start();
1099 dist2_start += m_di.dx_start();
1100 if(dist1_start < 0) ++npix;
1101 if(dist2_start < 0) ++npix;
1102 ++dy;
1104 while(base_type::m_dist[dy] <= base_type::m_width);
1105 if(npix == 0) break;
1106 npix = 0;
1108 while(--base_type::m_step >= -base_type::m_max_extent);
1110 base_type::m_li.adjust_forward();
1111 base_type::m_step -= base_type::m_max_extent;
1115 //---------------------------------------------------------------------
1116 bool step_hor()
1118 int dist_start;
1119 int dist_end;
1120 int dist;
1121 int dy;
1122 int s1 = base_type::step_hor_base(m_di);
1123 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
1124 cover_type* p1 = p0;
1126 dist_start = m_di.dist_start();
1127 dist_end = m_di.dist_end();
1129 int npix = 0;
1130 *p1 = 0;
1131 if(dist_end > 0)
1133 if(dist_start <= 0)
1135 *p1 = (cover_type)base_type::m_ren.cover(s1);
1137 ++npix;
1139 ++p1;
1141 dy = 1;
1142 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
1144 dist_start -= m_di.dx_start();
1145 dist_end -= m_di.dx_end();
1146 *p1 = 0;
1147 if(dist_end > 0 && dist_start <= 0)
1149 *p1 = (cover_type)base_type::m_ren.cover(dist);
1150 ++npix;
1152 ++p1;
1153 ++dy;
1156 dy = 1;
1157 dist_start = m_di.dist_start();
1158 dist_end = m_di.dist_end();
1159 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
1161 dist_start += m_di.dx_start();
1162 dist_end += m_di.dx_end();
1163 *--p0 = 0;
1164 if(dist_end > 0 && dist_start <= 0)
1166 *p0 = (cover_type)base_type::m_ren.cover(dist);
1167 ++npix;
1169 ++dy;
1171 base_type::m_ren.blend_solid_vspan(base_type::m_x,
1172 base_type::m_y - dy + 1,
1173 unsigned(p1 - p0),
1174 p0);
1175 return npix && ++base_type::m_step < base_type::m_count;
1178 //---------------------------------------------------------------------
1179 bool step_ver()
1181 int dist_start;
1182 int dist_end;
1183 int dist;
1184 int dx;
1185 int s1 = base_type::step_ver_base(m_di);
1186 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
1187 cover_type* p1 = p0;
1189 dist_start = m_di.dist_start();
1190 dist_end = m_di.dist_end();
1192 int npix = 0;
1193 *p1 = 0;
1194 if(dist_end > 0)
1196 if(dist_start <= 0)
1198 *p1 = (cover_type)base_type::m_ren.cover(s1);
1200 ++npix;
1202 ++p1;
1204 dx = 1;
1205 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
1207 dist_start += m_di.dy_start();
1208 dist_end += m_di.dy_end();
1209 *p1 = 0;
1210 if(dist_end > 0 && dist_start <= 0)
1212 *p1 = (cover_type)base_type::m_ren.cover(dist);
1213 ++npix;
1215 ++p1;
1216 ++dx;
1219 dx = 1;
1220 dist_start = m_di.dist_start();
1221 dist_end = m_di.dist_end();
1222 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
1224 dist_start -= m_di.dy_start();
1225 dist_end -= m_di.dy_end();
1226 *--p0 = 0;
1227 if(dist_end > 0 && dist_start <= 0)
1229 *p0 = (cover_type)base_type::m_ren.cover(dist);
1230 ++npix;
1232 ++dx;
1234 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
1235 base_type::m_y,
1236 unsigned(p1 - p0),
1237 p0);
1238 return npix && ++base_type::m_step < base_type::m_count;
1241 private:
1242 line_interpolator_aa3(const line_interpolator_aa3<Renderer>&);
1243 const line_interpolator_aa3<Renderer>&
1244 operator = (const line_interpolator_aa3<Renderer>&);
1246 //---------------------------------------------------------------------
1247 distance_interpolator3 m_di;
1253 //==========================================================line_profile_aa
1255 // See Implementation agg_line_profile_aa.cpp
1257 class line_profile_aa
1259 public:
1260 //---------------------------------------------------------------------
1261 typedef int8u value_type;
1262 enum
1264 subpixel_shift = line_subpixel_shift,
1265 subpixel_size = 1 << subpixel_shift,
1266 subpixel_mask = subpixel_size - 1
1269 enum
1271 aa_shift = 8,
1272 aa_num = 1 << aa_shift,
1273 aa_mask = aa_num - 1
1276 //---------------------------------------------------------------------
1277 ~line_profile_aa() { delete [] m_profile; }
1279 //---------------------------------------------------------------------
1280 line_profile_aa() :
1281 m_size(0),
1282 m_profile(0),
1283 m_subpixel_width(0),
1284 m_min_width(1.0),
1285 m_smoother_width(1.0)
1287 int i;
1288 for(i = 0; i < aa_num; i++) m_gamma[i] = (value_type)i;
1291 //---------------------------------------------------------------------
1292 template<class GammaF>
1293 line_profile_aa(double w, const GammaF& gamma_function) :
1294 m_size(0),
1295 m_profile(0),
1296 m_subpixel_width(0),
1297 m_min_width(1.0),
1298 m_smoother_width(1.0)
1300 gamma(gamma_function);
1301 width(w);
1304 //---------------------------------------------------------------------
1305 void min_width(double w) { m_min_width = w; }
1306 void smoother_width(double w) { m_smoother_width = w; }
1308 //---------------------------------------------------------------------
1309 template<class GammaF> void gamma(const GammaF& gamma_function)
1311 int i;
1312 for(i = 0; i < aa_num; i++)
1314 m_gamma[i] = value_type(
1315 floor(
1316 gamma_function(double(i) / aa_mask) * aa_mask + 0.5));
1320 void width(double w);
1322 unsigned profile_size() const { return m_size; }
1323 int subpixel_width() const { return m_subpixel_width; }
1325 //---------------------------------------------------------------------
1326 double min_width() const { return m_min_width; }
1327 double smoother_width() const { return m_smoother_width; }
1329 //---------------------------------------------------------------------
1330 value_type value(int dist) const
1332 return m_profile[dist + subpixel_size*2];
1335 private:
1336 line_profile_aa(const line_profile_aa&);
1337 const line_profile_aa& operator = (const line_profile_aa&);
1339 value_type* profile(double w);
1340 void set(double center_width, double smoother_width);
1342 //---------------------------------------------------------------------
1343 unsigned m_size;
1344 value_type* m_profile;
1345 value_type m_gamma[aa_num];
1346 int m_subpixel_width;
1347 double m_min_width;
1348 double m_smoother_width;
1352 //======================================================renderer_outline_aa
1353 template<class BaseRenderer> class renderer_outline_aa
1355 public:
1356 //---------------------------------------------------------------------
1357 typedef BaseRenderer base_ren_type;
1358 typedef renderer_outline_aa<base_ren_type> self_type;
1359 typedef typename base_ren_type::color_type color_type;
1361 //---------------------------------------------------------------------
1362 renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) :
1363 m_ren(&ren),
1364 m_profile(&prof)
1368 //---------------------------------------------------------------------
1369 void color(const color_type& c) { m_color = c; }
1370 const color_type& color() const { return m_color; }
1372 //---------------------------------------------------------------------
1373 void profile(const line_profile_aa& prof) { m_profile = &prof; }
1374 const line_profile_aa& profile() const { return *m_profile; }
1375 line_profile_aa& profile() { return const_cast<line_profile_aa&>(*m_profile); }
1377 //---------------------------------------------------------------------
1378 int subpixel_width() const { return m_profile->subpixel_width(); }
1380 //---------------------------------------------------------------------
1381 int cover(int d) const
1383 return m_profile->value(d);
1386 //-------------------------------------------------------------------------
1387 void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers)
1389 m_ren->blend_solid_hspan(x, y, len, m_color, covers);
1392 //-------------------------------------------------------------------------
1393 void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers)
1395 m_ren->blend_solid_vspan(x, y, len, m_color, covers);
1398 //-------------------------------------------------------------------------
1399 static bool accurate_join_only() { return false; }
1401 //-------------------------------------------------------------------------
1402 template<class Cmp>
1403 void semidot_hline(Cmp cmp,
1404 int xc1, int yc1, int xc2, int yc2,
1405 int x1, int y1, int x2)
1407 cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
1408 cover_type* p0 = covers;
1409 cover_type* p1 = covers;
1410 int x = x1 << line_subpixel_shift;
1411 int y = y1 << line_subpixel_shift;
1412 int w = subpixel_width();
1413 distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y);
1414 x += line_subpixel_size/2;
1415 y += line_subpixel_size/2;
1417 int x0 = x1;
1418 int dx = x - xc1;
1419 int dy = y - yc1;
1422 int d = int(fast_sqrt(dx*dx + dy*dy));
1423 *p1 = 0;
1424 if(cmp(di.dist()) && d <= w)
1426 *p1 = (cover_type)cover(d);
1428 ++p1;
1429 dx += line_subpixel_size;
1430 di.inc_x();
1432 while(++x1 <= x2);
1433 m_ren->blend_solid_hspan(x0, y1,
1434 unsigned(p1 - p0),
1435 color(),
1436 p0);
1439 //-------------------------------------------------------------------------
1440 template<class Cmp>
1441 void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2)
1443 int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1444 if(r < 1) r = 1;
1445 ellipse_bresenham_interpolator ei(r, r);
1446 int dx = 0;
1447 int dy = -r;
1448 int dy0 = dy;
1449 int dx0 = dx;
1450 int x = xc1 >> line_subpixel_shift;
1451 int y = yc1 >> line_subpixel_shift;
1455 dx += ei.dx();
1456 dy += ei.dy();
1458 if(dy != dy0)
1460 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1461 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0);
1463 dx0 = dx;
1464 dy0 = dy;
1465 ++ei;
1467 while(dy < 0);
1468 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1471 //-------------------------------------------------------------------------
1472 void line0(const line_parameters& lp)
1474 line_interpolator_aa0<self_type> li(*this, lp);
1475 if(li.count())
1477 if(li.vertical())
1479 while(li.step_ver()) ;
1481 else
1483 while(li.step_hor()) ;
1488 //-------------------------------------------------------------------------
1489 void line1(const line_parameters& lp, int sx, int sy)
1491 fix_degenerate_bisectrix_start(lp, &sx, &sy);
1492 line_interpolator_aa1<self_type> li(*this, lp, sx, sy);
1493 if(li.vertical())
1495 while(li.step_ver()) ;
1497 else
1499 while(li.step_hor()) ;
1503 //-------------------------------------------------------------------------
1504 void line2(const line_parameters& lp, int ex, int ey)
1506 fix_degenerate_bisectrix_end(lp, &ex, &ey);
1507 line_interpolator_aa2<self_type> li(*this, lp, ex, ey);
1508 if(li.vertical())
1510 while(li.step_ver()) ;
1512 else
1514 while(li.step_hor()) ;
1518 //-------------------------------------------------------------------------
1519 void line3(const line_parameters& lp,
1520 int sx, int sy, int ex, int ey)
1522 fix_degenerate_bisectrix_start(lp, &sx, &sy);
1523 fix_degenerate_bisectrix_end(lp, &ex, &ey);
1524 line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey);
1525 if(li.vertical())
1527 while(li.step_ver()) ;
1529 else
1531 while(li.step_hor()) ;
1535 private:
1536 base_ren_type* m_ren;
1537 const line_profile_aa* m_profile;
1538 color_type m_color;
1545 #endif