Anti-Grain Geometry - AGG (libagg)
2.5
|
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