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 //----------------------------------------------------------------------------
15 #ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED
16 #define AGG_RENDERER_OUTLINE_AA_INCLUDED
18 #include "agg_basics.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"
29 //===================================================distance_interpolator0
30 class distance_interpolator0
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 //---------------------------------------------------------------------
55 if(_dy
> 0) m_dist
-= m_dx
;
56 if(_dy
< 0) m_dist
+= m_dx
;
59 //---------------------------------------------------------------------
63 if(_dy
> 0) m_dist
-= m_dx
;
64 if(_dy
< 0) m_dist
+= m_dx
;
67 //---------------------------------------------------------------------
71 if(_dx
> 0) m_dist
+= m_dy
;
72 if(_dx
< 0) m_dist
-= m_dy
;
76 //---------------------------------------------------------------------
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
; }
89 //---------------------------------------------------------------------
97 //===================================================distance_interpolator1
98 class distance_interpolator1
101 //---------------------------------------------------------------------
102 distance_interpolator1() {}
103 distance_interpolator1(int x1
, int y1
, int x2
, int y2
, int x
, int y
) :
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 //---------------------------------------------------------------------
123 if(_dy
> 0) m_dist
-= m_dx
;
124 if(_dy
< 0) m_dist
+= m_dx
;
127 //---------------------------------------------------------------------
131 if(_dy
> 0) m_dist
-= m_dx
;
132 if(_dy
< 0) m_dist
+= m_dx
;
135 //---------------------------------------------------------------------
139 if(_dx
> 0) m_dist
+= m_dy
;
140 if(_dx
< 0) m_dist
-= m_dy
;
144 //---------------------------------------------------------------------
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
; }
157 //---------------------------------------------------------------------
167 //===================================================distance_interpolator2
168 class distance_interpolator2
171 //---------------------------------------------------------------------
172 distance_interpolator2() {}
173 distance_interpolator2(int x1
, int y1
, int x2
, int y2
,
174 int sx
, int sy
, int x
, int y
) :
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) :
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 //---------------------------------------------------------------------
222 m_dist_start
+= m_dy_start
;
226 m_dist_start
-= m_dx_start
;
231 m_dist_start
+= m_dx_start
;
235 //---------------------------------------------------------------------
239 m_dist_start
-= m_dy_start
;
243 m_dist_start
-= m_dx_start
;
248 m_dist_start
+= m_dx_start
;
252 //---------------------------------------------------------------------
256 m_dist_start
-= m_dx_start
;
260 m_dist_start
+= m_dy_start
;
265 m_dist_start
-= m_dy_start
;
269 //---------------------------------------------------------------------
273 m_dist_start
+= m_dx_start
;
277 m_dist_start
+= m_dy_start
;
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
; }
300 //---------------------------------------------------------------------
314 //===================================================distance_interpolator3
315 class distance_interpolator3
318 //---------------------------------------------------------------------
319 distance_interpolator3() {}
320 distance_interpolator3(int x1
, int y1
, int x2
, int y2
,
321 int sx
, int sy
, int ex
, int ey
,
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 //---------------------------------------------------------------------
357 m_dist_start
+= m_dy_start
;
358 m_dist_end
+= m_dy_end
;
362 m_dist_start
-= m_dx_start
;
363 m_dist_end
-= m_dx_end
;
368 m_dist_start
+= m_dx_start
;
369 m_dist_end
+= m_dx_end
;
373 //---------------------------------------------------------------------
377 m_dist_start
-= m_dy_start
;
378 m_dist_end
-= m_dy_end
;
382 m_dist_start
-= m_dx_start
;
383 m_dist_end
-= m_dx_end
;
388 m_dist_start
+= m_dx_start
;
389 m_dist_end
+= m_dx_end
;
393 //---------------------------------------------------------------------
397 m_dist_start
-= m_dx_start
;
398 m_dist_end
-= m_dx_end
;
402 m_dist_start
+= m_dy_start
;
403 m_dist_end
+= m_dy_end
;
408 m_dist_start
-= m_dy_start
;
409 m_dist_end
-= m_dy_end
;
413 //---------------------------------------------------------------------
417 m_dist_start
+= m_dx_start
;
418 m_dist_end
+= m_dx_end
;
422 m_dist_start
+= m_dy_start
;
423 m_dist_end
+= m_dy_end
;
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
; }
447 //---------------------------------------------------------------------
464 //================================================line_interpolator_aa_base
465 template<class Renderer
> class line_interpolator_aa_base
468 typedef Renderer renderer_type
;
469 typedef typename
Renderer::color_type color_type
;
471 //---------------------------------------------------------------------
477 //---------------------------------------------------------------------
478 line_interpolator_aa_base(renderer_type
& ren
, const line_parameters
& 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),
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
),
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)),
496 agg::dda2_line_interpolator
li(0, lp
.vertical
?
497 (lp
.dy
<< agg::line_subpixel_shift
) :
498 (lp
.dx
<< agg::line_subpixel_shift
),
502 int stop
= m_width
+ line_subpixel_size
* 2;
503 for(i
= 0; i
< max_half_width
; ++i
)
506 if(m_dist
[i
] >= stop
) break;
509 m_dist
[i
++] = 0x7FFF0000;
512 //---------------------------------------------------------------------
513 template<class DI
> int step_hor_base(DI
& di
)
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
);
524 return di
.dist() / m_len
;
527 //---------------------------------------------------------------------
528 template<class DI
> int step_ver_base(DI
& di
)
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
);
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
; }
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
>&);
553 const line_parameters
* m_lp
;
554 dda2_line_interpolator m_li
;
555 renderer_type
& m_ren
;
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
>
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 //---------------------------------------------------------------------
598 int s1
= base_type::step_hor_base(m_di
);
599 cover_type
* p0
= base_type::m_covers
+ base_type::max_half_width
+ 2;
602 *p1
++ = (cover_type
)base_type::m_ren
.cover(s1
);
605 while((dist
= base_type::m_dist
[dy
] - s1
) <= base_type::m_width
)
607 *p1
++ = (cover_type
)base_type::m_ren
.cover(dist
);
612 while((dist
= base_type::m_dist
[dy
] + s1
) <= base_type::m_width
)
614 *--p0
= (cover_type
)base_type::m_ren
.cover(dist
);
617 base_type::m_ren
.blend_solid_vspan(base_type::m_x
,
618 base_type::m_y
- dy
+ 1,
621 return ++base_type::m_step
< base_type::m_count
;
624 //---------------------------------------------------------------------
629 int s1
= base_type::step_ver_base(m_di
);
630 cover_type
* p0
= base_type::m_covers
+ base_type::max_half_width
+ 2;
633 *p1
++ = (cover_type
)base_type::m_ren
.cover(s1
);
636 while((dist
= base_type::m_dist
[dx
] - s1
) <= base_type::m_width
)
638 *p1
++ = (cover_type
)base_type::m_ren
.cover(dist
);
643 while((dist
= base_type::m_dist
[dx
] + s1
) <= base_type::m_width
)
645 *--p0
= (cover_type
)base_type::m_ren
.cover(dist
);
648 base_type::m_ren
.blend_solid_hspan(base_type::m_x
- dx
+ 1,
652 return ++base_type::m_step
< base_type::m_count
;
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
>
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
,
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
)
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();
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
;
715 while(base_type::m_dist
[dx
] <= base_type::m_width
);
720 while(base_type::m_step
>= -base_type::m_max_extent
);
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();
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
;
747 while(base_type::m_dist
[dy
] <= base_type::m_width
);
752 while(base_type::m_step
>= -base_type::m_max_extent
);
754 base_type::m_li
.adjust_forward();
757 //---------------------------------------------------------------------
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;
772 *p1
= (cover_type
)base_type::m_ren
.cover(s1
);
777 while((dist
= base_type::m_dist
[dy
] - s1
) <= base_type::m_width
)
779 dist_start
-= m_di
.dx_start();
783 *p1
= (cover_type
)base_type::m_ren
.cover(dist
);
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();
797 *p0
= (cover_type
)base_type::m_ren
.cover(dist
);
802 base_type::m_ren
.blend_solid_vspan(base_type::m_x
,
803 base_type::m_y
- dy
+ 1,
806 return ++base_type::m_step
< base_type::m_count
;
809 //---------------------------------------------------------------------
815 int s1
= base_type::step_ver_base(m_di
);
816 cover_type
* p0
= base_type::m_covers
+ base_type::max_half_width
+ 2;
819 dist_start
= m_di
.dist_start();
824 *p1
= (cover_type
)base_type::m_ren
.cover(s1
);
829 while((dist
= base_type::m_dist
[dx
] - s1
) <= base_type::m_width
)
831 dist_start
+= m_di
.dy_start();
835 *p1
= (cover_type
)base_type::m_ren
.cover(dist
);
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();
849 *p0
= (cover_type
)base_type::m_ren
.cover(dist
);
853 base_type::m_ren
.blend_solid_hspan(base_type::m_x
- dx
+ 1,
857 return ++base_type::m_step
< base_type::m_count
;
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
>
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
,
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 //---------------------------------------------------------------------
907 int s1
= base_type::step_hor_base(m_di
);
908 cover_type
* p0
= base_type::m_covers
+ base_type::max_half_width
+ 2;
911 dist_end
= m_di
.dist_end();
917 *p1
= (cover_type
)base_type::m_ren
.cover(s1
);
923 while((dist
= base_type::m_dist
[dy
] - s1
) <= base_type::m_width
)
925 dist_end
-= m_di
.dx_end();
929 *p1
= (cover_type
)base_type::m_ren
.cover(dist
);
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();
944 *p0
= (cover_type
)base_type::m_ren
.cover(dist
);
949 base_type::m_ren
.blend_solid_vspan(base_type::m_x
,
950 base_type::m_y
- dy
+ 1,
953 return npix
&& ++base_type::m_step
< base_type::m_count
;
956 //---------------------------------------------------------------------
962 int s1
= base_type::step_ver_base(m_di
);
963 cover_type
* p0
= base_type::m_covers
+ base_type::max_half_width
+ 2;
966 dist_end
= m_di
.dist_end();
972 *p1
= (cover_type
)base_type::m_ren
.cover(s1
);
978 while((dist
= base_type::m_dist
[dx
] - s1
) <= base_type::m_width
)
980 dist_end
+= m_di
.dy_end();
984 *p1
= (cover_type
)base_type::m_ren
.cover(dist
);
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();
999 *p0
= (cover_type
)base_type::m_ren
.cover(dist
);
1004 base_type::m_ren
.blend_solid_hspan(base_type::m_x
- dx
+ 1,
1008 return npix
&& ++base_type::m_step
< base_type::m_count
;
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
>
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
)
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();
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
;
1073 while(base_type::m_dist
[dx
] <= base_type::m_width
);
1074 if(npix
== 0) break;
1077 while(--base_type::m_step
>= -base_type::m_max_extent
);
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();
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
;
1104 while(base_type::m_dist
[dy
] <= base_type::m_width
);
1105 if(npix
== 0) break;
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 //---------------------------------------------------------------------
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();
1135 *p1
= (cover_type
)base_type::m_ren
.cover(s1
);
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();
1147 if(dist_end
> 0 && dist_start
<= 0)
1149 *p1
= (cover_type
)base_type::m_ren
.cover(dist
);
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();
1164 if(dist_end
> 0 && dist_start
<= 0)
1166 *p0
= (cover_type
)base_type::m_ren
.cover(dist
);
1171 base_type::m_ren
.blend_solid_vspan(base_type::m_x
,
1172 base_type::m_y
- dy
+ 1,
1175 return npix
&& ++base_type::m_step
< base_type::m_count
;
1178 //---------------------------------------------------------------------
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();
1198 *p1
= (cover_type
)base_type::m_ren
.cover(s1
);
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();
1210 if(dist_end
> 0 && dist_start
<= 0)
1212 *p1
= (cover_type
)base_type::m_ren
.cover(dist
);
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();
1227 if(dist_end
> 0 && dist_start
<= 0)
1229 *p0
= (cover_type
)base_type::m_ren
.cover(dist
);
1234 base_type::m_ren
.blend_solid_hspan(base_type::m_x
- dx
+ 1,
1238 return npix
&& ++base_type::m_step
< base_type::m_count
;
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
1260 //---------------------------------------------------------------------
1261 typedef int8u value_type
;
1264 subpixel_shift
= line_subpixel_shift
,
1265 subpixel_size
= 1 << subpixel_shift
,
1266 subpixel_mask
= subpixel_size
- 1
1272 aa_num
= 1 << aa_shift
,
1273 aa_mask
= aa_num
- 1
1276 //---------------------------------------------------------------------
1277 ~line_profile_aa() { delete [] m_profile
; }
1279 //---------------------------------------------------------------------
1283 m_subpixel_width(0),
1285 m_smoother_width(1.0)
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
) :
1296 m_subpixel_width(0),
1298 m_smoother_width(1.0)
1300 gamma(gamma_function
);
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
)
1312 for(i
= 0; i
< aa_num
; i
++)
1314 m_gamma
[i
] = value_type(
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];
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 //---------------------------------------------------------------------
1344 value_type
* m_profile
;
1345 value_type m_gamma
[aa_num
];
1346 int m_subpixel_width
;
1348 double m_smoother_width
;
1352 //======================================================renderer_outline_aa
1353 template<class BaseRenderer
> class renderer_outline_aa
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
) :
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 //-------------------------------------------------------------------------
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;
1422 int d
= int(fast_sqrt(dx
*dx
+ dy
*dy
));
1424 if(cmp(di
.dist()) && d
<= w
)
1426 *p1
= (cover_type
)cover(d
);
1429 dx
+= line_subpixel_size
;
1433 m_ren
->blend_solid_hspan(x0
, y1
,
1439 //-------------------------------------------------------------------------
1441 void semidot(Cmp cmp
, int xc1
, int yc1
, int xc2
, int yc2
)
1443 int r
= ((subpixel_width() + line_subpixel_mask
) >> line_subpixel_shift
);
1445 ellipse_bresenham_interpolator
ei(r
, r
);
1450 int x
= xc1
>> line_subpixel_shift
;
1451 int y
= yc1
>> line_subpixel_shift
;
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
);
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
);
1479 while(li
.step_ver()) ;
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
);
1495 while(li
.step_ver()) ;
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
);
1510 while(li
.step_ver()) ;
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
);
1527 while(li
.step_ver()) ;
1531 while(li
.step_hor()) ;
1536 base_ren_type
* m_ren
;
1537 const line_profile_aa
* m_profile
;