1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
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_array.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"
25 #include "agg_clip_liang_barsky.h"
30 //===================================================distance_interpolator0
31 class distance_interpolator0
34 //---------------------------------------------------------------------
35 distance_interpolator0() {}
36 distance_interpolator0(int x1
, int y1
, int x2
, int y2
, int x
, int y
) :
37 m_dx(line_mr(x2
) - line_mr(x1
)),
38 m_dy(line_mr(y2
) - line_mr(y1
)),
39 m_dist((line_mr(x
+ line_subpixel_scale
/2) - line_mr(x2
)) * m_dy
-
40 (line_mr(y
+ line_subpixel_scale
/2) - line_mr(y2
)) * m_dx
)
42 m_dx
<<= line_mr_subpixel_shift
;
43 m_dy
<<= line_mr_subpixel_shift
;
46 //---------------------------------------------------------------------
47 void inc_x() { m_dist
+= m_dy
; }
48 int dist() const { return m_dist
; }
51 //---------------------------------------------------------------------
57 //==================================================distance_interpolator00
58 class distance_interpolator00
61 //---------------------------------------------------------------------
62 distance_interpolator00() {}
63 distance_interpolator00(int xc
, int yc
,
64 int x1
, int y1
, int x2
, int y2
,
66 m_dx1(line_mr(x1
) - line_mr(xc
)),
67 m_dy1(line_mr(y1
) - line_mr(yc
)),
68 m_dx2(line_mr(x2
) - line_mr(xc
)),
69 m_dy2(line_mr(y2
) - line_mr(yc
)),
70 m_dist1((line_mr(x
+ line_subpixel_scale
/2) - line_mr(x1
)) * m_dy1
-
71 (line_mr(y
+ line_subpixel_scale
/2) - line_mr(y1
)) * m_dx1
),
72 m_dist2((line_mr(x
+ line_subpixel_scale
/2) - line_mr(x2
)) * m_dy2
-
73 (line_mr(y
+ line_subpixel_scale
/2) - line_mr(y2
)) * m_dx2
)
75 m_dx1
<<= line_mr_subpixel_shift
;
76 m_dy1
<<= line_mr_subpixel_shift
;
77 m_dx2
<<= line_mr_subpixel_shift
;
78 m_dy2
<<= line_mr_subpixel_shift
;
81 //---------------------------------------------------------------------
82 void inc_x() { m_dist1
+= m_dy1
; m_dist2
+= m_dy2
; }
83 int dist1() const { return m_dist1
; }
84 int dist2() const { return m_dist2
; }
87 //---------------------------------------------------------------------
96 //===================================================distance_interpolator1
97 class distance_interpolator1
100 //---------------------------------------------------------------------
101 distance_interpolator1() {}
102 distance_interpolator1(int x1
, int y1
, int x2
, int y2
, int x
, int y
) :
105 m_dist(iround(double(x
+ line_subpixel_scale
/2 - x2
) * double(m_dy
) -
106 double(y
+ line_subpixel_scale
/2 - y2
) * double(m_dx
)))
108 m_dx
<<= line_subpixel_shift
;
109 m_dy
<<= line_subpixel_shift
;
112 //---------------------------------------------------------------------
113 void inc_x() { m_dist
+= m_dy
; }
114 void dec_x() { m_dist
-= m_dy
; }
115 void inc_y() { m_dist
-= m_dx
; }
116 void dec_y() { m_dist
+= m_dx
; }
118 //---------------------------------------------------------------------
122 if(dy
> 0) m_dist
-= m_dx
;
123 if(dy
< 0) m_dist
+= m_dx
;
126 //---------------------------------------------------------------------
130 if(dy
> 0) m_dist
-= m_dx
;
131 if(dy
< 0) m_dist
+= m_dx
;
134 //---------------------------------------------------------------------
138 if(dx
> 0) m_dist
+= m_dy
;
139 if(dx
< 0) m_dist
-= m_dy
;
143 //---------------------------------------------------------------------
146 if(dx
> 0) m_dist
+= m_dy
;
147 if(dx
< 0) m_dist
-= m_dy
;
150 //---------------------------------------------------------------------
151 int dist() const { return m_dist
; }
152 int dx() const { return m_dx
; }
153 int dy() const { return m_dy
; }
156 //---------------------------------------------------------------------
166 //===================================================distance_interpolator2
167 class distance_interpolator2
170 //---------------------------------------------------------------------
171 distance_interpolator2() {}
172 distance_interpolator2(int x1
, int y1
, int x2
, int y2
,
173 int sx
, int sy
, int x
, int y
) :
176 m_dx_start(line_mr(sx
) - line_mr(x1
)),
177 m_dy_start(line_mr(sy
) - line_mr(y1
)),
179 m_dist(iround(double(x
+ line_subpixel_scale
/2 - x2
) * double(m_dy
) -
180 double(y
+ line_subpixel_scale
/2 - y2
) * double(m_dx
))),
182 m_dist_start((line_mr(x
+ line_subpixel_scale
/2) - line_mr(sx
)) * m_dy_start
-
183 (line_mr(y
+ line_subpixel_scale
/2) - line_mr(sy
)) * m_dx_start
)
185 m_dx
<<= line_subpixel_shift
;
186 m_dy
<<= line_subpixel_shift
;
187 m_dx_start
<<= line_mr_subpixel_shift
;
188 m_dy_start
<<= line_mr_subpixel_shift
;
191 distance_interpolator2(int x1
, int y1
, int x2
, int y2
,
192 int ex
, int ey
, int x
, int y
, int) :
195 m_dx_start(line_mr(ex
) - line_mr(x2
)),
196 m_dy_start(line_mr(ey
) - line_mr(y2
)),
198 m_dist(iround(double(x
+ line_subpixel_scale
/2 - x2
) * double(m_dy
) -
199 double(y
+ line_subpixel_scale
/2 - y2
) * double(m_dx
))),
201 m_dist_start((line_mr(x
+ line_subpixel_scale
/2) - line_mr(ex
)) * m_dy_start
-
202 (line_mr(y
+ line_subpixel_scale
/2) - line_mr(ey
)) * m_dx_start
)
204 m_dx
<<= line_subpixel_shift
;
205 m_dy
<<= line_subpixel_shift
;
206 m_dx_start
<<= line_mr_subpixel_shift
;
207 m_dy_start
<<= line_mr_subpixel_shift
;
211 //---------------------------------------------------------------------
212 void inc_x() { m_dist
+= m_dy
; m_dist_start
+= m_dy_start
; }
213 void dec_x() { m_dist
-= m_dy
; m_dist_start
-= m_dy_start
; }
214 void inc_y() { m_dist
-= m_dx
; m_dist_start
-= m_dx_start
; }
215 void dec_y() { m_dist
+= m_dx
; m_dist_start
+= m_dx_start
; }
217 //---------------------------------------------------------------------
221 m_dist_start
+= m_dy_start
;
225 m_dist_start
-= m_dx_start
;
230 m_dist_start
+= m_dx_start
;
234 //---------------------------------------------------------------------
238 m_dist_start
-= m_dy_start
;
242 m_dist_start
-= m_dx_start
;
247 m_dist_start
+= m_dx_start
;
251 //---------------------------------------------------------------------
255 m_dist_start
-= m_dx_start
;
259 m_dist_start
+= m_dy_start
;
264 m_dist_start
-= m_dy_start
;
268 //---------------------------------------------------------------------
272 m_dist_start
+= m_dx_start
;
276 m_dist_start
+= m_dy_start
;
281 m_dist_start
-= m_dy_start
;
285 //---------------------------------------------------------------------
286 int dist() const { return m_dist
; }
287 int dist_start() const { return m_dist_start
; }
288 int dist_end() const { return m_dist_start
; }
290 //---------------------------------------------------------------------
291 int dx() const { return m_dx
; }
292 int dy() const { return m_dy
; }
293 int dx_start() const { return m_dx_start
; }
294 int dy_start() const { return m_dy_start
; }
295 int dx_end() const { return m_dx_start
; }
296 int dy_end() const { return m_dy_start
; }
299 //---------------------------------------------------------------------
313 //===================================================distance_interpolator3
314 class distance_interpolator3
317 //---------------------------------------------------------------------
318 distance_interpolator3() {}
319 distance_interpolator3(int x1
, int y1
, int x2
, int y2
,
320 int sx
, int sy
, int ex
, int ey
,
324 m_dx_start(line_mr(sx
) - line_mr(x1
)),
325 m_dy_start(line_mr(sy
) - line_mr(y1
)),
326 m_dx_end(line_mr(ex
) - line_mr(x2
)),
327 m_dy_end(line_mr(ey
) - line_mr(y2
)),
329 m_dist(iround(double(x
+ line_subpixel_scale
/2 - x2
) * double(m_dy
) -
330 double(y
+ line_subpixel_scale
/2 - y2
) * double(m_dx
))),
332 m_dist_start((line_mr(x
+ line_subpixel_scale
/2) - line_mr(sx
)) * m_dy_start
-
333 (line_mr(y
+ line_subpixel_scale
/2) - line_mr(sy
)) * m_dx_start
),
335 m_dist_end((line_mr(x
+ line_subpixel_scale
/2) - line_mr(ex
)) * m_dy_end
-
336 (line_mr(y
+ line_subpixel_scale
/2) - line_mr(ey
)) * m_dx_end
)
338 m_dx
<<= line_subpixel_shift
;
339 m_dy
<<= line_subpixel_shift
;
340 m_dx_start
<<= line_mr_subpixel_shift
;
341 m_dy_start
<<= line_mr_subpixel_shift
;
342 m_dx_end
<<= line_mr_subpixel_shift
;
343 m_dy_end
<<= line_mr_subpixel_shift
;
346 //---------------------------------------------------------------------
347 void inc_x() { m_dist
+= m_dy
; m_dist_start
+= m_dy_start
; m_dist_end
+= m_dy_end
; }
348 void dec_x() { m_dist
-= m_dy
; m_dist_start
-= m_dy_start
; m_dist_end
-= m_dy_end
; }
349 void inc_y() { m_dist
-= m_dx
; m_dist_start
-= m_dx_start
; m_dist_end
-= m_dx_end
; }
350 void dec_y() { m_dist
+= m_dx
; m_dist_start
+= m_dx_start
; m_dist_end
+= m_dx_end
; }
352 //---------------------------------------------------------------------
356 m_dist_start
+= m_dy_start
;
357 m_dist_end
+= m_dy_end
;
361 m_dist_start
-= m_dx_start
;
362 m_dist_end
-= m_dx_end
;
367 m_dist_start
+= m_dx_start
;
368 m_dist_end
+= m_dx_end
;
372 //---------------------------------------------------------------------
376 m_dist_start
-= m_dy_start
;
377 m_dist_end
-= m_dy_end
;
381 m_dist_start
-= m_dx_start
;
382 m_dist_end
-= m_dx_end
;
387 m_dist_start
+= m_dx_start
;
388 m_dist_end
+= m_dx_end
;
392 //---------------------------------------------------------------------
396 m_dist_start
-= m_dx_start
;
397 m_dist_end
-= m_dx_end
;
401 m_dist_start
+= m_dy_start
;
402 m_dist_end
+= m_dy_end
;
407 m_dist_start
-= m_dy_start
;
408 m_dist_end
-= m_dy_end
;
412 //---------------------------------------------------------------------
416 m_dist_start
+= m_dx_start
;
417 m_dist_end
+= m_dx_end
;
421 m_dist_start
+= m_dy_start
;
422 m_dist_end
+= m_dy_end
;
427 m_dist_start
-= m_dy_start
;
428 m_dist_end
-= m_dy_end
;
432 //---------------------------------------------------------------------
433 int dist() const { return m_dist
; }
434 int dist_start() const { return m_dist_start
; }
435 int dist_end() const { return m_dist_end
; }
437 //---------------------------------------------------------------------
438 int dx() const { return m_dx
; }
439 int dy() const { return m_dy
; }
440 int dx_start() const { return m_dx_start
; }
441 int dy_start() const { return m_dy_start
; }
442 int dx_end() const { return m_dx_end
; }
443 int dy_end() const { return m_dy_end
; }
446 //---------------------------------------------------------------------
463 //================================================line_interpolator_aa_base
464 template<class Renderer
> class line_interpolator_aa_base
467 typedef Renderer renderer_type
;
468 typedef typename
Renderer::color_type color_type
;
470 //---------------------------------------------------------------------
471 enum max_half_width_e
476 //---------------------------------------------------------------------
477 line_interpolator_aa_base(renderer_type
& ren
, const line_parameters
& lp
) :
479 m_li(lp
.vertical
? line_dbl_hr(lp
.x2
- lp
.x1
) :
480 line_dbl_hr(lp
.y2
- lp
.y1
),
481 lp
.vertical
? abs(lp
.y2
- lp
.y1
) :
482 abs(lp
.x2
- lp
.x1
) + 1),
484 m_len((lp
.vertical
== (lp
.inc
> 0)) ? -lp
.len
: lp
.len
),
485 m_x(lp
.x1
>> line_subpixel_shift
),
486 m_y(lp
.y1
>> line_subpixel_shift
),
489 m_count((lp
.vertical
? abs((lp
.y2
>> line_subpixel_shift
) - m_y
) :
490 abs((lp
.x2
>> line_subpixel_shift
) - m_x
))),
491 m_width(ren
.subpixel_width()),
492 //m_max_extent(m_width >> (line_subpixel_shift - 2)),
493 m_max_extent((m_width
+ line_subpixel_mask
) >> line_subpixel_shift
),
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_scale
* 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
;
1262 enum subpixel_scale_e
1264 subpixel_shift
= line_subpixel_shift
,
1265 subpixel_scale
= 1 << subpixel_shift
,
1266 subpixel_mask
= subpixel_scale
- 1
1272 aa_scale
= 1 << aa_shift
,
1273 aa_mask
= aa_scale
- 1
1276 //---------------------------------------------------------------------
1278 m_subpixel_width(0),
1280 m_smoother_width(1.0)
1283 for(i
= 0; i
< aa_scale
; i
++) m_gamma
[i
] = (value_type
)i
;
1286 //---------------------------------------------------------------------
1287 template<class GammaF
>
1288 line_profile_aa(double w
, const GammaF
& gamma_function
) :
1289 m_subpixel_width(0),
1291 m_smoother_width(1.0)
1293 gamma(gamma_function
);
1297 //---------------------------------------------------------------------
1298 void min_width(double w
) { m_min_width
= w
; }
1299 void smoother_width(double w
) { m_smoother_width
= w
; }
1301 //---------------------------------------------------------------------
1302 template<class GammaF
> void gamma(const GammaF
& gamma_function
)
1305 for(i
= 0; i
< aa_scale
; i
++)
1307 m_gamma
[i
] = value_type(
1308 uround(gamma_function(double(i
) / aa_mask
) * aa_mask
));
1312 void width(double w
);
1314 unsigned profile_size() const { return m_profile
.size(); }
1315 int subpixel_width() const { return m_subpixel_width
; }
1317 //---------------------------------------------------------------------
1318 double min_width() const { return m_min_width
; }
1319 double smoother_width() const { return m_smoother_width
; }
1321 //---------------------------------------------------------------------
1322 value_type
value(int dist
) const
1324 return m_profile
[dist
+ subpixel_scale
*2];
1328 line_profile_aa(const line_profile_aa
&);
1329 const line_profile_aa
& operator = (const line_profile_aa
&);
1331 value_type
* profile(double w
);
1332 void set(double center_width
, double smoother_width
);
1334 //---------------------------------------------------------------------
1335 pod_array
<value_type
> m_profile
;
1336 value_type m_gamma
[aa_scale
];
1337 int m_subpixel_width
;
1339 double m_smoother_width
;
1343 //======================================================renderer_outline_aa
1344 template<class BaseRenderer
> class renderer_outline_aa
1347 //---------------------------------------------------------------------
1348 typedef BaseRenderer base_ren_type
;
1349 typedef renderer_outline_aa
<base_ren_type
> self_type
;
1350 typedef typename
base_ren_type::color_type color_type
;
1352 //---------------------------------------------------------------------
1353 renderer_outline_aa(base_ren_type
& ren
, const line_profile_aa
& prof
) :
1356 m_clip_box(0,0,0,0),
1359 void attach(base_ren_type
& ren
) { m_ren
= &ren
; }
1361 //---------------------------------------------------------------------
1362 void color(const color_type
& c
) { m_color
= c
; }
1363 const color_type
& color() const { return m_color
; }
1365 //---------------------------------------------------------------------
1366 void profile(const line_profile_aa
& prof
) { m_profile
= &prof
; }
1367 const line_profile_aa
& profile() const { return *m_profile
; }
1368 line_profile_aa
& profile() { return *(line_profile_aa
*)m_profile
; }
1370 //---------------------------------------------------------------------
1371 int subpixel_width() const { return m_profile
->subpixel_width(); }
1373 //---------------------------------------------------------------------
1374 void reset_clipping() { m_clipping
= false; }
1375 void clip_box(double x1
, double y1
, double x2
, double y2
)
1377 m_clip_box
.x1
= line_coord_sat::conv(x1
);
1378 m_clip_box
.y1
= line_coord_sat::conv(y1
);
1379 m_clip_box
.x2
= line_coord_sat::conv(x2
);
1380 m_clip_box
.y2
= line_coord_sat::conv(y2
);
1384 //---------------------------------------------------------------------
1385 int cover(int d
) const
1387 return m_profile
->value(d
);
1390 //-------------------------------------------------------------------------
1391 void blend_solid_hspan(int x
, int y
, unsigned len
, const cover_type
* covers
)
1393 m_ren
->blend_solid_hspan(x
, y
, len
, m_color
, covers
);
1396 //-------------------------------------------------------------------------
1397 void blend_solid_vspan(int x
, int y
, unsigned len
, const cover_type
* covers
)
1399 m_ren
->blend_solid_vspan(x
, y
, len
, m_color
, covers
);
1402 //-------------------------------------------------------------------------
1403 static bool accurate_join_only() { return false; }
1405 //-------------------------------------------------------------------------
1407 void semidot_hline(Cmp cmp
,
1408 int xc1
, int yc1
, int xc2
, int yc2
,
1409 int x1
, int y1
, int x2
)
1411 cover_type covers
[line_interpolator_aa_base
<self_type
>::max_half_width
* 2 + 4];
1412 cover_type
* p0
= covers
;
1413 cover_type
* p1
= covers
;
1414 int x
= x1
<< line_subpixel_shift
;
1415 int y
= y1
<< line_subpixel_shift
;
1416 int w
= subpixel_width();
1417 distance_interpolator0
di(xc1
, yc1
, xc2
, yc2
, x
, y
);
1418 x
+= line_subpixel_scale
/2;
1419 y
+= line_subpixel_scale
/2;
1426 int d
= int(fast_sqrt(dx
*dx
+ dy
*dy
));
1428 if(cmp(di
.dist()) && d
<= w
)
1430 *p1
= (cover_type
)cover(d
);
1433 dx
+= line_subpixel_scale
;
1437 m_ren
->blend_solid_hspan(x0
, y1
,
1443 //-------------------------------------------------------------------------
1445 void semidot(Cmp cmp
, int xc1
, int yc1
, int xc2
, int yc2
)
1447 if(m_clipping
&& clipping_flags(xc1
, yc1
, m_clip_box
)) return;
1449 int r
= ((subpixel_width() + line_subpixel_mask
) >> line_subpixel_shift
);
1451 ellipse_bresenham_interpolator
ei(r
, r
);
1456 int x
= xc1
>> line_subpixel_shift
;
1457 int y
= yc1
>> line_subpixel_shift
;
1466 semidot_hline(cmp
, xc1
, yc1
, xc2
, yc2
, x
-dx0
, y
+dy0
, x
+dx0
);
1467 semidot_hline(cmp
, xc1
, yc1
, xc2
, yc2
, x
-dx0
, y
-dy0
, x
+dx0
);
1474 semidot_hline(cmp
, xc1
, yc1
, xc2
, yc2
, x
-dx0
, y
+dy0
, x
+dx0
);
1477 //-------------------------------------------------------------------------
1478 void pie_hline(int xc
, int yc
, int xp1
, int yp1
, int xp2
, int yp2
,
1479 int xh1
, int yh1
, int xh2
)
1481 if(m_clipping
&& clipping_flags(xc
, yc
, m_clip_box
)) return;
1483 cover_type covers
[line_interpolator_aa_base
<self_type
>::max_half_width
* 2 + 4];
1484 cover_type
* p0
= covers
;
1485 cover_type
* p1
= covers
;
1486 int x
= xh1
<< line_subpixel_shift
;
1487 int y
= yh1
<< line_subpixel_shift
;
1488 int w
= subpixel_width();
1490 distance_interpolator00
di(xc
, yc
, xp1
, yp1
, xp2
, yp2
, x
, y
);
1491 x
+= line_subpixel_scale
/2;
1492 y
+= line_subpixel_scale
/2;
1499 int d
= int(fast_sqrt(dx
*dx
+ dy
*dy
));
1501 if(di
.dist1() <= 0 && di
.dist2() > 0 && d
<= w
)
1503 *p1
= (cover_type
)cover(d
);
1506 dx
+= line_subpixel_scale
;
1509 while(++xh1
<= xh2
);
1510 m_ren
->blend_solid_hspan(xh0
, yh1
,
1517 //-------------------------------------------------------------------------
1518 void pie(int xc
, int yc
, int x1
, int y1
, int x2
, int y2
)
1520 int r
= ((subpixel_width() + line_subpixel_mask
) >> line_subpixel_shift
);
1522 ellipse_bresenham_interpolator
ei(r
, r
);
1527 int x
= xc
>> line_subpixel_shift
;
1528 int y
= yc
>> line_subpixel_shift
;
1537 pie_hline(xc
, yc
, x1
, y1
, x2
, y2
, x
-dx0
, y
+dy0
, x
+dx0
);
1538 pie_hline(xc
, yc
, x1
, y1
, x2
, y2
, x
-dx0
, y
-dy0
, x
+dx0
);
1545 pie_hline(xc
, yc
, x1
, y1
, x2
, y2
, x
-dx0
, y
+dy0
, x
+dx0
);
1548 //-------------------------------------------------------------------------
1549 void line0_no_clip(const line_parameters
& lp
)
1551 if(lp
.len
> line_max_length
)
1553 line_parameters lp1
, lp2
;
1554 lp
.divide(lp1
, lp2
);
1560 line_interpolator_aa0
<self_type
> li(*this, lp
);
1565 while(li
.step_ver());
1569 while(li
.step_hor());
1574 //-------------------------------------------------------------------------
1575 void line0(const line_parameters
& lp
)
1583 unsigned flags
= clip_line_segment(&x1
, &y1
, &x2
, &y2
, m_clip_box
);
1584 if((flags
& 4) == 0)
1588 line_parameters
lp2(x1
, y1
, x2
, y2
,
1589 uround(calc_distance(x1
, y1
, x2
, y2
)));
1604 //-------------------------------------------------------------------------
1605 void line1_no_clip(const line_parameters
& lp
, int sx
, int sy
)
1607 if(lp
.len
> line_max_length
)
1609 line_parameters lp1
, lp2
;
1610 lp
.divide(lp1
, lp2
);
1611 line1_no_clip(lp1
, (lp
.x1
+ sx
) >> 1, (lp
.y1
+ sy
) >> 1);
1612 line1_no_clip(lp2
, lp1
.x2
+ (lp1
.y2
- lp1
.y1
), lp1
.y2
- (lp1
.x2
- lp1
.x1
));
1616 fix_degenerate_bisectrix_start(lp
, &sx
, &sy
);
1617 line_interpolator_aa1
<self_type
> li(*this, lp
, sx
, sy
);
1620 while(li
.step_ver());
1624 while(li
.step_hor());
1629 //-------------------------------------------------------------------------
1630 void line1(const line_parameters
& lp
, int sx
, int sy
)
1638 unsigned flags
= clip_line_segment(&x1
, &y1
, &x2
, &y2
, m_clip_box
);
1639 if((flags
& 4) == 0)
1643 line_parameters
lp2(x1
, y1
, x2
, y2
,
1644 uround(calc_distance(x1
, y1
, x2
, y2
)));
1647 sx
= x1
+ (y2
- y1
);
1648 sy
= y1
- (x2
- x1
);
1652 while(abs(sx
- lp
.x1
) + abs(sy
- lp
.y1
) > lp2
.len
)
1654 sx
= (lp
.x1
+ sx
) >> 1;
1655 sy
= (lp
.y1
+ sy
) >> 1;
1658 line1_no_clip(lp2
, sx
, sy
);
1662 line1_no_clip(lp
, sx
, sy
);
1668 line1_no_clip(lp
, sx
, sy
);
1672 //-------------------------------------------------------------------------
1673 void line2_no_clip(const line_parameters
& lp
, int ex
, int ey
)
1675 if(lp
.len
> line_max_length
)
1677 line_parameters lp1
, lp2
;
1678 lp
.divide(lp1
, lp2
);
1679 line2_no_clip(lp1
, lp1
.x2
+ (lp1
.y2
- lp1
.y1
), lp1
.y2
- (lp1
.x2
- lp1
.x1
));
1680 line2_no_clip(lp2
, (lp
.x2
+ ex
) >> 1, (lp
.y2
+ ey
) >> 1);
1684 fix_degenerate_bisectrix_end(lp
, &ex
, &ey
);
1685 line_interpolator_aa2
<self_type
> li(*this, lp
, ex
, ey
);
1688 while(li
.step_ver());
1692 while(li
.step_hor());
1696 //-------------------------------------------------------------------------
1697 void line2(const line_parameters
& lp
, int ex
, int ey
)
1705 unsigned flags
= clip_line_segment(&x1
, &y1
, &x2
, &y2
, m_clip_box
);
1706 if((flags
& 4) == 0)
1710 line_parameters
lp2(x1
, y1
, x2
, y2
,
1711 uround(calc_distance(x1
, y1
, x2
, y2
)));
1714 ex
= x2
+ (y2
- y1
);
1715 ey
= y2
- (x2
- x1
);
1719 while(abs(ex
- lp
.x2
) + abs(ey
- lp
.y2
) > lp2
.len
)
1721 ex
= (lp
.x2
+ ex
) >> 1;
1722 ey
= (lp
.y2
+ ey
) >> 1;
1725 line2_no_clip(lp2
, ex
, ey
);
1729 line2_no_clip(lp
, ex
, ey
);
1735 line2_no_clip(lp
, ex
, ey
);
1739 //-------------------------------------------------------------------------
1740 void line3_no_clip(const line_parameters
& lp
,
1741 int sx
, int sy
, int ex
, int ey
)
1743 if(lp
.len
> line_max_length
)
1745 line_parameters lp1
, lp2
;
1746 lp
.divide(lp1
, lp2
);
1747 int mx
= lp1
.x2
+ (lp1
.y2
- lp1
.y1
);
1748 int my
= lp1
.y2
- (lp1
.x2
- lp1
.x1
);
1749 line3_no_clip(lp1
, (lp
.x1
+ sx
) >> 1, (lp
.y1
+ sy
) >> 1, mx
, my
);
1750 line3_no_clip(lp2
, mx
, my
, (lp
.x2
+ ex
) >> 1, (lp
.y2
+ ey
) >> 1);
1754 fix_degenerate_bisectrix_start(lp
, &sx
, &sy
);
1755 fix_degenerate_bisectrix_end(lp
, &ex
, &ey
);
1756 line_interpolator_aa3
<self_type
> li(*this, lp
, sx
, sy
, ex
, ey
);
1759 while(li
.step_ver());
1763 while(li
.step_hor());
1767 //-------------------------------------------------------------------------
1768 void line3(const line_parameters
& lp
,
1769 int sx
, int sy
, int ex
, int ey
)
1777 unsigned flags
= clip_line_segment(&x1
, &y1
, &x2
, &y2
, m_clip_box
);
1778 if((flags
& 4) == 0)
1782 line_parameters
lp2(x1
, y1
, x2
, y2
,
1783 uround(calc_distance(x1
, y1
, x2
, y2
)));
1786 sx
= x1
+ (y2
- y1
);
1787 sy
= y1
- (x2
- x1
);
1791 while(abs(sx
- lp
.x1
) + abs(sy
- lp
.y1
) > lp2
.len
)
1793 sx
= (lp
.x1
+ sx
) >> 1;
1794 sy
= (lp
.y1
+ sy
) >> 1;
1799 ex
= x2
+ (y2
- y1
);
1800 ey
= y2
- (x2
- x1
);
1804 while(abs(ex
- lp
.x2
) + abs(ey
- lp
.y2
) > lp2
.len
)
1806 ex
= (lp
.x2
+ ex
) >> 1;
1807 ey
= (lp
.y2
+ ey
) >> 1;
1810 line3_no_clip(lp2
, sx
, sy
, ex
, ey
);
1814 line3_no_clip(lp
, sx
, sy
, ex
, ey
);
1820 line3_no_clip(lp
, sx
, sy
, ex
, ey
);
1826 base_ren_type
* m_ren
;
1827 const line_profile_aa
* m_profile
;