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_RGBA_INCLUDED 00034 #define AGG_SPAN_GOURAUD_RGBA_INCLUDED 00035 00036 #include "agg_basics.h" 00037 #include "agg_color_rgba.h" 00038 #include "agg_dda_line.h" 00039 #include "agg_span_gouraud.h" 00040 00041 namespace agg 00042 { 00043 00044 //=======================================================span_gouraud_rgba 00045 template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT> 00046 { 00047 public: 00048 typedef ColorT color_type; 00049 typedef typename ColorT::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 rgba_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 = (dy < 1e-5) ? 1e5 : 1.0 / dy; 00069 m_r1 = c1.color.r; 00070 m_g1 = c1.color.g; 00071 m_b1 = c1.color.b; 00072 m_a1 = c1.color.a; 00073 m_dr = c2.color.r - m_r1; 00074 m_dg = c2.color.g - m_g1; 00075 m_db = c2.color.b - m_b1; 00076 m_da = c2.color.a - m_a1; 00077 } 00078 00079 void calc(double y) 00080 { 00081 double k = (y - m_y1) * m_1dy; 00082 if(k < 0.0) k = 0.0; 00083 if(k > 1.0) k = 1.0; 00084 m_r = m_r1 + iround(m_dr * k); 00085 m_g = m_g1 + iround(m_dg * k); 00086 m_b = m_b1 + iround(m_db * k); 00087 m_a = m_a1 + iround(m_da * k); 00088 m_x = iround((m_x1 + m_dx * k) * subpixel_scale); 00089 } 00090 00091 double m_x1; 00092 double m_y1; 00093 double m_dx; 00094 double m_1dy; 00095 int m_r1; 00096 int m_g1; 00097 int m_b1; 00098 int m_a1; 00099 int m_dr; 00100 int m_dg; 00101 int m_db; 00102 int m_da; 00103 int m_r; 00104 int m_g; 00105 int m_b; 00106 int m_a; 00107 int m_x; 00108 }; 00109 00110 public: 00111 00112 //-------------------------------------------------------------------- 00113 span_gouraud_rgba() {} 00114 span_gouraud_rgba(const color_type& c1, 00115 const color_type& c2, 00116 const color_type& c3, 00117 double x1, double y1, 00118 double x2, double y2, 00119 double x3, double y3, 00120 double d = 0) : 00121 base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) 00122 {} 00123 00124 //-------------------------------------------------------------------- 00125 void prepare() 00126 { 00127 coord_type coord[3]; 00128 base_type::arrange_vertices(coord); 00129 00130 m_y2 = int(coord[1].y); 00131 00132 m_swap = cross_product(coord[0].x, coord[0].y, 00133 coord[2].x, coord[2].y, 00134 coord[1].x, coord[1].y) < 0.0; 00135 00136 m_rgba1.init(coord[0], coord[2]); 00137 m_rgba2.init(coord[0], coord[1]); 00138 m_rgba3.init(coord[1], coord[2]); 00139 } 00140 00141 //-------------------------------------------------------------------- 00142 void generate(color_type* span, int x, int y, unsigned len) 00143 { 00144 m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); 00145 const rgba_calc* pc1 = &m_rgba1; 00146 const rgba_calc* pc2 = &m_rgba2; 00147 00148 if(y <= m_y2) 00149 { 00150 // Bottom part of the triangle (first subtriangle) 00151 //------------------------- 00152 m_rgba2.calc(y + m_rgba2.m_1dy); 00153 } 00154 else 00155 { 00156 // Upper part (second subtriangle) 00157 m_rgba3.calc(y - m_rgba3.m_1dy); 00158 //------------------------- 00159 pc2 = &m_rgba3; 00160 } 00161 00162 if(m_swap) 00163 { 00164 // It means that the triangle is oriented clockwise, 00165 // so that we need to swap the controlling structures 00166 //------------------------- 00167 const rgba_calc* t = pc2; 00168 pc2 = pc1; 00169 pc1 = t; 00170 } 00171 00172 // Get the horizontal length with subpixel accuracy 00173 // and protect it from division by zero 00174 //------------------------- 00175 int nlen = abs(pc2->m_x - pc1->m_x); 00176 if(nlen <= 0) nlen = 1; 00177 00178 dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen); 00179 dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen); 00180 dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen); 00181 dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); 00182 00183 // Calculate the starting point of the gradient with subpixel 00184 // accuracy and correct (roll back) the interpolators. 00185 // This operation will also clip the beginning of the span 00186 // if necessary. 00187 //------------------------- 00188 int start = pc1->m_x - (x << subpixel_shift); 00189 r -= start; 00190 g -= start; 00191 b -= start; 00192 a -= start; 00193 nlen += start; 00194 00195 int vr, vg, vb, va; 00196 enum lim_e { lim = color_type::base_mask }; 00197 00198 // Beginning part of the span. Since we rolled back the 00199 // interpolators, the color values may have overflow. 00200 // So that, we render the beginning part with checking 00201 // for overflow. It lasts until "start" is positive; 00202 // typically it's 1-2 pixels, but may be more in some cases. 00203 //------------------------- 00204 while(len && start > 0) 00205 { 00206 vr = r.y(); 00207 vg = g.y(); 00208 vb = b.y(); 00209 va = a.y(); 00210 if(vr < 0) vr = 0; if(vr > lim) vr = lim; 00211 if(vg < 0) vg = 0; if(vg > lim) vg = lim; 00212 if(vb < 0) vb = 0; if(vb > lim) vb = lim; 00213 if(va < 0) va = 0; if(va > lim) va = lim; 00214 span->r = (value_type)vr; 00215 span->g = (value_type)vg; 00216 span->b = (value_type)vb; 00217 span->a = (value_type)va; 00218 r += subpixel_scale; 00219 g += subpixel_scale; 00220 b += subpixel_scale; 00221 a += subpixel_scale; 00222 nlen -= subpixel_scale; 00223 start -= subpixel_scale; 00224 ++span; 00225 --len; 00226 } 00227 00228 // Middle part, no checking for overflow. 00229 // Actual spans can be longer than the calculated length 00230 // because of anti-aliasing, thus, the interpolators can 00231 // overflow. But while "nlen" is positive we are safe. 00232 //------------------------- 00233 while(len && nlen > 0) 00234 { 00235 span->r = (value_type)r.y(); 00236 span->g = (value_type)g.y(); 00237 span->b = (value_type)b.y(); 00238 span->a = (value_type)a.y(); 00239 r += subpixel_scale; 00240 g += subpixel_scale; 00241 b += subpixel_scale; 00242 a += subpixel_scale; 00243 nlen -= subpixel_scale; 00244 ++span; 00245 --len; 00246 } 00247 00248 // Ending part; checking for overflow. 00249 // Typically it's 1-2 pixels, but may be more in some cases. 00250 //------------------------- 00251 while(len) 00252 { 00253 vr = r.y(); 00254 vg = g.y(); 00255 vb = b.y(); 00256 va = a.y(); 00257 if(vr < 0) vr = 0; if(vr > lim) vr = lim; 00258 if(vg < 0) vg = 0; if(vg > lim) vg = lim; 00259 if(vb < 0) vb = 0; if(vb > lim) vb = lim; 00260 if(va < 0) va = 0; if(va > lim) va = lim; 00261 span->r = (value_type)vr; 00262 span->g = (value_type)vg; 00263 span->b = (value_type)vb; 00264 span->a = (value_type)va; 00265 r += subpixel_scale; 00266 g += subpixel_scale; 00267 b += subpixel_scale; 00268 a += subpixel_scale; 00269 ++span; 00270 --len; 00271 } 00272 } 00273 00274 private: 00275 bool m_swap; 00276 int m_y2; 00277 rgba_calc m_rgba1; 00278 rgba_calc m_rgba2; 00279 rgba_calc m_rgba3; 00280 }; 00281 00282 00283 00284 } 00285 00286 #endif