xref: /haiku/headers/libs/agg/agg_renderer_outline_aa.h (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.2
3 // Copyright (C) 2002-2004 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
17 
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"
25 
26 namespace agg
27 {
28 
29     //===================================================distance_interpolator0
30     class distance_interpolator0
31     {
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)
40         {
41             m_dx <<= line_mr_subpixel_shift;
42             m_dy <<= line_mr_subpixel_shift;
43         }
44 
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; }
50 
51         //---------------------------------------------------------------------
52         void inc_x(int dy)
53         {
54             m_dist += m_dy;
55             if(dy > 0) m_dist -= m_dx;
56             if(dy < 0) m_dist += m_dx;
57         }
58 
59         //---------------------------------------------------------------------
60         void dec_x(int dy)
61         {
62             m_dist -= m_dy;
63             if(dy > 0) m_dist -= m_dx;
64             if(dy < 0) m_dist += m_dx;
65         }
66 
67         //---------------------------------------------------------------------
68         void inc_y(int dx)
69         {
70             m_dist -= m_dx;
71             if(dx > 0) m_dist += m_dy;
72             if(dx < 0) m_dist -= m_dy;
73         }
74 
75         void dec_y(int dx)
76         //---------------------------------------------------------------------
77         {
78             m_dist += m_dx;
79             if(dx > 0) m_dist += m_dy;
80             if(dx < 0) m_dist -= m_dy;
81         }
82 
83         //---------------------------------------------------------------------
84         int dist()     const { return m_dist; }
85         int dx()       const { return m_dx;   }
86         int dy()       const { return m_dy;   }
87 
88     private:
89         //---------------------------------------------------------------------
90         int m_dx;
91         int m_dy;
92         int m_dist;
93     };
94 
95 
96 
97     //===================================================distance_interpolator1
98     class distance_interpolator1
99     {
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)))
108         {
109             m_dx <<= line_subpixel_shift;
110             m_dy <<= line_subpixel_shift;
111         }
112 
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; }
118 
119         //---------------------------------------------------------------------
120         void inc_x(int dy)
121         {
122             m_dist += m_dy;
123             if(dy > 0) m_dist -= m_dx;
124             if(dy < 0) m_dist += m_dx;
125         }
126 
127         //---------------------------------------------------------------------
128         void dec_x(int dy)
129         {
130             m_dist -= m_dy;
131             if(dy > 0) m_dist -= m_dx;
132             if(dy < 0) m_dist += m_dx;
133         }
134 
135         //---------------------------------------------------------------------
136         void inc_y(int dx)
137         {
138             m_dist -= m_dx;
139             if(dx > 0) m_dist += m_dy;
140             if(dx < 0) m_dist -= m_dy;
141         }
142 
143         void dec_y(int dx)
144         //---------------------------------------------------------------------
145         {
146             m_dist += m_dx;
147             if(dx > 0) m_dist += m_dy;
148             if(dx < 0) m_dist -= m_dy;
149         }
150 
151         //---------------------------------------------------------------------
152         int dist() const { return m_dist; }
153         int dx()   const { return m_dx;   }
154         int dy()   const { return m_dy;   }
155 
156     private:
157         //---------------------------------------------------------------------
158         int m_dx;
159         int m_dy;
160         int m_dist;
161     };
162 
163 
164 
165 
166 
167     //===================================================distance_interpolator2
168     class distance_interpolator2
169     {
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)),
179 
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))),
182 
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)
185         {
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;
190         }
191 
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)),
198 
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))),
201 
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)
204         {
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;
209         }
210 
211 
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; }
217 
218         //---------------------------------------------------------------------
219         void inc_x(int dy)
220         {
221             m_dist       += m_dy;
222             m_dist_start += m_dy_start;
223             if(dy > 0)
224             {
225                 m_dist       -= m_dx;
226                 m_dist_start -= m_dx_start;
227             }
228             if(dy < 0)
229             {
230                 m_dist       += m_dx;
231                 m_dist_start += m_dx_start;
232             }
233         }
234 
235         //---------------------------------------------------------------------
236         void dec_x(int dy)
237         {
238             m_dist       -= m_dy;
239             m_dist_start -= m_dy_start;
240             if(dy > 0)
241             {
242                 m_dist       -= m_dx;
243                 m_dist_start -= m_dx_start;
244             }
245             if(dy < 0)
246             {
247                 m_dist       += m_dx;
248                 m_dist_start += m_dx_start;
249             }
250         }
251 
252         //---------------------------------------------------------------------
253         void inc_y(int dx)
254         {
255             m_dist       -= m_dx;
256             m_dist_start -= m_dx_start;
257             if(dx > 0)
258             {
259                 m_dist       += m_dy;
260                 m_dist_start += m_dy_start;
261             }
262             if(dx < 0)
263             {
264                 m_dist       -= m_dy;
265                 m_dist_start -= m_dy_start;
266             }
267         }
268 
269         //---------------------------------------------------------------------
270         void dec_y(int dx)
271         {
272             m_dist       += m_dx;
273             m_dist_start += m_dx_start;
274             if(dx > 0)
275             {
276                 m_dist       += m_dy;
277                 m_dist_start += m_dy_start;
278             }
279             if(dx < 0)
280             {
281                 m_dist       -= m_dy;
282                 m_dist_start -= m_dy_start;
283             }
284         }
285 
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; }
290 
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; }
298 
299     private:
300         //---------------------------------------------------------------------
301         int m_dx;
302         int m_dy;
303         int m_dx_start;
304         int m_dy_start;
305 
306         int m_dist;
307         int m_dist_start;
308     };
309 
310 
311 
312 
313 
314     //===================================================distance_interpolator3
315     class distance_interpolator3
316     {
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)),
329 
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))),
332 
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),
335 
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)
338         {
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;
345         }
346 
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; }
352 
353         //---------------------------------------------------------------------
354         void inc_x(int dy)
355         {
356             m_dist       += m_dy;
357             m_dist_start += m_dy_start;
358             m_dist_end   += m_dy_end;
359             if(dy > 0)
360             {
361                 m_dist       -= m_dx;
362                 m_dist_start -= m_dx_start;
363                 m_dist_end   -= m_dx_end;
364             }
365             if(dy < 0)
366             {
367                 m_dist       += m_dx;
368                 m_dist_start += m_dx_start;
369                 m_dist_end   += m_dx_end;
370             }
371         }
372 
373         //---------------------------------------------------------------------
374         void dec_x(int dy)
375         {
376             m_dist       -= m_dy;
377             m_dist_start -= m_dy_start;
378             m_dist_end   -= m_dy_end;
379             if(dy > 0)
380             {
381                 m_dist       -= m_dx;
382                 m_dist_start -= m_dx_start;
383                 m_dist_end   -= m_dx_end;
384             }
385             if(dy < 0)
386             {
387                 m_dist       += m_dx;
388                 m_dist_start += m_dx_start;
389                 m_dist_end   += m_dx_end;
390             }
391         }
392 
393         //---------------------------------------------------------------------
394         void inc_y(int dx)
395         {
396             m_dist       -= m_dx;
397             m_dist_start -= m_dx_start;
398             m_dist_end   -= m_dx_end;
399             if(dx > 0)
400             {
401                 m_dist       += m_dy;
402                 m_dist_start += m_dy_start;
403                 m_dist_end   += m_dy_end;
404             }
405             if(dx < 0)
406             {
407                 m_dist       -= m_dy;
408                 m_dist_start -= m_dy_start;
409                 m_dist_end   -= m_dy_end;
410             }
411         }
412 
413         //---------------------------------------------------------------------
414         void dec_y(int dx)
415         {
416             m_dist       += m_dx;
417             m_dist_start += m_dx_start;
418             m_dist_end   += m_dx_end;
419             if(dx > 0)
420             {
421                 m_dist       += m_dy;
422                 m_dist_start += m_dy_start;
423                 m_dist_end   += m_dy_end;
424             }
425             if(dx < 0)
426             {
427                 m_dist       -= m_dy;
428                 m_dist_start -= m_dy_start;
429                 m_dist_end   -= m_dy_end;
430             }
431         }
432 
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;   }
437 
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;   }
445 
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;
454 
455         int m_dist;
456         int m_dist_start;
457         int m_dist_end;
458     };
459 
460 
461 
462 
463 
464     //================================================line_interpolator_aa_base
465     template<class Renderer> class line_interpolator_aa_base
466     {
467     public:
468         typedef Renderer renderer_type;
469         typedef typename Renderer::color_type color_type;
470 
471         //---------------------------------------------------------------------
472         enum
473         {
474             max_half_width = 64
475         };
476 
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)
495         {
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);
500 
501             unsigned i;
502             int stop = m_width + line_subpixel_size * 2;
503             for(i = 0; i < max_half_width; ++i)
504             {
505                 m_dist[i] = li.y();
506                 if(m_dist[i] >= stop) break;
507                 ++li;
508             }
509             m_dist[i++] = 0x7FFF0000;
510         }
511 
512         //---------------------------------------------------------------------
513         template<class DI> int step_hor_base(DI& di)
514         {
515             ++m_li;
516             m_x += m_lp->inc;
517             m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift;
518 
519             if(m_lp->inc > 0) di.inc_x(m_y - m_old_y);
520             else              di.dec_x(m_y - m_old_y);
521 
522             m_old_y = m_y;
523 
524             return di.dist() / m_len;
525         }
526 
527         //---------------------------------------------------------------------
528         template<class DI> int step_ver_base(DI& di)
529         {
530             ++m_li;
531             m_y += m_lp->inc;
532             m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift;
533 
534             if(m_lp->inc > 0) di.inc_y(m_x - m_old_x);
535             else              di.dec_y(m_x - m_old_x);
536 
537             m_old_x = m_x;
538 
539             return di.dist() / m_len;
540         }
541 
542         //---------------------------------------------------------------------
543         bool vertical() const { return m_lp->vertical; }
544         int  width() const { return m_width; }
545         int  count() const { return m_count; }
546 
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>&);
551 
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];
567     };
568 
569 
570 
571 
572 
573 
574 
575     //====================================================line_interpolator_aa0
576     template<class Renderer> class line_interpolator_aa0 :
577     public line_interpolator_aa_base<Renderer>
578     {
579     public:
580         typedef Renderer renderer_type;
581         typedef typename Renderer::color_type color_type;
582         typedef line_interpolator_aa_base<Renderer> base_type;
583 
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)
589         {
590             base_type::m_li.adjust_forward();
591         }
592 
593         //---------------------------------------------------------------------
594         bool step_hor()
595         {
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;
601 
602             *p1++ = (cover_type)base_type::m_ren.cover(s1);
603 
604             dy = 1;
605             while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
606             {
607                 *p1++ = (cover_type)base_type::m_ren.cover(dist);
608                 ++dy;
609             }
610 
611             dy = 1;
612             while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
613             {
614                 *--p0 = (cover_type)base_type::m_ren.cover(dist);
615                 ++dy;
616             }
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;
622         }
623 
624         //---------------------------------------------------------------------
625         bool step_ver()
626         {
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;
632 
633             *p1++ = (cover_type)base_type::m_ren.cover(s1);
634 
635             dx = 1;
636             while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
637             {
638                 *p1++ = (cover_type)base_type::m_ren.cover(dist);
639                 ++dx;
640             }
641 
642             dx = 1;
643             while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
644             {
645                 *--p0 = (cover_type)base_type::m_ren.cover(dist);
646                 ++dx;
647             }
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;
653         }
654 
655     private:
656         line_interpolator_aa0(const line_interpolator_aa0<Renderer>&);
657         const line_interpolator_aa0<Renderer>&
658             operator = (const line_interpolator_aa0<Renderer>&);
659 
660         //---------------------------------------------------------------------
661         distance_interpolator1 m_di;
662     };
663 
664 
665 
666 
667 
668 
669     //====================================================line_interpolator_aa1
670     template<class Renderer> class line_interpolator_aa1 :
671     public line_interpolator_aa_base<Renderer>
672     {
673     public:
674         typedef Renderer renderer_type;
675         typedef typename Renderer::color_type color_type;
676         typedef line_interpolator_aa_base<Renderer> base_type;
677 
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)
684         {
685             int dist1_start;
686             int dist2_start;
687 
688             int npix = 1;
689 
690             if(lp.vertical)
691             {
692                 do
693                 {
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;
697 
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);
700 
701                     base_type::m_old_x = base_type::m_x;
702 
703                     dist1_start = dist2_start = m_di.dist_start();
704 
705                     int dx = 0;
706                     if(dist1_start < 0) ++npix;
707                     do
708                     {
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;
714                     }
715                     while(base_type::m_dist[dx] <= base_type::m_width);
716                     --base_type::m_step;
717                     if(npix == 0) break;
718                     npix = 0;
719                 }
720                 while(base_type::m_step >= -base_type::m_max_extent);
721             }
722             else
723             {
724                 do
725                 {
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;
729 
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);
732 
733                     base_type::m_old_y = base_type::m_y;
734 
735                     dist1_start = dist2_start = m_di.dist_start();
736 
737                     int dy = 0;
738                     if(dist1_start < 0) ++npix;
739                     do
740                     {
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;
746                     }
747                     while(base_type::m_dist[dy] <= base_type::m_width);
748                     --base_type::m_step;
749                     if(npix == 0) break;
750                     npix = 0;
751                 }
752                 while(base_type::m_step >= -base_type::m_max_extent);
753             }
754             base_type::m_li.adjust_forward();
755         }
756 
757         //---------------------------------------------------------------------
758         bool step_hor()
759         {
760             int dist_start;
761             int dist;
762             int dy;
763             int s1 = base_type::step_hor_base(m_di);
764 
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;
768 
769             *p1 = 0;
770             if(dist_start <= 0)
771             {
772                 *p1 = (cover_type)base_type::m_ren.cover(s1);
773             }
774             ++p1;
775 
776             dy = 1;
777             while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
778             {
779                 dist_start -= m_di.dx_start();
780                 *p1 = 0;
781                 if(dist_start <= 0)
782                 {
783                     *p1 = (cover_type)base_type::m_ren.cover(dist);
784                 }
785                 ++p1;
786                 ++dy;
787             }
788 
789             dy = 1;
790             dist_start = m_di.dist_start();
791             while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
792             {
793                 dist_start += m_di.dx_start();
794                 *--p0 = 0;
795                 if(dist_start <= 0)
796                 {
797                     *p0 = (cover_type)base_type::m_ren.cover(dist);
798                 }
799                 ++dy;
800             }
801 
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;
807         }
808 
809         //---------------------------------------------------------------------
810         bool step_ver()
811         {
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;
818 
819             dist_start = m_di.dist_start();
820 
821             *p1 = 0;
822             if(dist_start <= 0)
823             {
824                 *p1 = (cover_type)base_type::m_ren.cover(s1);
825             }
826             ++p1;
827 
828             dx = 1;
829             while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
830             {
831                 dist_start += m_di.dy_start();
832                 *p1 = 0;
833                 if(dist_start <= 0)
834                 {
835                     *p1 = (cover_type)base_type::m_ren.cover(dist);
836                 }
837                 ++p1;
838                 ++dx;
839             }
840 
841             dx = 1;
842             dist_start = m_di.dist_start();
843             while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
844             {
845                 dist_start -= m_di.dy_start();
846                 *--p0 = 0;
847                 if(dist_start <= 0)
848                 {
849                     *p0 = (cover_type)base_type::m_ren.cover(dist);
850                 }
851                 ++dx;
852             }
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;
858         }
859 
860     private:
861         line_interpolator_aa1(const line_interpolator_aa1<Renderer>&);
862         const line_interpolator_aa1<Renderer>&
863             operator = (const line_interpolator_aa1<Renderer>&);
864 
865         //---------------------------------------------------------------------
866         distance_interpolator2 m_di;
867     };
868 
869 
870 
871 
872 
873 
874 
875 
876 
877 
878 
879 
880     //====================================================line_interpolator_aa2
881     template<class Renderer> class line_interpolator_aa2 :
882     public line_interpolator_aa_base<Renderer>
883     {
884     public:
885         typedef Renderer renderer_type;
886         typedef typename Renderer::color_type color_type;
887         typedef line_interpolator_aa_base<Renderer> base_type;
888 
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,
895                  0)
896         {
897             base_type::m_li.adjust_forward();
898             base_type::m_step -= base_type::m_max_extent;
899         }
900 
901         //---------------------------------------------------------------------
902         bool step_hor()
903         {
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;
910 
911             dist_end = m_di.dist_end();
912 
913             int npix = 0;
914             *p1 = 0;
915             if(dist_end > 0)
916             {
917                 *p1 = (cover_type)base_type::m_ren.cover(s1);
918                 ++npix;
919             }
920             ++p1;
921 
922             dy = 1;
923             while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
924             {
925                 dist_end -= m_di.dx_end();
926                 *p1 = 0;
927                 if(dist_end > 0)
928                 {
929                     *p1 = (cover_type)base_type::m_ren.cover(dist);
930                     ++npix;
931                 }
932                 ++p1;
933                 ++dy;
934             }
935 
936             dy = 1;
937             dist_end = m_di.dist_end();
938             while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
939             {
940                 dist_end += m_di.dx_end();
941                 *--p0 = 0;
942                 if(dist_end > 0)
943                 {
944                     *p0 = (cover_type)base_type::m_ren.cover(dist);
945                     ++npix;
946                 }
947                 ++dy;
948             }
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;
954         }
955 
956         //---------------------------------------------------------------------
957         bool step_ver()
958         {
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;
965 
966             dist_end = m_di.dist_end();
967 
968             int npix = 0;
969             *p1 = 0;
970             if(dist_end > 0)
971             {
972                 *p1 = (cover_type)base_type::m_ren.cover(s1);
973                 ++npix;
974             }
975             ++p1;
976 
977             dx = 1;
978             while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
979             {
980                 dist_end += m_di.dy_end();
981                 *p1 = 0;
982                 if(dist_end > 0)
983                 {
984                     *p1 = (cover_type)base_type::m_ren.cover(dist);
985                     ++npix;
986                 }
987                 ++p1;
988                 ++dx;
989             }
990 
991             dx = 1;
992             dist_end = m_di.dist_end();
993             while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
994             {
995                 dist_end -= m_di.dy_end();
996                 *--p0 = 0;
997                 if(dist_end > 0)
998                 {
999                     *p0 = (cover_type)base_type::m_ren.cover(dist);
1000                     ++npix;
1001                 }
1002                 ++dx;
1003             }
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;
1009         }
1010 
1011     private:
1012         line_interpolator_aa2(const line_interpolator_aa2<Renderer>&);
1013         const line_interpolator_aa2<Renderer>&
1014             operator = (const line_interpolator_aa2<Renderer>&);
1015 
1016         //---------------------------------------------------------------------
1017         distance_interpolator2 m_di;
1018     };
1019 
1020 
1021 
1022 
1023 
1024 
1025 
1026 
1027 
1028 
1029     //====================================================line_interpolator_aa3
1030     template<class Renderer> class line_interpolator_aa3 :
1031     public line_interpolator_aa_base<Renderer>
1032     {
1033     public:
1034         typedef Renderer renderer_type;
1035         typedef typename Renderer::color_type color_type;
1036         typedef line_interpolator_aa_base<Renderer> base_type;
1037 
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)
1044         {
1045             int dist1_start;
1046             int dist2_start;
1047             int npix = 1;
1048             if(lp.vertical)
1049             {
1050                 do
1051                 {
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;
1055 
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);
1058 
1059                     base_type::m_old_x = base_type::m_x;
1060 
1061                     dist1_start = dist2_start = m_di.dist_start();
1062 
1063                     int dx = 0;
1064                     if(dist1_start < 0) ++npix;
1065                     do
1066                     {
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;
1072                     }
1073                     while(base_type::m_dist[dx] <= base_type::m_width);
1074                     if(npix == 0) break;
1075                     npix = 0;
1076                 }
1077                 while(--base_type::m_step >= -base_type::m_max_extent);
1078             }
1079             else
1080             {
1081                 do
1082                 {
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;
1086 
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);
1089 
1090                     base_type::m_old_y = base_type::m_y;
1091 
1092                     dist1_start = dist2_start = m_di.dist_start();
1093 
1094                     int dy = 0;
1095                     if(dist1_start < 0) ++npix;
1096                     do
1097                     {
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;
1103                     }
1104                     while(base_type::m_dist[dy] <= base_type::m_width);
1105                     if(npix == 0) break;
1106                     npix = 0;
1107                 }
1108                 while(--base_type::m_step >= -base_type::m_max_extent);
1109             }
1110             base_type::m_li.adjust_forward();
1111             base_type::m_step -= base_type::m_max_extent;
1112         }
1113 
1114 
1115         //---------------------------------------------------------------------
1116         bool step_hor()
1117         {
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;
1125 
1126             dist_start = m_di.dist_start();
1127             dist_end   = m_di.dist_end();
1128 
1129             int npix = 0;
1130             *p1 = 0;
1131             if(dist_end > 0)
1132             {
1133                 if(dist_start <= 0)
1134                 {
1135                     *p1 = (cover_type)base_type::m_ren.cover(s1);
1136                 }
1137                 ++npix;
1138             }
1139             ++p1;
1140 
1141             dy = 1;
1142             while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
1143             {
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)
1148                 {
1149                     *p1 = (cover_type)base_type::m_ren.cover(dist);
1150                     ++npix;
1151                 }
1152                 ++p1;
1153                 ++dy;
1154             }
1155 
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)
1160             {
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)
1165                 {
1166                     *p0 = (cover_type)base_type::m_ren.cover(dist);
1167                     ++npix;
1168                 }
1169                 ++dy;
1170             }
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;
1176         }
1177 
1178         //---------------------------------------------------------------------
1179         bool step_ver()
1180         {
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;
1188 
1189             dist_start = m_di.dist_start();
1190             dist_end   = m_di.dist_end();
1191 
1192             int npix = 0;
1193             *p1 = 0;
1194             if(dist_end > 0)
1195             {
1196                 if(dist_start <= 0)
1197                 {
1198                     *p1 = (cover_type)base_type::m_ren.cover(s1);
1199                 }
1200                 ++npix;
1201             }
1202             ++p1;
1203 
1204             dx = 1;
1205             while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
1206             {
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)
1211                 {
1212                     *p1 = (cover_type)base_type::m_ren.cover(dist);
1213                     ++npix;
1214                 }
1215                 ++p1;
1216                 ++dx;
1217             }
1218 
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)
1223             {
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)
1228                 {
1229                     *p0 = (cover_type)base_type::m_ren.cover(dist);
1230                     ++npix;
1231                 }
1232                 ++dx;
1233             }
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;
1239         }
1240 
1241     private:
1242         line_interpolator_aa3(const line_interpolator_aa3<Renderer>&);
1243         const line_interpolator_aa3<Renderer>&
1244             operator = (const line_interpolator_aa3<Renderer>&);
1245 
1246         //---------------------------------------------------------------------
1247         distance_interpolator3 m_di;
1248     };
1249 
1250 
1251 
1252 
1253     //==========================================================line_profile_aa
1254     //
1255     // See Implementation agg_line_profile_aa.cpp
1256     //
1257     class line_profile_aa
1258     {
1259     public:
1260         //---------------------------------------------------------------------
1261         typedef int8u value_type;
1262         enum
1263         {
1264             subpixel_shift = line_subpixel_shift,
1265             subpixel_size  = 1 << subpixel_shift,
1266             subpixel_mask  = subpixel_size - 1
1267         };
1268 
1269         enum
1270         {
1271             aa_shift = 8,
1272             aa_num   = 1 << aa_shift,
1273             aa_mask  = aa_num - 1
1274         };
1275 
1276         //---------------------------------------------------------------------
1277         ~line_profile_aa() { delete [] m_profile; }
1278 
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)
1286         {
1287             int i;
1288             for(i = 0; i < aa_num; i++) m_gamma[i] = (value_type)i;
1289         }
1290 
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)
1299         {
1300             gamma(gamma_function);
1301             width(w);
1302         }
1303 
1304         //---------------------------------------------------------------------
1305         void min_width(double w) { m_min_width = w; }
1306         void smoother_width(double w) { m_smoother_width = w; }
1307 
1308         //---------------------------------------------------------------------
1309         template<class GammaF> void gamma(const GammaF& gamma_function)
1310         {
1311             int i;
1312             for(i = 0; i < aa_num; i++)
1313             {
1314                 m_gamma[i] = value_type(
1315                     floor(
1316                         gamma_function(double(i) / aa_mask) * aa_mask + 0.5));
1317             }
1318         }
1319 
1320         void width(double w);
1321 
1322         unsigned profile_size() const { return m_size; }
1323         int subpixel_width() const { return m_subpixel_width; }
1324 
1325         //---------------------------------------------------------------------
1326         double min_width() const { return m_min_width; }
1327         double smoother_width() const { return m_smoother_width; }
1328 
1329         //---------------------------------------------------------------------
1330         value_type value(int dist) const
1331         {
1332             return m_profile[dist + subpixel_size*2];
1333         }
1334 
1335     private:
1336         line_profile_aa(const line_profile_aa&);
1337         const line_profile_aa& operator = (const line_profile_aa&);
1338 
1339         value_type* profile(double w);
1340         void set(double center_width, double smoother_width);
1341 
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;
1349     };
1350 
1351 
1352 
1353 
1354 
1355 
1356     //======================================================renderer_outline_aa
1357     template<class BaseRenderer> class renderer_outline_aa
1358     {
1359     public:
1360         //---------------------------------------------------------------------
1361         typedef BaseRenderer base_ren_type;
1362         typedef renderer_outline_aa<base_ren_type> self_type;
1363         typedef typename base_ren_type::color_type color_type;
1364 
1365         //---------------------------------------------------------------------
1366         renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) :
1367             m_ren(&ren),
1368             m_profile(&prof)
1369         {
1370         }
1371 
1372         //---------------------------------------------------------------------
1373         void color(const color_type& c) { m_color = c; }
1374         const color_type& color() const { return m_color; }
1375 
1376         //---------------------------------------------------------------------
1377         void profile(const line_profile_aa& prof) { m_profile = &prof; }
1378         const line_profile_aa& profile() const { return *m_profile; }
1379         line_profile_aa& profile() { return *m_profile; }
1380 
1381         //---------------------------------------------------------------------
1382         int subpixel_width() const { return m_profile->subpixel_width(); }
1383 
1384         //---------------------------------------------------------------------
1385         int cover(int d) const
1386         {
1387             return m_profile->value(d);
1388         }
1389 
1390         //-------------------------------------------------------------------------
1391         void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers)
1392         {
1393             m_ren->blend_solid_hspan(x, y, len, m_color, covers);
1394         }
1395 
1396         //-------------------------------------------------------------------------
1397         void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers)
1398         {
1399             m_ren->blend_solid_vspan(x, y, len, m_color, covers);
1400         }
1401 
1402         //-------------------------------------------------------------------------
1403         static bool accurate_join_only() { return false; }
1404 
1405         //-------------------------------------------------------------------------
1406         template<class Cmp>
1407         void semidot_hline(Cmp cmp,
1408                            int xc1, int yc1, int xc2, int yc2,
1409                            int x1,  int y1,  int x2)
1410         {
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_size/2;
1419             y += line_subpixel_size/2;
1420 
1421             int x0 = x1;
1422             int dx = x - xc1;
1423             int dy = y - yc1;
1424             do
1425             {
1426                 int d = int(fast_sqrt(dx*dx + dy*dy));
1427                 *p1 = 0;
1428                 if(cmp(di.dist()) && d <= w)
1429                 {
1430                     *p1 = (cover_type)cover(d);
1431                 }
1432                 ++p1;
1433                 dx += line_subpixel_size;
1434                 di.inc_x();
1435             }
1436             while(++x1 <= x2);
1437             m_ren->blend_solid_hspan(x0, y1,
1438                                      unsigned(p1 - p0),
1439                                      color(),
1440                                      p0);
1441         }
1442 
1443         //-------------------------------------------------------------------------
1444         template<class Cmp>
1445         void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2)
1446         {
1447             int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1448             if(r < 1) r = 1;
1449             ellipse_bresenham_interpolator ei(r, r);
1450             int dx = 0;
1451             int dy = -r;
1452             int dy0 = dy;
1453             int dx0 = dx;
1454             int x = xc1 >> line_subpixel_shift;
1455             int y = yc1 >> line_subpixel_shift;
1456 
1457             do
1458             {
1459                 dx += ei.dx();
1460                 dy += ei.dy();
1461 
1462                 if(dy != dy0)
1463                 {
1464                     semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1465                     semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0);
1466                 }
1467                 dx0 = dx;
1468                 dy0 = dy;
1469                 ++ei;
1470             }
1471             while(dy < 0);
1472             semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1473         }
1474 
1475         //-------------------------------------------------------------------------
1476         void line0(const line_parameters& lp)
1477         {
1478             line_interpolator_aa0<self_type> li(*this, lp);
1479             if(li.count())
1480             {
1481                 if(li.vertical())
1482                 {
1483                     while(li.step_ver());
1484                 }
1485                 else
1486                 {
1487                     while(li.step_hor());
1488                 }
1489             }
1490         }
1491 
1492         //-------------------------------------------------------------------------
1493         void line1(const line_parameters& lp, int sx, int sy)
1494         {
1495             line_interpolator_aa1<self_type> li(*this, lp, sx, sy);
1496             if(li.vertical())
1497             {
1498                 while(li.step_ver());
1499             }
1500             else
1501             {
1502                 while(li.step_hor());
1503             }
1504         }
1505 
1506         //-------------------------------------------------------------------------
1507         void line2(const line_parameters& lp, int ex, int ey)
1508         {
1509             line_interpolator_aa2<self_type> li(*this, lp, ex, ey);
1510             if(li.vertical())
1511             {
1512                 while(li.step_ver());
1513             }
1514             else
1515             {
1516                 while(li.step_hor());
1517             }
1518         }
1519 
1520         //-------------------------------------------------------------------------
1521         void line3(const line_parameters& lp,
1522                    int sx, int sy, int ex, int ey)
1523         {
1524             line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey);
1525             if(li.vertical())
1526             {
1527                 while(li.step_ver());
1528             }
1529             else
1530             {
1531                 while(li.step_hor());
1532             }
1533         }
1534 
1535     private:
1536         base_ren_type*   m_ren;
1537         const line_profile_aa* m_profile;
1538         color_type       m_color;
1539     };
1540 
1541 
1542 
1543 }
1544 
1545 #endif
1546