Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_renderer_outline_image.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_IMAGE_INCLUDED
00026 #define AGG_RENDERER_OUTLINE_IMAGE_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_rendering_buffer.h"
00033 #include "agg_clip_liang_barsky.h"
00034 
00035 
00036 namespace agg
00037 {
00038     //========================================================line_image_scale
00039     template<class Source> class line_image_scale
00040     {
00041     public:
00042         typedef typename Source::color_type color_type;
00043 
00044         line_image_scale(const Source& src, double height) :
00045             m_source(src), 
00046             m_height(height),
00047             m_scale(src.height() / height)
00048         {
00049         }
00050 
00051         double width()  const { return m_source.width(); }
00052         double height() const { return m_height; }
00053 
00054         color_type pixel(int x, int y) const 
00055         { 
00056             double src_y = (y + 0.5) * m_scale - 0.5;
00057             int h  = m_source.height() - 1;
00058             int y1 = ufloor(src_y);
00059             int y2 = y1 + 1;
00060             color_type pix1 = (y1 < 0) ? color_type::no_color() : m_source.pixel(x, y1);
00061             color_type pix2 = (y2 > h) ? color_type::no_color() : m_source.pixel(x, y2);
00062             return pix1.gradient(pix2, src_y - y1);
00063         }
00064 
00065     private:
00066         line_image_scale(const line_image_scale<Source>&);
00067         const line_image_scale<Source>& operator = (const line_image_scale<Source>&);
00068 
00069         const Source& m_source;
00070         double        m_height;
00071         double        m_scale;
00072     };
00073 
00074 
00075 
00076     //======================================================line_image_pattern
00077     template<class Filter> class line_image_pattern
00078     {
00079     public:
00080         typedef Filter filter_type;
00081         typedef typename filter_type::color_type color_type;
00082 
00083         //--------------------------------------------------------------------
00084         line_image_pattern(const Filter& filter) :
00085             m_filter(&filter),
00086             m_dilation(filter.dilation() + 1),
00087             m_dilation_hr(m_dilation << line_subpixel_shift),
00088             m_data(),
00089             m_width(0),
00090             m_height(0),
00091             m_width_hr(0),
00092             m_half_height_hr(0),
00093             m_offset_y_hr(0)
00094         {
00095         }
00096 
00097         // Create
00098         //--------------------------------------------------------------------
00099         template<class Source> 
00100         line_image_pattern(const Filter& filter, const Source& src) :
00101             m_filter(&filter),
00102             m_dilation(filter.dilation() + 1),
00103             m_dilation_hr(m_dilation << line_subpixel_shift),
00104             m_data(),
00105             m_width(0),
00106             m_height(0),
00107             m_width_hr(0),
00108             m_half_height_hr(0),
00109             m_offset_y_hr(0)
00110         {
00111             create(src);
00112         }
00113 
00114         // Create
00115         //--------------------------------------------------------------------
00116         template<class Source> void create(const Source& src)
00117         {
00118             m_height = uceil(src.height());
00119             m_width  = uceil(src.width());
00120             m_width_hr = uround(src.width() * line_subpixel_scale);
00121             m_half_height_hr = uround(src.height() * line_subpixel_scale/2);
00122             m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2;
00123             m_half_height_hr += line_subpixel_scale/2;
00124 
00125             m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2));
00126 
00127             m_buf.attach(&m_data[0], m_width  + m_dilation * 2, 
00128                                      m_height + m_dilation * 2, 
00129                                      m_width  + m_dilation * 2);
00130             unsigned x, y;
00131             color_type* d1;
00132             color_type* d2;
00133             for(y = 0; y < m_height; y++)
00134             {
00135                 d1 = m_buf.row_ptr(y + m_dilation) + m_dilation;
00136                 for(x = 0; x < m_width; x++)
00137                 {
00138                     *d1++ = src.pixel(x, y);
00139                 }
00140             }
00141 
00142             const color_type* s1;
00143             const color_type* s2;
00144             for(y = 0; y < m_dilation; y++)
00145             {
00146                 //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation;
00147                 //s2 = m_buf.row_ptr(m_dilation) + m_dilation;
00148                 d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation;
00149                 d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation;
00150                 for(x = 0; x < m_width; x++)
00151                 {
00152                     //*d1++ = color_type(*s1++, 0);
00153                     //*d2++ = color_type(*s2++, 0);
00154                     *d1++ = color_type::no_color();
00155                     *d2++ = color_type::no_color();
00156                 }
00157             }
00158 
00159             unsigned h = m_height + m_dilation * 2;
00160             for(y = 0; y < h; y++)
00161             {
00162                 s1 = m_buf.row_ptr(y) + m_dilation;
00163                 s2 = m_buf.row_ptr(y) + m_dilation + m_width;
00164                 d1 = m_buf.row_ptr(y) + m_dilation + m_width;
00165                 d2 = m_buf.row_ptr(y) + m_dilation;
00166 
00167                 for(x = 0; x < m_dilation; x++)
00168                 {
00169                     *d1++ = *s1++;
00170                     *--d2 = *--s2;
00171                 }
00172             }
00173         }
00174 
00175         //--------------------------------------------------------------------
00176         int pattern_width() const { return m_width_hr; }
00177         int line_width()    const { return m_half_height_hr; }
00178         double width()      const { return m_height; }
00179 
00180         //--------------------------------------------------------------------
00181         void pixel(color_type* p, int x, int y) const
00182         {
00183             m_filter->pixel_high_res(m_buf.rows(), 
00184                                      p, 
00185                                      x % m_width_hr + m_dilation_hr,
00186                                      y + m_offset_y_hr);
00187         }
00188 
00189         //--------------------------------------------------------------------
00190         const filter_type& filter() const { return *m_filter; }
00191 
00192     private:
00193         line_image_pattern(const line_image_pattern<filter_type>&);
00194         const line_image_pattern<filter_type>& 
00195             operator = (const line_image_pattern<filter_type>&);
00196 
00197     protected:
00198         row_ptr_cache<color_type> m_buf;
00199         const filter_type*        m_filter;
00200         unsigned                  m_dilation;
00201         int                       m_dilation_hr;
00202         pod_array<color_type>     m_data;
00203         unsigned                  m_width;
00204         unsigned                  m_height;
00205         int                       m_width_hr;
00206         int                       m_half_height_hr;
00207         int                       m_offset_y_hr;
00208     };
00209 
00210 
00211 
00212 
00213 
00214 
00215     //=================================================line_image_pattern_pow2
00216     template<class Filter> class line_image_pattern_pow2 : 
00217     public line_image_pattern<Filter>
00218     {
00219     public:
00220         typedef Filter filter_type;
00221         typedef typename filter_type::color_type color_type;
00222         typedef line_image_pattern<Filter> base_type;
00223         
00224         //--------------------------------------------------------------------
00225         line_image_pattern_pow2(const Filter& filter) :
00226             line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {}
00227 
00228         //--------------------------------------------------------------------
00229         template<class Source> 
00230         line_image_pattern_pow2(const Filter& filter, const Source& src) :
00231             line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask)
00232         {
00233             create(src);
00234         }
00235             
00236         //--------------------------------------------------------------------
00237         template<class Source> void create(const Source& src)
00238         {
00239             line_image_pattern<Filter>::create(src);
00240             m_mask = 1;
00241             while(m_mask < base_type::m_width) 
00242             {
00243                 m_mask <<= 1;
00244                 m_mask |= 1;
00245             }
00246             m_mask <<= line_subpixel_shift - 1;
00247             m_mask |=  line_subpixel_mask;
00248             base_type::m_width_hr = m_mask + 1;
00249         }
00250 
00251         //--------------------------------------------------------------------
00252         void pixel(color_type* p, int x, int y) const
00253         {
00254             base_type::m_filter->pixel_high_res(
00255                     base_type::m_buf.rows(), 
00256                     p,
00257                     (x & m_mask) + base_type::m_dilation_hr,
00258                     y + base_type::m_offset_y_hr);
00259         }
00260     private:
00261         unsigned m_mask;
00262     };
00263     
00264     
00265     
00266     
00267     
00268     
00269     
00270     //===================================================distance_interpolator4
00271     class distance_interpolator4
00272     {
00273     public:
00274         //---------------------------------------------------------------------
00275         distance_interpolator4() {}
00276         distance_interpolator4(int x1,  int y1, int x2, int y2,
00277                                int sx,  int sy, int ex, int ey, 
00278                                int len, double scale, int x, int y) :
00279             m_dx(x2 - x1),
00280             m_dy(y2 - y1),
00281             m_dx_start(line_mr(sx) - line_mr(x1)),
00282             m_dy_start(line_mr(sy) - line_mr(y1)),
00283             m_dx_end(line_mr(ex) - line_mr(x2)),
00284             m_dy_end(line_mr(ey) - line_mr(y2)),
00285 
00286             m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - 
00287                           double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
00288 
00289             m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - 
00290                          (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start),
00291 
00292             m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - 
00293                        (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end),
00294             m_len(uround(len / scale))
00295         {
00296             double d = len * scale;
00297             int dx = iround(((x2 - x1) << line_subpixel_shift) / d);
00298             int dy = iround(((y2 - y1) << line_subpixel_shift) / d);
00299             m_dx_pict   = -dy;
00300             m_dy_pict   =  dx;
00301             m_dist_pict =  ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict - 
00302                             (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >> 
00303                            line_subpixel_shift;
00304 
00305             m_dx       <<= line_subpixel_shift;
00306             m_dy       <<= line_subpixel_shift;
00307             m_dx_start <<= line_mr_subpixel_shift;
00308             m_dy_start <<= line_mr_subpixel_shift;
00309             m_dx_end   <<= line_mr_subpixel_shift;
00310             m_dy_end   <<= line_mr_subpixel_shift;
00311         }
00312 
00313         //---------------------------------------------------------------------
00314         void inc_x() 
00315         { 
00316             m_dist += m_dy; 
00317             m_dist_start += m_dy_start; 
00318             m_dist_pict += m_dy_pict; 
00319             m_dist_end += m_dy_end; 
00320         }
00321 
00322         //---------------------------------------------------------------------
00323         void dec_x() 
00324         { 
00325             m_dist -= m_dy; 
00326             m_dist_start -= m_dy_start; 
00327             m_dist_pict -= m_dy_pict; 
00328             m_dist_end -= m_dy_end; 
00329         }
00330 
00331         //---------------------------------------------------------------------
00332         void inc_y() 
00333         { 
00334             m_dist -= m_dx; 
00335             m_dist_start -= m_dx_start; 
00336             m_dist_pict -= m_dx_pict; 
00337             m_dist_end -= m_dx_end; 
00338         }
00339 
00340         //---------------------------------------------------------------------
00341         void dec_y() 
00342         { 
00343             m_dist += m_dx; 
00344             m_dist_start += m_dx_start; 
00345             m_dist_pict += m_dx_pict; 
00346             m_dist_end += m_dx_end; 
00347         }
00348 
00349         //---------------------------------------------------------------------
00350         void inc_x(int dy)
00351         {
00352             m_dist       += m_dy; 
00353             m_dist_start += m_dy_start; 
00354             m_dist_pict  += m_dy_pict; 
00355             m_dist_end   += m_dy_end;
00356             if(dy > 0)
00357             {
00358                 m_dist       -= m_dx; 
00359                 m_dist_start -= m_dx_start; 
00360                 m_dist_pict  -= m_dx_pict; 
00361                 m_dist_end   -= m_dx_end;
00362             }
00363             if(dy < 0)
00364             {
00365                 m_dist       += m_dx; 
00366                 m_dist_start += m_dx_start; 
00367                 m_dist_pict  += m_dx_pict; 
00368                 m_dist_end   += m_dx_end;
00369             }
00370         }
00371 
00372         //---------------------------------------------------------------------
00373         void dec_x(int dy)
00374         {
00375             m_dist       -= m_dy; 
00376             m_dist_start -= m_dy_start; 
00377             m_dist_pict  -= m_dy_pict; 
00378             m_dist_end   -= m_dy_end;
00379             if(dy > 0)
00380             {
00381                 m_dist       -= m_dx; 
00382                 m_dist_start -= m_dx_start; 
00383                 m_dist_pict  -= m_dx_pict; 
00384                 m_dist_end   -= m_dx_end;
00385             }
00386             if(dy < 0)
00387             {
00388                 m_dist       += m_dx; 
00389                 m_dist_start += m_dx_start; 
00390                 m_dist_pict  += m_dx_pict; 
00391                 m_dist_end   += m_dx_end;
00392             }
00393         }
00394 
00395         //---------------------------------------------------------------------
00396         void inc_y(int dx)
00397         {
00398             m_dist       -= m_dx; 
00399             m_dist_start -= m_dx_start; 
00400             m_dist_pict  -= m_dx_pict; 
00401             m_dist_end   -= m_dx_end;
00402             if(dx > 0)
00403             {
00404                 m_dist       += m_dy; 
00405                 m_dist_start += m_dy_start; 
00406                 m_dist_pict  += m_dy_pict; 
00407                 m_dist_end   += m_dy_end;
00408             }
00409             if(dx < 0)
00410             {
00411                 m_dist       -= m_dy; 
00412                 m_dist_start -= m_dy_start; 
00413                 m_dist_pict  -= m_dy_pict; 
00414                 m_dist_end   -= m_dy_end;
00415             }
00416         }
00417 
00418         //---------------------------------------------------------------------
00419         void dec_y(int dx)
00420         {
00421             m_dist       += m_dx; 
00422             m_dist_start += m_dx_start; 
00423             m_dist_pict  += m_dx_pict; 
00424             m_dist_end   += m_dx_end;
00425             if(dx > 0)
00426             {
00427                 m_dist       += m_dy; 
00428                 m_dist_start += m_dy_start; 
00429                 m_dist_pict  += m_dy_pict; 
00430                 m_dist_end   += m_dy_end;
00431             }
00432             if(dx < 0)
00433             {
00434                 m_dist       -= m_dy; 
00435                 m_dist_start -= m_dy_start; 
00436                 m_dist_pict  -= m_dy_pict; 
00437                 m_dist_end   -= m_dy_end;
00438             }
00439         }
00440 
00441         //---------------------------------------------------------------------
00442         int dist()       const { return m_dist;       }
00443         int dist_start() const { return m_dist_start; }
00444         int dist_pict()  const { return m_dist_pict;  }
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_pict()  const { return m_dx_pict;  }
00453         int dy_pict()  const { return m_dy_pict;  }
00454         int dx_end()   const { return m_dx_end;   }
00455         int dy_end()   const { return m_dy_end;   }
00456         int len()      const { return m_len;      }
00457 
00458     private:
00459         //---------------------------------------------------------------------
00460         int m_dx;
00461         int m_dy;
00462         int m_dx_start;
00463         int m_dy_start;
00464         int m_dx_pict;
00465         int m_dy_pict;
00466         int m_dx_end;
00467         int m_dy_end;
00468 
00469         int m_dist;
00470         int m_dist_start;
00471         int m_dist_pict;
00472         int m_dist_end;
00473         int m_len;
00474     };
00475 
00476 
00477 
00478 
00479 
00480     //==================================================line_interpolator_image
00481     template<class Renderer> class line_interpolator_image
00482     {
00483     public:
00484         typedef Renderer renderer_type;
00485         typedef typename Renderer::color_type color_type;
00486 
00487         //---------------------------------------------------------------------
00488         enum max_half_width_e
00489         { 
00490             max_half_width = 64
00491         };
00492 
00493         //---------------------------------------------------------------------
00494         line_interpolator_image(renderer_type& ren, const line_parameters& lp,
00495                                 int sx, int sy, int ex, int ey, 
00496                                 int pattern_start,
00497                                 double scale_x) :
00498             m_lp(lp),
00499             m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
00500                                line_dbl_hr(lp.y2 - lp.y1),
00501                  lp.vertical ? abs(lp.y2 - lp.y1) : 
00502                                abs(lp.x2 - lp.x1) + 1),
00503             m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
00504                  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask),
00505             m_ren(ren),
00506             m_x(lp.x1 >> line_subpixel_shift),
00507             m_y(lp.y1 >> line_subpixel_shift),
00508             m_old_x(m_x),
00509             m_old_y(m_y),
00510             m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
00511                                    abs((lp.x2 >> line_subpixel_shift) - m_x))),
00512             m_width(ren.subpixel_width()),
00513             //m_max_extent(m_width >> (line_subpixel_shift - 2)),
00514             m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift),
00515             m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()),
00516             m_step(0)
00517         {
00518             agg::dda2_line_interpolator li(0, lp.vertical ? 
00519                                               (lp.dy << agg::line_subpixel_shift) :
00520                                               (lp.dx << agg::line_subpixel_shift),
00521                                            lp.len);
00522 
00523             unsigned i;
00524             int stop = m_width + line_subpixel_scale * 2;
00525             for(i = 0; i < max_half_width; ++i)
00526             {
00527                 m_dist_pos[i] = li.y();
00528                 if(m_dist_pos[i] >= stop) break;
00529                 ++li;
00530             }
00531             m_dist_pos[i] = 0x7FFF0000;
00532 
00533             int dist1_start;
00534             int dist2_start;
00535             int npix = 1;
00536 
00537             if(lp.vertical)
00538             {
00539                 do
00540                 {
00541                     --m_li;
00542                     m_y -= lp.inc;
00543                     m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
00544 
00545                     if(lp.inc > 0) m_di.dec_y(m_x - m_old_x);
00546                     else           m_di.inc_y(m_x - m_old_x);
00547 
00548                     m_old_x = m_x;
00549 
00550                     dist1_start = dist2_start = m_di.dist_start(); 
00551 
00552                     int dx = 0;
00553                     if(dist1_start < 0) ++npix;
00554                     do
00555                     {
00556                         dist1_start += m_di.dy_start();
00557                         dist2_start -= m_di.dy_start();
00558                         if(dist1_start < 0) ++npix;
00559                         if(dist2_start < 0) ++npix;
00560                         ++dx;
00561                     }
00562                     while(m_dist_pos[dx] <= m_width);
00563                     if(npix == 0) break;
00564 
00565                     npix = 0;
00566                 }
00567                 while(--m_step >= -m_max_extent);
00568             }
00569             else
00570             {
00571                 do
00572                 {
00573                     --m_li;
00574 
00575                     m_x -= lp.inc;
00576                     m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
00577 
00578                     if(lp.inc > 0) m_di.dec_x(m_y - m_old_y);
00579                     else           m_di.inc_x(m_y - m_old_y);
00580 
00581                     m_old_y = m_y;
00582 
00583                     dist1_start = dist2_start = m_di.dist_start(); 
00584 
00585                     int dy = 0;
00586                     if(dist1_start < 0) ++npix;
00587                     do
00588                     {
00589                         dist1_start -= m_di.dx_start();
00590                         dist2_start += m_di.dx_start();
00591                         if(dist1_start < 0) ++npix;
00592                         if(dist2_start < 0) ++npix;
00593                         ++dy;
00594                     }
00595                     while(m_dist_pos[dy] <= m_width);
00596                     if(npix == 0) break;
00597 
00598                     npix = 0;
00599                 }
00600                 while(--m_step >= -m_max_extent);
00601             }
00602             m_li.adjust_forward();
00603             m_step -= m_max_extent;
00604         }
00605 
00606         //---------------------------------------------------------------------
00607         bool step_hor()
00608         {
00609             ++m_li;
00610             m_x += m_lp.inc;
00611             m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
00612 
00613             if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y);
00614             else             m_di.dec_x(m_y - m_old_y);
00615 
00616             m_old_y = m_y;
00617 
00618             int s1 = m_di.dist() / m_lp.len;
00619             int s2 = -s1;
00620 
00621             if(m_lp.inc < 0) s1 = -s1;
00622 
00623             int dist_start;
00624             int dist_pict;
00625             int dist_end;
00626             int dy;
00627             int dist;
00628 
00629             dist_start = m_di.dist_start();
00630             dist_pict  = m_di.dist_pict() + m_start;
00631             dist_end   = m_di.dist_end();
00632             color_type* p0 = m_colors + max_half_width + 2;
00633             color_type* p1 = p0;
00634 
00635             int npix = 0;
00636             p1->clear();
00637             if(dist_end > 0)
00638             {
00639                 if(dist_start <= 0)
00640                 {
00641                     m_ren.pixel(p1, dist_pict, s2);
00642                 }
00643                 ++npix;
00644             }
00645             ++p1;
00646 
00647             dy = 1;
00648             while((dist = m_dist_pos[dy]) - s1 <= m_width)
00649             {
00650                 dist_start -= m_di.dx_start();
00651                 dist_pict  -= m_di.dx_pict();
00652                 dist_end   -= m_di.dx_end();
00653                 p1->clear();
00654                 if(dist_end > 0 && dist_start <= 0)
00655                 {   
00656                     if(m_lp.inc > 0) dist = -dist;
00657                     m_ren.pixel(p1, dist_pict, s2 - dist);
00658                     ++npix;
00659                 }
00660                 ++p1;
00661                 ++dy;
00662             }
00663 
00664             dy = 1;
00665             dist_start = m_di.dist_start();
00666             dist_pict  = m_di.dist_pict() + m_start;
00667             dist_end   = m_di.dist_end();
00668             while((dist = m_dist_pos[dy]) + s1 <= m_width)
00669             {
00670                 dist_start += m_di.dx_start();
00671                 dist_pict  += m_di.dx_pict();
00672                 dist_end   += m_di.dx_end();
00673                 --p0;
00674                 p0->clear();
00675                 if(dist_end > 0 && dist_start <= 0)
00676                 {   
00677                     if(m_lp.inc > 0) dist = -dist;
00678                     m_ren.pixel(p0, dist_pict, s2 + dist);
00679                     ++npix;
00680                 }
00681                 ++dy;
00682             }
00683             m_ren.blend_color_vspan(m_x, 
00684                                     m_y - dy + 1, 
00685                                     unsigned(p1 - p0), 
00686                                     p0); 
00687             return npix && ++m_step < m_count;
00688         }
00689 
00690 
00691 
00692         //---------------------------------------------------------------------
00693         bool step_ver()
00694         {
00695             ++m_li;
00696             m_y += m_lp.inc;
00697             m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
00698 
00699             if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x);
00700             else             m_di.dec_y(m_x - m_old_x);
00701 
00702             m_old_x = m_x;
00703 
00704             int s1 = m_di.dist() / m_lp.len;
00705             int s2 = -s1;
00706 
00707             if(m_lp.inc > 0) s1 = -s1;
00708 
00709             int dist_start;
00710             int dist_pict;
00711             int dist_end;
00712             int dist;
00713             int dx;
00714 
00715             dist_start = m_di.dist_start();
00716             dist_pict  = m_di.dist_pict() + m_start;
00717             dist_end   = m_di.dist_end();
00718             color_type* p0 = m_colors + max_half_width + 2;
00719             color_type* p1 = p0;
00720 
00721             int npix = 0;
00722             p1->clear();
00723             if(dist_end > 0)
00724             {
00725                 if(dist_start <= 0)
00726                 {
00727                     m_ren.pixel(p1, dist_pict, s2);
00728                 }
00729                 ++npix;
00730             }
00731             ++p1;
00732 
00733             dx = 1;
00734             while((dist = m_dist_pos[dx]) - s1 <= m_width)
00735             {
00736                 dist_start += m_di.dy_start();
00737                 dist_pict  += m_di.dy_pict();
00738                 dist_end   += m_di.dy_end();
00739                 p1->clear();
00740                 if(dist_end > 0 && dist_start <= 0)
00741                 {   
00742                     if(m_lp.inc > 0) dist = -dist;
00743                     m_ren.pixel(p1, dist_pict, s2 + dist);
00744                     ++npix;
00745                 }
00746                 ++p1;
00747                 ++dx;
00748             }
00749 
00750             dx = 1;
00751             dist_start = m_di.dist_start();
00752             dist_pict  = m_di.dist_pict() + m_start;
00753             dist_end   = m_di.dist_end();
00754             while((dist = m_dist_pos[dx]) + s1 <= m_width)
00755             {
00756                 dist_start -= m_di.dy_start();
00757                 dist_pict  -= m_di.dy_pict();
00758                 dist_end   -= m_di.dy_end();
00759                 --p0;
00760                 p0->clear();
00761                 if(dist_end > 0 && dist_start <= 0)
00762                 {   
00763                     if(m_lp.inc > 0) dist = -dist;
00764                     m_ren.pixel(p0, dist_pict, s2 - dist);
00765                     ++npix;
00766                 }
00767                 ++dx;
00768             }
00769             m_ren.blend_color_hspan(m_x - dx + 1, 
00770                                     m_y, 
00771                                     unsigned(p1 - p0), 
00772                                     p0);
00773             return npix && ++m_step < m_count;
00774         }
00775 
00776 
00777         //---------------------------------------------------------------------
00778         int  pattern_end() const { return m_start + m_di.len(); }
00779 
00780         //---------------------------------------------------------------------
00781         bool vertical() const { return m_lp.vertical; }
00782         int  width() const { return m_width; }
00783         int  count() const { return m_count; }
00784 
00785     private:
00786         line_interpolator_image(const line_interpolator_image<Renderer>&);
00787         const line_interpolator_image<Renderer>&
00788             operator = (const line_interpolator_image<Renderer>&);
00789 
00790     protected:
00791         const line_parameters& m_lp;
00792         dda2_line_interpolator m_li;
00793         distance_interpolator4 m_di; 
00794         renderer_type&         m_ren;
00795         int m_plen;
00796         int m_x;
00797         int m_y;
00798         int m_old_x;
00799         int m_old_y;
00800         int m_count;
00801         int m_width;
00802         int m_max_extent;
00803         int m_start;
00804         int m_step;
00805         int m_dist_pos[max_half_width + 1];
00806         color_type m_colors[max_half_width * 2 + 4];
00807     };
00808 
00809 
00810 
00811 
00812 
00813 
00814 
00815 
00816     //===================================================renderer_outline_image
00817     template<class BaseRenderer, class ImagePattern> 
00818     class renderer_outline_image
00819     {
00820     public:
00821         //---------------------------------------------------------------------
00822         typedef BaseRenderer base_ren_type;
00823         typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type;
00824         typedef typename base_ren_type::color_type color_type;
00825         typedef ImagePattern pattern_type;
00826 
00827 
00828         //---------------------------------------------------------------------
00829         renderer_outline_image(base_ren_type& ren, const pattern_type& patt) :
00830             m_ren(&ren),
00831             m_pattern(&patt),
00832             m_start(0),
00833             m_scale_x(1.0),
00834             m_clip_box(0,0,0,0),
00835             m_clipping(false)
00836         {}
00837         void attach(base_ren_type& ren) { m_ren = &ren; }
00838 
00839         //---------------------------------------------------------------------
00840         void pattern(const pattern_type& p) { m_pattern = &p; }
00841         const pattern_type& pattern() const { return *m_pattern; }
00842 
00843         //---------------------------------------------------------------------
00844         void reset_clipping() { m_clipping = false; }
00845         void clip_box(double x1, double y1, double x2, double y2)
00846         {
00847             m_clip_box.x1 = line_coord_sat::conv(x1);
00848             m_clip_box.y1 = line_coord_sat::conv(y1);
00849             m_clip_box.x2 = line_coord_sat::conv(x2);
00850             m_clip_box.y2 = line_coord_sat::conv(y2);
00851             m_clipping = true;
00852         }
00853 
00854         //---------------------------------------------------------------------
00855         void   scale_x(double s) { m_scale_x = s; }
00856         double scale_x() const   { return m_scale_x; }
00857 
00858         //---------------------------------------------------------------------
00859         void   start_x(double s) { m_start = iround(s * line_subpixel_scale); }
00860         double start_x() const   { return double(m_start) / line_subpixel_scale; }
00861 
00862         //---------------------------------------------------------------------
00863         int subpixel_width() const { return m_pattern->line_width(); }
00864         int pattern_width() const { return m_pattern->pattern_width(); }
00865         double width() const { return double(subpixel_width()) / line_subpixel_scale; }
00866 
00867         //-------------------------------------------------------------------------
00868         void pixel(color_type* p, int x, int y) const
00869         {
00870             m_pattern->pixel(p, x, y);
00871         }
00872 
00873         //-------------------------------------------------------------------------
00874         void blend_color_hspan(int x, int y, unsigned len, const color_type* colors)
00875         {
00876             m_ren->blend_color_hspan(x, y, len, colors, 0);
00877         }
00878 
00879         //-------------------------------------------------------------------------
00880         void blend_color_vspan(int x, int y, unsigned len, const color_type* colors)
00881         {
00882             m_ren->blend_color_vspan(x, y, len, colors, 0);
00883         }
00884 
00885         //-------------------------------------------------------------------------
00886         static bool accurate_join_only() { return true; }
00887 
00888         //-------------------------------------------------------------------------
00889         template<class Cmp> 
00890         void semidot(Cmp, int, int, int, int)
00891         {
00892         }
00893 
00894         //-------------------------------------------------------------------------
00895         void pie(int, int, int, int, int, int)
00896         {
00897         }
00898 
00899         //-------------------------------------------------------------------------
00900         void line0(const line_parameters&)
00901         {
00902         }
00903 
00904         //-------------------------------------------------------------------------
00905         void line1(const line_parameters&, int, int)
00906         {
00907         }
00908 
00909         //-------------------------------------------------------------------------
00910         void line2(const line_parameters&, int, int)
00911         {
00912         }
00913 
00914         //-------------------------------------------------------------------------
00915         void line3_no_clip(const line_parameters& lp, 
00916                            int sx, int sy, int ex, int ey)
00917         {
00918             if(lp.len > line_max_length)
00919             {
00920                 line_parameters lp1, lp2;
00921                 lp.divide(lp1, lp2);
00922                 int mx = lp1.x2 + (lp1.y2 - lp1.y1);
00923                 int my = lp1.y2 - (lp1.x2 - lp1.x1);
00924                 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
00925                 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
00926                 return;
00927             }
00928             
00929             fix_degenerate_bisectrix_start(lp, &sx, &sy);
00930             fix_degenerate_bisectrix_end(lp, &ex, &ey);
00931             line_interpolator_image<self_type> li(*this, lp, 
00932                                                   sx, sy, 
00933                                                   ex, ey, 
00934                                                   m_start, m_scale_x);
00935             if(li.vertical())
00936             {
00937                 while(li.step_ver());
00938             }
00939             else
00940             {
00941                 while(li.step_hor());
00942             }
00943             m_start += uround(lp.len / m_scale_x);
00944         }
00945 
00946         //-------------------------------------------------------------------------
00947         void line3(const line_parameters& lp, 
00948                    int sx, int sy, int ex, int ey)
00949         {
00950             if(m_clipping)
00951             {
00952                 int x1 = lp.x1;
00953                 int y1 = lp.y1;
00954                 int x2 = lp.x2;
00955                 int y2 = lp.y2;
00956                 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
00957                 int start = m_start;
00958                 if((flags & 4) == 0)
00959                 {
00960                     if(flags)
00961                     {
00962                         line_parameters lp2(x1, y1, x2, y2, 
00963                                            uround(calc_distance(x1, y1, x2, y2)));
00964                         if(flags & 1)
00965                         {
00966                             m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x);
00967                             sx = x1 + (y2 - y1); 
00968                             sy = y1 - (x2 - x1);
00969                         }
00970                         else
00971                         {
00972                             while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
00973                             {
00974                                 sx = (lp.x1 + sx) >> 1;
00975                                 sy = (lp.y1 + sy) >> 1;
00976                             }
00977                         }
00978                         if(flags & 2)
00979                         {
00980                             ex = x2 + (y2 - y1); 
00981                             ey = y2 - (x2 - x1);
00982                         }
00983                         else
00984                         {
00985                             while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
00986                             {
00987                                 ex = (lp.x2 + ex) >> 1;
00988                                 ey = (lp.y2 + ey) >> 1;
00989                             }
00990                         }
00991                         line3_no_clip(lp2, sx, sy, ex, ey);
00992                     }
00993                     else
00994                     {
00995                         line3_no_clip(lp, sx, sy, ex, ey);
00996                     }
00997                 }
00998                 m_start = start + uround(lp.len / m_scale_x);
00999             }
01000             else
01001             {
01002                 line3_no_clip(lp, sx, sy, ex, ey);
01003             }
01004         }
01005 
01006     private:
01007         base_ren_type*      m_ren;
01008         const pattern_type* m_pattern;
01009         int                 m_start;
01010         double              m_scale_x;
01011         rect_i              m_clip_box;
01012         bool                m_clipping;
01013     };
01014 
01015 
01016 
01017 
01018 
01019 }
01020 
01021 
01022 
01023 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines