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 agg
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,line_parameters & lp)477         line_interpolator_aa_base(renderer_type& ren, 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         //---------------------------------------------------------------------
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         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,line_parameters & lp)585         line_interpolator_aa0(renderer_type& ren, 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,line_parameters & lp,int sx,int sy)679         line_interpolator_aa1(renderer_type& ren, 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,line_parameters & lp,int ex,int ey)890         line_interpolator_aa2(renderer_type& ren, 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,line_parameters & lp,int sx,int sy,int ex,int ey)1039         line_interpolator_aa3(renderer_type& ren, 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,line_profile_aa & prof)1353         renderer_outline_aa(base_ren_type& ren, 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(line_profile_aa & prof)1366         void profile(line_profile_aa& prof) { m_profile = &prof; }
profile()1367         line_profile_aa& profile() const { return *m_profile; }
profile()1368         line_profile_aa& profile() { return *m_profile; }
1369 
1370         //---------------------------------------------------------------------
subpixel_width()1371         int subpixel_width() const { return m_profile->subpixel_width(); }
1372 
1373         //---------------------------------------------------------------------
reset_clipping()1374         void reset_clipping() { m_clipping = false; }
clip_box(double x1,double y1,double x2,double y2)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         //---------------------------------------------------------------------
cover(int d)1385         int cover(int d) const
1386         {
1387             return m_profile->value(d);
1388         }
1389 
1390         //-------------------------------------------------------------------------
blend_solid_hspan(int x,int y,unsigned len,const cover_type * covers)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         //-------------------------------------------------------------------------
blend_solid_vspan(int x,int y,unsigned len,const cover_type * covers)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         //-------------------------------------------------------------------------
accurate_join_only()1403         static bool accurate_join_only() { return false; }
1404 
1405         //-------------------------------------------------------------------------
1406         template<class Cmp>
semidot_hline(Cmp cmp,int xc1,int yc1,int xc2,int yc2,int x1,int y1,int x2)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>
semidot(Cmp cmp,int xc1,int yc1,int xc2,int yc2)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         //-------------------------------------------------------------------------
pie_hline(int xc,int yc,int xp1,int yp1,int xp2,int yp2,int xh1,int yh1,int xh2)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         //-------------------------------------------------------------------------
pie(int xc,int yc,int x1,int y1,int x2,int y2)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         //-------------------------------------------------------------------------
line0_no_clip(line_parameters & lp)1549         void line0_no_clip(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         //-------------------------------------------------------------------------
line0(line_parameters & lp)1575         void line0(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         //-------------------------------------------------------------------------
line1_no_clip(line_parameters & lp,int sx,int sy)1605         void line1_no_clip(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         //-------------------------------------------------------------------------
line1(line_parameters & lp,int sx,int sy)1630         void line1(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         //-------------------------------------------------------------------------
line2_no_clip(line_parameters & lp,int ex,int ey)1673         void line2_no_clip(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         //-------------------------------------------------------------------------
line2(line_parameters & lp,int ex,int ey)1697         void line2(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         //-------------------------------------------------------------------------
line3_no_clip(line_parameters & lp,int sx,int sy,int ex,int ey)1740         void line3_no_clip(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         //-------------------------------------------------------------------------
line3(line_parameters & lp,int sx,int sy,int ex,int ey)1768         void line3(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         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