Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_span_gouraud_gray.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 // 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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines