Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_span_gradient.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_SPAN_GRADIENT_INCLUDED
00026 #define AGG_SPAN_GRADIENT_INCLUDED
00027 
00028 #include <math.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include "agg_basics.h"
00032 #include "agg_math.h"
00033 #include "agg_array.h"
00034 
00035 
00036 namespace agg
00037 {
00038 
00039     enum gradient_subpixel_scale_e
00040     {
00041         gradient_subpixel_shift = 4,                              //-----gradient_subpixel_shift
00042         gradient_subpixel_scale = 1 << gradient_subpixel_shift,   //-----gradient_subpixel_scale
00043         gradient_subpixel_mask  = gradient_subpixel_scale - 1     //-----gradient_subpixel_mask
00044     };
00045 
00046 
00047 
00048     //==========================================================span_gradient
00049     template<class ColorT,
00050              class Interpolator,
00051              class GradientF, 
00052              class ColorF>
00053     class span_gradient
00054     {
00055     public:
00056         typedef Interpolator interpolator_type;
00057         typedef ColorT color_type;
00058 
00059         enum downscale_shift_e
00060         {
00061             downscale_shift = interpolator_type::subpixel_shift - 
00062                               gradient_subpixel_shift
00063         };
00064 
00065         //--------------------------------------------------------------------
00066         span_gradient() {}
00067 
00068         //--------------------------------------------------------------------
00069         span_gradient(interpolator_type& inter,
00070                       const GradientF& gradient_function,
00071                       const ColorF& color_function,
00072                       double d1, double d2) : 
00073             m_interpolator(&inter),
00074             m_gradient_function(&gradient_function),
00075             m_color_function(&color_function),
00076             m_d1(iround(d1 * gradient_subpixel_scale)),
00077             m_d2(iround(d2 * gradient_subpixel_scale))
00078         {}
00079 
00080         //--------------------------------------------------------------------
00081         interpolator_type& interpolator() { return *m_interpolator; }
00082         const GradientF& gradient_function() const { return *m_gradient_function; }
00083         const ColorF& color_function() const { return *m_color_function; }
00084         double d1() const { return double(m_d1) / gradient_subpixel_scale; }
00085         double d2() const { return double(m_d2) / gradient_subpixel_scale; }
00086 
00087         //--------------------------------------------------------------------
00088         void interpolator(interpolator_type& i) { m_interpolator = &i; }
00089         void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
00090         void color_function(const ColorF& cf) { m_color_function = &cf; }
00091         void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
00092         void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
00093 
00094         //--------------------------------------------------------------------
00095         void prepare() {}
00096 
00097         //--------------------------------------------------------------------
00098         void generate(color_type* span, int x, int y, unsigned len)
00099         {   
00100             int dd = m_d2 - m_d1;
00101             if(dd < 1) dd = 1;
00102             m_interpolator->begin(x+0.5, y+0.5, len);
00103             do
00104             {
00105                 m_interpolator->coordinates(&x, &y);
00106                 int d = m_gradient_function->calculate(x >> downscale_shift, 
00107                                                        y >> downscale_shift, m_d2);
00108                 d = ((d - m_d1) * (int)m_color_function->size()) / dd;
00109                 if(d < 0) d = 0;
00110                 if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1;
00111                 *span++ = (*m_color_function)[d];
00112                 ++(*m_interpolator);
00113             }
00114             while(--len);
00115         }
00116 
00117     private:
00118         interpolator_type* m_interpolator;
00119         const GradientF*   m_gradient_function;
00120         const ColorF*      m_color_function;
00121         int                m_d1;
00122         int                m_d2;
00123     };
00124 
00125 
00126 
00127 
00128     //=====================================================gradient_linear_color
00129     template<class ColorT> 
00130     struct gradient_linear_color
00131     {
00132         typedef ColorT color_type;
00133 
00134         gradient_linear_color() {}
00135         gradient_linear_color(const color_type& c1, const color_type& c2, 
00136                               unsigned size = 256) :
00137             m_c1(c1), m_c2(c2), m_size(size) {}
00138 
00139         unsigned size() const { return m_size; }
00140         color_type operator [] (unsigned v) const 
00141         {
00142             return m_c1.gradient(m_c2, double(v) / double(m_size - 1));
00143         }
00144 
00145         void colors(const color_type& c1, const color_type& c2, unsigned size = 256)
00146         {
00147             m_c1 = c1;
00148             m_c2 = c2;
00149             m_size = size;
00150         }
00151 
00152         color_type m_c1;
00153         color_type m_c2;
00154         unsigned m_size;
00155     };
00156 
00157 
00158 
00159 
00160 
00161 
00162     //==========================================================gradient_circle
00163     class gradient_circle
00164     {
00165         // Actually the same as radial. Just for compatibility
00166     public:
00167         static AGG_INLINE int calculate(int x, int y, int)
00168         {
00169             return int(fast_sqrt(x*x + y*y));
00170         }
00171     };
00172 
00173 
00174     //==========================================================gradient_radial
00175     class gradient_radial
00176     {
00177     public:
00178         static AGG_INLINE int calculate(int x, int y, int)
00179         {
00180             return int(fast_sqrt(x*x + y*y));
00181         }
00182     };
00183 
00184     //========================================================gradient_radial_d
00185     class gradient_radial_d
00186     {
00187     public:
00188         static AGG_INLINE int calculate(int x, int y, int)
00189         {
00190             return uround(sqrt(double(x)*double(x) + double(y)*double(y)));
00191         }
00192     };
00193 
00194     //====================================================gradient_radial_focus
00195     class gradient_radial_focus
00196     {
00197     public:
00198         //---------------------------------------------------------------------
00199         gradient_radial_focus() : 
00200             m_r(100 * gradient_subpixel_scale), 
00201             m_fx(0), 
00202             m_fy(0)
00203         {
00204             update_values();
00205         }
00206 
00207         //---------------------------------------------------------------------
00208         gradient_radial_focus(double r, double fx, double fy) : 
00209             m_r (iround(r  * gradient_subpixel_scale)), 
00210             m_fx(iround(fx * gradient_subpixel_scale)), 
00211             m_fy(iround(fy * gradient_subpixel_scale))
00212         {
00213             update_values();
00214         }
00215 
00216         //---------------------------------------------------------------------
00217         void init(double r, double fx, double fy)
00218         {
00219             m_r  = iround(r  * gradient_subpixel_scale);
00220             m_fx = iround(fx * gradient_subpixel_scale);
00221             m_fy = iround(fy * gradient_subpixel_scale);
00222             update_values();
00223         }
00224 
00225         //---------------------------------------------------------------------
00226         double radius()  const { return double(m_r)  / gradient_subpixel_scale; }
00227         double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
00228         double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
00229 
00230         //---------------------------------------------------------------------
00231         int calculate(int x, int y, int) const
00232         {
00233             double dx = x - m_fx;
00234             double dy = y - m_fy;
00235             double d2 = dx * m_fy - dy * m_fx;
00236             double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
00237             return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul);
00238         }
00239 
00240     private:
00241         //---------------------------------------------------------------------
00242         void update_values()
00243         {
00244             // Calculate the invariant values. In case the focal center
00245             // lies exactly on the gradient circle the divisor degenerates
00246             // into zero. In this case we just move the focal center by
00247             // one subpixel unit possibly in the direction to the origin (0,0)
00248             // and calculate the values again.
00249             //-------------------------
00250             m_r2  = double(m_r)  * double(m_r);
00251             m_fx2 = double(m_fx) * double(m_fx);
00252             m_fy2 = double(m_fy) * double(m_fy);
00253             double d = (m_r2 - (m_fx2 + m_fy2));
00254             if(d == 0)
00255             {
00256                 if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; }
00257                 if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; }
00258                 m_fx2 = double(m_fx) * double(m_fx);
00259                 m_fy2 = double(m_fy) * double(m_fy);
00260                 d = (m_r2 - (m_fx2 + m_fy2));
00261             }
00262             m_mul = m_r / d;
00263         }
00264 
00265         int    m_r;
00266         int    m_fx;
00267         int    m_fy;
00268         double m_r2;
00269         double m_fx2;
00270         double m_fy2;
00271         double m_mul;
00272     };
00273 
00274 
00275     //==============================================================gradient_x
00276     class gradient_x
00277     {
00278     public:
00279         static int calculate(int x, int, int) { return x; }
00280     };
00281 
00282 
00283     //==============================================================gradient_y
00284     class gradient_y
00285     {
00286     public:
00287         static int calculate(int, int y, int) { return y; }
00288     };
00289 
00290     //========================================================gradient_diamond
00291     class gradient_diamond
00292     {
00293     public:
00294         static AGG_INLINE int calculate(int x, int y, int) 
00295         { 
00296             int ax = abs(x);
00297             int ay = abs(y);
00298             return ax > ay ? ax : ay; 
00299         }
00300     };
00301 
00302     //=============================================================gradient_xy
00303     class gradient_xy
00304     {
00305     public:
00306         static AGG_INLINE int calculate(int x, int y, int d) 
00307         { 
00308             return abs(x) * abs(y) / d; 
00309         }
00310     };
00311 
00312     //========================================================gradient_sqrt_xy
00313     class gradient_sqrt_xy
00314     {
00315     public:
00316         static AGG_INLINE int calculate(int x, int y, int) 
00317         { 
00318             return fast_sqrt(abs(x) * abs(y)); 
00319         }
00320     };
00321 
00322     //==========================================================gradient_conic
00323     class gradient_conic
00324     {
00325     public:
00326         static AGG_INLINE int calculate(int x, int y, int d) 
00327         { 
00328             return uround(fabs(atan2(double(y), double(x))) * double(d) / pi);
00329         }
00330     };
00331 
00332     //=================================================gradient_repeat_adaptor
00333     template<class GradientF> class gradient_repeat_adaptor
00334     {
00335     public:
00336         gradient_repeat_adaptor(const GradientF& gradient) : 
00337             m_gradient(&gradient) {}
00338 
00339         AGG_INLINE int calculate(int x, int y, int d) const
00340         {
00341             int ret = m_gradient->calculate(x, y, d) % d;
00342             if(ret < 0) ret += d;
00343             return ret;
00344         }
00345 
00346     private:
00347         const GradientF* m_gradient;
00348     };
00349 
00350     //================================================gradient_reflect_adaptor
00351     template<class GradientF> class gradient_reflect_adaptor
00352     {
00353     public:
00354         gradient_reflect_adaptor(const GradientF& gradient) : 
00355             m_gradient(&gradient) {}
00356 
00357         AGG_INLINE int calculate(int x, int y, int d) const
00358         {
00359             int d2 = d << 1;
00360             int ret = m_gradient->calculate(x, y, d) % d2;
00361             if(ret <  0) ret += d2;
00362             if(ret >= d) ret  = d2 - ret;
00363             return ret;
00364         }
00365 
00366     private:
00367         const GradientF* m_gradient;
00368     };
00369 
00370 
00371 }
00372 
00373 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines