Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_rasterizer_sl_clip.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_RASTERIZER_SL_CLIP_INCLUDED
00026 #define AGG_RASTERIZER_SL_CLIP_INCLUDED
00027 
00028 #include "agg_clip_liang_barsky.h"
00029 
00030 namespace agg
00031 {
00032     //--------------------------------------------------------poly_max_coord_e
00033     enum poly_max_coord_e
00034     {
00035         poly_max_coord = (1 << 30) - 1 //----poly_max_coord
00036     };
00037     
00038     //------------------------------------------------------------ras_conv_int
00039     struct ras_conv_int
00040     {
00041         typedef int coord_type;
00042         static AGG_INLINE int mul_div(double a, double b, double c)
00043         {
00044             return iround(a * b / c);
00045         }
00046         static int xi(int v) { return v; }
00047         static int yi(int v) { return v; }
00048         static int upscale(double v) { return iround(v * poly_subpixel_scale); }
00049         static int downscale(int v)  { return v; }
00050     };
00051 
00052     //--------------------------------------------------------ras_conv_int_sat
00053     struct ras_conv_int_sat
00054     {
00055         typedef int coord_type;
00056         static AGG_INLINE int mul_div(double a, double b, double c)
00057         {
00058             return saturation<poly_max_coord>::iround(a * b / c);
00059         }
00060         static int xi(int v) { return v; }
00061         static int yi(int v) { return v; }
00062         static int upscale(double v) 
00063         { 
00064             return saturation<poly_max_coord>::iround(v * poly_subpixel_scale); 
00065         }
00066         static int downscale(int v) { return v; }
00067     };
00068 
00069     //---------------------------------------------------------ras_conv_int_3x
00070     struct ras_conv_int_3x
00071     {
00072         typedef int coord_type;
00073         static AGG_INLINE int mul_div(double a, double b, double c)
00074         {
00075             return iround(a * b / c);
00076         }
00077         static int xi(int v) { return v * 3; }
00078         static int yi(int v) { return v; }
00079         static int upscale(double v) { return iround(v * poly_subpixel_scale); }
00080         static int downscale(int v)  { return v; }
00081     };
00082 
00083     //-----------------------------------------------------------ras_conv_dbl
00084     struct ras_conv_dbl
00085     {
00086         typedef double coord_type;
00087         static AGG_INLINE double mul_div(double a, double b, double c)
00088         {
00089             return a * b / c;
00090         }
00091         static int xi(double v) { return iround(v * poly_subpixel_scale); }
00092         static int yi(double v) { return iround(v * poly_subpixel_scale); }
00093         static double upscale(double v) { return v; }
00094         static double downscale(int v)  { return v / double(poly_subpixel_scale); }
00095     };
00096 
00097     //--------------------------------------------------------ras_conv_dbl_3x
00098     struct ras_conv_dbl_3x
00099     {
00100         typedef double coord_type;
00101         static AGG_INLINE double mul_div(double a, double b, double c)
00102         {
00103             return a * b / c;
00104         }
00105         static int xi(double v) { return iround(v * poly_subpixel_scale * 3); }
00106         static int yi(double v) { return iround(v * poly_subpixel_scale); }
00107         static double upscale(double v) { return v; }
00108         static double downscale(int v)  { return v / double(poly_subpixel_scale); }
00109     };
00110 
00111 
00112 
00113 
00114 
00115     //------------------------------------------------------rasterizer_sl_clip
00116     template<class Conv> class rasterizer_sl_clip
00117     {
00118     public:
00119         typedef Conv                      conv_type;
00120         typedef typename Conv::coord_type coord_type;
00121         typedef rect_base<coord_type>     rect_type;
00122 
00123         //--------------------------------------------------------------------
00124         rasterizer_sl_clip() :  
00125             m_clip_box(0,0,0,0),
00126             m_x1(0),
00127             m_y1(0),
00128             m_f1(0),
00129             m_clipping(false) 
00130         {}
00131 
00132         //--------------------------------------------------------------------
00133         void reset_clipping()
00134         {
00135             m_clipping = false;
00136         }
00137 
00138         //--------------------------------------------------------------------
00139         void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2)
00140         {
00141             m_clip_box = rect_type(x1, y1, x2, y2);
00142             m_clip_box.normalize();
00143             m_clipping = true;
00144         }
00145 
00146         //--------------------------------------------------------------------
00147         void move_to(coord_type x1, coord_type y1)
00148         {
00149             m_x1 = x1;
00150             m_y1 = y1;
00151             if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box);
00152         }
00153 
00154     private:
00155         //------------------------------------------------------------------------
00156         template<class Rasterizer>
00157         AGG_INLINE void line_clip_y(Rasterizer& ras,
00158                                     coord_type x1, coord_type y1, 
00159                                     coord_type x2, coord_type y2, 
00160                                     unsigned   f1, unsigned   f2) const
00161         {
00162             f1 &= 10;
00163             f2 &= 10;
00164             if((f1 | f2) == 0)
00165             {
00166                 // Fully visible
00167                 ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2)); 
00168             }
00169             else
00170             {
00171                 if(f1 == f2)
00172                 {
00173                     // Invisible by Y
00174                     return;
00175                 }
00176 
00177                 coord_type tx1 = x1;
00178                 coord_type ty1 = y1;
00179                 coord_type tx2 = x2;
00180                 coord_type ty2 = y2;
00181 
00182                 if(f1 & 8) // y1 < clip.y1
00183                 {
00184                     tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
00185                     ty1 = m_clip_box.y1;
00186                 }
00187 
00188                 if(f1 & 2) // y1 > clip.y2
00189                 {
00190                     tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
00191                     ty1 = m_clip_box.y2;
00192                 }
00193 
00194                 if(f2 & 8) // y2 < clip.y1
00195                 {
00196                     tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
00197                     ty2 = m_clip_box.y1;
00198                 }
00199 
00200                 if(f2 & 2) // y2 > clip.y2
00201                 {
00202                     tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
00203                     ty2 = m_clip_box.y2;
00204                 }
00205                 ras.line(Conv::xi(tx1), Conv::yi(ty1), 
00206                          Conv::xi(tx2), Conv::yi(ty2)); 
00207             }
00208         }
00209 
00210 
00211     public:
00212         //--------------------------------------------------------------------
00213         template<class Rasterizer>
00214         void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
00215         {
00216             if(m_clipping)
00217             {
00218                 unsigned f2 = clipping_flags(x2, y2, m_clip_box);
00219 
00220                 if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
00221                 {
00222                     // Invisible by Y
00223                     m_x1 = x2;
00224                     m_y1 = y2;
00225                     m_f1 = f2;
00226                     return;
00227                 }
00228 
00229                 coord_type x1 = m_x1;
00230                 coord_type y1 = m_y1;
00231                 unsigned   f1 = m_f1;
00232                 coord_type y3, y4;
00233                 unsigned   f3, f4;
00234 
00235                 switch(((f1 & 5) << 1) | (f2 & 5))
00236                 {
00237                 case 0: // Visible by X
00238                     line_clip_y(ras, x1, y1, x2, y2, f1, f2);
00239                     break;
00240 
00241                 case 1: // x2 > clip.x2
00242                     y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
00243                     f3 = clipping_flags_y(y3, m_clip_box);
00244                     line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3);
00245                     line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2);
00246                     break;
00247 
00248                 case 2: // x1 > clip.x2
00249                     y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
00250                     f3 = clipping_flags_y(y3, m_clip_box);
00251                     line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
00252                     line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2);
00253                     break;
00254 
00255                 case 3: // x1 > clip.x2 && x2 > clip.x2
00256                     line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2);
00257                     break;
00258 
00259                 case 4: // x2 < clip.x1
00260                     y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
00261                     f3 = clipping_flags_y(y3, m_clip_box);
00262                     line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3);
00263                     line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2);
00264                     break;
00265 
00266                 case 6: // x1 > clip.x2 && x2 < clip.x1
00267                     y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
00268                     y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
00269                     f3 = clipping_flags_y(y3, m_clip_box);
00270                     f4 = clipping_flags_y(y4, m_clip_box);
00271                     line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
00272                     line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4);
00273                     line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2);
00274                     break;
00275 
00276                 case 8: // x1 < clip.x1
00277                     y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
00278                     f3 = clipping_flags_y(y3, m_clip_box);
00279                     line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
00280                     line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2);
00281                     break;
00282 
00283                 case 9:  // x1 < clip.x1 && x2 > clip.x2
00284                     y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
00285                     y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
00286                     f3 = clipping_flags_y(y3, m_clip_box);
00287                     f4 = clipping_flags_y(y4, m_clip_box);
00288                     line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
00289                     line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4);
00290                     line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2);
00291                     break;
00292 
00293                 case 12: // x1 < clip.x1 && x2 < clip.x1
00294                     line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2);
00295                     break;
00296                 }
00297                 m_f1 = f2;
00298             }
00299             else
00300             {
00301                 ras.line(Conv::xi(m_x1), Conv::yi(m_y1), 
00302                          Conv::xi(x2),   Conv::yi(y2)); 
00303             }
00304             m_x1 = x2;
00305             m_y1 = y2;
00306         }
00307 
00308 
00309     private:
00310         rect_type        m_clip_box;
00311         coord_type       m_x1;
00312         coord_type       m_y1;
00313         unsigned         m_f1;
00314         bool             m_clipping;
00315     };
00316 
00317 
00318 
00319 
00320     //---------------------------------------------------rasterizer_sl_no_clip
00321     class rasterizer_sl_no_clip
00322     {
00323     public:
00324         typedef ras_conv_int conv_type;
00325         typedef int          coord_type;
00326 
00327         rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
00328 
00329         void reset_clipping() {}
00330         void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {}
00331         void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
00332 
00333         template<class Rasterizer>
00334         void line_to(Rasterizer& ras, coord_type x2, coord_type y2) 
00335         { 
00336             ras.line(m_x1, m_y1, x2, y2); 
00337             m_x1 = x2; 
00338             m_y1 = y2;
00339         }
00340 
00341     private:
00342         int m_x1, m_y1;
00343     };
00344 
00345 
00346     //                                         -----rasterizer_sl_clip_int
00347     //                                         -----rasterizer_sl_clip_int_sat
00348     //                                         -----rasterizer_sl_clip_int_3x
00349     //                                         -----rasterizer_sl_clip_dbl
00350     //                                         -----rasterizer_sl_clip_dbl_3x
00351     //------------------------------------------------------------------------
00352     typedef rasterizer_sl_clip<ras_conv_int>     rasterizer_sl_clip_int;
00353     typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat;
00354     typedef rasterizer_sl_clip<ras_conv_int_3x>  rasterizer_sl_clip_int_3x;
00355     typedef rasterizer_sl_clip<ras_conv_dbl>     rasterizer_sl_clip_dbl;
00356     typedef rasterizer_sl_clip<ras_conv_dbl_3x>  rasterizer_sl_clip_dbl_3x;
00357 
00358 
00359 }
00360 
00361 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines