Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_renderer_outline_aa.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 
00025 #ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED
00026 #define AGG_RENDERER_OUTLINE_AA_INCLUDED
00027 
00028 #include "agg_array.h"
00029 #include "agg_math.h"
00030 #include "agg_line_aa_basics.h"
00031 #include "agg_dda_line.h"
00032 #include "agg_ellipse_bresenham.h"
00033 #include "agg_renderer_base.h"
00034 #include "agg_gamma_functions.h"
00035 #include "agg_clip_liang_barsky.h"
00036 
00037 namespace agg
00038 {
00039 
00040     //===================================================distance_interpolator0
00041     class distance_interpolator0
00042     {
00043     public:
00044         //---------------------------------------------------------------------
00045         distance_interpolator0() {}
00046         distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) :
00047             m_dx(line_mr(x2) - line_mr(x1)),
00048             m_dy(line_mr(y2) - line_mr(y1)),
00049             m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy - 
00050                    (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx)
00051         {
00052             m_dx <<= line_mr_subpixel_shift;
00053             m_dy <<= line_mr_subpixel_shift;
00054         }
00055 
00056         //---------------------------------------------------------------------
00057         void inc_x() { m_dist += m_dy; }
00058         int  dist() const { return m_dist; }
00059 
00060     private:
00061         //---------------------------------------------------------------------
00062         int m_dx;
00063         int m_dy;
00064         int m_dist;
00065     };
00066 
00067     //==================================================distance_interpolator00
00068     class distance_interpolator00
00069     {
00070     public:
00071         //---------------------------------------------------------------------
00072         distance_interpolator00() {}
00073         distance_interpolator00(int xc, int yc, 
00074                                 int x1, int y1, int x2, int y2, 
00075                                 int x,  int y) :
00076             m_dx1(line_mr(x1) - line_mr(xc)),
00077             m_dy1(line_mr(y1) - line_mr(yc)),
00078             m_dx2(line_mr(x2) - line_mr(xc)),
00079             m_dy2(line_mr(y2) - line_mr(yc)),
00080             m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 - 
00081                     (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1),
00082             m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 - 
00083                     (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2)
00084         {
00085             m_dx1 <<= line_mr_subpixel_shift;
00086             m_dy1 <<= line_mr_subpixel_shift;
00087             m_dx2 <<= line_mr_subpixel_shift;
00088             m_dy2 <<= line_mr_subpixel_shift;
00089         }
00090 
00091         //---------------------------------------------------------------------
00092         void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; }
00093         int  dist1() const { return m_dist1; }
00094         int  dist2() const { return m_dist2; }
00095 
00096     private:
00097         //---------------------------------------------------------------------
00098         int m_dx1;
00099         int m_dy1;
00100         int m_dx2;
00101         int m_dy2;
00102         int m_dist1;
00103         int m_dist2;
00104     };
00105 
00106     //===================================================distance_interpolator1
00107     class distance_interpolator1
00108     {
00109     public:
00110         //---------------------------------------------------------------------
00111         distance_interpolator1() {}
00112         distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) :
00113             m_dx(x2 - x1),
00114             m_dy(y2 - y1),
00115             m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 
00116                           double(y + line_subpixel_scale/2 - y2) * double(m_dx)))
00117         {
00118             m_dx <<= line_subpixel_shift;
00119             m_dy <<= line_subpixel_shift;
00120         }
00121 
00122         //---------------------------------------------------------------------
00123         void inc_x() { m_dist += m_dy; }
00124         void dec_x() { m_dist -= m_dy; }
00125         void inc_y() { m_dist -= m_dx; }
00126         void dec_y() { m_dist += m_dx; }
00127 
00128         //---------------------------------------------------------------------
00129         void inc_x(int dy)
00130         {
00131             m_dist += m_dy; 
00132             if(dy > 0) m_dist -= m_dx; 
00133             if(dy < 0) m_dist += m_dx; 
00134         }
00135 
00136         //---------------------------------------------------------------------
00137         void dec_x(int dy)
00138         {
00139             m_dist -= m_dy; 
00140             if(dy > 0) m_dist -= m_dx; 
00141             if(dy < 0) m_dist += m_dx; 
00142         }
00143 
00144         //---------------------------------------------------------------------
00145         void inc_y(int dx)
00146         {
00147             m_dist -= m_dx; 
00148             if(dx > 0) m_dist += m_dy; 
00149             if(dx < 0) m_dist -= m_dy; 
00150         }
00151 
00152         void dec_y(int dx)
00153         //---------------------------------------------------------------------
00154         {
00155             m_dist += m_dx; 
00156             if(dx > 0) m_dist += m_dy; 
00157             if(dx < 0) m_dist -= m_dy; 
00158         }
00159 
00160         //---------------------------------------------------------------------
00161         int dist() const { return m_dist; }
00162         int dx()   const { return m_dx;   }
00163         int dy()   const { return m_dy;   }
00164 
00165     private:
00166         //---------------------------------------------------------------------
00167         int m_dx;
00168         int m_dy;
00169         int m_dist;
00170     };
00171 
00172 
00173 
00174 
00175 
00176     //===================================================distance_interpolator2
00177     class distance_interpolator2
00178     {
00179     public:
00180         //---------------------------------------------------------------------
00181         distance_interpolator2() {}
00182         distance_interpolator2(int x1, int y1, int x2, int y2,
00183                                int sx, int sy, int x,  int y) :
00184             m_dx(x2 - x1),
00185             m_dy(y2 - y1),
00186             m_dx_start(line_mr(sx) - line_mr(x1)),
00187             m_dy_start(line_mr(sy) - line_mr(y1)),
00188 
00189             m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 
00190                           double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
00191 
00192             m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - 
00193                          (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start)
00194         {
00195             m_dx       <<= line_subpixel_shift;
00196             m_dy       <<= line_subpixel_shift;
00197             m_dx_start <<= line_mr_subpixel_shift;
00198             m_dy_start <<= line_mr_subpixel_shift;
00199         }
00200 
00201         distance_interpolator2(int x1, int y1, int x2, int y2,
00202                                int ex, int ey, int x,  int y, int) :
00203             m_dx(x2 - x1),
00204             m_dy(y2 - y1),
00205             m_dx_start(line_mr(ex) - line_mr(x2)),
00206             m_dy_start(line_mr(ey) - line_mr(y2)),
00207 
00208             m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 
00209                           double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
00210 
00211             m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start - 
00212                          (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start)
00213         {
00214             m_dx       <<= line_subpixel_shift;
00215             m_dy       <<= line_subpixel_shift;
00216             m_dx_start <<= line_mr_subpixel_shift;
00217             m_dy_start <<= line_mr_subpixel_shift;
00218         }
00219 
00220 
00221         //---------------------------------------------------------------------
00222         void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; }
00223         void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; }
00224         void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; }
00225         void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; }
00226 
00227         //---------------------------------------------------------------------
00228         void inc_x(int dy)
00229         {
00230             m_dist       += m_dy; 
00231             m_dist_start += m_dy_start; 
00232             if(dy > 0)
00233             {
00234                 m_dist       -= m_dx; 
00235                 m_dist_start -= m_dx_start; 
00236             }
00237             if(dy < 0)
00238             {
00239                 m_dist       += m_dx; 
00240                 m_dist_start += m_dx_start; 
00241             }
00242         }
00243 
00244         //---------------------------------------------------------------------
00245         void dec_x(int dy)
00246         {
00247             m_dist       -= m_dy; 
00248             m_dist_start -= m_dy_start; 
00249             if(dy > 0)
00250             {
00251                 m_dist       -= m_dx; 
00252                 m_dist_start -= m_dx_start; 
00253             }
00254             if(dy < 0)
00255             {
00256                 m_dist       += m_dx; 
00257                 m_dist_start += m_dx_start; 
00258             }
00259         }
00260 
00261         //---------------------------------------------------------------------
00262         void inc_y(int dx)
00263         {
00264             m_dist       -= m_dx; 
00265             m_dist_start -= m_dx_start; 
00266             if(dx > 0)
00267             {
00268                 m_dist       += m_dy; 
00269                 m_dist_start += m_dy_start; 
00270             }
00271             if(dx < 0)
00272             {
00273                 m_dist       -= m_dy; 
00274                 m_dist_start -= m_dy_start; 
00275             }
00276         }
00277 
00278         //---------------------------------------------------------------------
00279         void dec_y(int dx)
00280         {
00281             m_dist       += m_dx; 
00282             m_dist_start += m_dx_start; 
00283             if(dx > 0)
00284             {
00285                 m_dist       += m_dy; 
00286                 m_dist_start += m_dy_start; 
00287             }
00288             if(dx < 0)
00289             {
00290                 m_dist       -= m_dy; 
00291                 m_dist_start -= m_dy_start; 
00292             }
00293         }
00294 
00295         //---------------------------------------------------------------------
00296         int dist()       const { return m_dist;       }
00297         int dist_start() const { return m_dist_start; }
00298         int dist_end()   const { return m_dist_start; }
00299 
00300         //---------------------------------------------------------------------
00301         int dx()       const { return m_dx;       }
00302         int dy()       const { return m_dy;       }
00303         int dx_start() const { return m_dx_start; }
00304         int dy_start() const { return m_dy_start; }
00305         int dx_end()   const { return m_dx_start; }
00306         int dy_end()   const { return m_dy_start; }
00307 
00308     private:
00309         //---------------------------------------------------------------------
00310         int m_dx;
00311         int m_dy;
00312         int m_dx_start;
00313         int m_dy_start;
00314 
00315         int m_dist;
00316         int m_dist_start;
00317     };
00318 
00319 
00320 
00321 
00322 
00323     //===================================================distance_interpolator3
00324     class distance_interpolator3
00325     {
00326     public:
00327         //---------------------------------------------------------------------
00328         distance_interpolator3() {}
00329         distance_interpolator3(int x1, int y1, int x2, int y2,
00330                                int sx, int sy, int ex, int ey, 
00331                                int x,  int y) :
00332             m_dx(x2 - x1),
00333             m_dy(y2 - y1),
00334             m_dx_start(line_mr(sx) - line_mr(x1)),
00335             m_dy_start(line_mr(sy) - line_mr(y1)),
00336             m_dx_end(line_mr(ex) - line_mr(x2)),
00337             m_dy_end(line_mr(ey) - line_mr(y2)),
00338 
00339             m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 
00340                           double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
00341 
00342             m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - 
00343                          (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start),
00344 
00345             m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - 
00346                        (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end)
00347         {
00348             m_dx       <<= line_subpixel_shift;
00349             m_dy       <<= line_subpixel_shift;
00350             m_dx_start <<= line_mr_subpixel_shift;
00351             m_dy_start <<= line_mr_subpixel_shift;
00352             m_dx_end   <<= line_mr_subpixel_shift;
00353             m_dy_end   <<= line_mr_subpixel_shift;
00354         }
00355 
00356         //---------------------------------------------------------------------
00357         void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; }
00358         void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; }
00359         void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; }
00360         void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; }
00361 
00362         //---------------------------------------------------------------------
00363         void inc_x(int dy)
00364         {
00365             m_dist       += m_dy; 
00366             m_dist_start += m_dy_start; 
00367             m_dist_end   += m_dy_end;
00368             if(dy > 0)
00369             {
00370                 m_dist       -= m_dx; 
00371                 m_dist_start -= m_dx_start; 
00372                 m_dist_end   -= m_dx_end;
00373             }
00374             if(dy < 0)
00375             {
00376                 m_dist       += m_dx; 
00377                 m_dist_start += m_dx_start; 
00378                 m_dist_end   += m_dx_end;
00379             }
00380         }
00381 
00382         //---------------------------------------------------------------------
00383         void dec_x(int dy)
00384         {
00385             m_dist       -= m_dy; 
00386             m_dist_start -= m_dy_start; 
00387             m_dist_end   -= m_dy_end;
00388             if(dy > 0)
00389             {
00390                 m_dist       -= m_dx; 
00391                 m_dist_start -= m_dx_start; 
00392                 m_dist_end   -= m_dx_end;
00393             }
00394             if(dy < 0)
00395             {
00396                 m_dist       += m_dx; 
00397                 m_dist_start += m_dx_start; 
00398                 m_dist_end   += m_dx_end;
00399             }
00400         }
00401 
00402         //---------------------------------------------------------------------
00403         void inc_y(int dx)
00404         {
00405             m_dist       -= m_dx; 
00406             m_dist_start -= m_dx_start; 
00407             m_dist_end   -= m_dx_end;
00408             if(dx > 0)
00409             {
00410                 m_dist       += m_dy; 
00411                 m_dist_start += m_dy_start; 
00412                 m_dist_end   += m_dy_end;
00413             }
00414             if(dx < 0)
00415             {
00416                 m_dist       -= m_dy; 
00417                 m_dist_start -= m_dy_start; 
00418                 m_dist_end   -= m_dy_end;
00419             }
00420         }
00421 
00422         //---------------------------------------------------------------------
00423         void dec_y(int dx)
00424         {
00425             m_dist       += m_dx; 
00426             m_dist_start += m_dx_start; 
00427             m_dist_end   += m_dx_end;
00428             if(dx > 0)
00429             {
00430                 m_dist       += m_dy; 
00431                 m_dist_start += m_dy_start; 
00432                 m_dist_end   += m_dy_end;
00433             }
00434             if(dx < 0)
00435             {
00436                 m_dist       -= m_dy; 
00437                 m_dist_start -= m_dy_start; 
00438                 m_dist_end   -= m_dy_end;
00439             }
00440         }
00441 
00442         //---------------------------------------------------------------------
00443         int dist()       const { return m_dist;       }
00444         int dist_start() const { return m_dist_start; }
00445         int dist_end()   const { return m_dist_end;   }
00446 
00447         //---------------------------------------------------------------------
00448         int dx()       const { return m_dx;       }
00449         int dy()       const { return m_dy;       }
00450         int dx_start() const { return m_dx_start; }
00451         int dy_start() const { return m_dy_start; }
00452         int dx_end()   const { return m_dx_end;   }
00453         int dy_end()   const { return m_dy_end;   }
00454 
00455     private:
00456         //---------------------------------------------------------------------
00457         int m_dx;
00458         int m_dy;
00459         int m_dx_start;
00460         int m_dy_start;
00461         int m_dx_end;
00462         int m_dy_end;
00463 
00464         int m_dist;
00465         int m_dist_start;
00466         int m_dist_end;
00467     };
00468 
00469 
00470 
00471 
00472     
00473     //================================================line_interpolator_aa_base
00474     template<class Renderer> class line_interpolator_aa_base
00475     {
00476     public:
00477         typedef Renderer renderer_type;
00478         typedef typename Renderer::color_type color_type;
00479 
00480         //---------------------------------------------------------------------
00481         enum max_half_width_e
00482         { 
00483             max_half_width = 64
00484         };
00485 
00486         //---------------------------------------------------------------------
00487         line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) :
00488             m_lp(&lp),
00489             m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
00490                                line_dbl_hr(lp.y2 - lp.y1),
00491                  lp.vertical ? abs(lp.y2 - lp.y1) : 
00492                                abs(lp.x2 - lp.x1) + 1),
00493             m_ren(ren),
00494             m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len),
00495             m_x(lp.x1 >> line_subpixel_shift),
00496             m_y(lp.y1 >> line_subpixel_shift),
00497             m_old_x(m_x),
00498             m_old_y(m_y),
00499             m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
00500                                    abs((lp.x2 >> line_subpixel_shift) - m_x))),
00501             m_width(ren.subpixel_width()),
00502             //m_max_extent(m_width >> (line_subpixel_shift - 2)),
00503             m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift),
00504             m_step(0)
00505         {
00506             agg::dda2_line_interpolator li(0, lp.vertical ? 
00507                                               (lp.dy << agg::line_subpixel_shift) :
00508                                               (lp.dx << agg::line_subpixel_shift),
00509                                            lp.len);
00510 
00511             unsigned i;
00512             int stop = m_width + line_subpixel_scale * 2;
00513             for(i = 0; i < max_half_width; ++i)
00514             {
00515                 m_dist[i] = li.y();
00516                 if(m_dist[i] >= stop) break;
00517                 ++li;
00518             }
00519             m_dist[i++] = 0x7FFF0000;
00520         }
00521 
00522         //---------------------------------------------------------------------
00523         template<class DI> int step_hor_base(DI& di)
00524         {
00525             ++m_li;
00526             m_x += m_lp->inc;
00527             m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift;
00528 
00529             if(m_lp->inc > 0) di.inc_x(m_y - m_old_y);
00530             else              di.dec_x(m_y - m_old_y);
00531 
00532             m_old_y = m_y;
00533 
00534             return di.dist() / m_len;
00535         }
00536 
00537         //---------------------------------------------------------------------
00538         template<class DI> int step_ver_base(DI& di)
00539         {
00540             ++m_li;
00541             m_y += m_lp->inc;
00542             m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift;
00543 
00544             if(m_lp->inc > 0) di.inc_y(m_x - m_old_x);
00545             else              di.dec_y(m_x - m_old_x);
00546 
00547             m_old_x = m_x;
00548 
00549             return di.dist() / m_len;
00550         }
00551 
00552         //---------------------------------------------------------------------
00553         bool vertical() const { return m_lp->vertical; }
00554         int  width() const { return m_width; }
00555         int  count() const { return m_count; }
00556 
00557     private:
00558         line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&);
00559         const line_interpolator_aa_base<Renderer>& 
00560             operator = (const line_interpolator_aa_base<Renderer>&);
00561 
00562     protected:
00563         const line_parameters* m_lp;
00564         dda2_line_interpolator m_li;
00565         renderer_type&         m_ren;
00566         int m_len;
00567         int m_x;
00568         int m_y;
00569         int m_old_x;
00570         int m_old_y;
00571         int m_count;
00572         int m_width;
00573         int m_max_extent;
00574         int m_step;
00575         int m_dist[max_half_width + 1];
00576         cover_type m_covers[max_half_width * 2 + 4];
00577     };
00578 
00579 
00580 
00581 
00582 
00583 
00584 
00585     //====================================================line_interpolator_aa0
00586     template<class Renderer> class line_interpolator_aa0 :
00587     public line_interpolator_aa_base<Renderer>
00588     {
00589     public:
00590         typedef Renderer renderer_type;
00591         typedef typename Renderer::color_type color_type;
00592         typedef line_interpolator_aa_base<Renderer> base_type;
00593 
00594         //---------------------------------------------------------------------
00595         line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) :
00596             line_interpolator_aa_base<Renderer>(ren, lp),
00597             m_di(lp.x1, lp.y1, lp.x2, lp.y2, 
00598                  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
00599         {
00600             base_type::m_li.adjust_forward();
00601         }
00602 
00603         //---------------------------------------------------------------------
00604         bool step_hor()
00605         {
00606             int dist;
00607             int dy;
00608             int s1 = base_type::step_hor_base(m_di);
00609             cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
00610             cover_type* p1 = p0;
00611 
00612             *p1++ = (cover_type)base_type::m_ren.cover(s1);
00613 
00614             dy = 1;
00615             while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
00616             {
00617                 *p1++ = (cover_type)base_type::m_ren.cover(dist);
00618                 ++dy;
00619             }
00620 
00621             dy = 1;
00622             while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
00623             {
00624                 *--p0 = (cover_type)base_type::m_ren.cover(dist);
00625                 ++dy;
00626             }
00627             base_type::m_ren.blend_solid_vspan(base_type::m_x, 
00628                                                base_type::m_y - dy + 1, 
00629                                                unsigned(p1 - p0), 
00630                                                p0);
00631             return ++base_type::m_step < base_type::m_count;
00632         }
00633 
00634         //---------------------------------------------------------------------
00635         bool step_ver()
00636         {
00637             int dist;
00638             int dx;
00639             int s1 = base_type::step_ver_base(m_di);
00640             cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
00641             cover_type* p1 = p0;
00642 
00643             *p1++ = (cover_type)base_type::m_ren.cover(s1);
00644 
00645             dx = 1;
00646             while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
00647             {
00648                 *p1++ = (cover_type)base_type::m_ren.cover(dist);
00649                 ++dx;
00650             }
00651 
00652             dx = 1;
00653             while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
00654             {
00655                 *--p0 = (cover_type)base_type::m_ren.cover(dist);
00656                 ++dx;
00657             }
00658             base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 
00659                                                base_type::m_y,
00660                                                unsigned(p1 - p0), 
00661                                                p0);
00662             return ++base_type::m_step < base_type::m_count;
00663         }
00664 
00665     private:
00666         line_interpolator_aa0(const line_interpolator_aa0<Renderer>&);
00667         const line_interpolator_aa0<Renderer>& 
00668             operator = (const line_interpolator_aa0<Renderer>&);
00669 
00670         //---------------------------------------------------------------------
00671         distance_interpolator1 m_di; 
00672     };
00673 
00674 
00675 
00676 
00677 
00678 
00679     //====================================================line_interpolator_aa1
00680     template<class Renderer> class line_interpolator_aa1 :
00681     public line_interpolator_aa_base<Renderer>
00682     {
00683     public:
00684         typedef Renderer renderer_type;
00685         typedef typename Renderer::color_type color_type;
00686         typedef line_interpolator_aa_base<Renderer> base_type;
00687 
00688         //---------------------------------------------------------------------
00689         line_interpolator_aa1(renderer_type& ren, const line_parameters& lp, 
00690                               int sx, int sy) :
00691             line_interpolator_aa_base<Renderer>(ren, lp),
00692             m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy,
00693                  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
00694         {
00695             int dist1_start;
00696             int dist2_start;
00697 
00698             int npix = 1;
00699 
00700             if(lp.vertical)
00701             {
00702                 do
00703                 {
00704                     --base_type::m_li;
00705                     base_type::m_y -= lp.inc;
00706                     base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
00707 
00708                     if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
00709                     else           m_di.inc_y(base_type::m_x - base_type::m_old_x);
00710 
00711                     base_type::m_old_x = base_type::m_x;
00712 
00713                     dist1_start = dist2_start = m_di.dist_start(); 
00714 
00715                     int dx = 0;
00716                     if(dist1_start < 0) ++npix;
00717                     do
00718                     {
00719                         dist1_start += m_di.dy_start();
00720                         dist2_start -= m_di.dy_start();
00721                         if(dist1_start < 0) ++npix;
00722                         if(dist2_start < 0) ++npix;
00723                         ++dx;
00724                     }
00725                     while(base_type::m_dist[dx] <= base_type::m_width);
00726                     --base_type::m_step;
00727                     if(npix == 0) break;
00728                     npix = 0;
00729                 }
00730                 while(base_type::m_step >= -base_type::m_max_extent);
00731             }
00732             else
00733             {
00734                 do
00735                 {
00736                     --base_type::m_li;
00737                     base_type::m_x -= lp.inc;
00738                     base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
00739 
00740                     if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
00741                     else           m_di.inc_x(base_type::m_y - base_type::m_old_y);
00742 
00743                     base_type::m_old_y = base_type::m_y;
00744 
00745                     dist1_start = dist2_start = m_di.dist_start(); 
00746 
00747                     int dy = 0;
00748                     if(dist1_start < 0) ++npix;
00749                     do
00750                     {
00751                         dist1_start -= m_di.dx_start();
00752                         dist2_start += m_di.dx_start();
00753                         if(dist1_start < 0) ++npix;
00754                         if(dist2_start < 0) ++npix;
00755                         ++dy;
00756                     }
00757                     while(base_type::m_dist[dy] <= base_type::m_width);
00758                     --base_type::m_step;
00759                     if(npix == 0) break;
00760                     npix = 0;
00761                 }
00762                 while(base_type::m_step >= -base_type::m_max_extent);
00763             }
00764             base_type::m_li.adjust_forward();
00765         }
00766 
00767         //---------------------------------------------------------------------
00768         bool step_hor()
00769         {
00770             int dist_start;
00771             int dist;
00772             int dy;
00773             int s1 = base_type::step_hor_base(m_di);
00774 
00775             dist_start = m_di.dist_start();
00776             cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
00777             cover_type* p1 = p0;
00778 
00779             *p1 = 0;
00780             if(dist_start <= 0)
00781             {
00782                 *p1 = (cover_type)base_type::m_ren.cover(s1);
00783             }
00784             ++p1;
00785 
00786             dy = 1;
00787             while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
00788             {
00789                 dist_start -= m_di.dx_start();
00790                 *p1 = 0;
00791                 if(dist_start <= 0)
00792                 {   
00793                     *p1 = (cover_type)base_type::m_ren.cover(dist);
00794                 }
00795                 ++p1;
00796                 ++dy;
00797             }
00798 
00799             dy = 1;
00800             dist_start = m_di.dist_start();
00801             while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
00802             {
00803                 dist_start += m_di.dx_start();
00804                 *--p0 = 0;
00805                 if(dist_start <= 0)
00806                 {   
00807                     *p0 = (cover_type)base_type::m_ren.cover(dist);
00808                 }
00809                 ++dy;
00810             }
00811 
00812             base_type::m_ren.blend_solid_vspan(base_type::m_x, 
00813                                                base_type::m_y - dy + 1,
00814                                                unsigned(p1 - p0), 
00815                                                p0);
00816             return ++base_type::m_step < base_type::m_count;
00817         }
00818 
00819         //---------------------------------------------------------------------
00820         bool step_ver()
00821         {
00822             int dist_start;
00823             int dist;
00824             int dx;
00825             int s1 = base_type::step_ver_base(m_di);
00826             cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
00827             cover_type* p1 = p0;
00828 
00829             dist_start = m_di.dist_start();
00830 
00831             *p1 = 0;
00832             if(dist_start <= 0)
00833             {
00834                 *p1 = (cover_type)base_type::m_ren.cover(s1);
00835             }
00836             ++p1;
00837 
00838             dx = 1;
00839             while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
00840             {
00841                 dist_start += m_di.dy_start();
00842                 *p1 = 0;
00843                 if(dist_start <= 0)
00844                 {   
00845                     *p1 = (cover_type)base_type::m_ren.cover(dist);
00846                 }
00847                 ++p1;
00848                 ++dx;
00849             }
00850 
00851             dx = 1;
00852             dist_start = m_di.dist_start();
00853             while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
00854             {
00855                 dist_start -= m_di.dy_start();
00856                 *--p0 = 0;
00857                 if(dist_start <= 0)
00858                 {   
00859                     *p0 = (cover_type)base_type::m_ren.cover(dist);
00860                 }
00861                 ++dx;
00862             }
00863             base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, 
00864                                                base_type::m_y,
00865                                                unsigned(p1 - p0), 
00866                                                p0);
00867             return ++base_type::m_step < base_type::m_count;
00868         }
00869 
00870     private:
00871         line_interpolator_aa1(const line_interpolator_aa1<Renderer>&);
00872         const line_interpolator_aa1<Renderer>& 
00873             operator = (const line_interpolator_aa1<Renderer>&);
00874 
00875         //---------------------------------------------------------------------
00876         distance_interpolator2 m_di; 
00877     };
00878 
00879 
00880 
00881 
00882 
00883 
00884 
00885 
00886 
00887 
00888 
00889 
00890     //====================================================line_interpolator_aa2
00891     template<class Renderer> class line_interpolator_aa2 :
00892     public line_interpolator_aa_base<Renderer>
00893     {
00894     public:
00895         typedef Renderer renderer_type;
00896         typedef typename Renderer::color_type color_type;
00897         typedef line_interpolator_aa_base<Renderer> base_type;
00898 
00899         //---------------------------------------------------------------------
00900         line_interpolator_aa2(renderer_type& ren, const line_parameters& lp, 
00901                               int ex, int ey) :
00902             line_interpolator_aa_base<Renderer>(ren, lp),
00903             m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey, 
00904                  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask,
00905                  0)
00906         {
00907             base_type::m_li.adjust_forward();
00908             base_type::m_step -= base_type::m_max_extent;
00909         }
00910 
00911         //---------------------------------------------------------------------
00912         bool step_hor()
00913         {
00914             int dist_end;
00915             int dist;
00916             int dy;
00917             int s1 = base_type::step_hor_base(m_di);
00918             cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
00919             cover_type* p1 = p0;
00920 
00921             dist_end = m_di.dist_end();
00922 
00923             int npix = 0;
00924             *p1 = 0;
00925             if(dist_end > 0)
00926             {
00927                 *p1 = (cover_type)base_type::m_ren.cover(s1);
00928                 ++npix;
00929             }
00930             ++p1;
00931 
00932             dy = 1;
00933             while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
00934             {
00935                 dist_end -= m_di.dx_end();
00936                 *p1 = 0;
00937                 if(dist_end > 0)
00938                 {   
00939                     *p1 = (cover_type)base_type::m_ren.cover(dist);
00940                     ++npix;
00941                 }
00942                 ++p1;
00943                 ++dy;
00944             }
00945 
00946             dy = 1;
00947             dist_end = m_di.dist_end();
00948             while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
00949             {
00950                 dist_end += m_di.dx_end();
00951                 *--p0 = 0;
00952                 if(dist_end > 0)
00953                 {   
00954                     *p0 = (cover_type)base_type::m_ren.cover(dist);
00955                     ++npix;
00956                 }
00957                 ++dy;
00958             }
00959             base_type::m_ren.blend_solid_vspan(base_type::m_x,
00960                                                base_type::m_y - dy + 1, 
00961                                                unsigned(p1 - p0), 
00962                                                p0);
00963             return npix && ++base_type::m_step < base_type::m_count;
00964         }
00965 
00966         //---------------------------------------------------------------------
00967         bool step_ver()
00968         {
00969             int dist_end;
00970             int dist;
00971             int dx;
00972             int s1 = base_type::step_ver_base(m_di);
00973             cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
00974             cover_type* p1 = p0;
00975 
00976             dist_end = m_di.dist_end();
00977 
00978             int npix = 0;
00979             *p1 = 0;
00980             if(dist_end > 0)
00981             {
00982                 *p1 = (cover_type)base_type::m_ren.cover(s1);
00983                 ++npix;
00984             }
00985             ++p1;
00986 
00987             dx = 1;
00988             while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
00989             {
00990                 dist_end += m_di.dy_end();
00991                 *p1 = 0;
00992                 if(dist_end > 0)
00993                 {   
00994                     *p1 = (cover_type)base_type::m_ren.cover(dist);
00995                     ++npix;
00996                 }
00997                 ++p1;
00998                 ++dx;
00999             }
01000 
01001             dx = 1;
01002             dist_end = m_di.dist_end();
01003             while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
01004             {
01005                 dist_end -= m_di.dy_end();
01006                 *--p0 = 0;
01007                 if(dist_end > 0)
01008                 {   
01009                     *p0 = (cover_type)base_type::m_ren.cover(dist);
01010                     ++npix;
01011                 }
01012                 ++dx;
01013             }
01014             base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
01015                                                base_type::m_y, 
01016                                                unsigned(p1 - p0), 
01017                                                p0);
01018             return npix && ++base_type::m_step < base_type::m_count;
01019         }
01020 
01021     private:
01022         line_interpolator_aa2(const line_interpolator_aa2<Renderer>&);
01023         const line_interpolator_aa2<Renderer>& 
01024             operator = (const line_interpolator_aa2<Renderer>&);
01025 
01026         //---------------------------------------------------------------------
01027         distance_interpolator2 m_di; 
01028     };
01029 
01030 
01031 
01032 
01033 
01034 
01035 
01036 
01037 
01038 
01039     //====================================================line_interpolator_aa3
01040     template<class Renderer> class line_interpolator_aa3 :
01041     public line_interpolator_aa_base<Renderer>
01042     {
01043     public:
01044         typedef Renderer renderer_type;
01045         typedef typename Renderer::color_type color_type;
01046         typedef line_interpolator_aa_base<Renderer> base_type;
01047 
01048         //---------------------------------------------------------------------
01049         line_interpolator_aa3(renderer_type& ren, const line_parameters& lp, 
01050                               int sx, int sy, int ex, int ey) :
01051             line_interpolator_aa_base<Renderer>(ren, lp),
01052             m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, 
01053                  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
01054         {
01055             int dist1_start;
01056             int dist2_start;
01057             int npix = 1;
01058             if(lp.vertical)
01059             {
01060                 do
01061                 {
01062                     --base_type::m_li;
01063                     base_type::m_y -= lp.inc;
01064                     base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
01065 
01066                     if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
01067                     else           m_di.inc_y(base_type::m_x - base_type::m_old_x);
01068 
01069                     base_type::m_old_x = base_type::m_x;
01070 
01071                     dist1_start = dist2_start = m_di.dist_start(); 
01072 
01073                     int dx = 0;
01074                     if(dist1_start < 0) ++npix;
01075                     do
01076                     {
01077                         dist1_start += m_di.dy_start();
01078                         dist2_start -= m_di.dy_start();
01079                         if(dist1_start < 0) ++npix;
01080                         if(dist2_start < 0) ++npix;
01081                         ++dx;
01082                     }
01083                     while(base_type::m_dist[dx] <= base_type::m_width);
01084                     if(npix == 0) break;
01085                     npix = 0;
01086                 }
01087                 while(--base_type::m_step >= -base_type::m_max_extent);
01088             }
01089             else
01090             {
01091                 do
01092                 {
01093                     --base_type::m_li;
01094                     base_type::m_x -= lp.inc;
01095                     base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
01096 
01097                     if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
01098                     else           m_di.inc_x(base_type::m_y - base_type::m_old_y);
01099 
01100                     base_type::m_old_y = base_type::m_y;
01101 
01102                     dist1_start = dist2_start = m_di.dist_start(); 
01103 
01104                     int dy = 0;
01105                     if(dist1_start < 0) ++npix;
01106                     do
01107                     {
01108                         dist1_start -= m_di.dx_start();
01109                         dist2_start += m_di.dx_start();
01110                         if(dist1_start < 0) ++npix;
01111                         if(dist2_start < 0) ++npix;
01112                         ++dy;
01113                     }
01114                     while(base_type::m_dist[dy] <= base_type::m_width);
01115                     if(npix == 0) break;
01116                     npix = 0;
01117                 }
01118                 while(--base_type::m_step >= -base_type::m_max_extent);
01119             }
01120             base_type::m_li.adjust_forward();
01121             base_type::m_step -= base_type::m_max_extent;
01122         }
01123 
01124 
01125         //---------------------------------------------------------------------
01126         bool step_hor()
01127         {
01128             int dist_start;
01129             int dist_end;
01130             int dist;
01131             int dy;
01132             int s1 = base_type::step_hor_base(m_di);
01133             cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
01134             cover_type* p1 = p0;
01135 
01136             dist_start = m_di.dist_start();
01137             dist_end   = m_di.dist_end();
01138 
01139             int npix = 0;
01140             *p1 = 0;
01141             if(dist_end > 0)
01142             {
01143                 if(dist_start <= 0)
01144                 {
01145                     *p1 = (cover_type)base_type::m_ren.cover(s1);
01146                 }
01147                 ++npix;
01148             }
01149             ++p1;
01150 
01151             dy = 1;
01152             while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
01153             {
01154                 dist_start -= m_di.dx_start();
01155                 dist_end   -= m_di.dx_end();
01156                 *p1 = 0;
01157                 if(dist_end > 0 && dist_start <= 0)
01158                 {   
01159                     *p1 = (cover_type)base_type::m_ren.cover(dist);
01160                     ++npix;
01161                 }
01162                 ++p1;
01163                 ++dy;
01164             }
01165 
01166             dy = 1;
01167             dist_start = m_di.dist_start();
01168             dist_end   = m_di.dist_end();
01169             while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
01170             {
01171                 dist_start += m_di.dx_start();
01172                 dist_end   += m_di.dx_end();
01173                 *--p0 = 0;
01174                 if(dist_end > 0 && dist_start <= 0)
01175                 {   
01176                     *p0 = (cover_type)base_type::m_ren.cover(dist);
01177                     ++npix;
01178                 }
01179                 ++dy;
01180             }
01181             base_type::m_ren.blend_solid_vspan(base_type::m_x,
01182                                                base_type::m_y - dy + 1, 
01183                                                unsigned(p1 - p0), 
01184                                                p0);
01185             return npix && ++base_type::m_step < base_type::m_count;
01186         }
01187 
01188         //---------------------------------------------------------------------
01189         bool step_ver()
01190         {
01191             int dist_start;
01192             int dist_end;
01193             int dist;
01194             int dx;
01195             int s1 = base_type::step_ver_base(m_di);
01196             cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
01197             cover_type* p1 = p0;
01198 
01199             dist_start = m_di.dist_start();
01200             dist_end   = m_di.dist_end();
01201 
01202             int npix = 0;
01203             *p1 = 0;
01204             if(dist_end > 0)
01205             {
01206                 if(dist_start <= 0)
01207                 {
01208                     *p1 = (cover_type)base_type::m_ren.cover(s1);
01209                 }
01210                 ++npix;
01211             }
01212             ++p1;
01213 
01214             dx = 1;
01215             while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
01216             {
01217                 dist_start += m_di.dy_start();
01218                 dist_end   += m_di.dy_end();
01219                 *p1 = 0;
01220                 if(dist_end > 0 && dist_start <= 0)
01221                 {   
01222                     *p1 = (cover_type)base_type::m_ren.cover(dist);
01223                     ++npix;
01224                 }
01225                 ++p1;
01226                 ++dx;
01227             }
01228 
01229             dx = 1;
01230             dist_start = m_di.dist_start();
01231             dist_end   = m_di.dist_end();
01232             while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
01233             {
01234                 dist_start -= m_di.dy_start();
01235                 dist_end   -= m_di.dy_end();
01236                 *--p0 = 0;
01237                 if(dist_end > 0 && dist_start <= 0)
01238                 {   
01239                     *p0 = (cover_type)base_type::m_ren.cover(dist);
01240                     ++npix;
01241                 }
01242                 ++dx;
01243             }
01244             base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
01245                                                base_type::m_y, 
01246                                                unsigned(p1 - p0), 
01247                                                p0);
01248             return npix && ++base_type::m_step < base_type::m_count;
01249         }
01250 
01251     private:
01252         line_interpolator_aa3(const line_interpolator_aa3<Renderer>&);
01253         const line_interpolator_aa3<Renderer>& 
01254             operator = (const line_interpolator_aa3<Renderer>&);
01255 
01256         //---------------------------------------------------------------------
01257         distance_interpolator3 m_di; 
01258     };
01259 
01260 
01261 
01262 
01263     //==========================================================line_profile_aa
01264     //
01265     // See Implementation agg_line_profile_aa.cpp 
01266     // 
01267     class line_profile_aa
01268     {
01269     public:
01270         //---------------------------------------------------------------------
01271         typedef int8u value_type;
01272         enum subpixel_scale_e
01273         {
01274             subpixel_shift = line_subpixel_shift,
01275             subpixel_scale = 1 << subpixel_shift,
01276             subpixel_mask  = subpixel_scale - 1
01277         };
01278 
01279         enum aa_scale_e
01280         {
01281             aa_shift = 8,
01282             aa_scale = 1 << aa_shift,
01283             aa_mask  = aa_scale - 1
01284         };
01285         
01286         //---------------------------------------------------------------------
01287         line_profile_aa() : 
01288             m_subpixel_width(0),
01289             m_min_width(1.0),
01290             m_smoother_width(1.0)
01291         {
01292             int i;
01293             for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i;
01294         }
01295 
01296         //---------------------------------------------------------------------
01297         template<class GammaF> 
01298         line_profile_aa(double w, const GammaF& gamma_function) : 
01299             m_subpixel_width(0),
01300             m_min_width(1.0),
01301             m_smoother_width(1.0)
01302         {
01303             gamma(gamma_function);
01304             width(w);
01305         }
01306 
01307         //---------------------------------------------------------------------
01308         void min_width(double w) { m_min_width = w; }
01309         void smoother_width(double w) { m_smoother_width = w; }
01310 
01311         //---------------------------------------------------------------------
01312         template<class GammaF> void gamma(const GammaF& gamma_function)
01313         { 
01314             int i;
01315             for(i = 0; i < aa_scale; i++)
01316             {
01317                 m_gamma[i] = value_type(
01318                     uround(gamma_function(double(i) / aa_mask) * aa_mask));
01319             }
01320         }
01321 
01322         void width(double w);
01323 
01324         unsigned profile_size() const { return m_profile.size(); }
01325         int subpixel_width() const { return m_subpixel_width; }
01326 
01327         //---------------------------------------------------------------------
01328         double min_width() const { return m_min_width; }
01329         double smoother_width() const { return m_smoother_width; }
01330 
01331         //---------------------------------------------------------------------
01332         value_type value(int dist) const
01333         {
01334             return m_profile[dist + subpixel_scale*2];
01335         }
01336 
01337     private:
01338         line_profile_aa(const line_profile_aa&);
01339         const line_profile_aa& operator = (const line_profile_aa&);
01340 
01341         value_type* profile(double w);
01342         void set(double center_width, double smoother_width);
01343 
01344         //---------------------------------------------------------------------
01345         pod_array<value_type> m_profile;
01346         value_type            m_gamma[aa_scale];
01347         int                   m_subpixel_width;
01348         double                m_min_width;
01349         double                m_smoother_width;
01350     };
01351 
01352 
01353     //======================================================renderer_outline_aa
01354     template<class BaseRenderer> class renderer_outline_aa
01355     {
01356     public:
01357         //---------------------------------------------------------------------
01358         typedef BaseRenderer base_ren_type;
01359         typedef renderer_outline_aa<base_ren_type> self_type;
01360         typedef typename base_ren_type::color_type color_type;
01361 
01362         //---------------------------------------------------------------------
01363         renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) :
01364             m_ren(&ren),
01365             m_profile(&prof),
01366             m_clip_box(0,0,0,0),
01367             m_clipping(false)
01368         {}
01369         void attach(base_ren_type& ren) { m_ren = &ren; }
01370 
01371         //---------------------------------------------------------------------
01372         void color(const color_type& c) { m_color = c; }
01373         const color_type& color() const { return m_color; }
01374 
01375         //---------------------------------------------------------------------
01376         void profile(const line_profile_aa& prof) { m_profile = &prof; }
01377         const line_profile_aa& profile() const { return *m_profile; }
01378         line_profile_aa& profile() { return *m_profile; }
01379 
01380         //---------------------------------------------------------------------
01381         int subpixel_width() const { return m_profile->subpixel_width(); }
01382 
01383         //---------------------------------------------------------------------
01384         void reset_clipping() { m_clipping = false; }
01385         void clip_box(double x1, double y1, double x2, double y2)
01386         {
01387             m_clip_box.x1 = line_coord_sat::conv(x1);
01388             m_clip_box.y1 = line_coord_sat::conv(y1);
01389             m_clip_box.x2 = line_coord_sat::conv(x2);
01390             m_clip_box.y2 = line_coord_sat::conv(y2);
01391             m_clipping = true;
01392         }
01393 
01394         //---------------------------------------------------------------------
01395         int cover(int d) const
01396         {
01397             return m_profile->value(d);
01398         }
01399 
01400         //-------------------------------------------------------------------------
01401         void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers)
01402         {
01403             m_ren->blend_solid_hspan(x, y, len, m_color, covers);
01404         }
01405 
01406         //-------------------------------------------------------------------------
01407         void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers)
01408         {
01409             m_ren->blend_solid_vspan(x, y, len, m_color, covers);
01410         }
01411 
01412         //-------------------------------------------------------------------------
01413         static bool accurate_join_only() { return false; }
01414 
01415         //-------------------------------------------------------------------------
01416         template<class Cmp>
01417         void semidot_hline(Cmp cmp,
01418                            int xc1, int yc1, int xc2, int yc2, 
01419                            int x1,  int y1,  int x2)
01420         {
01421             cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
01422             cover_type* p0 = covers;
01423             cover_type* p1 = covers;
01424             int x = x1 << line_subpixel_shift;
01425             int y = y1 << line_subpixel_shift;
01426             int w = subpixel_width();
01427             distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y);
01428             x += line_subpixel_scale/2;
01429             y += line_subpixel_scale/2;
01430 
01431             int x0 = x1;
01432             int dx = x - xc1;
01433             int dy = y - yc1;
01434             do
01435             {
01436                 int d = int(fast_sqrt(dx*dx + dy*dy));
01437                 *p1 = 0;
01438                 if(cmp(di.dist()) && d <= w)
01439                 {
01440                     *p1 = (cover_type)cover(d);
01441                 }
01442                 ++p1;
01443                 dx += line_subpixel_scale;
01444                 di.inc_x();
01445             }
01446             while(++x1 <= x2);
01447             m_ren->blend_solid_hspan(x0, y1, 
01448                                      unsigned(p1 - p0), 
01449                                      color(), 
01450                                      p0);
01451         }
01452 
01453         //-------------------------------------------------------------------------
01454         template<class Cmp> 
01455         void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2)
01456         {
01457             if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return;
01458 
01459             int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
01460             if(r < 1) r = 1;
01461             ellipse_bresenham_interpolator ei(r, r);
01462             int dx = 0;
01463             int dy = -r;
01464             int dy0 = dy;
01465             int dx0 = dx;
01466             int x = xc1 >> line_subpixel_shift;
01467             int y = yc1 >> line_subpixel_shift;
01468 
01469             do
01470             {
01471                 dx += ei.dx();
01472                 dy += ei.dy();
01473 
01474                 if(dy != dy0)
01475                 {
01476                     semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
01477                     semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0);
01478                 }
01479                 dx0 = dx;
01480                 dy0 = dy;
01481                 ++ei;
01482             }
01483             while(dy < 0);
01484             semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
01485         }
01486 
01487         //-------------------------------------------------------------------------
01488         void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2, 
01489                        int xh1, int yh1, int xh2)
01490         {
01491             if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return;
01492            
01493             cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
01494             cover_type* p0 = covers;
01495             cover_type* p1 = covers;
01496             int x = xh1 << line_subpixel_shift;
01497             int y = yh1 << line_subpixel_shift;
01498             int w = subpixel_width();
01499 
01500             distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y);
01501             x += line_subpixel_scale/2;
01502             y += line_subpixel_scale/2;
01503 
01504             int xh0 = xh1;
01505             int dx = x - xc;
01506             int dy = y - yc;
01507             do
01508             {
01509                 int d = int(fast_sqrt(dx*dx + dy*dy));
01510                 *p1 = 0;
01511                 if(di.dist1() <= 0 && di.dist2() > 0 && d <= w)
01512                 {
01513                     *p1 = (cover_type)cover(d);
01514                 }
01515                 ++p1;
01516                 dx += line_subpixel_scale;
01517                 di.inc_x();
01518             }
01519             while(++xh1 <= xh2);
01520             m_ren->blend_solid_hspan(xh0, yh1, 
01521                                      unsigned(p1 - p0), 
01522                                      color(), 
01523                                      p0);
01524         }
01525 
01526 
01527         //-------------------------------------------------------------------------
01528         void pie(int xc, int yc, int x1, int y1, int x2, int y2)
01529         {
01530             int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
01531             if(r < 1) r = 1;
01532             ellipse_bresenham_interpolator ei(r, r);
01533             int dx = 0;
01534             int dy = -r;
01535             int dy0 = dy;
01536             int dx0 = dx;
01537             int x = xc >> line_subpixel_shift;
01538             int y = yc >> line_subpixel_shift;
01539 
01540             do
01541             {
01542                 dx += ei.dx();
01543                 dy += ei.dy();
01544 
01545                 if(dy != dy0)
01546                 {
01547                     pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
01548                     pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0);
01549                 }
01550                 dx0 = dx;
01551                 dy0 = dy;
01552                 ++ei;
01553             }
01554             while(dy < 0);
01555             pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
01556         }
01557 
01558         //-------------------------------------------------------------------------
01559         void line0_no_clip(const line_parameters& lp)
01560         {
01561             if(lp.len > line_max_length)
01562             {
01563                 line_parameters lp1, lp2;
01564                 lp.divide(lp1, lp2);
01565                 line0_no_clip(lp1);
01566                 line0_no_clip(lp2);
01567                 return;
01568             }
01569 
01570             line_interpolator_aa0<self_type> li(*this, lp);
01571             if(li.count())
01572             {
01573                 if(li.vertical())
01574                 {
01575                     while(li.step_ver());
01576                 }
01577                 else
01578                 {
01579                     while(li.step_hor());
01580                 }
01581             }
01582         }
01583 
01584         //-------------------------------------------------------------------------
01585         void line0(const line_parameters& lp)
01586         {
01587             if(m_clipping)
01588             {
01589                 int x1 = lp.x1;
01590                 int y1 = lp.y1;
01591                 int x2 = lp.x2;
01592                 int y2 = lp.y2;
01593                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
01594                 if((flags & 4) == 0)
01595                 {
01596                     if(flags)
01597                     {
01598                         line_parameters lp2(x1, y1, x2, y2, 
01599                                            uround(calc_distance(x1, y1, x2, y2)));
01600                         line0_no_clip(lp2);
01601                     }
01602                     else
01603                     {
01604                         line0_no_clip(lp);
01605                     }
01606                 }
01607             }
01608             else
01609             {
01610                 line0_no_clip(lp);
01611             }
01612         }
01613 
01614         //-------------------------------------------------------------------------
01615         void line1_no_clip(const line_parameters& lp, int sx, int sy)
01616         {
01617             if(lp.len > line_max_length)
01618             {
01619                 line_parameters lp1, lp2;
01620                 lp.divide(lp1, lp2);
01621                 line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1);
01622                 line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
01623                 return;
01624             }
01625 
01626             fix_degenerate_bisectrix_start(lp, &sx, &sy);
01627             line_interpolator_aa1<self_type> li(*this, lp, sx, sy);
01628             if(li.vertical())
01629             {
01630                 while(li.step_ver());
01631             }
01632             else
01633             {
01634                 while(li.step_hor());
01635             }
01636         }
01637 
01638 
01639         //-------------------------------------------------------------------------
01640         void line1(const line_parameters& lp, int sx, int sy)
01641         {
01642             if(m_clipping)
01643             {
01644                 int x1 = lp.x1;
01645                 int y1 = lp.y1;
01646                 int x2 = lp.x2;
01647                 int y2 = lp.y2;
01648                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
01649                 if((flags & 4) == 0)
01650                 {
01651                     if(flags)
01652                     {
01653                         line_parameters lp2(x1, y1, x2, y2, 
01654                                            uround(calc_distance(x1, y1, x2, y2)));
01655                         if(flags & 1)
01656                         {
01657                             sx = x1 + (y2 - y1); 
01658                             sy = y1 - (x2 - x1);
01659                         }
01660                         else
01661                         {
01662                             while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
01663                             {
01664                                 sx = (lp.x1 + sx) >> 1;
01665                                 sy = (lp.y1 + sy) >> 1;
01666                             }
01667                         }
01668                         line1_no_clip(lp2, sx, sy);
01669                     }
01670                     else
01671                     {
01672                         line1_no_clip(lp, sx, sy);
01673                     }
01674                 }
01675             }
01676             else
01677             {
01678                 line1_no_clip(lp, sx, sy);
01679             }
01680         }
01681 
01682         //-------------------------------------------------------------------------
01683         void line2_no_clip(const line_parameters& lp, int ex, int ey)
01684         {
01685             if(lp.len > line_max_length)
01686             {
01687                 line_parameters lp1, lp2;
01688                 lp.divide(lp1, lp2);
01689                 line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
01690                 line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
01691                 return;
01692             }
01693 
01694             fix_degenerate_bisectrix_end(lp, &ex, &ey);
01695             line_interpolator_aa2<self_type> li(*this, lp, ex, ey);
01696             if(li.vertical())
01697             {
01698                 while(li.step_ver());
01699             }
01700             else
01701             {
01702                 while(li.step_hor());
01703             }
01704         }
01705 
01706         //-------------------------------------------------------------------------
01707         void line2(const line_parameters& lp, int ex, int ey)
01708         {
01709             if(m_clipping)
01710             {
01711                 int x1 = lp.x1;
01712                 int y1 = lp.y1;
01713                 int x2 = lp.x2;
01714                 int y2 = lp.y2;
01715                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
01716                 if((flags & 4) == 0)
01717                 {
01718                     if(flags)
01719                     {
01720                         line_parameters lp2(x1, y1, x2, y2, 
01721                                            uround(calc_distance(x1, y1, x2, y2)));
01722                         if(flags & 2)
01723                         {
01724                             ex = x2 + (y2 - y1); 
01725                             ey = y2 - (x2 - x1);
01726                         }
01727                         else
01728                         {
01729                             while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
01730                             {
01731                                 ex = (lp.x2 + ex) >> 1;
01732                                 ey = (lp.y2 + ey) >> 1;
01733                             }
01734                         }
01735                         line2_no_clip(lp2, ex, ey);
01736                     }
01737                     else
01738                     {
01739                         line2_no_clip(lp, ex, ey);
01740                     }
01741                 }
01742             }
01743             else
01744             {
01745                 line2_no_clip(lp, ex, ey);
01746             }
01747         }
01748 
01749         //-------------------------------------------------------------------------
01750         void line3_no_clip(const line_parameters& lp, 
01751                            int sx, int sy, int ex, int ey)
01752         {
01753             if(lp.len > line_max_length)
01754             {
01755                 line_parameters lp1, lp2;
01756                 lp.divide(lp1, lp2);
01757                 int mx = lp1.x2 + (lp1.y2 - lp1.y1);
01758                 int my = lp1.y2 - (lp1.x2 - lp1.x1);
01759                 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
01760                 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
01761                 return;
01762             }
01763 
01764             fix_degenerate_bisectrix_start(lp, &sx, &sy);
01765             fix_degenerate_bisectrix_end(lp, &ex, &ey);
01766             line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey);
01767             if(li.vertical())
01768             {
01769                 while(li.step_ver());
01770             }
01771             else
01772             {
01773                 while(li.step_hor());
01774             }
01775         }
01776 
01777         //-------------------------------------------------------------------------
01778         void line3(const line_parameters& lp, 
01779                    int sx, int sy, int ex, int ey)
01780         {
01781             if(m_clipping)
01782             {
01783                 int x1 = lp.x1;
01784                 int y1 = lp.y1;
01785                 int x2 = lp.x2;
01786                 int y2 = lp.y2;
01787                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
01788                 if((flags & 4) == 0)
01789                 {
01790                     if(flags)
01791                     {
01792                         line_parameters lp2(x1, y1, x2, y2, 
01793                                            uround(calc_distance(x1, y1, x2, y2)));
01794                         if(flags & 1)
01795                         {
01796                             sx = x1 + (y2 - y1); 
01797                             sy = y1 - (x2 - x1);
01798                         }
01799                         else
01800                         {
01801                             while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
01802                             {
01803                                 sx = (lp.x1 + sx) >> 1;
01804                                 sy = (lp.y1 + sy) >> 1;
01805                             }
01806                         }
01807                         if(flags & 2)
01808                         {
01809                             ex = x2 + (y2 - y1); 
01810                             ey = y2 - (x2 - x1);
01811                         }
01812                         else
01813                         {
01814                             while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
01815                             {
01816                                 ex = (lp.x2 + ex) >> 1;
01817                                 ey = (lp.y2 + ey) >> 1;
01818                             }
01819                         }
01820                         line3_no_clip(lp2, sx, sy, ex, ey);
01821                     }
01822                     else
01823                     {
01824                         line3_no_clip(lp, sx, sy, ex, ey);
01825                     }
01826                 }
01827             }
01828             else
01829             {
01830                 line3_no_clip(lp, sx, sy, ex, ey);
01831             }
01832         }
01833 
01834 
01835     private:
01836         base_ren_type*         m_ren;
01837         const line_profile_aa* m_profile; 
01838         color_type             m_color;
01839         rect_i                 m_clip_box;
01840         bool                   m_clipping;
01841     };
01842 
01843 
01844 
01845 }
01846 
01847 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines