1//----------------------------------------------------------------------------
2// Anti-Grain Geometry - Version 2.4
3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4//
5// Permission to copy, use, modify, sell and distribute this software
6// is granted provided this copyright notice appears in all copies.
7// This software is provided "as is" without express or implied
8// warranty, and with no claim as to its suitability for any purpose.
9//
10//----------------------------------------------------------------------------
11// Contact: mcseem@antigrain.com
12//          mcseemagg@yahoo.com
13//          http://www.antigrain.com
14//----------------------------------------------------------------------------
15#ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED
16#define AGG_RENDERER_OUTLINE_AA_INCLUDED
17
18#include "agg_array.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#include "agg_clip_liang_barsky.h"
26
27namespace agg
28{
29
30    //===================================================distance_interpolator0
31    class distance_interpolator0
32    {
33    public:
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)
41        {
42            m_dx <<= line_mr_subpixel_shift;
43            m_dy <<= line_mr_subpixel_shift;
44        }
45
46        //---------------------------------------------------------------------
47        void inc_x() { m_dist += m_dy; }
48        int  dist() const { return m_dist; }
49
50    private:
51        //---------------------------------------------------------------------
52        int m_dx;
53        int m_dy;
54        int m_dist;
55    };
56
57    //==================================================distance_interpolator00
58    class distance_interpolator00
59    {
60    public:
61        //---------------------------------------------------------------------
62        distance_interpolator00() {}
63        distance_interpolator00(int xc, int yc,
64                                int x1, int y1, int x2, int y2,
65                                int x,  int y) :
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)
74        {
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;
79        }
80
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; }
85
86    private:
87        //---------------------------------------------------------------------
88        int m_dx1;
89        int m_dy1;
90        int m_dx2;
91        int m_dy2;
92        int m_dist1;
93        int m_dist2;
94    };
95
96    //===================================================distance_interpolator1
97    class distance_interpolator1
98    {
99    public:
100        //---------------------------------------------------------------------
101        distance_interpolator1() {}
102        distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) :
103            m_dx(x2 - x1),
104            m_dy(y2 - y1),
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)))
107        {
108            m_dx <<= line_subpixel_shift;
109            m_dy <<= line_subpixel_shift;
110        }
111
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; }
117
118        //---------------------------------------------------------------------
119        void inc_x(int dy)
120        {
121            m_dist += m_dy;
122            if(dy > 0) m_dist -= m_dx;
123            if(dy < 0) m_dist += m_dx;
124        }
125
126        //---------------------------------------------------------------------
127        void dec_x(int dy)
128        {
129            m_dist -= m_dy;
130            if(dy > 0) m_dist -= m_dx;
131            if(dy < 0) m_dist += m_dx;
132        }
133
134        //---------------------------------------------------------------------
135        void inc_y(int dx)
136        {
137            m_dist -= m_dx;
138            if(dx > 0) m_dist += m_dy;
139            if(dx < 0) m_dist -= m_dy;
140        }
141
142        void dec_y(int dx)
143        //---------------------------------------------------------------------
144        {
145            m_dist += m_dx;
146            if(dx > 0) m_dist += m_dy;
147            if(dx < 0) m_dist -= m_dy;
148        }
149
150        //---------------------------------------------------------------------
151        int dist() const { return m_dist; }
152        int dx()   const { return m_dx;   }
153        int dy()   const { return m_dy;   }
154
155    private:
156        //---------------------------------------------------------------------
157        int m_dx;
158        int m_dy;
159        int m_dist;
160    };
161
162
163
164
165
166    //===================================================distance_interpolator2
167    class distance_interpolator2
168    {
169    public:
170        //---------------------------------------------------------------------
171        distance_interpolator2() {}
172        distance_interpolator2(int x1, int y1, int x2, int y2,
173                               int sx, int sy, int x,  int y) :
174            m_dx(x2 - x1),
175            m_dy(y2 - y1),
176            m_dx_start(line_mr(sx) - line_mr(x1)),
177            m_dy_start(line_mr(sy) - line_mr(y1)),
178
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))),
181
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)
184        {
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;
189        }
190
191        distance_interpolator2(int x1, int y1, int x2, int y2,
192                               int ex, int ey, int x,  int y, int) :
193            m_dx(x2 - x1),
194            m_dy(y2 - y1),
195            m_dx_start(line_mr(ex) - line_mr(x2)),
196            m_dy_start(line_mr(ey) - line_mr(y2)),
197
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))),
200
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)
203        {
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;
208        }
209
210
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; }
216
217        //---------------------------------------------------------------------
218        void inc_x(int dy)
219        {
220            m_dist       += m_dy;
221            m_dist_start += m_dy_start;
222            if(dy > 0)
223            {
224                m_dist       -= m_dx;
225                m_dist_start -= m_dx_start;
226            }
227            if(dy < 0)
228            {
229                m_dist       += m_dx;
230                m_dist_start += m_dx_start;
231            }
232        }
233
234        //---------------------------------------------------------------------
235        void dec_x(int dy)
236        {
237            m_dist       -= m_dy;
238            m_dist_start -= m_dy_start;
239            if(dy > 0)
240            {
241                m_dist       -= m_dx;
242                m_dist_start -= m_dx_start;
243            }
244            if(dy < 0)
245            {
246                m_dist       += m_dx;
247                m_dist_start += m_dx_start;
248            }
249        }
250
251        //---------------------------------------------------------------------
252        void inc_y(int dx)
253        {
254            m_dist       -= m_dx;
255            m_dist_start -= m_dx_start;
256            if(dx > 0)
257            {
258                m_dist       += m_dy;
259                m_dist_start += m_dy_start;
260            }
261            if(dx < 0)
262            {
263                m_dist       -= m_dy;
264                m_dist_start -= m_dy_start;
265            }
266        }
267
268        //---------------------------------------------------------------------
269        void dec_y(int dx)
270        {
271            m_dist       += m_dx;
272            m_dist_start += m_dx_start;
273            if(dx > 0)
274            {
275                m_dist       += m_dy;
276                m_dist_start += m_dy_start;
277            }
278            if(dx < 0)
279            {
280                m_dist       -= m_dy;
281                m_dist_start -= m_dy_start;
282            }
283        }
284
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; }
289
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; }
297
298    private:
299        //---------------------------------------------------------------------
300        int m_dx;
301        int m_dy;
302        int m_dx_start;
303        int m_dy_start;
304
305        int m_dist;
306        int m_dist_start;
307    };
308
309
310
311
312
313    //===================================================distance_interpolator3
314    class distance_interpolator3
315    {
316    public:
317        //---------------------------------------------------------------------
318        distance_interpolator3() {}
319        distance_interpolator3(int x1, int y1, int x2, int y2,
320                               int sx, int sy, int ex, int ey,
321                               int x,  int y) :
322            m_dx(x2 - x1),
323            m_dy(y2 - y1),
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)),
328
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))),
331
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),
334
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)
337        {
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;
344        }
345
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; }
351
352        //---------------------------------------------------------------------
353        void inc_x(int dy)
354        {
355            m_dist       += m_dy;
356            m_dist_start += m_dy_start;
357            m_dist_end   += m_dy_end;
358            if(dy > 0)
359            {
360                m_dist       -= m_dx;
361                m_dist_start -= m_dx_start;
362                m_dist_end   -= m_dx_end;
363            }
364            if(dy < 0)
365            {
366                m_dist       += m_dx;
367                m_dist_start += m_dx_start;
368                m_dist_end   += m_dx_end;
369            }
370        }
371
372        //---------------------------------------------------------------------
373        void dec_x(int dy)
374        {
375            m_dist       -= m_dy;
376            m_dist_start -= m_dy_start;
377            m_dist_end   -= m_dy_end;
378            if(dy > 0)
379            {
380                m_dist       -= m_dx;
381                m_dist_start -= m_dx_start;
382                m_dist_end   -= m_dx_end;
383            }
384            if(dy < 0)
385            {
386                m_dist       += m_dx;
387                m_dist_start += m_dx_start;
388                m_dist_end   += m_dx_end;
389            }
390        }
391
392        //---------------------------------------------------------------------
393        void inc_y(int dx)
394        {
395            m_dist       -= m_dx;
396            m_dist_start -= m_dx_start;
397            m_dist_end   -= m_dx_end;
398            if(dx > 0)
399            {
400                m_dist       += m_dy;
401                m_dist_start += m_dy_start;
402                m_dist_end   += m_dy_end;
403            }
404            if(dx < 0)
405            {
406                m_dist       -= m_dy;
407                m_dist_start -= m_dy_start;
408                m_dist_end   -= m_dy_end;
409            }
410        }
411
412        //---------------------------------------------------------------------
413        void dec_y(int dx)
414        {
415            m_dist       += m_dx;
416            m_dist_start += m_dx_start;
417            m_dist_end   += m_dx_end;
418            if(dx > 0)
419            {
420                m_dist       += m_dy;
421                m_dist_start += m_dy_start;
422                m_dist_end   += m_dy_end;
423            }
424            if(dx < 0)
425            {
426                m_dist       -= m_dy;
427                m_dist_start -= m_dy_start;
428                m_dist_end   -= m_dy_end;
429            }
430        }
431
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;   }
436
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;   }
444
445    private:
446        //---------------------------------------------------------------------
447        int m_dx;
448        int m_dy;
449        int m_dx_start;
450        int m_dy_start;
451        int m_dx_end;
452        int m_dy_end;
453
454        int m_dist;
455        int m_dist_start;
456        int m_dist_end;
457    };
458
459
460
461
462
463    //================================================line_interpolator_aa_base
464    template<class Renderer> class line_interpolator_aa_base
465    {
466    public:
467        typedef Renderer renderer_type;
468        typedef typename Renderer::color_type color_type;
469
470        //---------------------------------------------------------------------
471        enum max_half_width_e
472        {
473            max_half_width = 64
474        };
475
476        //---------------------------------------------------------------------
477        line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) :
478            m_lp(&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),
483            m_ren(ren),
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),
487            m_old_x(m_x),
488            m_old_y(m_y),
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),
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_scale * 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 subpixel_scale_e
1263        {
1264            subpixel_shift = line_subpixel_shift,
1265            subpixel_scale = 1 << subpixel_shift,
1266            subpixel_mask  = subpixel_scale - 1
1267        };
1268
1269        enum aa_scale_e
1270        {
1271            aa_shift = 8,
1272            aa_scale = 1 << aa_shift,
1273            aa_mask  = aa_scale - 1
1274        };
1275
1276        //---------------------------------------------------------------------
1277        line_profile_aa() :
1278            m_subpixel_width(0),
1279            m_min_width(1.0),
1280            m_smoother_width(1.0)
1281        {
1282            int i;
1283            for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i;
1284        }
1285
1286        //---------------------------------------------------------------------
1287        template<class GammaF>
1288        line_profile_aa(double w, const GammaF& gamma_function) :
1289            m_subpixel_width(0),
1290            m_min_width(1.0),
1291            m_smoother_width(1.0)
1292        {
1293            gamma(gamma_function);
1294            width(w);
1295        }
1296
1297        //---------------------------------------------------------------------
1298        void min_width(double w) { m_min_width = w; }
1299        void smoother_width(double w) { m_smoother_width = w; }
1300
1301        //---------------------------------------------------------------------
1302        template<class GammaF> void gamma(const GammaF& gamma_function)
1303        {
1304            int i;
1305            for(i = 0; i < aa_scale; i++)
1306            {
1307                m_gamma[i] = value_type(
1308                    uround(gamma_function(double(i) / aa_mask) * aa_mask));
1309            }
1310        }
1311
1312        void width(double w);
1313
1314        unsigned profile_size() const { return m_profile.size(); }
1315        int subpixel_width() const { return m_subpixel_width; }
1316
1317        //---------------------------------------------------------------------
1318        double min_width() const { return m_min_width; }
1319        double smoother_width() const { return m_smoother_width; }
1320
1321        //---------------------------------------------------------------------
1322        value_type value(int dist) const
1323        {
1324            return m_profile[dist + subpixel_scale*2];
1325        }
1326
1327    private:
1328        line_profile_aa(const line_profile_aa&);
1329        const line_profile_aa& operator = (const line_profile_aa&);
1330
1331        value_type* profile(double w);
1332        void set(double center_width, double smoother_width);
1333
1334        //---------------------------------------------------------------------
1335        pod_array<value_type> m_profile;
1336        value_type            m_gamma[aa_scale];
1337        int                   m_subpixel_width;
1338        double                m_min_width;
1339        double                m_smoother_width;
1340    };
1341
1342
1343    //======================================================renderer_outline_aa
1344    template<class BaseRenderer> class renderer_outline_aa
1345    {
1346    public:
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;
1351
1352        //---------------------------------------------------------------------
1353        renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) :
1354            m_ren(&ren),
1355            m_profile(&prof),
1356            m_clip_box(0,0,0,0),
1357            m_clipping(false)
1358        {}
1359        void attach(base_ren_type& ren) { m_ren = &ren; }
1360
1361        //---------------------------------------------------------------------
1362        void color(const color_type& c) { m_color = c; }
1363        const color_type& color() const { return m_color; }
1364
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; }
1369
1370        //---------------------------------------------------------------------
1371        int subpixel_width() const { return m_profile->subpixel_width(); }
1372
1373        //---------------------------------------------------------------------
1374        void reset_clipping() { m_clipping = false; }
1375        void clip_box(double x1, double y1, double x2, double y2)
1376        {
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);
1381            m_clipping = true;
1382        }
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_scale/2;
1419            y += line_subpixel_scale/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_scale;
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            if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return;
1448
1449            int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1450            if(r < 1) r = 1;
1451            ellipse_bresenham_interpolator ei(r, r);
1452            int dx = 0;
1453            int dy = -r;
1454            int dy0 = dy;
1455            int dx0 = dx;
1456            int x = xc1 >> line_subpixel_shift;
1457            int y = yc1 >> line_subpixel_shift;
1458
1459            do
1460            {
1461                dx += ei.dx();
1462                dy += ei.dy();
1463
1464                if(dy != dy0)
1465                {
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);
1468                }
1469                dx0 = dx;
1470                dy0 = dy;
1471                ++ei;
1472            }
1473            while(dy < 0);
1474            semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1475        }
1476
1477        //-------------------------------------------------------------------------
1478        void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2,
1479                       int xh1, int yh1, int xh2)
1480        {
1481            if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return;
1482
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();
1489
1490            distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y);
1491            x += line_subpixel_scale/2;
1492            y += line_subpixel_scale/2;
1493
1494            int xh0 = xh1;
1495            int dx = x - xc;
1496            int dy = y - yc;
1497            do
1498            {
1499                int d = int(fast_sqrt(dx*dx + dy*dy));
1500                *p1 = 0;
1501                if(di.dist1() <= 0 && di.dist2() > 0 && d <= w)
1502                {
1503                    *p1 = (cover_type)cover(d);
1504                }
1505                ++p1;
1506                dx += line_subpixel_scale;
1507                di.inc_x();
1508            }
1509            while(++xh1 <= xh2);
1510            m_ren->blend_solid_hspan(xh0, yh1,
1511                                     unsigned(p1 - p0),
1512                                     color(),
1513                                     p0);
1514        }
1515
1516
1517        //-------------------------------------------------------------------------
1518        void pie(int xc, int yc, int x1, int y1, int x2, int y2)
1519        {
1520            int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1521            if(r < 1) r = 1;
1522            ellipse_bresenham_interpolator ei(r, r);
1523            int dx = 0;
1524            int dy = -r;
1525            int dy0 = dy;
1526            int dx0 = dx;
1527            int x = xc >> line_subpixel_shift;
1528            int y = yc >> line_subpixel_shift;
1529
1530            do
1531            {
1532                dx += ei.dx();
1533                dy += ei.dy();
1534
1535                if(dy != dy0)
1536                {
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);
1539                }
1540                dx0 = dx;
1541                dy0 = dy;
1542                ++ei;
1543            }
1544            while(dy < 0);
1545            pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
1546        }
1547
1548        //-------------------------------------------------------------------------
1549        void line0_no_clip(const line_parameters& lp)
1550        {
1551            if(lp.len > line_max_length)
1552            {
1553                line_parameters lp1, lp2;
1554                lp.divide(lp1, lp2);
1555                line0_no_clip(lp1);
1556                line0_no_clip(lp2);
1557                return;
1558            }
1559
1560            line_interpolator_aa0<self_type> li(*this, lp);
1561            if(li.count())
1562            {
1563                if(li.vertical())
1564                {
1565                    while(li.step_ver());
1566                }
1567                else
1568                {
1569                    while(li.step_hor());
1570                }
1571            }
1572        }
1573
1574        //-------------------------------------------------------------------------
1575        void line0(const line_parameters& lp)
1576        {
1577            if(m_clipping)
1578            {
1579                int x1 = lp.x1;
1580                int y1 = lp.y1;
1581                int x2 = lp.x2;
1582                int y2 = lp.y2;
1583                unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1584                if((flags & 4) == 0)
1585                {
1586                    if(flags)
1587                    {
1588                        line_parameters lp2(x1, y1, x2, y2,
1589                                           uround(calc_distance(x1, y1, x2, y2)));
1590                        line0_no_clip(lp2);
1591                    }
1592                    else
1593                    {
1594                        line0_no_clip(lp);
1595                    }
1596                }
1597            }
1598            else
1599            {
1600                line0_no_clip(lp);
1601            }
1602        }
1603
1604        //-------------------------------------------------------------------------
1605        void line1_no_clip(const line_parameters& lp, int sx, int sy)
1606        {
1607            if(lp.len > line_max_length)
1608            {
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));
1613                return;
1614            }
1615
1616            fix_degenerate_bisectrix_start(lp, &sx, &sy);
1617            line_interpolator_aa1<self_type> li(*this, lp, sx, sy);
1618            if(li.vertical())
1619            {
1620                while(li.step_ver());
1621            }
1622            else
1623            {
1624                while(li.step_hor());
1625            }
1626        }
1627
1628
1629        //-------------------------------------------------------------------------
1630        void line1(const line_parameters& lp, int sx, int sy)
1631        {
1632            if(m_clipping)
1633            {
1634                int x1 = lp.x1;
1635                int y1 = lp.y1;
1636                int x2 = lp.x2;
1637                int y2 = lp.y2;
1638                unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1639                if((flags & 4) == 0)
1640                {
1641                    if(flags)
1642                    {
1643                        line_parameters lp2(x1, y1, x2, y2,
1644                                           uround(calc_distance(x1, y1, x2, y2)));
1645                        if(flags & 1)
1646                        {
1647                            sx = x1 + (y2 - y1);
1648                            sy = y1 - (x2 - x1);
1649                        }
1650                        else
1651                        {
1652                            while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
1653                            {
1654                                sx = (lp.x1 + sx) >> 1;
1655                                sy = (lp.y1 + sy) >> 1;
1656                            }
1657                        }
1658                        line1_no_clip(lp2, sx, sy);
1659                    }
1660                    else
1661                    {
1662                        line1_no_clip(lp, sx, sy);
1663                    }
1664                }
1665            }
1666            else
1667            {
1668                line1_no_clip(lp, sx, sy);
1669            }
1670        }
1671
1672        //-------------------------------------------------------------------------
1673        void line2_no_clip(const line_parameters& lp, int ex, int ey)
1674        {
1675            if(lp.len > line_max_length)
1676            {
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);
1681                return;
1682            }
1683
1684            fix_degenerate_bisectrix_end(lp, &ex, &ey);
1685            line_interpolator_aa2<self_type> li(*this, lp, ex, ey);
1686            if(li.vertical())
1687            {
1688                while(li.step_ver());
1689            }
1690            else
1691            {
1692                while(li.step_hor());
1693            }
1694        }
1695
1696        //-------------------------------------------------------------------------
1697        void line2(const line_parameters& lp, int ex, int ey)
1698        {
1699            if(m_clipping)
1700            {
1701                int x1 = lp.x1;
1702                int y1 = lp.y1;
1703                int x2 = lp.x2;
1704                int y2 = lp.y2;
1705                unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1706                if((flags & 4) == 0)
1707                {
1708                    if(flags)
1709                    {
1710                        line_parameters lp2(x1, y1, x2, y2,
1711                                           uround(calc_distance(x1, y1, x2, y2)));
1712                        if(flags & 2)
1713                        {
1714                            ex = x2 + (y2 - y1);
1715                            ey = y2 - (x2 - x1);
1716                        }
1717                        else
1718                        {
1719                            while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
1720                            {
1721                                ex = (lp.x2 + ex) >> 1;
1722                                ey = (lp.y2 + ey) >> 1;
1723                            }
1724                        }
1725                        line2_no_clip(lp2, ex, ey);
1726                    }
1727                    else
1728                    {
1729                        line2_no_clip(lp, ex, ey);
1730                    }
1731                }
1732            }
1733            else
1734            {
1735                line2_no_clip(lp, ex, ey);
1736            }
1737        }
1738
1739        //-------------------------------------------------------------------------
1740        void line3_no_clip(const line_parameters& lp,
1741                           int sx, int sy, int ex, int ey)
1742        {
1743            if(lp.len > line_max_length)
1744            {
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);
1751                return;
1752            }
1753
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);
1757            if(li.vertical())
1758            {
1759                while(li.step_ver());
1760            }
1761            else
1762            {
1763                while(li.step_hor());
1764            }
1765        }
1766
1767        //-------------------------------------------------------------------------
1768        void line3(const line_parameters& lp,
1769                   int sx, int sy, int ex, int ey)
1770        {
1771            if(m_clipping)
1772            {
1773                int x1 = lp.x1;
1774                int y1 = lp.y1;
1775                int x2 = lp.x2;
1776                int y2 = lp.y2;
1777                unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1778                if((flags & 4) == 0)
1779                {
1780                    if(flags)
1781                    {
1782                        line_parameters lp2(x1, y1, x2, y2,
1783                                           uround(calc_distance(x1, y1, x2, y2)));
1784                        if(flags & 1)
1785                        {
1786                            sx = x1 + (y2 - y1);
1787                            sy = y1 - (x2 - x1);
1788                        }
1789                        else
1790                        {
1791                            while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
1792                            {
1793                                sx = (lp.x1 + sx) >> 1;
1794                                sy = (lp.y1 + sy) >> 1;
1795                            }
1796                        }
1797                        if(flags & 2)
1798                        {
1799                            ex = x2 + (y2 - y1);
1800                            ey = y2 - (x2 - x1);
1801                        }
1802                        else
1803                        {
1804                            while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
1805                            {
1806                                ex = (lp.x2 + ex) >> 1;
1807                                ey = (lp.y2 + ey) >> 1;
1808                            }
1809                        }
1810                        line3_no_clip(lp2, sx, sy, ex, ey);
1811                    }
1812                    else
1813                    {
1814                        line3_no_clip(lp, sx, sy, ex, ey);
1815                    }
1816                }
1817            }
1818            else
1819            {
1820                line3_no_clip(lp, sx, sy, ex, ey);
1821            }
1822        }
1823
1824
1825    private:
1826        base_ren_type*         m_ren;
1827        const line_profile_aa* m_profile;
1828        color_type             m_color;
1829        rect_i                 m_clip_box;
1830        bool                   m_clipping;
1831    };
1832
1833
1834
1835}
1836
1837#endif
1838