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 
27 namespace mapserver
28 {
29 
30     //===================================================distance_interpolator0
31     class distance_interpolator0
32     {
33     public:
34         //---------------------------------------------------------------------
distance_interpolator0()35         distance_interpolator0() {}
distance_interpolator0(int x1,int y1,int x2,int y2,int x,int y)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         //---------------------------------------------------------------------
inc_x()47         void inc_x() { m_dist += m_dy; }
dist()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         //---------------------------------------------------------------------
distance_interpolator00()62         distance_interpolator00() {}
distance_interpolator00(int xc,int yc,int x1,int y1,int x2,int y2,int x,int y)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         //---------------------------------------------------------------------
inc_x()82         void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; }
dist1()83         int  dist1() const { return m_dist1; }
dist2()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         //---------------------------------------------------------------------
distance_interpolator1()101         distance_interpolator1() {}
distance_interpolator1(int x1,int y1,int x2,int y2,int x,int y)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         //---------------------------------------------------------------------
inc_x()113         void inc_x() { m_dist += m_dy; }
dec_x()114         void dec_x() { m_dist -= m_dy; }
inc_y()115         void inc_y() { m_dist -= m_dx; }
dec_y()116         void dec_y() { m_dist += m_dx; }
117 
118         //---------------------------------------------------------------------
inc_x(int dy)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         //---------------------------------------------------------------------
dec_x(int dy)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         //---------------------------------------------------------------------
inc_y(int dx)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 
dec_y(int dx)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         //---------------------------------------------------------------------
dist()151         int dist() const { return m_dist; }
dx()152         int dx()   const { return m_dx;   }
dy()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         //---------------------------------------------------------------------
distance_interpolator2()171         distance_interpolator2() {}
distance_interpolator2(int x1,int y1,int x2,int y2,int sx,int sy,int x,int y)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 
distance_interpolator2(int x1,int y1,int x2,int y2,int ex,int ey,int x,int y,int)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         //---------------------------------------------------------------------
inc_x()212         void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; }
dec_x()213         void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; }
inc_y()214         void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; }
dec_y()215         void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; }
216 
217         //---------------------------------------------------------------------
inc_x(int dy)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         //---------------------------------------------------------------------
dec_x(int dy)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         //---------------------------------------------------------------------
inc_y(int dx)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         //---------------------------------------------------------------------
dec_y(int dx)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         //---------------------------------------------------------------------
dist()286         int dist()       const { return m_dist;       }
dist_start()287         int dist_start() const { return m_dist_start; }
dist_end()288         int dist_end()   const { return m_dist_start; }
289 
290         //---------------------------------------------------------------------
dx()291         int dx()       const { return m_dx;       }
dy()292         int dy()       const { return m_dy;       }
dx_start()293         int dx_start() const { return m_dx_start; }
dy_start()294         int dy_start() const { return m_dy_start; }
dx_end()295         int dx_end()   const { return m_dx_start; }
dy_end()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         //---------------------------------------------------------------------
distance_interpolator3()318         distance_interpolator3() {}
distance_interpolator3(int x1,int y1,int x2,int y2,int sx,int sy,int ex,int ey,int x,int y)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         //---------------------------------------------------------------------
inc_x()347         void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; }
dec_x()348         void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; }
inc_y()349         void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; }
dec_y()350         void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; }
351 
352         //---------------------------------------------------------------------
inc_x(int dy)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         //---------------------------------------------------------------------
dec_x(int dy)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         //---------------------------------------------------------------------
inc_y(int dx)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         //---------------------------------------------------------------------
dec_y(int dx)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         //---------------------------------------------------------------------
dist()433         int dist()       const { return m_dist;       }
dist_start()434         int dist_start() const { return m_dist_start; }
dist_end()435         int dist_end()   const { return m_dist_end;   }
436 
437         //---------------------------------------------------------------------
dx()438         int dx()       const { return m_dx;       }
dy()439         int dy()       const { return m_dy;       }
dx_start()440         int dx_start() const { return m_dx_start; }
dy_start()441         int dy_start() const { return m_dy_start; }
dx_end()442         int dx_end()   const { return m_dx_end;   }
dy_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         //---------------------------------------------------------------------
line_interpolator_aa_base(renderer_type & ren,const line_parameters & lp)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             mapserver::dda2_line_interpolator li(0, lp.vertical ?
497                                               (lp.dy << mapserver::line_subpixel_shift) :
498                                               (lp.dx << mapserver::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         //---------------------------------------------------------------------
step_hor_base(DI & di)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         //---------------------------------------------------------------------
step_ver_base(DI & di)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         //---------------------------------------------------------------------
vertical()543         bool vertical() const { return m_lp->vertical; }
width()544         int  width() const { return m_width; }
count()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         //---------------------------------------------------------------------
line_interpolator_aa0(renderer_type & ren,const line_parameters & lp)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         //---------------------------------------------------------------------
step_hor()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         //---------------------------------------------------------------------
step_ver()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         //---------------------------------------------------------------------
line_interpolator_aa1(renderer_type & ren,const line_parameters & lp,int sx,int sy)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         //---------------------------------------------------------------------
step_hor()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         //---------------------------------------------------------------------
step_ver()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         //---------------------------------------------------------------------
line_interpolator_aa2(renderer_type & ren,const line_parameters & lp,int ex,int ey)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         //---------------------------------------------------------------------
step_hor()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         //---------------------------------------------------------------------
step_ver()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         //---------------------------------------------------------------------
line_interpolator_aa3(renderer_type & ren,const line_parameters & lp,int sx,int sy,int ex,int ey)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         //---------------------------------------------------------------------
step_hor()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         //---------------------------------------------------------------------
step_ver()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         //---------------------------------------------------------------------
line_profile_aa()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>
line_profile_aa(double w,const GammaF & gamma_function)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         //---------------------------------------------------------------------
min_width(double w)1298         void min_width(double w) { m_min_width = w; }
smoother_width(double w)1299         void smoother_width(double w) { m_smoother_width = w; }
1300 
1301         //---------------------------------------------------------------------
gamma(const GammaF & gamma_function)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 
profile_size()1314         unsigned profile_size() const { return m_profile.size(); }
subpixel_width()1315         int subpixel_width() const { return m_subpixel_width; }
1316 
1317         //---------------------------------------------------------------------
min_width()1318         double min_width() const { return m_min_width; }
smoother_width()1319         double smoother_width() const { return m_smoother_width; }
1320 
1321         //---------------------------------------------------------------------
value(int dist)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         //---------------------------------------------------------------------
renderer_outline_aa(base_ren_type & ren,const line_profile_aa & prof)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         {}
attach(base_ren_type & ren)1359         void attach(base_ren_type& ren) { m_ren = &ren; }
1360 
1361         //---------------------------------------------------------------------
color(const color_type & c)1362         void color(const color_type& c) { m_color = c; }
color()1363         const color_type& color() const { return m_color; }
1364 
1365         //---------------------------------------------------------------------
profile(const line_profile_aa & prof)1366         void profile(const line_profile_aa& prof) { m_profile = &prof; }
profile()1367         const line_profile_aa& profile() const { return *m_profile; }
1368 
1369         //---------------------------------------------------------------------
subpixel_width()1370         int subpixel_width() const { return m_profile->subpixel_width(); }
1371 
1372         //---------------------------------------------------------------------
reset_clipping()1373         void reset_clipping() { m_clipping = false; }
clip_box(double x1,double y1,double x2,double y2)1374         void clip_box(double x1, double y1, double x2, double y2)
1375         {
1376             m_clip_box.x1 = line_coord_sat::conv(x1);
1377             m_clip_box.y1 = line_coord_sat::conv(y1);
1378             m_clip_box.x2 = line_coord_sat::conv(x2);
1379             m_clip_box.y2 = line_coord_sat::conv(y2);
1380             m_clipping = true;
1381         }
1382 
1383         //---------------------------------------------------------------------
cover(int d)1384         int cover(int d) const
1385         {
1386             return m_profile->value(d);
1387         }
1388 
1389         //-------------------------------------------------------------------------
blend_solid_hspan(int x,int y,unsigned len,const cover_type * covers)1390         void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers)
1391         {
1392             m_ren->blend_solid_hspan(x, y, len, m_color, covers);
1393         }
1394 
1395         //-------------------------------------------------------------------------
blend_solid_vspan(int x,int y,unsigned len,const cover_type * covers)1396         void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers)
1397         {
1398             m_ren->blend_solid_vspan(x, y, len, m_color, covers);
1399         }
1400 
1401         //-------------------------------------------------------------------------
accurate_join_only()1402         static bool accurate_join_only() { return false; }
1403 
1404         //-------------------------------------------------------------------------
1405         template<class Cmp>
semidot_hline(Cmp cmp,int xc1,int yc1,int xc2,int yc2,int x1,int y1,int x2)1406         void semidot_hline(Cmp cmp,
1407                            int xc1, int yc1, int xc2, int yc2,
1408                            int x1,  int y1,  int x2)
1409         {
1410             cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
1411             cover_type* p0 = covers;
1412             cover_type* p1 = covers;
1413             int x = x1 << line_subpixel_shift;
1414             int y = y1 << line_subpixel_shift;
1415             int w = subpixel_width();
1416             distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y);
1417             x += line_subpixel_scale/2;
1418             y += line_subpixel_scale/2;
1419 
1420             int x0 = x1;
1421             int dx = x - xc1;
1422             int dy = y - yc1;
1423             do
1424             {
1425                 int d = int(fast_sqrt(dx*dx + dy*dy));
1426                 *p1 = 0;
1427                 if(cmp(di.dist()) && d <= w)
1428                 {
1429                     *p1 = (cover_type)cover(d);
1430                 }
1431                 ++p1;
1432                 dx += line_subpixel_scale;
1433                 di.inc_x();
1434             }
1435             while(++x1 <= x2);
1436             m_ren->blend_solid_hspan(x0, y1,
1437                                      unsigned(p1 - p0),
1438                                      color(),
1439                                      p0);
1440         }
1441 
1442         //-------------------------------------------------------------------------
1443         template<class Cmp>
semidot(Cmp cmp,int xc1,int yc1,int xc2,int yc2)1444         void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2)
1445         {
1446             if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return;
1447 
1448             int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1449             if(r < 1) r = 1;
1450             ellipse_bresenham_interpolator ei(r, r);
1451             int dx = 0;
1452             int dy = -r;
1453             int dy0 = dy;
1454             int dx0 = dx;
1455             int x = xc1 >> line_subpixel_shift;
1456             int y = yc1 >> line_subpixel_shift;
1457 
1458             do
1459             {
1460                 dx += ei.dx();
1461                 dy += ei.dy();
1462 
1463                 if(dy != dy0)
1464                 {
1465                     semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1466                     semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0);
1467                 }
1468                 dx0 = dx;
1469                 dy0 = dy;
1470                 ++ei;
1471             }
1472             while(dy < 0);
1473             semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1474         }
1475 
1476         //-------------------------------------------------------------------------
pie_hline(int xc,int yc,int xp1,int yp1,int xp2,int yp2,int xh1,int yh1,int xh2)1477         void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2,
1478                        int xh1, int yh1, int xh2)
1479         {
1480             if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return;
1481 
1482             cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
1483             cover_type* p0 = covers;
1484             cover_type* p1 = covers;
1485             int x = xh1 << line_subpixel_shift;
1486             int y = yh1 << line_subpixel_shift;
1487             int w = subpixel_width();
1488 
1489             distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y);
1490             x += line_subpixel_scale/2;
1491             y += line_subpixel_scale/2;
1492 
1493             int xh0 = xh1;
1494             int dx = x - xc;
1495             int dy = y - yc;
1496             do
1497             {
1498                 int d = int(fast_sqrt(dx*dx + dy*dy));
1499                 *p1 = 0;
1500                 if(di.dist1() <= 0 && di.dist2() > 0 && d <= w)
1501                 {
1502                     *p1 = (cover_type)cover(d);
1503                 }
1504                 ++p1;
1505                 dx += line_subpixel_scale;
1506                 di.inc_x();
1507             }
1508             while(++xh1 <= xh2);
1509             m_ren->blend_solid_hspan(xh0, yh1,
1510                                      unsigned(p1 - p0),
1511                                      color(),
1512                                      p0);
1513         }
1514 
1515 
1516         //-------------------------------------------------------------------------
pie(int xc,int yc,int x1,int y1,int x2,int y2)1517         void pie(int xc, int yc, int x1, int y1, int x2, int y2)
1518         {
1519             int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1520             if(r < 1) r = 1;
1521             ellipse_bresenham_interpolator ei(r, r);
1522             int dx = 0;
1523             int dy = -r;
1524             int dy0 = dy;
1525             int dx0 = dx;
1526             int x = xc >> line_subpixel_shift;
1527             int y = yc >> line_subpixel_shift;
1528 
1529             do
1530             {
1531                 dx += ei.dx();
1532                 dy += ei.dy();
1533 
1534                 if(dy != dy0)
1535                 {
1536                     pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
1537                     pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0);
1538                 }
1539                 dx0 = dx;
1540                 dy0 = dy;
1541                 ++ei;
1542             }
1543             while(dy < 0);
1544             pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
1545         }
1546 
1547         //-------------------------------------------------------------------------
line0_no_clip(const line_parameters & lp)1548         void line0_no_clip(const line_parameters& lp)
1549         {
1550             if(lp.len > line_max_length)
1551             {
1552                 line_parameters lp1, lp2;
1553                 lp.divide(lp1, lp2);
1554                 line0_no_clip(lp1);
1555                 line0_no_clip(lp2);
1556                 return;
1557             }
1558 
1559             line_interpolator_aa0<self_type> li(*this, lp);
1560             if(li.count())
1561             {
1562                 if(li.vertical())
1563                 {
1564                     while(li.step_ver());
1565                 }
1566                 else
1567                 {
1568                     while(li.step_hor());
1569                 }
1570             }
1571         }
1572 
1573         //-------------------------------------------------------------------------
line0(const line_parameters & lp)1574         void line0(const line_parameters& lp)
1575         {
1576             if(m_clipping)
1577             {
1578                 int x1 = lp.x1;
1579                 int y1 = lp.y1;
1580                 int x2 = lp.x2;
1581                 int y2 = lp.y2;
1582                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1583                 if((flags & 4) == 0)
1584                 {
1585                     if(flags)
1586                     {
1587                         line_parameters lp2(x1, y1, x2, y2,
1588                                            uround(calc_distance(x1, y1, x2, y2)));
1589                         line0_no_clip(lp2);
1590                     }
1591                     else
1592                     {
1593                         line0_no_clip(lp);
1594                     }
1595                 }
1596             }
1597             else
1598             {
1599                 line0_no_clip(lp);
1600             }
1601         }
1602 
1603         //-------------------------------------------------------------------------
line1_no_clip(const line_parameters & lp,int sx,int sy)1604         void line1_no_clip(const line_parameters& lp, int sx, int sy)
1605         {
1606             if(lp.len > line_max_length)
1607             {
1608                 line_parameters lp1, lp2;
1609                 lp.divide(lp1, lp2);
1610                 line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1);
1611                 line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
1612                 return;
1613             }
1614 
1615             fix_degenerate_bisectrix_start(lp, &sx, &sy);
1616             line_interpolator_aa1<self_type> li(*this, lp, sx, sy);
1617             if(li.vertical())
1618             {
1619                 while(li.step_ver());
1620             }
1621             else
1622             {
1623                 while(li.step_hor());
1624             }
1625         }
1626 
1627 
1628         //-------------------------------------------------------------------------
line1(const line_parameters & lp,int sx,int sy)1629         void line1(const line_parameters& lp, int sx, int sy)
1630         {
1631             if(m_clipping)
1632             {
1633                 int x1 = lp.x1;
1634                 int y1 = lp.y1;
1635                 int x2 = lp.x2;
1636                 int y2 = lp.y2;
1637                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1638                 if((flags & 4) == 0)
1639                 {
1640                     if(flags)
1641                     {
1642                         line_parameters lp2(x1, y1, x2, y2,
1643                                            uround(calc_distance(x1, y1, x2, y2)));
1644                         if(flags & 1)
1645                         {
1646                             sx = x1 + (y2 - y1);
1647                             sy = y1 - (x2 - x1);
1648                         }
1649                         else
1650                         {
1651                             while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
1652                             {
1653                                 sx = (lp.x1 + sx) >> 1;
1654                                 sy = (lp.y1 + sy) >> 1;
1655                             }
1656                         }
1657                         line1_no_clip(lp2, sx, sy);
1658                     }
1659                     else
1660                     {
1661                         line1_no_clip(lp, sx, sy);
1662                     }
1663                 }
1664             }
1665             else
1666             {
1667                 line1_no_clip(lp, sx, sy);
1668             }
1669         }
1670 
1671         //-------------------------------------------------------------------------
line2_no_clip(const line_parameters & lp,int ex,int ey)1672         void line2_no_clip(const line_parameters& lp, int ex, int ey)
1673         {
1674             if(lp.len > line_max_length)
1675             {
1676                 line_parameters lp1, lp2;
1677                 lp.divide(lp1, lp2);
1678                 line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
1679                 line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
1680                 return;
1681             }
1682 
1683             fix_degenerate_bisectrix_end(lp, &ex, &ey);
1684             line_interpolator_aa2<self_type> li(*this, lp, ex, ey);
1685             if(li.vertical())
1686             {
1687                 while(li.step_ver());
1688             }
1689             else
1690             {
1691                 while(li.step_hor());
1692             }
1693         }
1694 
1695         //-------------------------------------------------------------------------
line2(const line_parameters & lp,int ex,int ey)1696         void line2(const line_parameters& lp, int ex, int ey)
1697         {
1698             if(m_clipping)
1699             {
1700                 int x1 = lp.x1;
1701                 int y1 = lp.y1;
1702                 int x2 = lp.x2;
1703                 int y2 = lp.y2;
1704                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1705                 if((flags & 4) == 0)
1706                 {
1707                     if(flags)
1708                     {
1709                         line_parameters lp2(x1, y1, x2, y2,
1710                                            uround(calc_distance(x1, y1, x2, y2)));
1711                         if(flags & 2)
1712                         {
1713                             ex = x2 + (y2 - y1);
1714                             ey = y2 - (x2 - x1);
1715                         }
1716                         else
1717                         {
1718                             while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
1719                             {
1720                                 ex = (lp.x2 + ex) >> 1;
1721                                 ey = (lp.y2 + ey) >> 1;
1722                             }
1723                         }
1724                         line2_no_clip(lp2, ex, ey);
1725                     }
1726                     else
1727                     {
1728                         line2_no_clip(lp, ex, ey);
1729                     }
1730                 }
1731             }
1732             else
1733             {
1734                 line2_no_clip(lp, ex, ey);
1735             }
1736         }
1737 
1738         //-------------------------------------------------------------------------
line3_no_clip(const line_parameters & lp,int sx,int sy,int ex,int ey)1739         void line3_no_clip(const line_parameters& lp,
1740                            int sx, int sy, int ex, int ey)
1741         {
1742             if(lp.len > line_max_length)
1743             {
1744                 line_parameters lp1, lp2;
1745                 lp.divide(lp1, lp2);
1746                 int mx = lp1.x2 + (lp1.y2 - lp1.y1);
1747                 int my = lp1.y2 - (lp1.x2 - lp1.x1);
1748                 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
1749                 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
1750                 return;
1751             }
1752 
1753             fix_degenerate_bisectrix_start(lp, &sx, &sy);
1754             fix_degenerate_bisectrix_end(lp, &ex, &ey);
1755             line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey);
1756             if(li.vertical())
1757             {
1758                 while(li.step_ver());
1759             }
1760             else
1761             {
1762                 while(li.step_hor());
1763             }
1764         }
1765 
1766         //-------------------------------------------------------------------------
line3(const line_parameters & lp,int sx,int sy,int ex,int ey)1767         void line3(const line_parameters& lp,
1768                    int sx, int sy, int ex, int ey)
1769         {
1770             if(m_clipping)
1771             {
1772                 int x1 = lp.x1;
1773                 int y1 = lp.y1;
1774                 int x2 = lp.x2;
1775                 int y2 = lp.y2;
1776                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1777                 if((flags & 4) == 0)
1778                 {
1779                     if(flags)
1780                     {
1781                         line_parameters lp2(x1, y1, x2, y2,
1782                                            uround(calc_distance(x1, y1, x2, y2)));
1783                         if(flags & 1)
1784                         {
1785                             sx = x1 + (y2 - y1);
1786                             sy = y1 - (x2 - x1);
1787                         }
1788                         else
1789                         {
1790                             while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
1791                             {
1792                                 sx = (lp.x1 + sx) >> 1;
1793                                 sy = (lp.y1 + sy) >> 1;
1794                             }
1795                         }
1796                         if(flags & 2)
1797                         {
1798                             ex = x2 + (y2 - y1);
1799                             ey = y2 - (x2 - x1);
1800                         }
1801                         else
1802                         {
1803                             while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
1804                             {
1805                                 ex = (lp.x2 + ex) >> 1;
1806                                 ey = (lp.y2 + ey) >> 1;
1807                             }
1808                         }
1809                         line3_no_clip(lp2, sx, sy, ex, ey);
1810                     }
1811                     else
1812                     {
1813                         line3_no_clip(lp, sx, sy, ex, ey);
1814                     }
1815                 }
1816             }
1817             else
1818             {
1819                 line3_no_clip(lp, sx, sy, ex, ey);
1820             }
1821         }
1822 
1823 
1824     private:
1825         base_ren_type*         m_ren;
1826         const line_profile_aa* m_profile;
1827         color_type             m_color;
1828         rect_i                 m_clip_box;
1829         bool                   m_clipping;
1830     };
1831 
1832 
1833 
1834 }
1835 
1836 #endif
1837