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 // Adaptation for high precision colors has been sponsored by 00026 // Liberty Technology Systems, Inc., visit http://lib-sys.com 00027 // 00028 // Liberty Technology Systems, Inc. is the provider of 00029 // PostScript and PDF technology for software developers. 00030 // 00031 //---------------------------------------------------------------------------- 00032 00033 #ifndef AGG_SPAN_GOURAUD_GRAY_INCLUDED 00034 #define AGG_SPAN_GOURAUD_GRAY_INCLUDED 00035 00036 #include "agg_basics.h" 00037 #include "agg_color_gray.h" 00038 #include "agg_dda_line.h" 00039 #include "agg_span_gouraud.h" 00040 00041 namespace agg 00042 { 00043 00044 //=======================================================span_gouraud_gray 00045 template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT> 00046 { 00047 public: 00048 typedef ColorT color_type; 00049 typedef typename color_type::value_type value_type; 00050 typedef span_gouraud<color_type> base_type; 00051 typedef typename base_type::coord_type coord_type; 00052 enum subpixel_scale_e 00053 { 00054 subpixel_shift = 4, 00055 subpixel_scale = 1 << subpixel_shift 00056 }; 00057 00058 private: 00059 //-------------------------------------------------------------------- 00060 struct gray_calc 00061 { 00062 void init(const coord_type& c1, const coord_type& c2) 00063 { 00064 m_x1 = c1.x - 0.5; 00065 m_y1 = c1.y - 0.5; 00066 m_dx = c2.x - c1.x; 00067 double dy = c2.y - c1.y; 00068 m_1dy = (fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy; 00069 m_v1 = c1.color.v; 00070 m_a1 = c1.color.a; 00071 m_dv = c2.color.v - m_v1; 00072 m_da = c2.color.a - m_a1; 00073 } 00074 00075 void calc(double y) 00076 { 00077 double k = (y - m_y1) * m_1dy; 00078 if(k < 0.0) k = 0.0; 00079 if(k > 1.0) k = 1.0; 00080 m_v = m_v1 + iround(m_dv * k); 00081 m_a = m_a1 + iround(m_da * k); 00082 m_x = iround((m_x1 + m_dx * k) * subpixel_scale); 00083 } 00084 00085 double m_x1; 00086 double m_y1; 00087 double m_dx; 00088 double m_1dy; 00089 int m_v1; 00090 int m_a1; 00091 int m_dv; 00092 int m_da; 00093 int m_v; 00094 int m_a; 00095 int m_x; 00096 }; 00097 00098 00099 public: 00100 //-------------------------------------------------------------------- 00101 span_gouraud_gray() {} 00102 span_gouraud_gray(const color_type& c1, 00103 const color_type& c2, 00104 const color_type& c3, 00105 double x1, double y1, 00106 double x2, double y2, 00107 double x3, double y3, 00108 double d = 0) : 00109 base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) 00110 {} 00111 00112 //-------------------------------------------------------------------- 00113 void prepare() 00114 { 00115 coord_type coord[3]; 00116 base_type::arrange_vertices(coord); 00117 00118 m_y2 = int(coord[1].y); 00119 00120 m_swap = cross_product(coord[0].x, coord[0].y, 00121 coord[2].x, coord[2].y, 00122 coord[1].x, coord[1].y) < 0.0; 00123 00124 m_c1.init(coord[0], coord[2]); 00125 m_c2.init(coord[0], coord[1]); 00126 m_c3.init(coord[1], coord[2]); 00127 } 00128 00129 //-------------------------------------------------------------------- 00130 void generate(color_type* span, int x, int y, unsigned len) 00131 { 00132 m_c1.calc(y); 00133 const gray_calc* pc1 = &m_c1; 00134 const gray_calc* pc2 = &m_c2; 00135 00136 if(y < m_y2) 00137 { 00138 // Bottom part of the triangle (first subtriangle) 00139 //------------------------- 00140 m_c2.calc(y + m_c2.m_1dy); 00141 } 00142 else 00143 { 00144 // Upper part (second subtriangle) 00145 //------------------------- 00146 m_c3.calc(y - m_c3.m_1dy); 00147 pc2 = &m_c3; 00148 } 00149 00150 if(m_swap) 00151 { 00152 // It means that the triangle is oriented clockwise, 00153 // so that we need to swap the controlling structures 00154 //------------------------- 00155 const gray_calc* t = pc2; 00156 pc2 = pc1; 00157 pc1 = t; 00158 } 00159 00160 // Get the horizontal length with subpixel accuracy 00161 // and protect it from division by zero 00162 //------------------------- 00163 int nlen = abs(pc2->m_x - pc1->m_x); 00164 if(nlen <= 0) nlen = 1; 00165 00166 dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen); 00167 dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); 00168 00169 // Calculate the starting point of the gradient with subpixel 00170 // accuracy and correct (roll back) the interpolators. 00171 // This operation will also clip the beginning of the span 00172 // if necessary. 00173 //------------------------- 00174 int start = pc1->m_x - (x << subpixel_shift); 00175 v -= start; 00176 a -= start; 00177 nlen += start; 00178 00179 int vv, va; 00180 enum lim_e { lim = color_type::base_mask }; 00181 00182 // Beginning part of the span. Since we rolled back the 00183 // interpolators, the color values may have overflow. 00184 // So that, we render the beginning part with checking 00185 // for overflow. It lasts until "start" is positive; 00186 // typically it's 1-2 pixels, but may be more in some cases. 00187 //------------------------- 00188 while(len && start > 0) 00189 { 00190 vv = v.y(); 00191 va = a.y(); 00192 if(vv < 0) vv = 0; if(vv > lim) vv = lim; 00193 if(va < 0) va = 0; if(va > lim) va = lim; 00194 span->v = (value_type)vv; 00195 span->a = (value_type)va; 00196 v += subpixel_scale; 00197 a += subpixel_scale; 00198 nlen -= subpixel_scale; 00199 start -= subpixel_scale; 00200 ++span; 00201 --len; 00202 } 00203 00204 // Middle part, no checking for overflow. 00205 // Actual spans can be longer than the calculated length 00206 // because of anti-aliasing, thus, the interpolators can 00207 // overflow. But while "nlen" is positive we are safe. 00208 //------------------------- 00209 while(len && nlen > 0) 00210 { 00211 span->v = (value_type)v.y(); 00212 span->a = (value_type)a.y(); 00213 v += subpixel_scale; 00214 a += subpixel_scale; 00215 nlen -= subpixel_scale; 00216 ++span; 00217 --len; 00218 } 00219 00220 // Ending part; checking for overflow. 00221 // Typically it's 1-2 pixels, but may be more in some cases. 00222 //------------------------- 00223 while(len) 00224 { 00225 vv = v.y(); 00226 va = a.y(); 00227 if(vv < 0) vv = 0; if(vv > lim) vv = lim; 00228 if(va < 0) va = 0; if(va > lim) va = lim; 00229 span->v = (value_type)vv; 00230 span->a = (value_type)va; 00231 v += subpixel_scale; 00232 a += subpixel_scale; 00233 ++span; 00234 --len; 00235 } 00236 } 00237 00238 00239 private: 00240 bool m_swap; 00241 int m_y2; 00242 gray_calc m_c1; 00243 gray_calc m_c2; 00244 gray_calc m_c3; 00245 }; 00246 00247 00248 } 00249 00250 #endif