incubator-ooo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From p..@apache.org
Subject svn commit: r1184758 [13/17] - in /incubator/ooo/trunk/main: ./ agg/inc/ agg/source/ solenv/config/
Date Sun, 16 Oct 2011 04:13:21 GMT
Modified: incubator/ooo/trunk/main/agg/inc/agg_span_gouraud_rgba.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_span_gouraud_rgba.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_span_gouraud_rgba.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_span_gouraud_rgba.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
 //----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 //
 // Permission to copy, use, modify, sell and distribute this software 
@@ -33,15 +33,18 @@ namespace agg
 {
 
     //=======================================================span_gouraud_rgba
-    template<class ColorT, class Allocator = span_allocator<ColorT> >
-    class span_gouraud_rgba : public span_gouraud<ColorT, Allocator>
+    template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT>
     {
     public:
-        typedef Allocator alloc_type;
         typedef ColorT color_type;
         typedef typename ColorT::value_type value_type;
-        typedef span_gouraud<color_type, alloc_type> base_type;
+        typedef span_gouraud<color_type> base_type;
         typedef typename base_type::coord_type coord_type;
+        enum subpixel_scale_e
+        { 
+            subpixel_shift = 4, 
+            subpixel_scale = 1 << subpixel_shift
+        };
 
     private:
         //--------------------------------------------------------------------
@@ -49,36 +52,37 @@ namespace agg
         {
             void init(const coord_type& c1, const coord_type& c2)
             {
-                m_x1 = c1.x;
-                m_y1 = c1.y;
-                m_dx = c2.x - c1.x;
-                m_dy = 1.0 / (c2.y - c1.y);
-                m_r1 = c1.color.r;
-                m_g1 = c1.color.g;
-                m_b1 = c1.color.b;
-                m_a1 = c1.color.a;
-                m_dr = c2.color.r - m_r1;
-                m_dg = c2.color.g - m_g1;
-                m_db = c2.color.b - m_b1;
-                m_da = c2.color.a - m_a1;
-            }
-
-            void calc(int y)
-            {
-                double k = 0.0;
-                if(y > m_y1) k = (y - m_y1) * m_dy;
-                color_type rgba;
-                m_r = m_r1 + int(m_dr * k);
-                m_g = m_g1 + int(m_dg * k);
-                m_b = m_b1 + int(m_db * k);
-                m_a = m_a1 + int(m_da * k);
-                m_x = int(m_x1 + m_dx * k);
+                m_x1  = c1.x - 0.5; 
+                m_y1  = c1.y - 0.5;
+                m_dx  = c2.x - c1.x;
+                double dy = c2.y - c1.y;
+                m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy;
+                m_r1  = c1.color.r;
+                m_g1  = c1.color.g;
+                m_b1  = c1.color.b;
+                m_a1  = c1.color.a;
+                m_dr  = c2.color.r - m_r1;
+                m_dg  = c2.color.g - m_g1;
+                m_db  = c2.color.b - m_b1;
+                m_da  = c2.color.a - m_a1;
+            }
+
+            void calc(double y)
+            {
+                double k = (y - m_y1) * m_1dy;
+                if(k < 0.0) k = 0.0;
+                if(k > 1.0) k = 1.0;
+                m_r = m_r1 + iround(m_dr * k);
+                m_g = m_g1 + iround(m_dg * k);
+                m_b = m_b1 + iround(m_db * k);
+                m_a = m_a1 + iround(m_da * k);
+                m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
             }
 
             double m_x1;
             double m_y1;
             double m_dx;
-            double m_dy;
+            double m_1dy;
             int    m_r1;
             int    m_g1;
             int    m_b1;
@@ -97,33 +101,28 @@ namespace agg
     public:
 
         //--------------------------------------------------------------------
-        span_gouraud_rgba(alloc_type& alloc) : base_type(alloc) {}
-
-        //--------------------------------------------------------------------
-        span_gouraud_rgba(alloc_type& alloc, 
-                          const color_type& c1, 
+        span_gouraud_rgba() {}
+        span_gouraud_rgba(const color_type& c1, 
                           const color_type& c2, 
                           const color_type& c3,
                           double x1, double y1, 
                           double x2, double y2,
                           double x3, double y3, 
                           double d = 0) : 
-            base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
+            base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
         {}
 
         //--------------------------------------------------------------------
-        void prepare(unsigned max_span_len)
+        void prepare()
         {
-            base_type::prepare(max_span_len);
-
             coord_type coord[3];
-            arrange_vertices(coord);
+            base_type::arrange_vertices(coord);
 
             m_y2 = int(coord[1].y);
 
-            m_swap = calc_point_location(coord[0].x, coord[0].y, 
-                                         coord[2].x, coord[2].y,
-                                         coord[1].x, coord[1].y) < 0.0;
+            m_swap = cross_product(coord[0].x, coord[0].y, 
+                                   coord[2].x, coord[2].y,
+                                   coord[1].x, coord[1].y) < 0.0;
 
             m_rgba1.init(coord[0], coord[2]);
             m_rgba2.init(coord[0], coord[1]);
@@ -131,65 +130,137 @@ namespace agg
         }
 
         //--------------------------------------------------------------------
-        color_type* generate(int x, int y, unsigned len)
+        void generate(color_type* span, int x, int y, unsigned len)
         {
-            m_rgba1.calc(y);
+            m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
             const rgba_calc* pc1 = &m_rgba1;
             const rgba_calc* pc2 = &m_rgba2;
 
-            if(y < m_y2)
-            {
-                m_rgba2.calc(y+1);
+            if(y <= m_y2)
+            {          
+                // Bottom part of the triangle (first subtriangle)
+                //-------------------------
+                m_rgba2.calc(y + m_rgba2.m_1dy);
             }
             else
             {
-                m_rgba3.calc(y);
+                // Upper part (second subtriangle)
+                m_rgba3.calc(y - m_rgba3.m_1dy);
+                //-------------------------
                 pc2 = &m_rgba3;
             }
 
             if(m_swap)
             {
+                // It means that the triangle is oriented clockwise, 
+                // so that we need to swap the controlling structures
+                //-------------------------
                 const rgba_calc* t = pc2;
                 pc2 = pc1;
                 pc1 = t;
             }
 
-            int nx = pc1->m_x;
-            unsigned nlen = pc2->m_x - pc1->m_x + 1;
-
-            if(nlen < len) nlen = len;
+            // Get the horizontal length with subpixel accuracy
+            // and protect it from division by zero
+            //-------------------------
+            int nlen = abs(pc2->m_x - pc1->m_x);
+            if(nlen <= 0) nlen = 1;
 
             dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen);
             dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen);
             dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen);
             dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
 
-            if(nx < x)
+            // Calculate the starting point of the gradient with subpixel 
+            // accuracy and correct (roll back) the interpolators.
+            // This operation will also clip the beginning of the span
+            // if necessary.
+            //-------------------------
+            int start = pc1->m_x - (x << subpixel_shift);
+            r    -= start; 
+            g    -= start; 
+            b    -= start; 
+            a    -= start;
+            nlen += start;
+
+            int vr, vg, vb, va;
+            enum lim_e { lim = color_type::base_mask };
+
+            // Beginning part of the span. Since we rolled back the 
+            // interpolators, the color values may have overflow.
+            // So that, we render the beginning part with checking 
+            // for overflow. It lasts until "start" is positive;
+            // typically it's 1-2 pixels, but may be more in some cases.
+            //-------------------------
+            while(len && start > 0)
             {
-                unsigned d = unsigned(x - nx);
-                r += d; 
-                g += d; 
-                b += d; 
-                a += d;
+                vr = r.y();
+                vg = g.y();
+                vb = b.y();
+                va = a.y();
+                if(vr < 0) vr = 0; if(vr > lim) vr = lim;
+                if(vg < 0) vg = 0; if(vg > lim) vg = lim;
+                if(vb < 0) vb = 0; if(vb > lim) vb = lim;
+                if(va < 0) va = 0; if(va > lim) va = lim;
+                span->r = (value_type)vr;
+                span->g = (value_type)vg;
+                span->b = (value_type)vb;
+                span->a = (value_type)va;
+                r     += subpixel_scale; 
+                g     += subpixel_scale; 
+                b     += subpixel_scale; 
+                a     += subpixel_scale;
+                nlen  -= subpixel_scale;
+                start -= subpixel_scale;
+                ++span;
+                --len;
             }
 
-            color_type* span = base_type::allocator().span();
-            do
+            // Middle part, no checking for overflow.
+            // Actual spans can be longer than the calculated length
+            // because of anti-aliasing, thus, the interpolators can 
+            // overflow. But while "nlen" is positive we are safe.
+            //-------------------------
+            while(len && nlen > 0)
             {
                 span->r = (value_type)r.y();
                 span->g = (value_type)g.y();
                 span->b = (value_type)b.y();
                 span->a = (value_type)a.y();
-                ++r; 
-                ++g; 
-                ++b; 
-                ++a;
+                r    += subpixel_scale; 
+                g    += subpixel_scale; 
+                b    += subpixel_scale; 
+                a    += subpixel_scale;
+                nlen -= subpixel_scale;
                 ++span;
+                --len;
             }
-            while(--len);
-            return base_type::allocator().span();
-        }
 
+            // Ending part; checking for overflow.
+            // Typically it's 1-2 pixels, but may be more in some cases.
+            //-------------------------
+            while(len)
+            {
+                vr = r.y();
+                vg = g.y();
+                vb = b.y();
+                va = a.y();
+                if(vr < 0) vr = 0; if(vr > lim) vr = lim;
+                if(vg < 0) vg = 0; if(vg > lim) vg = lim;
+                if(vb < 0) vb = 0; if(vb > lim) vb = lim;
+                if(va < 0) va = 0; if(va > lim) va = lim;
+                span->r = (value_type)vr;
+                span->g = (value_type)vg;
+                span->b = (value_type)vb;
+                span->a = (value_type)va;
+                r += subpixel_scale; 
+                g += subpixel_scale; 
+                b += subpixel_scale; 
+                a += subpixel_scale;
+                ++span;
+                --len;
+            }
+        }
 
     private:
         bool      m_swap;

Modified: incubator/ooo/trunk/main/agg/inc/agg_span_gradient.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_span_gradient.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_span_gradient.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_span_gradient.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
 //----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 //
 // Permission to copy, use, modify, sell and distribute this software 
@@ -20,7 +20,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include "agg_basics.h"
-#include "agg_span_generator.h"
 #include "agg_math.h"
 #include "agg_array.h"
 
@@ -28,11 +27,11 @@
 namespace agg
 {
 
-    enum
+    enum gradient_subpixel_scale_e
     {
         gradient_subpixel_shift = 4,                              //-----gradient_subpixel_shift
-        gradient_subpixel_size  = 1 << gradient_subpixel_shift,   //-----gradient_subpixel_size
-        gradient_subpixel_mask  = gradient_subpixel_size - 1      //-----gradient_subpixel_mask
+        gradient_subpixel_scale = 1 << gradient_subpixel_shift,   //-----gradient_subpixel_scale
+        gradient_subpixel_mask  = gradient_subpixel_scale - 1     //-----gradient_subpixel_mask
     };
 
 
@@ -41,57 +40,54 @@ namespace agg
     template<class ColorT,
              class Interpolator,
              class GradientF, 
-             class ColorF,
-             class Allocator = span_allocator<ColorT> >
-    class span_gradient : public span_generator<ColorT, Allocator>
+             class ColorF>
+    class span_gradient
     {
     public:
         typedef Interpolator interpolator_type;
-        typedef Allocator alloc_type;
         typedef ColorT color_type;
-        typedef span_generator<color_type, alloc_type> base_type;
 
-        enum
+        enum downscale_shift_e
         {
             downscale_shift = interpolator_type::subpixel_shift - 
                               gradient_subpixel_shift
         };
 
         //--------------------------------------------------------------------
-        span_gradient(alloc_type& alloc) : base_type(alloc) {}
+        span_gradient() {}
 
         //--------------------------------------------------------------------
-        span_gradient(alloc_type& alloc,
-                      interpolator_type& inter,
-                      const GradientF& gradient_function_,
-                      const ColorF& color_function_,
-                      double d1_, double d2_) : 
-            base_type(alloc),
+        span_gradient(interpolator_type& inter,
+                      const GradientF& gradient_function,
+                      const ColorF& color_function,
+                      double d1, double d2) : 
             m_interpolator(&inter),
-            m_gradient_function(&gradient_function_),
-            m_color_function(&color_function_),
-            m_d1(int(d1_ * gradient_subpixel_size)),
-            m_d2(int(d2_ * gradient_subpixel_size))
+            m_gradient_function(&gradient_function),
+            m_color_function(&color_function),
+            m_d1(iround(d1 * gradient_subpixel_scale)),
+            m_d2(iround(d2 * gradient_subpixel_scale))
         {}
 
         //--------------------------------------------------------------------
         interpolator_type& interpolator() { return *m_interpolator; }
         const GradientF& gradient_function() const { return *m_gradient_function; }
         const ColorF& color_function() const { return *m_color_function; }
-        double d1() const { return double(m_d1) / gradient_subpixel_size; }
-        double d2() const { return double(m_d2) / gradient_subpixel_size; }
+        double d1() const { return double(m_d1) / gradient_subpixel_scale; }
+        double d2() const { return double(m_d2) / gradient_subpixel_scale; }
 
         //--------------------------------------------------------------------
         void interpolator(interpolator_type& i) { m_interpolator = &i; }
         void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
         void color_function(const ColorF& cf) { m_color_function = &cf; }
-        void d1(double v) { m_d1 = int(v * gradient_subpixel_size); }
-        void d2(double v) { m_d2 = int(v * gradient_subpixel_size); }
+        void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
+        void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
 
         //--------------------------------------------------------------------
-        color_type* generate(int x, int y, unsigned len)
+        void prepare() {}
+
+        //--------------------------------------------------------------------
+        void generate(color_type* span, int x, int y, unsigned len)
         {   
-            color_type* span = base_type::allocator().span();
             int dd = m_d2 - m_d1;
             if(dd < 1) dd = 1;
             m_interpolator->begin(x+0.5, y+0.5, len);
@@ -99,7 +95,7 @@ namespace agg
             {
                 m_interpolator->coordinates(&x, &y);
                 int d = m_gradient_function->calculate(x >> downscale_shift, 
-                                                       y >> downscale_shift, dd);
+                                                       y >> downscale_shift, m_d2);
                 d = ((d - m_d1) * (int)m_color_function->size()) / dd;
                 if(d < 0) d = 0;
                 if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1;
@@ -107,7 +103,6 @@ namespace agg
                 ++(*m_interpolator);
             }
             while(--len);
-            return base_type::allocator().span();
         }
 
     private:
@@ -151,6 +146,10 @@ namespace agg
     };
 
 
+
+
+
+
     //==========================================================gradient_circle
     class gradient_circle
     {
@@ -173,36 +172,34 @@ namespace agg
         }
     };
 
-
     //========================================================gradient_radial_d
     class gradient_radial_d
     {
     public:
         static AGG_INLINE int calculate(int x, int y, int)
         {
-            return int(sqrt(double(x)*double(x) + double(y)*double(y)));
+            return uround(sqrt(double(x)*double(x) + double(y)*double(y)));
         }
     };
 
-
     //====================================================gradient_radial_focus
     class gradient_radial_focus
     {
     public:
         //---------------------------------------------------------------------
         gradient_radial_focus() : 
-            m_radius(100 * gradient_subpixel_size), 
-            m_focus_x(0), 
-            m_focus_y(0)
+            m_r(100 * gradient_subpixel_scale), 
+            m_fx(0), 
+            m_fy(0)
         {
             update_values();
         }
 
         //---------------------------------------------------------------------
         gradient_radial_focus(double r, double fx, double fy) : 
-            m_radius (int(r  * gradient_subpixel_size)), 
-            m_focus_x(int(fx * gradient_subpixel_size)), 
-            m_focus_y(int(fy * gradient_subpixel_size))
+            m_r (iround(r  * gradient_subpixel_scale)), 
+            m_fx(iround(fx * gradient_subpixel_scale)), 
+            m_fy(iround(fy * gradient_subpixel_scale))
         {
             update_values();
         }
@@ -210,111 +207,62 @@ namespace agg
         //---------------------------------------------------------------------
         void init(double r, double fx, double fy)
         {
-            m_radius  = int(r  * gradient_subpixel_size);
-            m_focus_x = int(fx * gradient_subpixel_size);
-            m_focus_y = int(fy * gradient_subpixel_size);
+            m_r  = iround(r  * gradient_subpixel_scale);
+            m_fx = iround(fx * gradient_subpixel_scale);
+            m_fy = iround(fy * gradient_subpixel_scale);
             update_values();
         }
 
         //---------------------------------------------------------------------
-        double radius()  const { return double(m_radius)  / gradient_subpixel_size; }
-        double focus_x() const { return double(m_focus_x) / gradient_subpixel_size; }
-        double focus_y() const { return double(m_focus_y) / gradient_subpixel_size; }
+        double radius()  const { return double(m_r)  / gradient_subpixel_scale; }
+        double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
+        double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
 
         //---------------------------------------------------------------------
-        int calculate(int x, int y, int d) const
+        int calculate(int x, int y, int) const
         {
-            double solution_x;
-            double solution_y;
-
-            // Special case to avoid divide by zero or very near zero
-            //---------------------------------
-            if(x == int(m_focus_x))
-            {		   
-                solution_x = m_focus_x;
-                solution_y = 0.0;
-                solution_y += (y > m_focus_y) ? m_trivial : -m_trivial;
-            }
-            else 
-            {    
-                // Slope of the focus-current line
-                //-------------------------------
-                double slope = double(y - m_focus_y) / double(x - m_focus_x);
-
-                // y-intercept of that same line
-                //--------------------------------
-                double yint  = double(y) - (slope * x); 
-		
-                // Use the classical quadratic formula to calculate 
-                // the intersection point		  
-                //--------------------------------
-                double a = (slope * slope) + 1; 
-                double b =  2 * slope * yint;
-                double c =  yint * yint - m_radius2;
-                double det = sqrt((b * b) - (4.0 * a * c));
-		        solution_x = -b;
-		
-                // Choose the positive or negative root depending
-                // on where the X coord lies with respect to the focus.
-                solution_x += (x < m_focus_x) ? -det : det;
-		        solution_x /= 2.0 * a;
-
-                // Calculating of Y is trivial
-                solution_y  = (slope * solution_x) + yint;
-            }	                    	
-
-            // Calculate the percentage (0...1) of the current point along the 
-            // focus-circumference line and return the normalized (0...d) value
-            //-------------------------------
-            solution_x -= double(m_focus_x);
-            solution_y -= double(m_focus_y);
-            double int_to_focus = solution_x * solution_x + solution_y * solution_y;
-            double cur_to_focus = double(x - m_focus_x) * double(x - m_focus_x) +
-                                  double(y - m_focus_y) * double(y - m_focus_y);
-
-            return int(sqrt(cur_to_focus / int_to_focus) * d);
+            double dx = x - m_fx;
+            double dy = y - m_fy;
+            double d2 = dx * m_fy - dy * m_fx;
+            double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
+            return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul);
         }
 
     private:
         //---------------------------------------------------------------------
         void update_values()
         {
-            // For use in the quadractic equation
-            //-------------------------------
-            m_radius2 = double(m_radius) * double(m_radius);
-
-            double dist = sqrt(double(m_focus_x) * double(m_focus_x) + 
-                               double(m_focus_y) * double(m_focus_y));
-
-            // Test if distance from focus to center is greater than the radius
-            // For the sake of assurance factor restrict the point to be 
-            // no further than 99% of the radius.
-            //-------------------------------
-            double r = m_radius * 0.99;
-            if(dist > r) 
-            { 
-                // clamp focus to radius
-                // x = r cos theta, y = r sin theta
-                //------------------------
-                double a = atan2(double(m_focus_y), double(m_focus_x));
-                m_focus_x = int(r * cos(a));
-                m_focus_y = int(r * sin(a));
+            // Calculate the invariant values. In case the focal center
+            // lies exactly on the gradient circle the divisor degenerates
+            // into zero. In this case we just move the focal center by
+            // one subpixel unit possibly in the direction to the origin (0,0)
+            // and calculate the values again.
+            //-------------------------
+            m_r2  = double(m_r)  * double(m_r);
+            m_fx2 = double(m_fx) * double(m_fx);
+            m_fy2 = double(m_fy) * double(m_fy);
+            double d = (m_r2 - (m_fx2 + m_fy2));
+            if(d == 0)
+            {
+                if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; }
+                if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; }
+                m_fx2 = double(m_fx) * double(m_fx);
+                m_fy2 = double(m_fy) * double(m_fy);
+                d = (m_r2 - (m_fx2 + m_fy2));
             }
-
-            // Calculate the solution to be used in the case where x == focus_x
-            //------------------------------
-            m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x));
+            m_mul = m_r / d;
         }
 
-        int m_radius;
-        int m_focus_x;
-        int m_focus_y;
-        double m_radius2;
-        double m_trivial;
+        int    m_r;
+        int    m_fx;
+        int    m_fy;
+        double m_r2;
+        double m_fx2;
+        double m_fy2;
+        double m_mul;
     };
 
 
-
     //==============================================================gradient_x
     class gradient_x
     {
@@ -330,7 +278,6 @@ namespace agg
         static int calculate(int, int y, int) { return y; }
     };
 
-
     //========================================================gradient_diamond
     class gradient_diamond
     {
@@ -343,7 +290,6 @@ namespace agg
         }
     };
 
-
     //=============================================================gradient_xy
     class gradient_xy
     {
@@ -354,7 +300,6 @@ namespace agg
         }
     };
 
-
     //========================================================gradient_sqrt_xy
     class gradient_sqrt_xy
     {
@@ -365,18 +310,16 @@ namespace agg
         }
     };
 
-
     //==========================================================gradient_conic
     class gradient_conic
     {
     public:
         static AGG_INLINE int calculate(int x, int y, int d) 
         { 
-            return int(fabs(atan2(double(y), double(x))) * double(d) / pi);
+            return uround(fabs(atan2(double(y), double(x))) * double(d) / pi);
         }
     };
 
-
     //=================================================gradient_repeat_adaptor
     template<class GradientF> class gradient_repeat_adaptor
     {
@@ -395,7 +338,6 @@ namespace agg
         const GradientF* m_gradient;
     };
 
-
     //================================================gradient_reflect_adaptor
     template<class GradientF> class gradient_reflect_adaptor
     {

Modified: incubator/ooo/trunk/main/agg/inc/agg_span_gradient_alpha.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_span_gradient_alpha.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_span_gradient_alpha.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_span_gradient_alpha.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
 //----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 //
 // Permission to copy, use, modify, sell and distribute this software 
@@ -32,7 +32,7 @@ namespace agg
         typedef ColorT color_type;
         typedef typename color_type::value_type alpha_type;
 
-        enum
+        enum downscale_shift_e
         {
             downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift
         };
@@ -49,26 +49,29 @@ namespace agg
             m_interpolator(&inter),
             m_gradient_function(&gradient_function),
             m_alpha_function(&alpha_function),
-            m_d1(int(d1 * gradient_subpixel_size)),
-            m_d2(int(d2 * gradient_subpixel_size))
+            m_d1(iround(d1 * gradient_subpixel_scale)),
+            m_d2(iround(d2 * gradient_subpixel_scale))
         {}
 
         //--------------------------------------------------------------------
         interpolator_type& interpolator() { return *m_interpolator; }
         const GradientF& gradient_function() const { return *m_gradient_function; }
         const AlphaF& alpha_function() const { return *m_alpha_function; }
-        double d1() const { return double(m_d1) / gradient_subpixel_size; }
-        double d2() const { return double(m_d2) / gradient_subpixel_size; }
+        double d1() const { return double(m_d1) / gradient_subpixel_scale; }
+        double d2() const { return double(m_d2) / gradient_subpixel_scale; }
 
         //--------------------------------------------------------------------
         void interpolator(interpolator_type& i) { m_interpolator = &i; }
         void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
         void alpha_function(const AlphaF& af) { m_alpha_function = &af; }
-        void d1(double v) { m_d1 = int(v * gradient_subpixel_size); }
-        void d2(double v) { m_d2 = int(v * gradient_subpixel_size); }
+        void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
+        void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
 
         //--------------------------------------------------------------------
-        void convert(color_type* span, int x, int y, unsigned len)
+        void prepare() {}
+
+        //--------------------------------------------------------------------
+        void generate(color_type* span, int x, int y, unsigned len)
         {   
             int dd = m_d2 - m_d1;
             if(dd < 1) dd = 1;
@@ -77,7 +80,7 @@ namespace agg
             {
                 m_interpolator->coordinates(&x, &y);
                 int d = m_gradient_function->calculate(x >> downscale_shift, 
-                                                       y >> downscale_shift, dd);
+                                                       y >> downscale_shift, m_d2);
                 d = ((d - m_d1) * (int)m_alpha_function->size()) / dd;
                 if(d < 0) d = 0;
                 if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1;

Modified: incubator/ooo/trunk/main/agg/inc/agg_span_image_filter.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_span_image_filter.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_span_image_filter.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_span_image_filter.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
 //----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 //
 // Permission to copy, use, modify, sell and distribute this software 
@@ -21,81 +21,63 @@
 
 #include "agg_basics.h"
 #include "agg_image_filters.h"
-#include "agg_rendering_buffer.h"
-#include "agg_span_generator.h"
-
+#include "agg_span_interpolator_linear.h"
 
 namespace agg
 {
 
-    //--------------------------------------------------span_image_filter
-    template<class ColorT, class Interpolator, class Allocator> 
-    class span_image_filter : public span_generator<ColorT, Allocator>
+    //-------------------------------------------------------span_image_filter
+    template<class Source, class Interpolator> class span_image_filter
     {
     public:
-        typedef ColorT color_type;
-        typedef Allocator alloc_type;
+        typedef Source source_type;
         typedef Interpolator interpolator_type;
-        typedef span_generator<color_type, alloc_type> base_type;
-
-        //----------------------------------------------------------------
-        span_image_filter(alloc_type& alloc) : 
-            span_generator<color_type, alloc_type>(alloc) 
-        {}
 
-        //----------------------------------------------------------------
-        span_image_filter(alloc_type& alloc,
-                          const rendering_buffer& src, 
-                          const color_type& back_color,
-                          interpolator_type& interpolator_,
-                          const image_filter_lut* filter_) : 
-            span_generator<color_type, alloc_type>(alloc),
+        //--------------------------------------------------------------------
+        span_image_filter() {}
+        span_image_filter(source_type& src, 
+                          interpolator_type& interpolator,
+                          const image_filter_lut* filter) : 
             m_src(&src),
-            m_back_color(back_color),
-            m_interpolator(&interpolator_),
-            m_filter(filter_),
+            m_interpolator(&interpolator),
+            m_filter(filter),
             m_dx_dbl(0.5),
             m_dy_dbl(0.5),
-            m_dx_int(image_subpixel_size / 2),
-            m_dy_int(image_subpixel_size / 2)
+            m_dx_int(image_subpixel_scale / 2),
+            m_dy_int(image_subpixel_scale / 2)
         {}
+        void attach(source_type& v) { m_src = &v; }
 
-        //----------------------------------------------------------------
-        const  rendering_buffer& source_image() const { return *m_src; }
-        const  color_type& background_color()   const { return m_back_color; }
-        const  image_filter_lut& filter()       const { return *m_filter; }
-        int    filter_dx_int()                  const { return m_dx_int; }
-        int    filter_dy_int()                  const { return m_dy_int; }
-        double filter_dx_dbl()                  const { return m_dx_dbl; }
-        double filter_dy_dbl()                  const { return m_dy_dbl; }
-
-        //----------------------------------------------------------------
-        void source_image(const rendering_buffer& v) { m_src = &v; }
-        void background_color(const color_type& v)   { m_back_color = v; }
-        void interpolator(interpolator_type& v)      { m_interpolator = &v; }
-        void filter(const image_filter_lut& v)       { m_filter = &v; }
+        //--------------------------------------------------------------------
+               source_type& source()            { return *m_src; }
+        const  source_type& source()      const { return *m_src; }
+        const  image_filter_lut& filter() const { return *m_filter; }
+        int    filter_dx_int()            const { return m_dx_int; }
+        int    filter_dy_int()            const { return m_dy_int; }
+        double filter_dx_dbl()            const { return m_dx_dbl; }
+        double filter_dy_dbl()            const { return m_dy_dbl; }
+
+        //--------------------------------------------------------------------
+        void interpolator(interpolator_type& v)  { m_interpolator = &v; }
+        void filter(const image_filter_lut& v)   { m_filter = &v; }
         void filter_offset(double dx, double dy)
         {
             m_dx_dbl = dx;
             m_dy_dbl = dy;
-            m_dx_int = int(dx * image_subpixel_size);
-            m_dy_int = int(dy * image_subpixel_size);
+            m_dx_int = iround(dx * image_subpixel_scale);
+            m_dy_int = iround(dy * image_subpixel_scale);
         }
         void filter_offset(double d) { filter_offset(d, d); }
 
-        //----------------------------------------------------------------
+        //--------------------------------------------------------------------
         interpolator_type& interpolator() { return *m_interpolator; }
 
         //--------------------------------------------------------------------
-        void prepare(unsigned max_span_len) 
-        {
-            base_type::prepare(max_span_len);
-        }
+        void prepare() {}
 
-        //----------------------------------------------------------------
+        //--------------------------------------------------------------------
     private:
-        const rendering_buffer* m_src;
-        color_type              m_back_color;
+        source_type*            m_src;
         interpolator_type*      m_interpolator;
         const image_filter_lut* m_filter;
         double   m_dx_dbl;
@@ -105,6 +87,160 @@ namespace agg
     };
 
 
+
+
+    //==============================================span_image_resample_affine
+    template<class Source> 
+    class span_image_resample_affine : 
+    public span_image_filter<Source, span_interpolator_linear<trans_affine> >
+    {
+    public:
+        typedef Source source_type;
+        typedef span_interpolator_linear<trans_affine> interpolator_type;
+        typedef span_image_filter<source_type, interpolator_type> base_type;
+
+        //--------------------------------------------------------------------
+        span_image_resample_affine() : 
+            m_scale_limit(200.0),
+            m_blur_x(1.0),
+            m_blur_y(1.0)
+        {}
+
+        //--------------------------------------------------------------------
+        span_image_resample_affine(source_type& src, 
+                                   interpolator_type& inter,
+                                   const image_filter_lut& filter) :
+            base_type(src, inter, &filter),
+            m_scale_limit(200.0),
+            m_blur_x(1.0),
+            m_blur_y(1.0)
+        {}
+
+
+        //--------------------------------------------------------------------
+        int  scale_limit() const { return uround(m_scale_limit); }
+        void scale_limit(int v)  { m_scale_limit = v; }
+
+        //--------------------------------------------------------------------
+        double blur_x() const { return m_blur_x; }
+        double blur_y() const { return m_blur_y; }
+        void blur_x(double v) { m_blur_x = v; }
+        void blur_y(double v) { m_blur_y = v; }
+        void blur(double v) { m_blur_x = m_blur_y = v; }
+
+        //--------------------------------------------------------------------
+        void prepare() 
+        {
+            double scale_x;
+            double scale_y;
+
+            base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
+
+            if(scale_x * scale_y > m_scale_limit)
+            {
+                scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
+                scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
+            }
+
+            if(scale_x < 1) scale_x = 1;
+            if(scale_y < 1) scale_y = 1;
+
+            if(scale_x > m_scale_limit) scale_x = m_scale_limit;
+            if(scale_y > m_scale_limit) scale_y = m_scale_limit;
+
+            scale_x *= m_blur_x;
+            scale_y *= m_blur_y;
+
+            if(scale_x < 1) scale_x = 1;
+            if(scale_y < 1) scale_y = 1;
+
+            m_rx     = uround(    scale_x * double(image_subpixel_scale));
+            m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale));
+
+            m_ry     = uround(    scale_y * double(image_subpixel_scale));
+            m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
+        }
+
+    protected:
+        int m_rx;
+        int m_ry;
+        int m_rx_inv;
+        int m_ry_inv;
+
+    private:
+        double m_scale_limit;
+        double m_blur_x;
+        double m_blur_y;
+    };
+
+
+
+    //=====================================================span_image_resample
+    template<class Source, class Interpolator> 
+    class span_image_resample : 
+    public span_image_filter<Source, Interpolator>
+    {
+    public:
+        typedef Source source_type;
+        typedef Interpolator interpolator_type;
+        typedef span_image_filter<source_type, interpolator_type> base_type;
+
+        //--------------------------------------------------------------------
+        span_image_resample() : 
+            m_scale_limit(20),
+            m_blur_x(image_subpixel_scale),
+            m_blur_y(image_subpixel_scale)
+        {}
+
+        //--------------------------------------------------------------------
+        span_image_resample(source_type& src, 
+                            interpolator_type& inter,
+                            const image_filter_lut& filter) :
+            base_type(src, inter, &filter),
+            m_scale_limit(20),
+            m_blur_x(image_subpixel_scale),
+            m_blur_y(image_subpixel_scale)
+        {}
+
+        //--------------------------------------------------------------------
+        int  scale_limit() const { return m_scale_limit; }
+        void scale_limit(int v)  { m_scale_limit = v; }
+
+        //--------------------------------------------------------------------
+        double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); }
+        double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); }
+        void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); }
+        void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); }
+        void blur(double v)   { m_blur_x = 
+                                m_blur_y = uround(v * double(image_subpixel_scale)); }
+
+    protected:
+        AGG_INLINE void adjust_scale(int* rx, int* ry)
+        {
+            if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
+            if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
+            if(*rx > image_subpixel_scale * m_scale_limit) 
+            {
+                *rx = image_subpixel_scale * m_scale_limit;
+            }
+            if(*ry > image_subpixel_scale * m_scale_limit) 
+            {
+                *ry = image_subpixel_scale * m_scale_limit;
+            }
+            *rx = (*rx * m_blur_x) >> image_subpixel_shift;
+            *ry = (*ry * m_blur_y) >> image_subpixel_shift;
+            if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
+            if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
+        }
+
+        int m_scale_limit;
+        int m_blur_x;
+        int m_blur_y;
+    };
+
+
+
+
 }
 
 #endif

Modified: incubator/ooo/trunk/main/agg/inc/agg_span_image_filter_gray.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_span_image_filter_gray.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_span_image_filter_gray.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_span_image_filter_gray.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
 //----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
 //
 // Permission to copy, use, modify, sell and distribute this software 
@@ -20,7 +20,6 @@
 // PostScript and PDF technology for software developers.
 // 
 //----------------------------------------------------------------------------
-
 #ifndef AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED
 #define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED
 
@@ -32,132 +31,168 @@
 namespace agg
 {
 
-
     //==============================================span_image_filter_gray_nn
-    template<class ColorT,
-             class Interpolator,
-             class Allocator = span_allocator<ColorT> > 
+    template<class Source, class Interpolator> 
     class span_image_filter_gray_nn : 
-    public span_image_filter<ColorT, Interpolator, Allocator>
+    public span_image_filter<Source, Interpolator>
     {
     public:
-        typedef ColorT color_type;
+        typedef Source source_type;
+        typedef typename source_type::color_type color_type;
         typedef Interpolator interpolator_type;
-        typedef Allocator alloc_type;
-        typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type;
+        typedef span_image_filter<source_type, interpolator_type> base_type;
         typedef typename color_type::value_type value_type;
         typedef typename color_type::calc_type calc_type;
-        enum
+        enum base_scale_e
         {
             base_shift = color_type::base_shift,
             base_mask  = color_type::base_mask
         };
 
         //--------------------------------------------------------------------
-        span_image_filter_gray_nn(alloc_type& alloc) : base_type(alloc) {}
-
-        //--------------------------------------------------------------------
-        span_image_filter_gray_nn(alloc_type& alloc,
-                                  const rendering_buffer& src, 
-                                  const color_type& back_color,
+        span_image_filter_gray_nn() {}
+        span_image_filter_gray_nn(source_type& src, 
                                   interpolator_type& inter) :
-            base_type(alloc, src, back_color, inter, 0) 
+            base_type(src, inter, 0) 
         {}
 
         //--------------------------------------------------------------------
-        color_type* generate(int x, int y, unsigned len)
+        void generate(color_type* span, int x, int y, unsigned len)
         {
             base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 
                                             y + base_type::filter_dy_dbl(), len);
+            do
+            {
+                base_type::interpolator().coordinates(&x, &y);
+                span->v = *(const value_type*)
+                    base_type::source().span(x >> image_subpixel_shift, 
+                                             y >> image_subpixel_shift, 
+                                             1);
+                span->a = base_mask;
+                ++span;
+                ++base_type::interpolator();
+            } while(--len);
+        }
+    };
 
-            calc_type fg;
-            calc_type src_alpha;
 
-            color_type* span = base_type::allocator().span();
 
-            int maxx = base_type::source_image().width() - 1;
-            int maxy = base_type::source_image().height() - 1;
+    //=========================================span_image_filter_gray_bilinear
+    template<class Source, class Interpolator> 
+    class span_image_filter_gray_bilinear : 
+    public span_image_filter<Source, Interpolator>
+    {
+    public:
+        typedef Source source_type;
+        typedef typename source_type::color_type color_type;
+        typedef Interpolator interpolator_type;
+        typedef span_image_filter<source_type, interpolator_type> base_type;
+        typedef typename color_type::value_type value_type;
+        typedef typename color_type::calc_type calc_type;
+        enum base_scale_e
+        {
+            base_shift = color_type::base_shift,
+            base_mask  = color_type::base_mask
+        };
+
+        //--------------------------------------------------------------------
+        span_image_filter_gray_bilinear() {}
+        span_image_filter_gray_bilinear(source_type& src, 
+                                        interpolator_type& inter) :
+            base_type(src, inter, 0) 
+        {}
+
 
+        //--------------------------------------------------------------------
+        void generate(color_type* span, int x, int y, unsigned len)
+        {
+            base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 
+                                            y + base_type::filter_dy_dbl(), len);
+            calc_type fg;
+            const value_type *fg_ptr;
             do
             {
-                base_type::interpolator().coordinates(&x, &y);
+                int x_hr;
+                int y_hr;
 
-                x >>= image_subpixel_shift;
-                y >>= image_subpixel_shift;
+                base_type::interpolator().coordinates(&x_hr, &y_hr);
 
-                if(x >= 0    && y >= 0 &&
-                   x <= maxx && y <= maxy) 
-                {
-                    fg = *((const value_type*)base_type::source_image().row(y) + x);
-                    src_alpha = base_mask;
-                }
-                else
-                {
-                    fg = base_type::background_color().v;
-                    src_alpha = base_type::background_color().a;
-                }
+                x_hr -= base_type::filter_dx_int();
+                y_hr -= base_type::filter_dy_int();
 
-                span->v = (value_type)fg;
-                span->a = (value_type)src_alpha;
+                int x_lr = x_hr >> image_subpixel_shift;
+                int y_lr = y_hr >> image_subpixel_shift;
+
+                fg = image_subpixel_scale * image_subpixel_scale / 2;
+
+                x_hr &= image_subpixel_mask;
+                y_hr &= image_subpixel_mask;
+
+                fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
+                fg    += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr);
+
+                fg_ptr = (const value_type*)base_type::source().next_x();
+                fg    += *fg_ptr * x_hr * (image_subpixel_scale - y_hr);
+
+                fg_ptr = (const value_type*)base_type::source().next_y();
+                fg    += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr;
+
+                fg_ptr = (const value_type*)base_type::source().next_x();
+                fg    += *fg_ptr * x_hr * y_hr;
+
+                span->v = value_type(fg >> (image_subpixel_shift * 2));
+                span->a = base_mask;
                 ++span;
                 ++base_type::interpolator();
 
             } while(--len);
-
-            return base_type::allocator().span();
         }
     };
 
 
-
-
-    //========================================span_image_filter_gray_bilinear
-    template<class ColorT,
-             class Interpolator, 
-             class Allocator = span_allocator<ColorT> > 
-    class span_image_filter_gray_bilinear : 
-    public span_image_filter<ColorT, Interpolator, Allocator>
+    //====================================span_image_filter_gray_bilinear_clip
+    template<class Source, class Interpolator> 
+    class span_image_filter_gray_bilinear_clip : 
+    public span_image_filter<Source, Interpolator>
     {
     public:
-        typedef ColorT color_type;
+        typedef Source source_type;
+        typedef typename source_type::color_type color_type;
         typedef Interpolator interpolator_type;
-        typedef Allocator alloc_type;
-        typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type;
+        typedef span_image_filter<source_type, interpolator_type> base_type;
         typedef typename color_type::value_type value_type;
         typedef typename color_type::calc_type calc_type;
-        enum
+        enum base_scale_e
         {
             base_shift = color_type::base_shift,
             base_mask  = color_type::base_mask
         };
 
         //--------------------------------------------------------------------
-        span_image_filter_gray_bilinear(alloc_type& alloc) : base_type(alloc) {}
-
-        //--------------------------------------------------------------------
-        span_image_filter_gray_bilinear(alloc_type& alloc,
-                                        const rendering_buffer& src, 
-                                        const color_type& back_color,
-                                        interpolator_type& inter) :
-            base_type(alloc, src, back_color, inter, 0) 
+        span_image_filter_gray_bilinear_clip() {}
+        span_image_filter_gray_bilinear_clip(source_type& src, 
+                                             const color_type& back_color,
+                                             interpolator_type& inter) :
+            base_type(src, inter, 0), 
+            m_back_color(back_color)
         {}
+        const color_type& background_color() const { return m_back_color; }
+        void background_color(const color_type& v)   { m_back_color = v; }
 
         //--------------------------------------------------------------------
-        color_type* generate(int x, int y, unsigned len)
+        void generate(color_type* span, int x, int y, unsigned len)
         {
             base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 
                                             y + base_type::filter_dy_dbl(), len);
             calc_type fg;
             calc_type src_alpha;
-            value_type back_v = base_type::background_color().v;
-            value_type back_a = base_type::background_color().a;
+            value_type back_v = m_back_color.v;
+            value_type back_a = m_back_color.a;
 
             const value_type *fg_ptr;
 
-            color_type* span = base_type::allocator().span();
-
-            int maxx = base_type::source_image().width() - 1;
-            int maxy = base_type::source_image().height() - 1;
+            int maxx = base_type::source().width() - 1;
+            int maxy = base_type::source().height() - 1;
 
             do
             {
@@ -175,18 +210,19 @@ namespace agg
                 if(x_lr >= 0    && y_lr >= 0 &&
                    x_lr <  maxx && y_lr <  maxy) 
                 {
-                    fg = image_subpixel_size * image_subpixel_size / 2;
+                    fg = image_subpixel_scale * image_subpixel_scale / 2;
 
                     x_hr &= image_subpixel_mask;
                     y_hr &= image_subpixel_mask;
-                    fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr;
+                    fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr;
 
-                    fg += *fg_ptr++ * (image_subpixel_size - x_hr) * (image_subpixel_size - y_hr);
-                    fg += *fg_ptr++ * (image_subpixel_size - y_hr) * x_hr;
+                    fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr);
+                    fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr;
 
-                    fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 2);
+                    ++y_lr;
+                    fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr;
 
-                    fg += *fg_ptr++ * (image_subpixel_size - x_hr) * y_hr;
+                    fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr;
                     fg += *fg_ptr++ * x_hr * y_hr;
 
                     fg >>= image_subpixel_shift * 2;
@@ -204,17 +240,18 @@ namespace agg
                     else
                     {
                         fg = 
-                        src_alpha = image_subpixel_size * image_subpixel_size / 2;
+                        src_alpha = image_subpixel_scale * image_subpixel_scale / 2;
 
                         x_hr &= image_subpixel_mask;
                         y_hr &= image_subpixel_mask;
 
-                        weight = (image_subpixel_size - x_hr) * 
-                                 (image_subpixel_size - y_hr);
+                        weight = (image_subpixel_scale - x_hr) * 
+                                 (image_subpixel_scale - y_hr);
                         if(x_lr >= 0    && y_lr >= 0 &&
                            x_lr <= maxx && y_lr <= maxy)
                         {
-                            fg        += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr);
+                            fg += weight * 
+                                *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
                             src_alpha += weight * base_mask;
                         }
                         else
@@ -225,11 +262,12 @@ namespace agg
 
                         x_lr++;
 
-                        weight = x_hr * (image_subpixel_size - y_hr);
+                        weight = x_hr * (image_subpixel_scale - y_hr);
                         if(x_lr >= 0    && y_lr >= 0 &&
                            x_lr <= maxx && y_lr <= maxy)
                         {
-                            fg        += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr);
+                            fg += weight * 
+                                *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
                             src_alpha += weight * base_mask;
                         }
                         else
@@ -241,11 +279,12 @@ namespace agg
                         x_lr--;
                         y_lr++;
 
-                        weight = (image_subpixel_size - x_hr) * y_hr;
+                        weight = (image_subpixel_scale - x_hr) * y_hr;
                         if(x_lr >= 0    && y_lr >= 0 &&
                            x_lr <= maxx && y_lr <= maxy)
                         {
-                            fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr);
+                            fg += weight * 
+                                *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
                             src_alpha += weight * base_mask;
                         }
                         else
@@ -260,7 +299,8 @@ namespace agg
                         if(x_lr >= 0    && y_lr >= 0 &&
                            x_lr <= maxx && y_lr <= maxy)
                         {
-                            fg        += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr);
+                            fg += weight * 
+                                *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr);
                             src_alpha += weight * base_mask;
                         }
                         else
@@ -280,74 +320,57 @@ namespace agg
                 ++base_type::interpolator();
 
             } while(--len);
-
-            return base_type::allocator().span();
         }
+    private:
+        color_type m_back_color;
     };
 
 
 
-
-
-
-
-    //========================================span_image_filter_gray_2x2
-    template<class ColorT,
-             class Interpolator, 
-             class Allocator = span_allocator<ColorT> > 
+    //==============================================span_image_filter_gray_2x2
+    template<class Source, class Interpolator> 
     class span_image_filter_gray_2x2 : 
-    public span_image_filter<ColorT, Interpolator, Allocator>
+    public span_image_filter<Source, Interpolator>
     {
     public:
-        typedef ColorT color_type;
+        typedef Source source_type;
+        typedef typename source_type::color_type color_type;
         typedef Interpolator interpolator_type;
-        typedef Allocator alloc_type;
-        typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type;
+        typedef span_image_filter<source_type, interpolator_type> base_type;
         typedef typename color_type::value_type value_type;
         typedef typename color_type::calc_type calc_type;
-        enum
+        enum base_scale_e
         {
             base_shift = color_type::base_shift,
             base_mask  = color_type::base_mask
         };
 
         //--------------------------------------------------------------------
-        span_image_filter_gray_2x2(alloc_type& alloc) : base_type(alloc) {}
-
-        //--------------------------------------------------------------------
-        span_image_filter_gray_2x2(alloc_type& alloc,
-                                   const rendering_buffer& src, 
-                                   const color_type& back_color,
+        span_image_filter_gray_2x2() {}
+        span_image_filter_gray_2x2(source_type& src, 
                                    interpolator_type& inter,
                                    const image_filter_lut& filter) :
-            base_type(alloc, src, back_color, inter, &filter) 
+            base_type(src, inter, &filter) 
         {}
 
+
         //--------------------------------------------------------------------
-        color_type* generate(int x, int y, unsigned len)
+        void generate(color_type* span, int x, int y, unsigned len)
         {
             base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 
                                             y + base_type::filter_dy_dbl(), len);
+
             calc_type fg;
-            calc_type src_alpha;
-            value_type back_v = base_type::background_color().v;
-            value_type back_a = base_type::background_color().a;
 
             const value_type *fg_ptr;
-
-            color_type* span = base_type::allocator().span();
             const int16* weight_array = base_type::filter().weight_array() + 
                                         ((base_type::filter().diameter()/2 - 1) << 
                                           image_subpixel_shift);
-
-            int maxx = base_type::source_image().width() - 1;
-            int maxy = base_type::source_image().height() - 1;
-
             do
             {
                 int x_hr;
                 int y_hr;
-                
+
                 base_type::interpolator().coordinates(&x_hr, &y_hr);
 
                 x_hr -= base_type::filter_dx_int();
@@ -356,213 +379,91 @@ namespace agg
                 int x_lr = x_hr >> image_subpixel_shift;
                 int y_lr = y_hr >> image_subpixel_shift;
 
-                if(x_lr >= 0    && y_lr >= 0 &&
-                   x_lr <  maxx && y_lr <  maxy) 
-                {
-                    fg = image_filter_size / 2;
-
-                    x_hr &= image_subpixel_mask;
-                    y_hr &= image_subpixel_mask;
-                    fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr;
-
-                    fg += *fg_ptr++ * ((weight_array[x_hr + image_subpixel_size] * 
-                                        weight_array[y_hr + image_subpixel_size] + 
-                                        image_filter_size / 2) >> 
-                                        image_filter_shift);
-                    fg += *fg_ptr++ * ((weight_array[x_hr] * 
-                                        weight_array[y_hr + image_subpixel_size] + 
-                                        image_filter_size / 2) >> 
-                                        image_filter_shift);
-
-                    fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 2);
-
-                    fg += *fg_ptr++ * ((weight_array[x_hr + image_subpixel_size] * 
-                                        weight_array[y_hr] + 
-                                        image_filter_size / 2) >> 
-                                        image_filter_shift);
-                    fg += *fg_ptr++ * ((weight_array[x_hr] * 
-                                        weight_array[y_hr] + 
-                                        image_filter_size / 2) >> 
-                                        image_filter_shift);
-
-                    fg >>= image_filter_shift;
-                    if(fg > base_mask) fg = base_mask;
-                    src_alpha = base_mask;
-                }
-                else
-                {
-                    unsigned weight;
-                    if(x_lr < -1   || y_lr < -1 ||
-                       x_lr > maxx || y_lr > maxy)
-                    {
-                        fg        = back_v;
-                        src_alpha = back_a;
-                    }
-                    else
-                    {
-                        fg = src_alpha = image_filter_size / 2;
-
-                        x_hr &= image_subpixel_mask;
-                        y_hr &= image_subpixel_mask;
-
-                        weight = (weight_array[x_hr + image_subpixel_size] * 
-                                  weight_array[y_hr + image_subpixel_size] + 
-                                  image_filter_size / 2) >> 
-                                  image_filter_shift;
-                        if(x_lr >= 0    && y_lr >= 0 &&
-                           x_lr <= maxx && y_lr <= maxy)
-                        {
-                            fg        += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr);
-                            src_alpha += weight * base_mask;
-                        }
-                        else
-                        {
-                            fg        += back_v * weight;
-                            src_alpha += back_a * weight;
-                        }
-
-                        x_lr++;
-
-                        weight = (weight_array[x_hr] * 
-                                  weight_array[y_hr + image_subpixel_size] + 
-                                  image_filter_size / 2) >> 
-                                  image_filter_shift;
-                        if(x_lr >= 0    && y_lr >= 0 &&
-                           x_lr <= maxx && y_lr <= maxy)
-                        {
-                            fg        += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr);
-                            src_alpha += weight * base_mask;
-                        }
-                        else
-                        {
-                            fg        += back_v * weight;
-                            src_alpha += back_a * weight;
-                        }
-
-                        x_lr--;
-                        y_lr++;
-
-                        weight = (weight_array[x_hr + image_subpixel_size] * 
-                                  weight_array[y_hr] + 
-                                  image_filter_size / 2) >> 
-                                  image_filter_shift;
-                        if(x_lr >= 0    && y_lr >= 0 &&
-                           x_lr <= maxx && y_lr <= maxy)
-                        {
-                            fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr);
-                            src_alpha += weight * base_mask;
-                        }
-                        else
-                        {
-                            fg        += back_v * weight;
-                            src_alpha += back_a * weight;
-                        }
-
-                        x_lr++;
+                unsigned weight;
+                fg = image_filter_scale / 2;
 
-                        weight = (weight_array[x_hr] * 
-                                  weight_array[y_hr] + 
-                                  image_filter_size / 2) >> 
-                                  image_filter_shift;
-                        if(x_lr >= 0    && y_lr >= 0 &&
-                           x_lr <= maxx && y_lr <= maxy)
-                        {
-                            fg        += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr);
-                            src_alpha += weight * base_mask;
-                        }
-                        else
-                        {
-                            fg        += back_v * weight;
-                            src_alpha += back_a * weight;
-                        }
-                        fg        >>= image_filter_shift;
-                        src_alpha >>= image_filter_shift;
+                x_hr &= image_subpixel_mask;
+                y_hr &= image_subpixel_mask;
 
-                        if(src_alpha > base_mask) src_alpha = base_mask;
-                        if(fg > src_alpha) fg = src_alpha;
+                fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2);
+                weight = (weight_array[x_hr + image_subpixel_scale] * 
+                          weight_array[y_hr + image_subpixel_scale] + 
+                          image_filter_scale / 2) >> 
+                          image_filter_shift;
+                fg += weight * *fg_ptr;
+
+                fg_ptr = (const value_type*)base_type::source().next_x();
+                weight = (weight_array[x_hr] * 
+                          weight_array[y_hr + image_subpixel_scale] + 
+                          image_filter_scale / 2) >> 
+                          image_filter_shift;
+                fg += weight * *fg_ptr;
+
+                fg_ptr = (const value_type*)base_type::source().next_y();
+                weight = (weight_array[x_hr + image_subpixel_scale] * 
+                          weight_array[y_hr] + 
+                          image_filter_scale / 2) >> 
+                          image_filter_shift;
+                fg += weight * *fg_ptr;
+
+                fg_ptr = (const value_type*)base_type::source().next_x();
+                weight = (weight_array[x_hr] * 
+                          weight_array[y_hr] + 
+                          image_filter_scale / 2) >> 
+                          image_filter_shift;
+                fg += weight * *fg_ptr;
 
-                    }
-                }
+                fg >>= image_filter_shift;
+                if(fg > base_mask) fg = base_mask;
 
                 span->v = (value_type)fg;
-                span->a = (value_type)src_alpha;
+                span->a = base_mask;
                 ++span;
                 ++base_type::interpolator();
-
             } while(--len);
-
-            return base_type::allocator().span();
         }
     };
 
 
 
-
-
-
-
-
-
-
-
-
-    //================================================span_image_filter_gray
-    template<class ColorT,
-             class Interpolator, 
-             class Allocator = span_allocator<ColorT> > 
+    //==================================================span_image_filter_gray
+    template<class Source, class Interpolator> 
     class span_image_filter_gray : 
-    public span_image_filter<ColorT, Interpolator, Allocator>
+    public span_image_filter<Source, Interpolator>
     {
     public:
-        typedef ColorT color_type;
+        typedef Source source_type;
+        typedef typename source_type::color_type color_type;
         typedef Interpolator interpolator_type;
-        typedef Allocator alloc_type;
-        typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type;
+        typedef span_image_filter<source_type, interpolator_type> base_type;
         typedef typename color_type::value_type value_type;
         typedef typename color_type::calc_type calc_type;
-        enum
+        enum base_scale_e
         {
             base_shift = color_type::base_shift,
             base_mask  = color_type::base_mask
         };
 
         //--------------------------------------------------------------------
-        span_image_filter_gray(alloc_type& alloc) : base_type(alloc) {}
-
-        //--------------------------------------------------------------------
-        span_image_filter_gray(alloc_type& alloc,
-                               const rendering_buffer& src, 
-                               const color_type& back_color,
+        span_image_filter_gray() {}
+        span_image_filter_gray(source_type& src, 
                                interpolator_type& inter,
                                const image_filter_lut& filter) :
-            base_type(alloc, src, back_color, inter, &filter) 
+            base_type(src, inter, &filter) 
         {}
 
         //--------------------------------------------------------------------
-        color_type* generate(int x, int y, unsigned len)
+        void generate(color_type* span, int x, int y, unsigned len)
         {
             base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 
                                             y + base_type::filter_dy_dbl(), len);
 
             int fg;
-            int src_alpha;
-            value_type back_v = base_type::background_color().v;
-            value_type back_a = base_type::background_color().a;
-
-            const value_type* fg_ptr;
-
-            unsigned   diameter     = base_type::filter().diameter();
-            int        start        = base_type::filter().start();
-            int        start1       = start - 1;
-            const int16* weight_array = base_type::filter().weight_array();
-
-            color_type* span = base_type::allocator().span();
-
-            int maxx = base_type::source_image().width() + start - 2;
-            int maxy = base_type::source_image().height() + start - 2;
+            const value_type *fg_ptr;
 
-            int maxx2 = base_type::source_image().width() - start - 1;
-            int maxy2 = base_type::source_image().height() - start - 1;
+            unsigned     diameter     = base_type::filter().diameter();
+            int          start        = base_type::filter().start();
+            const int16* weight_array = base_type::filter().weight_array();
 
             int x_count; 
             int weight_y;
@@ -574,124 +475,270 @@ namespace agg
                 x -= base_type::filter_dx_int();
                 y -= base_type::filter_dy_int();
 
-                int x_hr = x;
-                int y_hr = y;
-            
+                int x_hr = x; 
+                int y_hr = y; 
+
                 int x_lr = x_hr >> image_subpixel_shift;
                 int y_lr = y_hr >> image_subpixel_shift;
 
-                fg = image_filter_size / 2;
+                fg = image_filter_scale / 2;
 
                 int x_fract = x_hr & image_subpixel_mask;
                 unsigned y_count = diameter;
 
-                if(x_lr >= -start && y_lr >= -start &&
-                   x_lr <= maxx   && y_lr <= maxy) 
+                y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
+                fg_ptr = (const value_type*)base_type::source().span(x_lr + start, 
+                                                                     y_lr + start, 
+                                                                     diameter);
+                for(;;)
                 {
-                    y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
-                    fg_ptr = (const value_type*)base_type::source_image().row(y_lr + start) + x_lr + start;
-                    do
+                    x_count  = diameter;
+                    weight_y = weight_array[y_hr];
+                    x_hr = image_subpixel_mask - x_fract;
+                    for(;;)
                     {
-                        x_count = diameter;
-                        weight_y = weight_array[y_hr];
-                        x_hr = image_subpixel_mask - x_fract;
+                        fg += *fg_ptr * 
+                              ((weight_y * weight_array[x_hr] + 
+                                image_filter_scale / 2) >> 
+                                image_filter_shift);
+                        if(--x_count == 0) break;
+                        x_hr  += image_subpixel_scale;
+                        fg_ptr = (const value_type*)base_type::source().next_x();
+                    }
 
-                        do
-                        {
-                            fg += *fg_ptr++ * ((weight_y * weight_array[x_hr] + 
-                                               image_filter_size / 2) >> 
-                                               image_filter_shift);
-                            x_hr += image_subpixel_size;
+                    if(--y_count == 0) break;
+                    y_hr  += image_subpixel_scale;
+                    fg_ptr = (const value_type*)base_type::source().next_y();
+                }
 
-                        } while(--x_count);
+                fg >>= image_filter_shift;
+                if(fg < 0) fg = 0;
+                if(fg > base_mask) fg = base_mask;
+                span->v = (value_type)fg;
+                span->a = base_mask;
+
+                ++span;
+                ++base_type::interpolator();
 
-                        y_hr += image_subpixel_size;
-                        fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - diameter);
+            } while(--len);
+        }
+    };
 
-                    } while(--y_count);
 
-                    fg >>= image_filter_shift;
 
-                    if(fg < 0)         fg = 0;
-                    if(fg > base_mask) fg = base_mask;
-                    src_alpha = base_mask;
-                }
-                else
+    //=========================================span_image_resample_gray_affine
+    template<class Source> 
+    class span_image_resample_gray_affine : 
+    public span_image_resample_affine<Source>
+    {
+    public:
+        typedef Source source_type;
+        typedef typename source_type::color_type color_type;
+        typedef span_image_resample_affine<source_type> base_type;
+        typedef typename base_type::interpolator_type interpolator_type;
+        typedef typename color_type::value_type value_type;
+        typedef typename color_type::long_type long_type;
+        enum base_scale_e
+        {
+            base_shift      = color_type::base_shift,
+            base_mask       = color_type::base_mask,
+            downscale_shift = image_filter_shift
+        };
+
+        //--------------------------------------------------------------------
+        span_image_resample_gray_affine() {}
+        span_image_resample_gray_affine(source_type& src, 
+                                        interpolator_type& inter,
+                                        const image_filter_lut& filter) :
+            base_type(src, inter, filter) 
+        {}
+
+
+        //--------------------------------------------------------------------
+        void generate(color_type* span, int x, int y, unsigned len)
+        {
+            base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 
+                                            y + base_type::filter_dy_dbl(), len);
+
+            long_type fg;
+
+            int diameter     = base_type::filter().diameter();
+            int filter_scale = diameter << image_subpixel_shift;
+            int radius_x     = (diameter * base_type::m_rx) >> 1;
+            int radius_y     = (diameter * base_type::m_ry) >> 1;
+            int len_x_lr     = 
+                (diameter * base_type::m_rx + image_subpixel_mask) >> 
+                    image_subpixel_shift;
+
+            const int16* weight_array = base_type::filter().weight_array();
+
+            do
+            {
+                base_type::interpolator().coordinates(&x, &y);
+
+                x += base_type::filter_dx_int() - radius_x;
+                y += base_type::filter_dy_int() - radius_y;
+
+                fg = image_filter_scale / 2;
+
+                int y_lr = y >> image_subpixel_shift;
+                int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 
+                                base_type::m_ry_inv) >> 
+                                    image_subpixel_shift;
+                int total_weight = 0;
+                int x_lr = x >> image_subpixel_shift;
+                int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 
+                                base_type::m_rx_inv) >> 
+                                    image_subpixel_shift;
+
+                int x_hr2 = x_hr;
+                const value_type* fg_ptr = 
+                    (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
+                for(;;)
                 {
-                    if(x_lr < start1 || y_lr < start1 ||
-                       x_lr > maxx2  || y_lr > maxy2) 
+                    int weight_y = weight_array[y_hr];
+                    x_hr = x_hr2;
+                    for(;;)
                     {
-                        fg        = back_v;
-                        src_alpha = back_a;
+                        int weight = (weight_y * weight_array[x_hr] + 
+                                     image_filter_scale / 2) >> 
+                                     downscale_shift;
+
+                        fg += *fg_ptr * weight;
+                        total_weight += weight;
+                        x_hr  += base_type::m_rx_inv;
+                        if(x_hr >= filter_scale) break;
+                        fg_ptr = (const value_type*)base_type::source().next_x();
                     }
-                    else
-                    {
-                        src_alpha = image_filter_size / 2;
-                        y_lr = (y >> image_subpixel_shift) + start;
-                        y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
+                    y_hr += base_type::m_ry_inv;
+                    if(y_hr >= filter_scale) break;
+                    fg_ptr = (const value_type*)base_type::source().next_y();
+                }
 
-                        do
-                        {
-                            x_count = diameter;
-                            weight_y = weight_array[y_hr];
-                            x_lr = (x >> image_subpixel_shift) + start;
-                            x_hr = image_subpixel_mask - x_fract;
-
-                            do
-                            {
-                                int weight = (weight_y * weight_array[x_hr] + 
-                                             image_filter_size / 2) >> 
-                                             image_filter_shift;
-
-                                if(x_lr >= 0 && y_lr >= 0 && 
-                                   x_lr < int(base_type::source_image().width()) && 
-                                   y_lr < int(base_type::source_image().height()))
-                                {
-                                    fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr;
-                                    fg        += *fg_ptr++ * weight;
-                                    src_alpha += base_mask * weight;
-                                }
-                                else
-                                {
-                                    fg        += back_v * weight;
-                                    src_alpha += back_a * weight;
-                                }
-                                x_hr += image_subpixel_size;
-                                x_lr++;
-
-                            } while(--x_count);
-
-                            y_hr += image_subpixel_size;
-                            y_lr++;
-
-                        } while(--y_count);
+                fg /= total_weight;
+                if(fg < 0) fg = 0;
+                if(fg > base_mask) fg = base_mask;
+
+                span->v = (value_type)fg;
+                span->a = base_mask;
+
+                ++span;
+                ++base_type::interpolator();
+            } while(--len);
+        }
+    };
+
+
+
+    //================================================span_image_resample_gray
+    template<class Source, class Interpolator>
+    class span_image_resample_gray : 
+    public span_image_resample<Source, Interpolator>
+    {
+    public:
+        typedef Source source_type;
+        typedef typename source_type::color_type color_type;
+        typedef Interpolator interpolator_type;
+        typedef span_image_resample<source_type, interpolator_type> base_type;
+        typedef typename color_type::value_type value_type;
+        typedef typename color_type::long_type long_type;
+        enum base_scale_e
+        {
+            base_shift = color_type::base_shift,
+            base_mask  = color_type::base_mask,
+            downscale_shift = image_filter_shift
+        };
+
+        //--------------------------------------------------------------------
+        span_image_resample_gray() {}
+        span_image_resample_gray(source_type& src, 
+                                 interpolator_type& inter,
+                                 const image_filter_lut& filter) :
+            base_type(src, inter, filter)
+        {}
 
+        //--------------------------------------------------------------------
+        void generate(color_type* span, int x, int y, unsigned len)
+        {
+            base_type::interpolator().begin(x + base_type::filter_dx_dbl(), 
+                                            y + base_type::filter_dy_dbl(), len);
+            long_type fg;
 
-                        fg        >>= image_filter_shift;
-                        src_alpha >>= image_filter_shift;
+            int diameter = base_type::filter().diameter();
+            int filter_scale = diameter << image_subpixel_shift;
 
-                        if(fg < 0)        fg = 0;
-                        if(src_alpha < 0) src_alpha = 0;
+            const int16* weight_array = base_type::filter().weight_array();
+            do
+            {
+                int rx;
+                int ry;
+                int rx_inv = image_subpixel_scale;
+                int ry_inv = image_subpixel_scale;
+                base_type::interpolator().coordinates(&x,  &y);
+                base_type::interpolator().local_scale(&rx, &ry);
+                base_type::adjust_scale(&rx, &ry);
+
+                rx_inv = image_subpixel_scale * image_subpixel_scale / rx;
+                ry_inv = image_subpixel_scale * image_subpixel_scale / ry;
+
+                int radius_x = (diameter * rx) >> 1;
+                int radius_y = (diameter * ry) >> 1;
+                int len_x_lr = 
+                    (diameter * rx + image_subpixel_mask) >> 
+                        image_subpixel_shift;
+
+                x += base_type::filter_dx_int() - radius_x;
+                y += base_type::filter_dy_int() - radius_y;
+
+                fg = image_filter_scale / 2;
+
+                int y_lr = y >> image_subpixel_shift;
+                int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * 
+                               ry_inv) >> 
+                                   image_subpixel_shift;
+                int total_weight = 0;
+                int x_lr = x >> image_subpixel_shift;
+                int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * 
+                               rx_inv) >> 
+                                   image_subpixel_shift;
+                int x_hr2 = x_hr;
+                const value_type* fg_ptr = 
+                    (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
 
-                        if(src_alpha > base_mask) src_alpha = base_mask;
-                        if(fg        > src_alpha) fg        = src_alpha;
+                for(;;)
+                {
+                    int weight_y = weight_array[y_hr];
+                    x_hr = x_hr2;
+                    for(;;)
+                    {
+                        int weight = (weight_y * weight_array[x_hr] + 
+                                     image_filter_scale / 2) >> 
+                                     downscale_shift;
+                        fg += *fg_ptr * weight;
+                        total_weight += weight;
+                        x_hr  += rx_inv;
+                        if(x_hr >= filter_scale) break;
+                        fg_ptr = (const value_type*)base_type::source().next_x();
                     }
+                    y_hr += ry_inv;
+                    if(y_hr >= filter_scale) break;
+                    fg_ptr = (const value_type*)base_type::source().next_y();
                 }
 
+                fg /= total_weight;
+                if(fg < 0) fg = 0;
+                if(fg > base_mask) fg = base_mask;
+
                 span->v = (value_type)fg;
-                span->a = (value_type)src_alpha;
+                span->a = base_mask;
 
                 ++span;
                 ++base_type::interpolator();
-
             } while(--len);
-
-            return base_type::allocator().span();
         }
     };
 
 
-
 }
 
 



Mime
View raw message