Remove .gitignore do nothing is ignored.
[synfig.git] / synfig-core / trunk / src / synfig / layer_shape.cpp
index 1d71677..2116d2f 100644 (file)
@@ -1,11 +1,12 @@
 /* === S Y N F I G ========================================================= */
 /*!    \file layer_shape.cpp
-**     \brief Template Header
+**     \brief Implementation of the "Shape" layer
 **
-**     $Id: layer_shape.cpp,v 1.2 2005/01/24 03:08:18 darco Exp $
+**     $Id$
 **
 **     \legal
 **     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
@@ -59,10 +60,10 @@ using namespace etl;
 
 SYNFIG_LAYER_INIT(Layer_Shape);
 SYNFIG_LAYER_SET_NAME(Layer_Shape,"shape");
-SYNFIG_LAYER_SET_LOCAL_NAME(Layer_Shape,_("Shape"));
-SYNFIG_LAYER_SET_CATEGORY(Layer_Shape,_("Internal"));
+SYNFIG_LAYER_SET_LOCAL_NAME(Layer_Shape,N_("Shape"));
+SYNFIG_LAYER_SET_CATEGORY(Layer_Shape,N_("Internal"));
 SYNFIG_LAYER_SET_VERSION(Layer_Shape,"0.1");
-SYNFIG_LAYER_SET_CVS_ID(Layer_Shape,"$Id: layer_shape.cpp,v 1.2 2005/01/24 03:08:18 darco Exp $");
+SYNFIG_LAYER_SET_CVS_ID(Layer_Shape,"$Id$");
 
 #define EPSILON        1e-12
 
@@ -79,9 +80,9 @@ struct Primitive
 {
        int             operation;
        int             number;
-       
+
        //Point data[0];
-       
+
        enum Operations
        {
                NONE = -1,
@@ -103,55 +104,55 @@ const int MIN_SUBDIVISION_DRAW_LEVELS = 4;
 static void Subd_Conic_Stack(Point *arc)
 {
        /*
-       
+
        b0
        *               0+1 a
        b1 b    *               1+2*1+2 a
        *               1+2     b       *
-       b2              *               
-       *               
-                       
+       b2              *
+       *
+
        0.1.2 ->        0.1 2 3.4
-       
+
        */
-       
+
        Real a,b;
-       
-       
+
+
        arc[4][0] = arc[2][0];
-       b = arc[1][0];          
-       
+       b = arc[1][0];
+
        a = arc[1][0] = (arc[0][0] + b)/2;
-       b = arc[3][0] = (arc[4][0] + b)/2;      
+       b = arc[3][0] = (arc[4][0] + b)/2;
        arc[2][0] = (a + b)/2;
-       
-       
+
+
        arc[4][1] = arc[2][1];
        b = arc[1][1];
-       
+
        a = arc[1][1] = (arc[0][1] + b)/2;
        b = arc[3][1] = (arc[4][1] + b)/2;
        arc[2][1] = (a + b)/2;
-       
+
        /* //USING SIMD
-       
+
        arc[4] = arc[2];
-       
+
        arc[3] = (arc[2] + arc[1])/2;
        arc[1] = (arc[0] + arc[1])/2;
 
        arc[2] = (arc[1] + arc[3])/2;
-       
+
        */
-       
+
 }
 
 static void Subd_Cubic_Stack(Point *arc)
 {
        Real a,b,c;
-       
+
        /*
-       
+
        b0
        *               0+1 a
        b1 b    *               1+2*1+2 a
@@ -159,56 +160,56 @@ static void Subd_Cubic_Stack(Point *arc)
        b2 c    *               1+2*2+2 b       *
        *               2+3     c       *
        b3              *
-       *               
-       
+       *
+
        0.1 2.3 ->      0.1 2 3 4 5.6
-       
+
        */
-       
+
        arc[6][0] = arc[3][0];
-       
+
        b = arc[1][0];
        c = arc[2][0];
-       
+
        a = arc[1][0] = (arc[0][0] + b)/2;
        b = (b + c)/2;
        c = arc[5][0] = (arc[6][0] + c)/2;
-       
+
        a = arc[2][0] = (a + b)/2;
        b = arc[4][0] = (b + c)/2;
-       
+
        arc[3][0] = (a + b)/2;
-       
-       
+
+
        arc[6][1] = arc[3][1];
-       
+
        b = arc[1][1];
        c = arc[2][1];
-       
+
        a = arc[1][1] = (arc[0][1] + b)/2;
        b = (b + c)/2;
        c = arc[5][1] = (arc[6][1] + c)/2;
-       
+
        a = arc[2][1] = (a + b)/2;
        b = arc[4][1] = (b + c)/2;
-       
+
        arc[3][1] = (a + b)/2;
-       
+
        /* //USING SIMD
        temp
-       
+
        arc[6] = arc[3];
-       
+
        //backwards to avoid overwriting
        arc[5] = (arc[2] + arc[3])/2;
        temp = (arc[1] + arc[2])/2;
        arc[1] = (arc[0] + arc[1])/2;
-       
+
        arc[4] = (temp + arc[5])/2;
        arc[2] = (arc[1] + temp)/2;
-       
+
        arc[3] = (arc[2] + arc[4])/2;
-       
+
        */
 }
 
@@ -220,9 +221,9 @@ struct MonoSegment
        Rect    aabb;
        int             ydir;
        vector<Point>   pointlist;
-       
+
        MonoSegment(int dir = 0, Real x0 = 0, Real x1 = 0, Real y0 = 0, Real y1 = 0)
-       { 
+       {
                aabb.minx = x0;
                aabb.maxx = x1;
                aabb.miny = y0;
@@ -230,34 +231,36 @@ struct MonoSegment
 
                ydir = dir;
        }
-       
+
        int intersect(Real x,Real y) const
        {
-               if((y < aabb.miny) | (y > aabb.maxy) | (x < aabb.minx)) return 0;
+               if((y < aabb.miny+EPSILON) || (y > aabb.maxy) || (x < aabb.minx)) return 0;
                if(x > aabb.maxx) return ydir;
-       
+
                //int i = 0;
                //int size = pointlist.size();
                //vector<Point>::const_iterator end = pointlist.end();
                vector<Point>::const_iterator p = pointlist.begin();
-               
+
                //assumes that the rect culled away anything that would be beyond the edges
                if(ydir > 0)
                {
-                       while(y > (*++p)[1]);
+                       while(y > (*++p)[1])
+                               ;
                }
                else
                {
-                       while(y < (*++p)[1]);
+                       while(y < (*++p)[1])
+                               ;
                }
-               
+
                //for the loop to break there must have been a slope (straight line would do nothing)
                //vector<Point>::const_iterator p1 = p-1;
                Real dy = p[-1][1] - p[0][1];
                Real dx = p[-1][0] - p[0][0];
-               
+
                assert(dy != 0);
-               
+
                Real xi = p[0][0] + (y - p[0][1]) * dx / dy;
                return (x > xi)*ydir;
        }
@@ -268,190 +271,190 @@ struct CurveArray
        Rect    aabb;   //not necessarily as effective - can only reject values
        vector<Point>   pointlist;      //run length - p0, p1, p2, p3 = p10, p11, p12, p13 = p20 ...
        vector<char>    degrees;
-       
+
        CurveArray(Real x0 = 0, Real x1 = 0, Real y0 = 0, Real y1 = 0)
-       { 
+       {
                aabb.set(x0,y0,x1,y1);
        }
-       
+
        void reset(Real x0 = 0, Real x1 = 0, Real y0 = 0, Real y1 = 0)
        {
                aabb.set(x0,y0,x1,y1);
                pointlist.clear();
                degrees.clear();
        }
-       
+
        int size () const
        {
                return degrees.size();
        }
-       
+
        void Start(Point m)
-       {               
+       {
                reset(m[0],m[0],m[1],m[1]);
-               pointlist.push_back(m);         
+               pointlist.push_back(m);
        }
-       
+
        void AddCubic(Point p1, Point p2, Point dest)
        {
                aabb.expand(p1[0],p1[1]);
                aabb.expand(p2[0],p2[1]);
                aabb.expand(dest[0],dest[1]);
-               
+
                pointlist.push_back(p1);
                pointlist.push_back(p2);
                pointlist.push_back(dest);
-               
+
                degrees.push_back(3);
        }
-       
+
        void AddConic(Point p1, Point dest)
        {
                aabb.expand(p1[0],p1[1]);
                aabb.expand(dest[0],dest[1]);
-               
+
                pointlist.push_back(p1);
                pointlist.push_back(dest);
-               
+
                degrees.push_back(2);
        }
-       
-       static int intersect_conic(Real x, Real y, Point *p, int level = 0)
+
+       static int intersect_conic(Real x, Real y, Point *p, int /*level*/ = 0)
        {
                Real ymin,ymax,xmin,xmax;
                int intersects = 0;
-               
+
                //sort the overall curve ys - degenerate detection
                ymin = min(p[0][1],p[2][1]);
                ymax = max(p[0][1],p[2][1]);
-               
+
                xmin = min(min(p[0][0],p[1][0]),p[2][0]);
                xmax = max(max(p[0][0],p[1][0]),p[2][0]);
-               
+
                //to the left, to the right and out of range y, or completely out of range y
                if( x < xmin ) return 0;
-               if( x > xmax  & (y > ymax | y < ymin) ) return 0;
-               if( (y > ymax & y > p[1][1]) | (y < ymin & y < p[1][1]) ) return 0;
-                       
+               if( x > xmax  && (y > ymax || y < ymin) ) return 0;
+               if( (y > ymax && y > p[1][1]) || (y < ymin && y < p[1][1]) ) return 0;
+
                //degenerate line max
-               if(ymin == ymax == p[1][1])
+               if(ymin == ymax && ymax == p[1][1])
                        return 0;
-               
+
                //degenerate accept - to the right and crossing the base line
                if(x > xmax)
                {
-                       return (y <= ymax & y >= ymin);
+                       return (y <= ymax && y >= ymin);
                }
 
                //solve for curve = y
-               
-               //real roots: 
+
+               //real roots:
                //0 roots       - 0 intersection
                //1 root        - get x, and figure out x
                //2 roots (non-double root)     - get 2 xs, and count xs to the left
-               
+
                //for conic we can assume 1 intersection for monotonic curve
                Real    a = p[2][1] -   2*p[1][1] +     p[0][1],
                                b =                     2*p[1][1] -     2*p[0][1],
                                c =                                                     p[0][1]         -       y;
-               
+
                Real t1 = -1, t2 = -1;
-               
+
                if(a == 0)
                {
                        //linear - easier :)
                        if(b == 0) return 0; //may not need this check
-                               
+
                        t1 = - c / b; //bt + c = 0 solved
                }else
                {
                        //2 degree polynomial
                        Real b2_4ac = b*b - 4*a*c;
-                       
+
                        //if there are double/no roots - no intersections (in real #s that is)
                        if(b2_4ac <= 0)
                        {
                                return 0;
                        }
-                       
+
                        b2_4ac = sqrt(b2_4ac);
-                       
+
                        t1 = (-b - b2_4ac) / 2*a,
                        t2 = (-b + b2_4ac) / 2*a;
                }
-               
-               //calculate number of intersections             
-               if(t1 >= 0 & t1 <= 1)
+
+               //calculate number of intersections
+               if(t1 >= 0 && t1 <= 1)
                {
                        const Real t = t1;
                        const Real invt = 1 - t;
-                       
+
                        //find x val and it counts if it's to the left of the point
                        const Real xi = invt*invt*p[0][0] + 2*t*invt*p[1][0] + t*t*p[2][0];
                        const Real dy_t = 2*a*t + b;
-                       
+
                        if(dy_t)
                        {
                                intersects += (x >= xi) * ( dy_t > 0 ? 1 : -1);
                        }
                }
 
-               if(t2 >= 0 & t2 <= 1)
+               if(t2 >= 0 && t2 <= 1)
                {
                        const Real t = t2;
                        const Real invt = 1 - t;
-                       
+
                        //find x val and it counts if it's to the left of the point
                        const Real xi = invt*invt*p[0][0] + 2*t*invt*p[1][0] + t*t*p[2][0];
                        const Real dy_t = 2*a*t + b;
-                       
+
                        if(dy_t)
                        {
                                intersects += (x >= xi) * ( dy_t > 0 ? 1 : -1);
                        }
                }
-               
+
                return intersects;
        }
-       
+
        static int      quadratic_eqn(Real a, Real b, Real c, Real *t0, Real *t1)
        {
                const Real b2_4ac = b*b - 4*a*c;
-               
+
                //degenerate reject (can't take sqrt)
                if(b2_4ac < 0)
                {
                        return 0;
                }
-               
-               const Real sqrtb2_4ac = sqrt(b2_4ac);           
+
+               const Real sqrtb2_4ac = sqrt(b2_4ac);
                const Real signb = b < 0 ? -1 : 1;
                const Real q = - 0.5 * (b + signb * sqrtb2_4ac);
-               
+
                *t0 = q/a;
                *t1 = c/q;
-               
+
                return sqrtb2_4ac == 0 ? 1 : 2;
        }
-       
+
        //Newton-Raphson root polishing (we don't care about bounds, assumes very near the desired root)
        static Real polish_cubicroot(Real a, Real b, Real c, Real d, Real t, Real *dpdt)
        {
                const Real cn[4] = {a,b,c,d};
                Real p,dp,newt,oldpmag=FLT_MAX;
-               
-               //eval cubic eqn and it's derivative
+
+               //eval cubic eqn and its derivative
                for(;;)
                {
                        p = cn[0]*t + cn[1];
                        dp = cn[0];
-                       
+
                        for(int i = 2; i < 4; i++)
                        {
                                dp = p + dp*t;
                                p = cn[i] + p*t;
                        }
-                       
+
                        if(dp == 0)
                        {
                                synfig::warning("polish_cubicroot: Derivative should not vanish!!!");
@@ -465,74 +468,74 @@ struct CurveArray
                                *dpdt = dp;
                                return t;
                        }
-                       
-                       t = newt;                               
+
+                       t = newt;
                        oldpmag = fabs(p);
                }
        }
-       
-       static int intersect_cubic(Real x, Real y, Point *p, int level = 0)
+
+       static int intersect_cubic(Real x, Real y, Point *p, int /*level*/ = 0)
        {
                const Real INVALIDROOT = -FLT_MAX;
                Real ymin,ymax,xmin,xmax;
                Real ymin2,ymax2,ymintot,ymaxtot;
                int intersects = 0;
-               
+
                //sort the overall curve ys and xs - degenerate detection
-               
+
                //open span for the two end points
                ymin = min(p[0][1],p[3][1]);
                ymax = max(p[0][1],p[3][1]);
-               
+
                //other points etc.
                ymin2 = min(p[1][1],p[2][1]);
                ymax2 = max(p[1][1],p[2][1]);
-               
+
                ymintot = min(ymin,ymin2);
                ymaxtot = max(ymax,ymax2);
-                               
+
                //the entire curve control polygon is in this x range
                xmin = min(min(p[0][0],p[1][0]),min(p[2][0],p[3][0]));
                xmax = max(max(p[0][0],p[1][0]),max(p[2][0],p[3][0]));
-                               
+
                //outside all y boundaries (no intersect)
                if( (y > ymaxtot) || (y < ymintot) ) return 0;
-               
+
                //left of curve (no intersect)
                if(x < xmin) return 0;
-               
+
                //right of curve (and outside base range)
                if( x > xmax )
                {
-                       if( (y > ymax) | (y < ymin) ) return 0;
-                               
+                       if( (y > ymax) || (y < ymin) ) return 0;
+
                        //degenerate accept - to the right and inside the [ymin,ymax] range (already rejected if out of range)
                        const Real n = p[3][1] - p[0][1];
-                       
+
                        //extract the sign from the value (we need valid data)
                        return n < 0 ? -1 : 1;
                }
-                       
+
                //degenerate horizontal line max -- doesn't happen enough to check for
                if( ymintot == ymaxtot ) return 0;
-               
+
                //calculate roots:
                // can have 0,1,2, or 3 real roots
                // if any of them are double then reject the two...
-               
+
                // y-coefficients for f_y(t) - y = 0
                Real    a = p[3][1]     - 3*p[2][1]     + 3*p[1][1]     -   p[0][1],
                                b =                       3*p[2][1]     - 6*p[1][1]     + 3*p[0][1],
                                c =                                                       3*p[1][1]     - 3*p[0][1],
                                d =                                                                             p[0][1] - y;
-               
+
                Real    ax = p[3][0]    - 3*p[2][0]     + 3*p[1][0]     -   p[0][0],
                                bx =                      3*p[2][0]     - 6*p[1][0]     + 3*p[0][0],
                                cx =                                              3*p[1][0]     - 3*p[0][0],
                                dx =                                                                            p[0][0];
-               
+
                Real t1 = INVALIDROOT, t2 = INVALIDROOT, t3 = INVALIDROOT, t, dydt;
-               
+
                if(a == 0)
                {
                        //only 2nd degree
@@ -540,22 +543,22 @@ struct CurveArray
                        {
                                //linear
                                if(c == 0) return 0;
-                                       
+
                                t1 = - d / c; //equation devolved into: ct + d = 0 - solve...
                        }else
                        {
                                //0 roots = 0 intersections, 1 root = 2 intersections at the same place (0 effective)
                                if(quadratic_eqn(a,b,c,&t1,&t2) != 2) return 0;
-                       }                       
+                       }
                }else
                {
                        //cubic - sigh....
-                       
+
                        //algorithm courtesy of Numerical Recipes in C (algorithm copied from pg. 184/185)
                        Real an = b / a,
                                 bn = c / a,
                                 cn = d / a;
-                       
+
                        //if cn is 0 (or really really close), then we can simplify this...
                        if(IsZero(cn))
                        {
@@ -568,21 +571,21 @@ struct CurveArray
                                }
                        }
                        else
-                       {                       
+                       {
                                //otherwise run the normal cubic root equation
                                Real Q = (an*an - 3.0*bn) / 9.0;
                                Real R = ((2.0*an*an - 9.0*bn)*an + 27.0*cn)/54.0;
-                               
+
                                if(R*R < Q*Q*Q)
                                {
                                        Real theta = acos(R / sqrt(Q*Q*Q));
-                                       
+
                                        t1 = -2.0*sqrt(Q)*cos(theta/3) - an/3.0;
                                        t2 = -2.0*sqrt(Q)*cos((theta+2*PI)/3.0) - an/3.0;
                                        t3 = -2.0*sqrt(Q)*cos((theta-2*PI)/3.0) - an/3.0;
-                                       
+
                                        //don't need to reorder,l just need to eliminate double/triple roots
-                                       //if(t3 == t2 & t1 == t2) t2 = t3 = INVALIDROOT;
+                                       //if(t3 == t2 && t1 == t2) t2 = t3 = INVALIDROOT;
                                        if(t3 == t2) t2 = t3 = INVALIDROOT;
                                        if(t1 == t2) t1 = t2 = INVALIDROOT;
                                        if(t1 == t3) t1 = t3 = INVALIDROOT;
@@ -590,28 +593,28 @@ struct CurveArray
                                {
                                        Real signR = R < 0 ? -1 : 1;
                                        Real A = - signR * pow(signR*R + sqrt(R*R - Q*Q*Q),1/3.0);
-                                       
+
                                        Real B;
                                        if(A == 0) B = 0;
                                        else B = Q / A;
-       
+
                                        //single real root in this case
                                        t1 = (A + B) - an/3.0;
                                }
                        }
                }
-               
+
                //if(t1 != INVALIDROOT)
                {
                        t = t1;//polish_cubicroot(a,b,c,d,t1,&dydt);
-                       if(t >= 0 & t < 1)
+                       if(t >= 0 && t < 1)
                        {
                                //const Real invt = 1 - t;
-                               
+
                                //find x val and it counts if it's to the left of the point
                                const Real xi = ((ax*t + bx)*t + cx)*t + dx;
                                dydt = (3*a*t + 2*b)*t + c;
-                               
+
                                if(dydt)
                                {
                                        intersects += (x >= xi) * ( dydt > 0 ? 1 : -1);
@@ -622,14 +625,14 @@ struct CurveArray
                //if(t2 != INVALIDROOT)
                {
                        t = t2;//polish_cubicroot(a,b,c,d,t2,&dydt);
-                       if(t >= 0 & t < 1)
+                       if(t >= 0 && t < 1)
                        {
                                //const Real invt = 1 - t;
-                               
+
                                //find x val and it counts if it's to the left of the point
                                const Real xi = ((ax*t + bx)*t + cx)*t + dx;
                                dydt = (3*a*t + 2*b)*t + c;
-                               
+
                                if(dydt)
                                {
                                        intersects += (x >= xi) * ( dydt > 0 ? 1 : -1);
@@ -640,37 +643,37 @@ struct CurveArray
                //if(t3 != INVALIDROOT)
                {
                        t = t3;//polish_cubicroot(a,b,c,d,t3,&dydt);
-                       if(t >= 0 & t < 1)
+                       if(t >= 0 && t < 1)
                        {
                                //const Real invt = 1 - t;
-                               
+
                                //find x val and it counts if it's to the left of the point
                                const Real xi = ((ax*t + bx)*t + cx)*t + dx;
                                dydt = (3*a*t + 2*b)*t + c;
-                               
+
                                if(dydt)
                                {
                                        intersects += (x >= xi) * ( dydt > 0 ? 1 : -1);
                                }
                        }
                }
-               
+
                return intersects;
        }
-       
+
        int intersect(Real x,Real y, Point *table) const
-       {               
-               if((y < aabb.miny) | (y > aabb.maxy) | (x < aabb.minx)) return 0;
-                       
+       {
+               if((y < aabb.miny) || (y > aabb.maxy) || (x < aabb.minx)) return 0;
+
                int i, curdeg, intersects = 0;
                const int numcurves = degrees.size();
-               
+
                vector<Point>::const_iterator   p = pointlist.begin();
-                                       
+
                for(i=0; i < numcurves; i++)
                {
                        curdeg = degrees[i];
-                       
+
                        switch(curdeg)
                        {
                                case 2:
@@ -678,102 +681,104 @@ struct CurveArray
                                        table[0] = *p++;
                                        table[1] = *p++;
                                        table[2] = *p;  //we want to include the last point for the next curve
-                                       
+
                                        intersects += intersect_conic(x,y,table);
-                                       
+
                                        break;
                                }
-                               
+
                                case 3:
                                {
                                        table[0] = *p++;
                                        table[1] = *p++;
                                        table[2] = *p++;
                                        table[3] = *p;  //we want to include the last point for the next curve
-                                       
+
                                        intersects += intersect_cubic(x,y,table);
-                                       
+
                                        break;
                                }
-                               
+
                                default:
                                {
                                        warning("Invalid degree (%d) inserted into the list (index: %d)\n", curdeg, i);
                                        return 0;
                                }
-                       }                               
+                       }
                }
-               
+
                return intersects;
        }
 };
 
 struct Layer_Shape::Intersector
-{      
+{
        Rect    aabb;
+
+       //! true iff aabb hasn't been initialized yet
        bool    initaabb;
-       
+
        int     flags;
-       
+
        enum IntersectorFlags
        {
                NotClosed = 0x8000
        };
-       
+
        enum PrimitiveType
        {
                TYPE_NONE = 0,
                TYPE_LINE,
                TYPE_CURVE
        };
-       
+
        Real    cur_x,cur_y;
        Real    close_x,close_y;
-       
-       vector<MonoSegment>                             segs;   //monotonically increasing 
+
+       vector<MonoSegment>                             segs;   //monotonically increasing
        vector<CurveArray>                              curves; //big array of consecutive curves
-       
+
        int                                                             prim;
        Vector                                                  tangent;
-       
+
        Intersector()
        {
                clear();
        }
-       
+
        bool notclosed()
        {
-               return (flags & NotClosed) | (cur_x != close_x) | (cur_y != close_y);
+               return (flags & NotClosed) || (cur_x != close_x) || (cur_y != close_y);
        }
-       
+
        void move_to(Real x, Real y)
        {
                close();
-               
+
                close_x = cur_x = x;
                close_y = cur_y = y;
-               
+
                tangent[0] = tangent[1] = 0;
-               
-               if(initaabb) 
+
+               if(initaabb)
                {
                        aabb.set_point(x,y);
                        initaabb = false;
                }else aabb.expand(x,y);
-               
+
                prim = TYPE_NONE;
        }
-       
+
        void line_to(Real x, Real y)
        {
                int dir = (y > cur_y)*1 + (-1)*(y < cur_y);
-               
+
                //check for context (if not line start a new segment)
-               //if we're not in line mode (cover's 0 set case), or if directions are different (not valid for 0 direction)
+               //if we're not in line mode (covers 0 set case), or if directions are different (not valid for 0 direction)
                if(prim != TYPE_LINE || (dir && segs.back().ydir != dir))
                {
                        MonoSegment             seg(dir,x,x,y,y);
-                       
+
                        seg.aabb.expand(cur_x,cur_y);
                        seg.pointlist.push_back(Point(cur_x,cur_y));
                        seg.pointlist.push_back(Point(x,y));
@@ -781,32 +786,32 @@ struct Layer_Shape::Intersector
                }
                //add to the last segment, because it works
                else
-               {                       
+               {
                        segs.back().pointlist.push_back(Point(x,y));
                        segs.back().aabb.expand(x,y);
                }
 
 
-                                               
+
                cur_x = x;
                cur_y = y;
-               aabb.expand(x,y); //expand the entire things bounding box
-               
+               aabb.expand(x,y); //expand the entire thing's bounding box
+
                tangent[0] = x - cur_x;
                tangent[1] = x - cur_y;
-               
+
                flags |= NotClosed;
                prim = TYPE_LINE;
        }
-       
+
        void conic_to_smooth(Real x, Real y)
        {
                const Real x1 = tangent[0]/2.0 + cur_x;
                const Real y1 = tangent[1]/2.0 + cur_y;
-               
+
                conic_to(x1,y1,x,y);
        }
-       
+
        void conic_to(Real x1, Real y1, Real x, Real y)
        {
                //if we're not already a curve start one
@@ -816,34 +821,34 @@ struct Layer_Shape::Intersector
 
                        c.Start(Point(cur_x,cur_y));
                        c.AddConic(Point(x1,y1),Point(x,y));
-                       
+
                        curves.push_back(c);
                }else
                {
                        curves.back().AddConic(Point(x1,y1),Point(x,y));
                }
-               
+
                cur_x = x;
                cur_y = y;
-               
+
                aabb.expand(x1,y1);
                aabb.expand(x,y);
-               
+
                tangent[0] = 2*(x - x1);
                tangent[1] = 2*(y - y1);
-               
+
                flags |= NotClosed;
                prim = TYPE_CURVE;
        }
-       
+
        void curve_to_smooth(Real x2, Real y2, Real x, Real y)
        {
                Real x1 = tangent[0]/3.0 + cur_x;
                Real y1 = tangent[1]/3.0 + cur_y;
-               
-               curve_to(x1,y1,x2,y2,x,y);              
+
+               curve_to(x1,y1,x2,y2,x,y);
        }
-       
+
        void curve_to(Real x1, Real y1, Real x2, Real y2, Real x, Real y)
        {
                //if we're not already a curve start one
@@ -853,28 +858,28 @@ struct Layer_Shape::Intersector
 
                        c.Start(Point(cur_x,cur_y));
                        c.AddCubic(Point(x1,y1),Point(x2,y2),Point(x,y));
-                       
+
                        curves.push_back(c);
                }else
                {
                        curves.back().AddCubic(Point(x1,y1),Point(x2,y2),Point(x,y));
                }
-               
+
                cur_x = x;
                cur_y = y;
-               
+
                //expand bounding box around ALL of it
                aabb.expand(x1,y1);
                aabb.expand(x2,y2);
                aabb.expand(x,y);
-               
+
                tangent[0] = 3*(x - x2);
                tangent[1] = 3*(y - y2);
-               
+
                flags |= NotClosed;
                prim = TYPE_CURVE;
        }
-       
+
        void close()
        {
                if(flags & NotClosed)
@@ -883,40 +888,40 @@ struct Layer_Shape::Intersector
                        {
                                line_to(close_x,close_y);
                        }
-                       
+
                        flags &= ~NotClosed;
                }
        }
-       
+
        //assumes the line to count the intersections with is (-1,0)
        int     intersect (Real x, Real y) const
        {
                int inter = 0;
                unsigned int i;
                vector<MonoSegment>::const_iterator s = segs.begin();
-               vector<CurveArray>::const_iterator c = curves.begin();          
-               
+               vector<CurveArray>::const_iterator c = curves.begin();
+
                Point   memory[3*MAX_SUBDIVISION_SIZE + 1];
-               
+
                for(i = 0; i < segs.size(); i++,s++)
                {
                        inter += s->intersect(x,y);
                }
-               
+
                for(i=0; i < curves.size(); i++,c++)
                        inter += c->intersect(x,y,memory);
-               
+
                return inter;
        }
-       
+
        //intersect an arbitrary line
        //int   intersect (Real x, Real y, Real vx, Real vy) {return 0;}
-       
+
        void clear()
-       { 
+       {
                segs.clear();
                curves.clear();
-               
+
                flags = 0;
                cur_x = cur_y = close_x = close_y = 0;
                prim = TYPE_NONE;
@@ -930,19 +935,19 @@ struct PenMark
 {
        int y,x;
        Real cover,area;
-       
-       PenMark(){}     
+
+       PenMark(){}
        PenMark(int xin, int yin, Real c, Real a)
                :y(yin),x(xin),cover(c),area(a) {}
-       
+
        void set(int xin, int yin, Real c, Real a)      { y = yin; x = xin; cover = c; area = a;        }
-       
+
        void setcoord(int xin, int yin)                         { y = yin; x = xin;     }
-       
+
        void setcover(Real c, Real a)                           { cover = c; area = a; }
        void addcover(Real c, Real a)                           { cover += c; area += a; }
-       
-       bool operator < (const PenMark &rhs) const
+
+       bool operator<(const PenMark &rhs) const
        {
                return y == rhs.y ? x < rhs.x : y < rhs.y;
        }
@@ -969,7 +974,7 @@ public:
        //starting position of current primitive list
        Real                    close_x;
        Real                    close_y;
-       
+
        //flags for the current segment
        int                             flags;
 
@@ -982,30 +987,30 @@ public:
                NotSorted = 0x8000,
                NotClosed =     0x4000
        };
-       
+
        //default constructor - 0 everything
        PolySpan() :current(0,0,0,0),flags(NotSorted)
        {
                cur_x = cur_y = close_x = close_y = 0;
                open_index = 0;
        }
-       
+
        bool notclosed() const
        {
-               return (flags & NotClosed) | (cur_x != close_x) | (cur_y != close_y);
+               return (flags & NotClosed) || (cur_x != close_x) || (cur_y != close_y);
        }
-       
-       //0 out all the variables involved in processing 
+
+       //0 out all the variables involved in processing
        void clear()
        {
                covers.clear();
                cur_x = cur_y = close_x = close_y = 0;
-               open_index = 0;         
+               open_index = 0;
                current.set(0,0,0,0);
                flags = NotSorted;
        }
 
-       //add the current cell, but only if there is information to add 
+       //add the current cell, but only if there is information to add
        void addcurrent()
        {
                if(current.cover || current.area)
@@ -1013,17 +1018,17 @@ public:
                        covers.push_back(current);
                }
        }
-       
+
        //move to the next cell (cover values 0 initially), keeping the current if necessary
        void move_pen(int x, int y)
        {
-               if(y != current.y | x != current.x)
+               if(y != current.y || x != current.x)
                {
                        addcurrent();
                        current.set(x,y,0,0);
                }
        }
-       
+
        //close the primitives with a line (or rendering will not work as expected)
        void close()
        {
@@ -1038,28 +1043,28 @@ public:
                        flags &= ~NotClosed;
                }
        }
-       
+
        // Not recommended - destroys any separation of spans currently held
        void merge_all()
        {
                sort(covers.begin(),covers.end());
                open_index = 0;
        }
-       
+
        //will sort the marks if they are not sorted
        void sort_marks()
        {
                if(flags & NotSorted)
                {
-                       //only sort the open index                      
+                       //only sort the open index
                        addcurrent();
                        current.setcover(0,0);
-                       
+
                        sort(covers.begin() + open_index,covers.end());
                        flags &= ~NotSorted;
                }
        }
-       
+
        //encapsulate the current sublist of marks (used for drawing)
        void encapsulate_current()
        {
@@ -1067,7 +1072,7 @@ public:
                sort_marks();
                open_index = covers.size();
        }
-       
+
        //move to start a new primitive list (enclose the last primitive if need be)
        void move_to(Real x, Real y)
        {
@@ -1083,24 +1088,32 @@ public:
        void line_to(Real x, Real y);
        void conic_to(Real x1, Real y1, Real x, Real y);
        void cubic_to(Real x1, Real y1, Real x2, Real y2, Real x, Real y);
-       
+
        void draw_scanline(int y, Real x1, Real y1, Real x2, Real y2);
        void draw_line(Real x1, Real y1, Real x2, Real y2);
-       
-       Real ExtractAlpha(Real area)
-       {
-               //non-zero winding style
-               if(area < 0) area = -area;
-               if(area > 1) area = 1;
-                       
-               //even-odd winding style
-               /*if(area < 0) area = -area;
-               
-               while(area > 2) area -= 2;
-               if(area > 1) area = 1-area; //want pyramid like thing
-               */
-               //broken? - yep broken
-                               
+
+       Real ExtractAlpha(Real area, WindingStyle winding_style)
+       {
+               if (area < 0)
+                       area = -area;
+
+               if (winding_style == WINDING_NON_ZERO)
+               {
+                       // non-zero winding style
+                       if (area > 1)
+                               return 1;
+               }
+               else // if (winding_style == WINDING_EVEN_ODD)
+               {
+                       // even-odd winding style
+                       while (area > 1)
+                               area -= 2;
+
+                       // want pyramid like thing
+                       if (area < 0)
+                               area = -area;
+               }
+
                return area;
        }
 };
@@ -1111,11 +1124,12 @@ Layer_Shape::Layer_Shape(const Real &a, const Color::BlendMethod m):
        Layer_Composite (a,m),
        edge_table              (new Intersector),
        color                   (Color::black()),
-       offset                  (0,0),
+       origin                  (0,0),
        invert                  (false),
        antialias               (true),
        blurtype                (Blur::FASTGAUSSIAN),
        feather                 (0),
+       winding_style   (WINDING_NON_ZERO),
        bytestream              (0),
        lastbyteop              (Primitive::NONE),
        lastoppos               (-1)
@@ -1133,17 +1147,22 @@ Layer_Shape::clear()
        edge_table->clear();
        bytestream.clear();
 }
-       
+
 bool
 Layer_Shape::set_param(const String & param, const ValueBase &value)
 {
-       IMPORT(color);
-       IMPORT(offset);
+       IMPORT_PLUS(color, { if (color.get_a() == 0) { if (converted_blend_) {
+                                       set_blend_method(Color::BLEND_ALPHA_OVER);
+                                       color.set_a(1); } else transparent_color_ = true; } });
+       IMPORT(origin);
        IMPORT(invert);
        IMPORT(antialias);
-       IMPORT(feather);
+       IMPORT_PLUS(feather, if(feather<0)feather=0;);
        IMPORT(blurtype);
-       
+       IMPORT(winding_style);
+
+       IMPORT_AS(origin,"offset");
+
        return Layer_Composite::set_param(param,value);
 }
 
@@ -1151,15 +1170,16 @@ ValueBase
 Layer_Shape::get_param(const String &param)const
 {
        EXPORT(color);
-       EXPORT(offset);
+       EXPORT(origin);
        EXPORT(invert);
        EXPORT(antialias);
        EXPORT(feather);
        EXPORT(blurtype);
-       
+       EXPORT(winding_style);
+
        EXPORT_NAME();
        EXPORT_VERSION();
-               
+
        return Layer_Composite::get_param(param);
 }
 
@@ -1167,20 +1187,20 @@ Layer::Vocab
 Layer_Shape::get_param_vocab()const
 {
        Layer::Vocab ret(Layer_Composite::get_param_vocab());
-       
+
        ret.push_back(ParamDesc("color")
                .set_local_name(_("Color"))
                .set_description(_("Layer_Shape Color"))
        );
-       ret.push_back(ParamDesc("offset")
-               .set_local_name(_("Position"))
+       ret.push_back(ParamDesc("origin")
+               .set_local_name(_("Origin"))
        );
        ret.push_back(ParamDesc("invert")
                .set_local_name(_("Invert"))
        );
        ret.push_back(ParamDesc("antialias")
                .set_local_name(_("Antialiasing"))
-       );      
+       );
        ret.push_back(ParamDesc("feather")
                .set_local_name(_("Feather"))
                .set_is_distance()
@@ -1195,15 +1215,22 @@ Layer_Shape::get_param_vocab()const
                .add_enum_value(Blur::GAUSSIAN,"gaussian",_("Gaussian Blur"))
                .add_enum_value(Blur::DISC,"disc",_("Disc Blur"))
        );
-       
+       ret.push_back(ParamDesc("winding_style")
+               .set_local_name(_("Winding Style"))
+               .set_description(_("Winding style to use"))
+               .set_hint("enum")
+               .add_enum_value(WINDING_NON_ZERO,"nonzero",_("Non Zero"))
+               .add_enum_value(WINDING_EVEN_ODD,"evenodd",_("Even/Odd"))
+       );
+
        return ret;
 }
 
 synfig::Layer::Handle
 Layer_Shape::hit_check(synfig::Context context, const synfig::Point &p)const
 {
-       Point pos(p-offset);
-               
+       Point pos(p-origin);
+
        int intercepts = edge_table->intersect(pos[0],pos[1]);
 
        // If we have an odd number of intercepts, we are inside.
@@ -1245,20 +1272,20 @@ Color
 Layer_Shape::get_color(Context context, const Point &p)const
 {
        Point pp = p;
-       
+
        if(feather)
                pp = Blur(feather,feather,blurtype)(p);
-       
-       Point pos(pp-offset);
-               
+
+       Point pos(pp-origin);
+
        int intercepts = edge_table->intersect(pos[0],pos[1]);
 
        // If we have an odd number of intercepts, we are inside.
        // If we have an even number of intercepts, we are outside.
        bool intersect = ((!!intercepts) ^ invert);
-       
+
        if(!intersect)
-               return context.get_color(pp);
+               return Color::blend(Color::alpha(),context.get_color(pp),get_amount(),get_blend_method());
 
        //Ok, we're inside... bummmm ba bum buM...
        if(get_blend_method() == Color::BLEND_STRAIGHT && get_amount() == 1)
@@ -1268,48 +1295,48 @@ Layer_Shape::get_color(Context context, const Point &p)const
 }
 
 //************** SCANLINE RENDERING *********************
-void Layer_Shape::PolySpan::line_to(Real x, Real y)    
-{      
-       Real n[4];
+void Layer_Shape::PolySpan::line_to(Real x, Real y)
+{
+       Real n[4] = {0,0,0,0};
        bool afterx = false;
-       
+
        const Real xin(x), yin(y);
-       
+
        Real dx = x - cur_x;
        Real dy = y - cur_y;
-       
+
        //CLIP IT!!!!
        try {
        //outside y - ignore entirely
-       if(      (cur_y >= window.maxy & y >= window.maxy)
-               |(cur_y <  window.miny & y <  window.miny) )
+       if(      (cur_y >= window.maxy && y >= window.maxy)
+          ||(cur_y <  window.miny && y <  window.miny) )
        {
                cur_x = x;
-               cur_y = y;      
+               cur_y = y;
        }
        else //not degenerate - more complicated
        {
                if(dy > 0) //be sure it's not tooooo small
-               {                               
+               {
                        // cur_y ... window.miny ... window.maxy ... y
-                       
+
                        //initial degenerate - initial clip
                        if(cur_y < window.miny)
                        {
                                //new clipped start point (must also move pen)
                                n[2] = cur_x + (window.miny - cur_y) * dx / dy;
-                               
+
                                cur_x = n[2];
                                cur_y = window.miny;
                                move_pen((int)floor(cur_x),window.miny);
                        }
-                       
-                       //generate data for the ending clipped info                     
+
+                       //generate data for the ending clipped info
                        if(y > window.maxy)
                        {
-                               //intial line to intersection (and degenerate)
+                               //initial line to intersection (and degenerate)
                                n[2] = x + (window.maxy - y) * dx / dy;
-       
+
                                //intersect coords
                                x = n[2];
                                y = window.maxy;
@@ -1319,27 +1346,27 @@ void Layer_Shape::PolySpan::line_to(Real x, Real y)
                {
                        //initial degenerate - initial clip
                        if(cur_y > window.maxy)
-                       {                               
+                       {
                                //new clipped start point (must also move pen)
                                n[2] = cur_x + (window.maxy - cur_y) * dx / dy;
-                               
+
                                cur_x = n[2];
                                cur_y = window.maxy;
                                move_pen((int)floor(cur_x),window.maxy);
                        }
-                       
-                       //generate data for the ending clipped info                     
+
+                       //generate data for the ending clipped info
                        if(y < window.miny)
                        {
-                               //intial line to intersection (and degenerate)
+                               //initial line to intersection (and degenerate)
                                n[2] = x + (window.miny - y) * dx / dy;
-       
+
                                //intersect coords
                                x = n[2];
                                y = window.miny;
                        }
                }
-               
+
                //all degenerate - but require bounded clipped values
                if(   (cur_x >= window.maxx && x >= window.maxx)
                        ||(cur_x <  window.minx && x <  window.minx) )
@@ -1347,19 +1374,19 @@ void Layer_Shape::PolySpan::line_to(Real x, Real y)
                        //clip both vertices - but only needed in the x direction
                        cur_x = max(cur_x,      (Real)window.minx);
                        cur_x = min(cur_x,      (Real)window.maxx);
-                       
-                       //clip the dest values - y is already clipped                           
+
+                       //clip the dest values - y is already clipped
                        x = max(x,(Real)window.minx);
                        x = min(x,(Real)window.maxx);
-                       
+
                        //must start at new point...
                        move_pen((int)floor(cur_x),(int)floor(cur_y));
-                       
+
                        draw_line(cur_x,cur_y,x,y);
-                       
+
                        cur_x = xin;
                        cur_y = yin;
-               }                               
+               }
                else
                {
                        //clip x
@@ -1370,23 +1397,23 @@ void Layer_Shape::PolySpan::line_to(Real x, Real y)
                                {
                                        //need to draw an initial segment from clippedx,cur_y to clippedx,intersecty
                                        n[2] = cur_y + (window.minx - cur_x) * dy / dx;
-                                       
+
                                        move_pen(window.minx,(int)floor(cur_y));
                                        draw_line(window.minx,cur_y,window.minx,n[2]);
-                                       
+
                                        cur_x = window.minx;
                                        cur_y = n[2];
                                }
-                               
-                               //generate data for the ending clipped info                     
+
+                               //generate data for the ending clipped info
                                if(x > window.maxx)
                                {
-                                       //intial line to intersection (and degenerate)
+                                       //initial line to intersection (and degenerate)
                                        n[2] = y + (window.maxx - x) * dy / dx;
-                                       
+
                                        n[0] = window.maxx;
                                        n[1] = y;
-               
+
                                        //intersect coords
                                        x = window.maxx;
                                        y = n[2];
@@ -1399,39 +1426,39 @@ void Layer_Shape::PolySpan::line_to(Real x, Real y)
                                {
                                        //need to draw an initial segment from clippedx,cur_y to clippedx,intersecty
                                        n[2] = cur_y + (window.maxx - cur_x) * dy / dx;
-                                       
+
                                        move_pen(window.maxx,(int)floor(cur_y));
                                        draw_line(window.maxx,cur_y,window.maxx,n[2]);
-                                       
+
                                        cur_x = window.maxx;
                                        cur_y = n[2];
                                }
-                               
-                               //generate data for the ending clipped info                     
+
+                               //generate data for the ending clipped info
                                if(x < window.minx)
                                {
-                                       //intial line to intersection (and degenerate)
+                                       //initial line to intersection (and degenerate)
                                        n[2] = y + (window.minx - x) * dy / dx;
-                                       
+
                                        n[0] = window.minx;
                                        n[1] = y;
-               
+
                                        //intersect coords
                                        x = window.minx;
                                        y = n[2];
                                        afterx = true;
                                }
                        }
-                       
+
                        move_pen((int)floor(cur_x),(int)floor(cur_y));
                        //draw the relevant line (clipped)
                        draw_line(cur_x,cur_y,x,y);
-                       
+
                        if(afterx)
                        {
                                draw_line(x,y,n[0],n[1]);
                        }
-                               
+
                        cur_x = xin;
                        cur_y = yin;
                }
@@ -1448,9 +1475,9 @@ static inline bool clip_conic(const Point *const p, const ContextRect &r)
        const Real maxx = max(max(p[0][0],p[1][0]),p[2][0]);
        const Real maxy = max(max(p[0][1],p[1][1]),p[2][1]);
 
-       return  (minx > r.maxx) |
-                       (maxx < r.minx) |
-                       (miny > r.maxy) |
+       return  (minx > r.maxx) ||
+                       (maxx < r.minx) ||
+                       (miny > r.maxy) ||
                        (maxy < r.miny);
 }
 
@@ -1465,28 +1492,28 @@ static inline bool clip_cubic(const Point *const p, const ContextRect &r)
                        (maxx < r.minx) ||
                        (miny > r.maxy) ||
                        (maxy < r.miny);*/
-       
-       return  ((p[0][0] > r.maxx) & (p[1][0] > r.maxx) & (p[2][0] > r.maxx) & (p[3][0] > r.maxx)) |
-                       ((p[0][0] < r.minx) & (p[1][0] < r.minx) & (p[2][0] < r.minx) & (p[3][0] < r.minx)) |
-                       ((p[0][1] > r.maxy) & (p[1][1] > r.maxy) & (p[2][1] > r.maxy) & (p[3][1] > r.maxy)) |
-                       ((p[0][1] < r.miny) & (p[1][1] < r.miny) & (p[2][1] < r.miny) & (p[3][1] < r.miny));
+
+       return  ((p[0][0] > r.maxx) && (p[1][0] > r.maxx) && (p[2][0] > r.maxx) && (p[3][0] > r.maxx)) ||
+                       ((p[0][0] < r.minx) && (p[1][0] < r.minx) && (p[2][0] < r.minx) && (p[3][0] < r.minx)) ||
+                       ((p[0][1] > r.maxy) && (p[1][1] > r.maxy) && (p[2][1] > r.maxy) && (p[3][1] > r.maxy)) ||
+                       ((p[0][1] < r.miny) && (p[1][1] < r.miny) && (p[2][1] < r.miny) && (p[3][1] < r.miny));
 }
 
 static inline Real max_edges_cubic(const Point *const p)
 {
        const Real x1 = p[1][0] - p[0][0];
        const Real y1 = p[1][1] - p[0][1];
-       
+
        const Real x2 = p[2][0] - p[1][0];
        const Real y2 = p[2][1] - p[1][1];
-       
+
        const Real x3 = p[3][0] - p[2][0];
        const Real y3 = p[3][1] - p[2][1];
-       
+
        const Real d1 = x1*x1 + y1*y1;
        const Real d2 = x2*x2 + y2*y2;
        const Real d3 = x3*x3 + y3*y3;
-       
+
        return max(max(d1,d2),d3);
 }
 
@@ -1494,13 +1521,13 @@ static inline Real max_edges_conic(const Point *const p)
 {
        const Real x1 = p[1][0] - p[0][0];
        const Real y1 = p[1][1] - p[0][1];
-       
+
        const Real x2 = p[2][0] - p[1][0];
        const Real y2 = p[2][1] - p[1][1];
-       
+
        const Real d1 = x1*x1 + y1*y1;
        const Real d2 = x2*x2 + y2*y2;
-       
+
        return max(d1,d2);
 }
 
@@ -1510,25 +1537,25 @@ void Layer_Shape::PolySpan::conic_to(Real x1, Real y1, Real x, Real y)
        int             level = 0;
        int     num = 0;
        bool    onsecond = false;
-       
+
        arc[0] = Point(x,y);
        arc[1] = Point(x1,y1);
        arc[2] = Point(cur_x,cur_y);
-       
+
        //just draw the line if it's outside
        if(clip_conic(arc,window))
        {
                line_to(x,y);
                return;
        }
-       
+
        //Ok so it's not super degenerate, subdivide and draw (run through minimum subdivision levels first)
        while(current >= arc)
        {
                if(num >= MAX_SUBDIVISION_SIZE)
                {
-                       warning("Curve subdivision somehow ran out of space while tesselating!");
-                       
+                       warning("Curve subdivision somehow ran out of space while tessellating!");
+
                        //do something...
                        assert(0);
                        return;
@@ -1567,7 +1594,7 @@ void Layer_Shape::PolySpan::conic_to(Real x1, Real y1, Real x, Real y)
                        //cur_x,cur_y = current[2], so we need to go 1,0
                        line_to(current[1][0],current[1][1]);
                        line_to(current[0][0],current[0][1]);
-                       
+
                        current -= 2;
                        if(onsecond) level--;
                        num--;
@@ -1582,32 +1609,32 @@ void Layer_Shape::PolySpan::cubic_to(Real x1, Real y1, Real x2, Real y2, Real x,
        int             num = 0;
        int             level = 0;
        bool    onsecond = false;
-       
+
        arc[0] = Point(x,y);
        arc[1] = Point(x2,y2);
        arc[2] = Point(x1,y1);
        arc[3] = Point(cur_x,cur_y);
-       
+
        //just draw the line if it's outside
        if(clip_cubic(arc,window))
        {
                line_to(x,y);
                return;
        }
-       
+
        //Ok so it's not super degenerate, subdivide and draw (run through minimum subdivision levels first)
        while(current >= arc) //once current goes below arc, there are no more curves left
        {
                if(num >= MAX_SUBDIVISION_SIZE)
                {
-                       warning("Curve subdivision somehow ran out of space while tesselating!");
-                       
+                       warning("Curve subdivision somehow ran out of space while tessellating!");
+
                        //do something...
                        assert(0);
                        return;
                }else
-               
-               //if we are not at the level minimum 
+
+               //if we are not at the level minimum
                if(level < MIN_SUBDIVISION_DRAW_LEVELS)
                {
                        Subd_Cubic_Stack(current);
@@ -1626,7 +1653,7 @@ void Layer_Shape::PolySpan::cubic_to(Real x1, Real y1, Real x2, Real y2, Real x,
                        onsecond = true;
                        num --;
                        continue;
-               }               
+               }
                else
                //split it again, if it's too big
                if(max_edges_cubic(current) > 0.25) //could use max_edges<3>
@@ -1643,18 +1670,18 @@ void Layer_Shape::PolySpan::cubic_to(Real x1, Real y1, Real x2, Real y2, Real x,
                        line_to(current[2][0],current[2][1]);
                        line_to(current[1][0],current[1][1]);
                        line_to(current[0][0],current[0][1]);
-                       
+
                        current -= 3;
                        if(onsecond) level--;
                        num --;
                        onsecond = true;
                }
-       }       
+       }
 }
 
 //******************** LINE ALGORITHMS ****************************
-// THESE CALCULATE THE AREA AND THE COVER FOR THE MARKS, TO THEN SCAN CONVERT 
-// - BROKEN UP INTO SCANLINES (draw_line - y intersections), 
+// THESE CALCULATE THE AREA AND THE COVER FOR THE MARKS, TO THEN SCAN CONVERT
+// - BROKEN UP INTO SCANLINES (draw_line - y intersections),
 //   THEN THE COVER AND AREA PER TOUCHED PIXEL IS CALCULATED (draw_scanline - x intersections)
 void Layer_Shape::PolySpan::draw_scanline(int y, Real x1, Real fy1, Real x2, Real fy2)
 {
@@ -1662,23 +1689,23 @@ void Layer_Shape::PolySpan::draw_scanline(int y, Real x1, Real fy1, Real x2, Rea
        int     ix2 = (int)floor(x2);
        Real fx1 = x1 - ix1;
        Real fx2 = x2 - ix2;
-       
+
        Real dx,dy,dydx,mult;
-       
+
        dx = x2 - x1;
        dy = fy2 - fy1;
-       
+
        //case horizontal line
        if(fy1 == fy2)
        {
                move_pen(ix2,y); //pen needs to be at the last coord
                return;
        }
-       
+
        //case all in same pixel
        if(ix1 == ix2)  //impossible for degenerate case (covered by the previous cases)
        {
-               current.addcover(dy,(fx1 + fx2)*dy/2); //horizontal trapazoid area
+               current.addcover(dy,(fx1 + fx2)*dy/2); //horizontal trapezoid area
                return;
        }
 
@@ -1686,32 +1713,32 @@ void Layer_Shape::PolySpan::draw_scanline(int y, Real x1, Real fy1, Real x2, Rea
        {
                // ---->        fx1...1  0...1  ...  0...1  0...fx2
                dydx = dy / dx;
-               
+
                //set initial values
                //Iterate through the covered pixels
                mult = (1 - fx1)*dydx;  //next y intersection diff value (at 1)
-               
+
                //first pixel
-               current.addcover(mult,(1 + fx1)*mult/2);        // fx1,fy1,1,fy@1 - starting trapazoidal area
-                       
+               current.addcover(mult,(1 + fx1)*mult/2);        // fx1,fy1,1,fy@1 - starting trapezoidal area
+
                //move to the next pixel
                fy1 += mult;
                ix1++;
-               
+
                move_pen(ix1,y);
-               
+
                //set up for whole ones
                while(ix1 != ix2)
                {
                        //trapezoid(0,y1,1,y1+dydx);
-                       current.addcover(dydx,dydx/2);  //accumulated area 1/2 the cover                        
-                       
+                       current.addcover(dydx,dydx/2);  //accumulated area 1/2 the cover
+
                        //move to next pixel (+1)
                        ix1++;
                        fy1 += dydx;
                        move_pen(ix1,y);
                }
-               
+
                //last pixel
                //final y-pos - last intersect pos
                mult = fx2 * dydx;
@@ -1722,35 +1749,35 @@ void Layer_Shape::PolySpan::draw_scanline(int y, Real x1, Real fy1, Real x2, Rea
                //mult = (0 - fx1) * dy / dx;
                //neg sign sucked into dydx
                dydx = -dy / dx;
-               
+
                //set initial values
                //Iterate through the covered pixels
                mult = fx1*dydx;        //next y intersection diff value
-               
+
                //first pixel
-               current.addcover(mult,fx1*mult/2);      // fx1,fy1,0,fy@0 - starting trapazoidal area
-               
+               current.addcover(mult,fx1*mult/2);      // fx1,fy1,0,fy@0 - starting trapezoidal area
+
                //move to next pixel
                fy1 += mult;
                ix1--;
-               
+
                move_pen(ix1,y);
-               
+
                //set up for whole ones
                while(ix1 != ix2)
                {
                        //trapezoid(0,y1,1,y1+dydx);
-                       current.addcover(dydx,dydx/2);  //accumulated area 1/2 the cover                        
-                       
+                       current.addcover(dydx,dydx/2);  //accumulated area 1/2 the cover
+
                        //move to next pixel (-1)
                        fy1 += dydx;
                        ix1--;
                        move_pen(ix1,y);
                }
-               
+
                //last pixel
                mult = fy2 - fy1; //final y-pos - last intersect pos
-               
+
                current.addcover(mult,(fx2+1)*mult/2);
        }
 }
@@ -1764,143 +1791,143 @@ void Layer_Shape::PolySpan::draw_line(Real x1, Real y1, Real x2, Real y2)
 
        assert(!isnan(fy1));
        assert(!isnan(fy2));
-       
+
        Real dx,dy,dxdy,mult,x_from,x_to;
-       
+
        const Real SLOPE_EPSILON = 1e-10;
-       
+
        //case all one scanline
        if(iy1 == iy2)
        {
                draw_scanline(iy1,x1,y1,x2,y2);
                return;
        }
-       
+
        //difference values
        dy = y2 - y1;
-       dx = x2 - x1;   
-       
+       dx = x2 - x1;
+
        //case vertical line
        if(dx < SLOPE_EPSILON && dx > -SLOPE_EPSILON)
        {
-               //calc area and cover on vertical line          
+               //calc area and cover on vertical line
                if(dy > 0)
                {
                        // ---->        fx1...1  0...1  ...  0...1  0...fx2
                        Real sub;
-                                               
+
                        int      ix1 = (int)floor(x1);
                        Real fx1 = x1 - ix1;
-                       
+
                        //current pixel
                        sub = 1 - fy1;
-                       
+
                        current.addcover(sub,fx1*sub);
-               
+
                        //next pixel
                        iy1++;
 
                        //move pen to next pixel
                        move_pen(ix1,iy1);
-                                               
+
                        while(iy1 != iy2)
-                       {                                       
+                       {
                                //accumulate cover
                                current.addcover(1,fx1);
-                               
+
                                //next pixel
                                iy1++;
                                move_pen(ix1,iy1);
                        }
-                       
+
                        //last pixel
                        current.addcover(fy2,fy2*fx1);
                }else
                {
                        Real sub;
-                                               
+
                        int      ix1 = (int)floor(x1);
                        Real fx1 = x1 - ix1;
-                       
+
                        //current pixel
                        sub = 0 - fy1;
-                       
+
                        current.addcover(sub,fx1*sub);
-               
+
                        //next pixel
                        iy1--;
-                       
+
                        move_pen(ix1,iy1);
-                       
+
                        while(iy1 != iy2)
                        {
                                //accumulate in current pixel
                                current.addcover(-1,-fx1);
-                               
+
                                //move to next
                                iy1--;
                                move_pen(ix1,iy1);
                        }
-                       
+
                        current.addcover(fy2-1,(fy2-1)*fx1);
                }
                return;
        }
 
        //case normal line - guaranteed dx != 0 && dy != 0
-       
+
        //calculate the initial intersection with "next" scanline
        if(dy > 0)
        {
                dxdy = dx / dy;
-               
+
                mult = (1 - fy1) * dxdy;
-               
-               //x interset scanline           
+
+               //x intersect scanline
                x_from = x1 + mult;
                draw_scanline(iy1,x1,fy1,x_from,1);
-       
+
                //move to next line
                iy1++;
-               
+
                move_pen((int)floor(x_from),iy1);
-               
+
                while(iy1 != iy2)
                {
                        //keep up on the x axis, and render the current scanline
                        x_to = x_from + dxdy;
                        draw_scanline(iy1,x_from,0,x_to,1);
                        x_from = x_to;
-                       
+
                        //move to next pixel
                        iy1++;
                        move_pen((int)floor(x_from),iy1);
                }
-               
+
                //draw the last one, fractional
                draw_scanline(iy2,x_from,0,x2,fy2);
-               
+
        }else
        {
                dxdy = -dx / dy;
-               
+
                mult = fy1 * dxdy;
-               
-               //x interset scanline
+
+               //x intersect scanline
                x_from = x1 + mult;
                draw_scanline(iy1,x1,fy1,x_from,0);
-               
+
                //each line after
                iy1--;
-               
+
                move_pen((int)floor(x_from),iy1);
-               
+
                while(iy1 != iy2)
                {
                        x_to = x_from + dxdy;
                        draw_scanline(iy1,x_from,1,x_to,0);
                        x_from = x_to;
-                       
+
                        iy1--;
                        move_pen((int)floor(x_from),iy1);
                }
@@ -1915,10 +1942,10 @@ void Layer_Shape::move_to(Real x, Real y)
        //const int sizeblock = sizeof(Primitive)+sizeof(Point);
        Primitive       op;
        Point           p(x,y);
-       
+
        op.operation = Primitive::MOVE_TO;
        op.number = 1;  //one point for now
-       
+
        if(lastbyteop == Primitive::MOVE_TO)
        {
                char *ptr = &bytestream[lastoppos];
@@ -1929,31 +1956,31 @@ void Layer_Shape::move_to(Real x, Real y)
        {
                lastbyteop = Primitive::MOVE_TO;
                lastoppos = bytestream.size();
-               
+
                bytestream.insert(bytestream.end(),(char*)&op,(char*)(&op+1));  //insert the bytes for the header
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));    //insert the bytes for data
        }
-       
+
        edge_table->move_to(x,y);
 }
 
 void Layer_Shape::close()
 {
        Primitive op;
-       
+
        op.operation = Primitive::CLOSE;
        op.number = 0;
-       
+
        if(lastbyteop == Primitive::CLOSE)
        {
        }else
        {
                lastbyteop = Primitive::CLOSE;
                lastoppos = bytestream.size();
-               
+
                bytestream.insert(bytestream.end(),(char*)&op,(char*)(&op+1)); //insert header
        }
-       
+
        edge_table->close();
        //should not affect the bounding box since it would just be returning to old point...
 }
@@ -1961,11 +1988,11 @@ void Layer_Shape::close()
 void Layer_Shape::endpath()
 {
        Primitive op;
-       
+
        op.operation = Primitive::END;
        op.number = 0;
-       
-       if(lastbyteop == Primitive::END | lastbyteop == Primitive::NONE)
+
+       if(lastbyteop == Primitive::END || lastbyteop == Primitive::NONE)
        {
        }else
        {
@@ -1978,30 +2005,30 @@ void Layer_Shape::line_to(Real x, Real y)
 {
        assert(!isnan(x));
        assert(!isnan(y));
-       
+
        //const int sizeblock = sizeof(Primitive)+sizeof(Point);
        Primitive       op;
        Point           p(x,y);
-       
+
        op.operation = Primitive::LINE_TO;
        op.number = 1;  //one point for now
-       
-       if(lastbyteop == Primitive::MOVE_TO | lastbyteop == Primitive::LINE_TO)
+
+       if(lastbyteop == Primitive::MOVE_TO || lastbyteop == Primitive::LINE_TO)
        {
                //only need to insert the point
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));
-               
+
                Primitive * prim = (Primitive *)&bytestream[lastoppos];
                prim->number++; //increment number of points in the list
        }else
        {
                lastbyteop = Primitive::LINE_TO;
                lastoppos = bytestream.size();
-               
+
                bytestream.insert(bytestream.end(),(char*)&op,(char*)(&op+1));  //insert the bytes for the header
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));    //insert the bytes for data
        }
-       
+
        edge_table->line_to(x,y);
 }
 
@@ -2011,28 +2038,28 @@ void Layer_Shape::conic_to(Real x1, Real y1, Real x, Real y)
        Primitive       op;
        Point           p(x,y);
        Point           p1(x1,y1);
-       
+
        op.operation = Primitive::CONIC_TO;
        op.number = 2;  //2 points for now
-       
+
        if(lastbyteop == Primitive::CONIC_TO)
        {
                //only need to insert the new points
                bytestream.insert(bytestream.end(),(char*)&p1,(char*)(&p1+1));
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));
-               
+
                Primitive * prim = (Primitive *)&bytestream[lastoppos];
                prim->number += 2; //increment number of points in the list
        }else
        {
                lastbyteop = Primitive::CONIC_TO;
                lastoppos = bytestream.size();
-               
+
                bytestream.insert(bytestream.end(),(char*)&op,(char*)(&op+1));  //insert the bytes for the header
                bytestream.insert(bytestream.end(),(char*)&p1,(char*)(&p1+1));  //insert the bytes for data
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));    //insert the bytes for data
        }
-       
+
        edge_table->conic_to(x1,y1,x,y);
 }
 
@@ -2041,26 +2068,26 @@ void Layer_Shape::conic_to_smooth(Real x, Real y)                               //x1,y1 derived from curren
        //const int sizeblock = sizeof(Primitive)+sizeof(Point);
        Primitive       op;
        Point           p(x,y);
-       
+
        op.operation = Primitive::CONIC_TO_SMOOTH;
        op.number = 1;  //2 points for now
-       
+
        if(lastbyteop == Primitive::CONIC_TO_SMOOTH)
        {
                //only need to insert the new point
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));
-               
+
                Primitive * prim = (Primitive *)&bytestream[lastoppos];
                prim->number += 1; //increment number of points in the list
        }else
        {
                lastbyteop = Primitive::CONIC_TO_SMOOTH;
                lastoppos = bytestream.size();
-               
+
                bytestream.insert(bytestream.end(),(char*)&op,(char*)(&op+1));  //insert the bytes for the header
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));    //insert the bytes for data
        }
-       
+
        edge_table->conic_to_smooth(x,y);
 }
 
@@ -2071,30 +2098,30 @@ void Layer_Shape::curve_to(Real x1, Real y1, Real x2, Real y2, Real x, Real y)
        Point           p(x,y);
        Point           p1(x1,y1);
        Point           p2(x2,y2);
-       
+
        op.operation = Primitive::CUBIC_TO;
        op.number = 3;  //3 points for now
-       
+
        if(lastbyteop == Primitive::CUBIC_TO)
        {
                //only need to insert the new points
                bytestream.insert(bytestream.end(),(char*)&p1,(char*)(&p1+1));
                bytestream.insert(bytestream.end(),(char*)&p2,(char*)(&p2+1));
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));
-               
+
                Primitive * prim = (Primitive *)&bytestream[lastoppos];
                prim->number += 3; //increment number of points in the list
        }else
        {
                lastbyteop = Primitive::CUBIC_TO;
                lastoppos = bytestream.size();
-               
+
                bytestream.insert(bytestream.end(),(char*)&op,(char*)(&op+1));  //insert the bytes for the header
                bytestream.insert(bytestream.end(),(char*)&p1,(char*)(&p1+1));  //insert the bytes for data
                bytestream.insert(bytestream.end(),(char*)&p2,(char*)(&p2+1));  //insert the bytes for data
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));    //insert the bytes for data
        }
-       
+
        edge_table->curve_to(x1,y1,x2,y2,x,y);
 }
 
@@ -2104,23 +2131,23 @@ void Layer_Shape::curve_to_smooth(Real x2, Real y2, Real x, Real y)             //x1,y1 der
        Primitive       op;
        Point           p(x,y);
        Point           p2(x2,y2);
-       
+
        op.operation = Primitive::CUBIC_TO_SMOOTH;
        op.number = 2;  //3 points for now
-       
+
        if(lastbyteop == Primitive::CUBIC_TO_SMOOTH)
        {
                //only need to insert the new points
                bytestream.insert(bytestream.end(),(char*)&p2,(char*)(&p2+1));
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));
-               
+
                Primitive * prim = (Primitive *)&bytestream[lastoppos];
                prim->number += 2; //increment number of points in the list
        }else
        {
                lastbyteop = Primitive::CUBIC_TO_SMOOTH;
                lastoppos = bytestream.size();
-               
+
                bytestream.insert(bytestream.end(),(char*)&op,(char*)(&op+1));  //insert the bytes for the header
                bytestream.insert(bytestream.end(),(char*)&p2,(char*)(&p2+1));  //insert the bytes for data
                bytestream.insert(bytestream.end(),(char*)&p,(char*)(&p+1));    //insert the bytes for data
@@ -2129,7 +2156,7 @@ void Layer_Shape::curve_to_smooth(Real x2, Real y2, Real x, Real y)               //x1,y1 der
 
 // ACCELERATED RENDER FUNCTION - TRANSLATE BYTE CODE INTO FUNCTION CALLS
 
-bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan, 
+bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan,
                                                                Color::BlendMethod got_blend_method, Color::value_type got_amount) const
 {
        Surface::alpha_pen p(surface->begin(),got_amount,_BlendFunc(got_blend_method));
@@ -2137,12 +2164,12 @@ bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan,
        PolySpan::cover_array::iterator end_mark = polyspan.covers.end();
 
        Real cover,area,alpha;
-       
+
        int     y,x;
-       
+
        p.set_value(color);
        cover = 0;
-       
+
        if(cur_mark == end_mark)
        {
                //no marks at all
@@ -2153,7 +2180,7 @@ bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan,
                }
                return true;
        }
-       
+
        //fill initial rect / line
        if(invert)
        {
@@ -2161,76 +2188,76 @@ bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan,
                p.move_to(polyspan.window.minx,polyspan.window.miny);
                y = polyspan.window.miny;
                int l = polyspan.window.maxx - polyspan.window.minx;
-       
+
                p.put_block(cur_mark->y - polyspan.window.miny,l);
-               
+
                //fill the area to the left of the first vertex on that line
                l = cur_mark->x - polyspan.window.minx;
                p.move_to(polyspan.window.minx,cur_mark->y);
                if(l) p.put_hline(l);
        }
-       
+
        for(;;)
        {
                y = cur_mark->y;
                x = cur_mark->x;
-               
+
                p.move_to(x,y);
-               
+
                area = cur_mark->area;
                cover += cur_mark->cover;
-                       
+
                //accumulate for the current pixel
                while(++cur_mark != polyspan.covers.end())
                {
-                       if(y != cur_mark->y | x != cur_mark->x)
+                       if(y != cur_mark->y || x != cur_mark->x)
                                break;
-                       
+
                        area += cur_mark->area;
                        cover += cur_mark->cover;
                }
-               
+
                //draw pixel - based on covered area
                if(area)        //if we're ok, draw the current pixel
                {
-                       alpha = polyspan.ExtractAlpha(cover - area);
+                       alpha = polyspan.ExtractAlpha(cover - area, winding_style);
                        if(invert) alpha = 1 - alpha;
-                       
+
                        if(!antialias)
                        {
                                if(alpha >= .5) p.put_value();
                        }
                        else if(alpha) p.put_value_alpha(alpha);
-                       
+
                        p.inc_x();
                        x++;
                }
-               
+
                //if we're done, don't use iterator and exit
                if(cur_mark == end_mark) break;
-                       
+
                //if there is no more live pixels on this line, goto next
                if(y != cur_mark->y)
                {
                        if(invert)
                        {
                                //fill the area at the end of the line
-                               p.put_hline(polyspan.window.maxx - x);                          
-                               
+                               p.put_hline(polyspan.window.maxx - x);
+
                                //fill area at the beginning of the next line
                                p.move_to(polyspan.window.minx,cur_mark->y);
                                p.put_hline(cur_mark->x - polyspan.window.minx);
                        }
-                       
-                       cover = 0;                      
-                       
+
+                       cover = 0;
+
                        continue;
                }
-               
+
                //draw span to next pixel - based on total amount of pixel cover
                if(x < cur_mark->x)
-               {                               
-                       alpha = polyspan.ExtractAlpha(cover);
+               {
+                       alpha = polyspan.ExtractAlpha(cover, winding_style);
                        if(invert) alpha = 1 - alpha;
 
                        if(!antialias)
@@ -2240,18 +2267,18 @@ bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan,
                        else if(alpha) p.put_hline(cur_mark->x - x,alpha);
                }
        }
-       
+
        //fill the after stuff
        if(invert)
        {
                //fill the area at the end of the line
-               p.put_hline(polyspan.window.maxx - x);                          
-               
+               p.put_hline(polyspan.window.maxx - x);
+
                //fill area at the beginning of the next line
                p.move_to(polyspan.window.minx,y+1);
                p.put_block(polyspan.window.maxy - y - 1,polyspan.window.maxx - polyspan.window.minx);
        }
-       
+
        return true;
 }
 
@@ -2262,14 +2289,14 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
        PolySpan::cover_array::iterator end_mark = polyspan.covers.end();
 
        Real cover,area,alpha;
-       
+
        int     y,x;
-       
-       cover = 0;      
-               
+
+       cover = 0;
+
        //the pen always writes 1 (unless told to do otherwise)
        p.set_value(1);
-       
+
        if(cur_mark == end_mark)
        {
                //no marks at all
@@ -2280,7 +2307,7 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                }
                return true;
        }
-       
+
        //fill initial rect / line
        if(invert)
        {
@@ -2288,70 +2315,70 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                p.move_to(polyspan.window.minx,polyspan.window.miny);
                y = polyspan.window.miny;
                int l = polyspan.window.maxx - polyspan.window.minx;
-       
+
                p.put_block(cur_mark->y - polyspan.window.miny,l);
-               
+
                //fill the area to the left of the first vertex on that line
                l = cur_mark->x - polyspan.window.minx;
                p.move_to(polyspan.window.minx,cur_mark->y);
                if(l) p.put_hline(l);
-               
+
                for(;;)
                {
                        y = cur_mark->y;
                        x = cur_mark->x;
-                       
+
                        p.move_to(x,y);
-                       
+
                        area = cur_mark->area;
                        cover += cur_mark->cover;
-                               
+
                        //accumulate for the current pixel
                        while(++cur_mark != polyspan.covers.end())
                        {
-                               if(y != cur_mark->y | x != cur_mark->x)
+                               if(y != cur_mark->y || x != cur_mark->x)
                                        break;
-                               
+
                                area += cur_mark->area;
                                cover += cur_mark->cover;
                        }
-                       
+
                        //draw pixel - based on covered area
                        if(area)        //if we're ok, draw the current pixel
                        {
-                               alpha = 1 - polyspan.ExtractAlpha(cover - area);                                
+                               alpha = 1 - polyspan.ExtractAlpha(cover - area, winding_style);
                                if(!antialias)
                                {
                                        if(alpha >= .5) p.put_value();
                                }
                                else if(alpha) p.put_value(alpha);
-                               
+
                                p.inc_x();
                                x++;
                        }
-                       
+
                        //if we're done, don't use iterator and exit
                        if(cur_mark == end_mark) break;
-                               
+
                        //if there is no more live pixels on this line, goto next
                        if(y != cur_mark->y)
                        {
                                //fill the area at the end of the line
                                p.put_hline(polyspan.window.maxx - x);
-                               
+
                                //fill area at the beginning of the next line
                                p.move_to(polyspan.window.minx,cur_mark->y);
                                p.put_hline(cur_mark->x - polyspan.window.minx);
-                       
-                               cover = 0;                      
-                               
+
+                               cover = 0;
+
                                continue;
                        }
-                       
+
                        //draw span to next pixel - based on total amount of pixel cover
                        if(x < cur_mark->x)
-                       {                               
-                               alpha = 1 - polyspan.ExtractAlpha(cover);
+                       {
+                               alpha = 1 - polyspan.ExtractAlpha(cover, winding_style);
                                if(!antialias)
                                {
                                        if(alpha >= .5) p.put_hline(cur_mark->x - x);
@@ -2359,10 +2386,10 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                                else if(alpha) p.put_hline(cur_mark->x - x,alpha);
                        }
                }
-               
+
                //fill the area at the end of the line
-               p.put_hline(polyspan.window.maxx - x);                          
-               
+               p.put_hline(polyspan.window.maxx - x);
+
                //fill area at the beginning of the next line
                p.move_to(polyspan.window.minx,y+1);
                p.put_block(polyspan.window.maxy - y - 1,polyspan.window.maxx - polyspan.window.minx);
@@ -2372,51 +2399,51 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                {
                        y = cur_mark->y;
                        x = cur_mark->x;
-                       
+
                        p.move_to(x,y);
-                       
+
                        area = cur_mark->area;
                        cover += cur_mark->cover;
-                               
+
                        //accumulate for the current pixel
                        while(++cur_mark != polyspan.covers.end())
                        {
-                               if(y != cur_mark->y | x != cur_mark->x)
+                               if(y != cur_mark->y || x != cur_mark->x)
                                        break;
-                               
+
                                area += cur_mark->area;
                                cover += cur_mark->cover;
                        }
-                       
+
                        //draw pixel - based on covered area
                        if(area)        //if we're ok, draw the current pixel
                        {
-                               alpha = polyspan.ExtractAlpha(cover - area);
+                               alpha = polyspan.ExtractAlpha(cover - area, winding_style);
                                if(!antialias)
                                {
                                        if(alpha >= .5) p.put_value();
                                }
                                else if(alpha) p.put_value(alpha);
-                               
+
                                p.inc_x();
                                x++;
                        }
-                       
+
                        //if we're done, don't use iterator and exit
                        if(cur_mark == end_mark) break;
-                               
+
                        //if there is no more live pixels on this line, goto next
                        if(y != cur_mark->y)
-                       {                               
-                               cover = 0;                      
-                               
+                       {
+                               cover = 0;
+
                                continue;
                        }
-                       
+
                        //draw span to next pixel - based on total amount of pixel cover
                        if(x < cur_mark->x)
-                       {                               
-                               alpha = polyspan.ExtractAlpha(cover);
+                       {
+                               alpha = polyspan.ExtractAlpha(cover, winding_style);
                                if(!antialias)
                                {
                                        if(alpha >= .5) p.put_hline(cur_mark->x - x);
@@ -2425,7 +2452,7 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                        }
                }
        }
-       
+
        return true;
 }
 
@@ -2434,60 +2461,60 @@ Layer_Shape::accelerated_render(Context context,Surface *surface,int quality, co
 {
        const unsigned int w = renddesc.get_w();
        const unsigned int h = renddesc.get_h();
-       
+
        const Real pw = abs(renddesc.get_pw());
        const Real ph = abs(renddesc.get_ph());
-       
+
        //const Real OFFSET_EPSILON = 1e-8;
        SuperCallback stageone(cb,1,10000,15001+renddesc.get_h());
        SuperCallback stagetwo(cb,10000,10001+renddesc.get_h(),15001+renddesc.get_h());
        SuperCallback stagethree(cb,10001+renddesc.get_h(),15001+renddesc.get_h(),15001+renddesc.get_h());
-       
+
        // Render what is behind us
-       
+
        //clip if it satisfies the invert solid thing
        if(is_solid_color() && invert)
-       {               
+       {
                Rect aabb = edge_table->aabb;
-               Point tl = renddesc.get_tl() - offset;
-               
+               Point tl = renddesc.get_tl() - origin;
+
                Real    pw = renddesc.get_pw(),
                                ph = renddesc.get_ph();
 
                Rect    nrect;
-               
-               Real    pixelfeatherx = abs(feather/pw),
-                               pixelfeathery = abs(feather/ph);
-               
+
+               Real    pixelfeatherx = quality == 10 ? 0 : abs(feather/pw),
+                               pixelfeathery = quality == 10 ? 0 : abs(feather/ph);
+
                nrect.set_point((aabb.minx - tl[0])/pw,(aabb.miny - tl[1])/ph);
                nrect.expand((aabb.maxx - tl[0])/pw,(aabb.maxy - tl[1])/ph);
-                               
+
                RendDesc        optdesc(renddesc);
-               
+
                //make sure to expand so we gain subpixels rather than lose them
                nrect.minx = floor(nrect.minx-pixelfeatherx); nrect.miny = floor(nrect.miny-pixelfeathery);
                nrect.maxx = ceil(nrect.maxx+pixelfeatherx); nrect.maxy = ceil(nrect.maxy+pixelfeathery);
-               
+
                //make sure the subwindow is clipped with our tile window (minimize useless drawing)
                set_intersect(nrect,nrect,Rect(0,0,renddesc.get_w(),renddesc.get_h()));
-               
+
                //must resize the surface first
                surface->set_wh(renddesc.get_w(),renddesc.get_h());
                surface->clear();
-               
+
                //only render anything if it's visible from our current tile
                if(nrect.valid())
                {
                        //set the subwindow to the viewable pixels and render it to the subsurface
                        optdesc.set_subwindow((int)nrect.minx, (int)nrect.miny,
                                (int)(nrect.maxx - nrect.minx), (int)(nrect.maxy - nrect.miny));
-                       
+
                        Surface optimizedbacksurf;
                        if(!context.accelerated_render(&optimizedbacksurf,quality,optdesc,&stageone))
                                return false;
-                       
+
                        //blit that onto the original surface so we can pretend that nothing ever happened
-                       Surface::pen p = surface->get_pen((int)nrect.minx,(int)nrect.miny); 
+                       Surface::pen p = surface->get_pen((int)nrect.minx,(int)nrect.miny);
                        optimizedbacksurf.blit_to(p);
                }
        }else
@@ -2495,22 +2522,22 @@ Layer_Shape::accelerated_render(Context context,Surface *surface,int quality, co
                if(!context.accelerated_render(surface,quality,renddesc,&stageone))
                        return false;
        }
-       
+
        if(cb && !cb->amount_complete(10000,10001+renddesc.get_h())) return false;
-               
-       if(feather)
+
+       if(feather && quality != 10)
        {
                //we have to blur rather than be crappy
-               
+
                //so make a separate surface
                RendDesc        workdesc(renddesc);
-               
+
                etl::surface<float>     shapesurface;
 
                //the expanded size = 1/2 the size in each direction rounded up
                int     halfsizex = (int) (abs(feather*.5/pw) + 3),
                        halfsizey = (int) (abs(feather*.5/ph) + 3);
-                       
+
                //expand by 1/2 size in each direction on either side
                switch(blurtype)
                {
@@ -2529,38 +2556,38 @@ Layer_Shape::accelerated_render(Context context,Surface *surface,int quality, co
                                        halfsizey*=2;
                                }
                                workdesc.set_subwindow(-max(1,halfsizex),-max(1,halfsizey),w+2*max(1,halfsizex),h+2*max(1,halfsizey));
-                               break;                          
+                               break;
                        }
                        case Blur::GAUSSIAN:
-                       {                               
+                       {
                        #define GAUSSIAN_ADJUSTMENT             (0.05)
                                Real    pw = (Real)workdesc.get_w()/(workdesc.get_br()[0]-workdesc.get_tl()[0]);
                                Real    ph = (Real)workdesc.get_h()/(workdesc.get_br()[1]-workdesc.get_tl()[1]);
-                               
+
                                pw=pw*pw;
                                ph=ph*ph;
-       
+
                                halfsizex = (int)(abs(pw)*feather*GAUSSIAN_ADJUSTMENT+0.5);
                                halfsizey = (int)(abs(ph)*feather*GAUSSIAN_ADJUSTMENT+0.5);
-       
+
                                halfsizex = (halfsizex + 1)/2;
                                halfsizey = (halfsizey + 1)/2;
                                workdesc.set_subwindow( -halfsizex, -halfsizey, w+2*halfsizex, h+2*halfsizey );
-                                                       
+
                                break;
                        }
                }
-               
+
                shapesurface.set_wh(workdesc.get_w(),workdesc.get_h());
                shapesurface.clear();
-               
+
                //render the shape
                if(!render_shape(&shapesurface,quality,workdesc,&stagetwo))return false;
-               
+
                //blur the image
                Blur(feather,feather,blurtype,&stagethree)(shapesurface,workdesc.get_br()-workdesc.get_tl(),shapesurface);
-               
-               //blend with stuff below it...          
+
+               //blend with stuff below it...
                unsigned int u = halfsizex, v = halfsizey, x = 0, y = 0;
                for(y = 0; y < h; y++,v++)
                {
@@ -2576,14 +2603,14 @@ Layer_Shape::accelerated_render(Context context,Surface *surface,int quality, co
                                //else (*surface)[y][x] = worksurface[v][u];
                        }
                }
-               
+
                //we are done
                if(cb && !cb->amount_complete(100,100))
                {
                        synfig::warning("Layer_Shape: could not set amount complete");
                        return false;
                }
-               
+
                return true;
        }else
        {
@@ -2594,17 +2621,17 @@ Layer_Shape::accelerated_render(Context context,Surface *surface,int quality, co
 }
 
 bool
-Layer_Shape::render_shape(Surface *surface,bool useblend,int quality,
+Layer_Shape::render_shape(Surface *surface,bool useblend,int /*quality*/,
                                                        const RendDesc &renddesc, ProgressCallback *cb)const
 {
        int tmp(0);
-       
+
        SuperCallback   progress(cb,0,renddesc.get_h(),renddesc.get_h());
-               
+
        // If our amount is set to zero, no need to render anything
        if(!get_amount())
                return true;
-       
+
        //test new polygon renderer
        // Build edge table
        // Width and Height of a pixel
@@ -2612,14 +2639,18 @@ Layer_Shape::render_shape(Surface *surface,bool useblend,int quality,
        const int       h = renddesc.get_h();
        const Real      pw = renddesc.get_w()/(renddesc.get_br()[0]-renddesc.get_tl()[0]);
        const Real      ph = renddesc.get_h()/(renddesc.get_br()[1]-renddesc.get_tl()[1]);
-       
+
        const Point     tl = renddesc.get_tl();
-       
+
        Vector tangent (0,0);
-               
+
        PolySpan        span;
-       
-       //optimization for tesselating only inside tiles
+
+       // if the pixels are zero sized then we're too zoomed out to see anything
+       if (pw == 0 || ph == 0)
+               return true;
+
+       //optimization for tessellating only inside tiles
        span.window.minx = 0;
        span.window.miny = 0;
        span.window.maxx = w;
@@ -2627,15 +2658,15 @@ Layer_Shape::render_shape(Surface *surface,bool useblend,int quality,
 
        //pointers for processing the bytestream
        const char *current     = &bytestream[0];
-       const char *end                 = &bytestream[bytestream.size()];       
-       
+       const char *end                 = &bytestream[bytestream.size()];
+
        int     operation       = Primitive::NONE;
        int number              = 0;
        int curnum;
-       
+
        Primitive       *curprim;
        Point           *data;
-       
+
        Real x,y,x1,y1,x2,y2;
 
 
@@ -2644,39 +2675,39 @@ Layer_Shape::render_shape(Surface *surface,bool useblend,int quality,
                tmp++;
 
                try {
-               
+
                //get the op code safely
                curprim = (Primitive *)current;
-               
+
                //advance past indices
                current += sizeof(Primitive);
                if(current > end)
                {
                        warning("Layer_Shape::accelerated_render - Error in the byte stream, not enough space for next declaration");
-                       return false;                   
+                       return false;
                }
-               
+
                //get the relevant data
                operation       = curprim->operation;
                number          = curprim->number;
-               
+
                if(operation == Primitive::END)
                        break;
-               
+
                if(operation == Primitive::CLOSE)
                {
                        if(span.notclosed())
                        {
                                tangent[0] = span.close_x - span.cur_x;
                                tangent[1] = span.close_y - span.cur_y;
-                               span.close();                                           
+                               span.close();
                        }
                        continue;
                }
-               
+
                data = (Point*)current;
                current += sizeof(Point)*number;
-               
+
                //check data positioning
                if(current > end)
                {
@@ -2688,20 +2719,20 @@ Layer_Shape::render_shape(Surface *surface,bool useblend,int quality,
 
                //transfer all the data - RLE optimized
                for(curnum=0; curnum < number;)
-               {                       
+               {
                        switch(operation)
                        {
                                case Primitive::MOVE_TO:
                                {
                                        x = data[curnum][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        if(curnum == 0)
                                        {
                                                span.move_to(x,y);
-                                               
+
                                                tangent[0] = 0;
                                                tangent[1] = 0;
                                        }
@@ -2709,138 +2740,138 @@ Layer_Shape::render_shape(Surface *surface,bool useblend,int quality,
                                        {
                                                tangent[0] = x - span.cur_x;
                                                tangent[1] = y - span.cur_y;
-                                               
+
                                                span.line_to(x,y);
                                        }
-                                       
+
                                        curnum++; //only advance one point
-                                       
+
                                        break;
                                }
-                               
+
                                case Primitive::LINE_TO:
                                {
                                        x = data[curnum][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        tangent[0] = x - span.cur_x;
                                        tangent[1] = y - span.cur_y;
-                                       
+
                                        span.line_to(x,y);
                                        curnum++;
                                        break;
                                }
-                               
+
                                case Primitive::CONIC_TO:
                                {
                                        x = data[curnum+1][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum+1][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        x1 = data[curnum][0];
-                                       x1 = (x1 - tl[0] + offset[0])*pw;
+                                       x1 = (x1 - tl[0] + origin[0])*pw;
                                        y1 = data[curnum][1];
-                                       y1 = (y1 - tl[1] + offset[1])*ph;
-                                       
+                                       y1 = (y1 - tl[1] + origin[1])*ph;
+
                                        tangent[0] = 2*(x - x1);
                                        tangent[1] = 2*(y - y1);
-                                       
+
                                        span.conic_to(x1,y1,x,y);
                                        curnum += 2;
                                        break;
                                }
-                               
+
                                case Primitive::CONIC_TO_SMOOTH:
                                {
                                        x = data[curnum][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        x1 = span.cur_x + tangent[0]/2;
                                        y1 = span.cur_y + tangent[1]/2;
 
                                        tangent[0] = 2*(x - x1);
                                        tangent[1] = 2*(y - y1);
-                                       
+
                                        span.conic_to(x1,y1,x,y);
                                        curnum ++;
-                                       
+
                                        break;
                                }
-                               
+
                                case Primitive::CUBIC_TO:
                                {
                                        x = data[curnum+2][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum+2][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        x2 = data[curnum+1][0];
-                                       x2 = (x2 - tl[0] + offset[0])*pw;
+                                       x2 = (x2 - tl[0] + origin[0])*pw;
                                        y2 = data[curnum+1][1];
-                                       y2 = (y2 - tl[1] + offset[1])*ph;
-                                       
+                                       y2 = (y2 - tl[1] + origin[1])*ph;
+
                                        x1 = data[curnum][0];
-                                       x1 = (x1 - tl[0] + offset[0])*pw;
+                                       x1 = (x1 - tl[0] + origin[0])*pw;
                                        y1 = data[curnum][1];
-                                       y1 = (y1 - tl[1] + offset[1])*ph;
-                                       
+                                       y1 = (y1 - tl[1] + origin[1])*ph;
+
                                        tangent[0] = 2*(x - x2);
                                        tangent[1] = 2*(y - y2);
-                                       
+
                                        span.cubic_to(x1,y1,x2,y2,x,y);
                                        curnum += 3;
-                                       
+
                                        break;
                                }
-                               
+
                                case Primitive::CUBIC_TO_SMOOTH:
                                {
                                        x = data[curnum+1][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum+1][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        x2 = data[curnum][0];
-                                       x2 = (x2 - tl[0] + offset[0])*pw;
+                                       x2 = (x2 - tl[0] + origin[0])*pw;
                                        y2 = data[curnum][1];
-                                       y2 = (y2 - tl[1] + offset[1])*ph;
-                                       
-                                       x1 = span.cur_x + tangent[0]/3.0;                                       
+                                       y2 = (y2 - tl[1] + origin[1])*ph;
+
+                                       x1 = span.cur_x + tangent[0]/3.0;
                                        y1 = span.cur_y + tangent[1]/3.0;
-                                       
+
                                        tangent[0] = 2*(x - x2);
                                        tangent[1] = 2*(y - y2);
-                                       
+
                                        span.cubic_to(x1,y1,x2,y2,x,y);
                                        curnum += 2;
-                                       
+
                                        break;
                                }
                        }
                }
        }
-       
+
        //sort the bastards so we can render everything
        span.sort_marks();
-       
-       return render_polyspan(surface, span, 
-                       useblend?get_blend_method():Color::BLEND_STRAIGHT, 
+
+       return render_polyspan(surface, span,
+                       useblend?get_blend_method():Color::BLEND_STRAIGHT,
                        useblend?get_amount():1.0);
 }
 
 bool
-Layer_Shape::render_shape(surface<float> *surface,int quality,
-                                                       const RendDesc &renddesc, ProgressCallback *cb)const
+Layer_Shape::render_shape(etl::surface<float> *surface,int /*quality*/,
+                                                       const RendDesc &renddesc, ProgressCallback */*cb*/)const
 {
        // If our amount is set to zero, no need to render anything
        if(!get_amount())
                return true;
-       
+
        //test new polygon renderer
        // Build edge table
        // Width and Height of a pixel
@@ -2848,14 +2879,14 @@ Layer_Shape::render_shape(surface<float> *surface,int quality,
        const int       h = renddesc.get_h();
        const Real      pw = renddesc.get_w()/(renddesc.get_br()[0]-renddesc.get_tl()[0]);
        const Real      ph = renddesc.get_h()/(renddesc.get_br()[1]-renddesc.get_tl()[1]);
-       
+
        const Point     tl = renddesc.get_tl();
-       
+
        Vector tangent (0,0);
-               
+
        PolySpan        span;
-       
-       //optimization for tesselating only inside tiles
+
+       //optimization for tessellating only inside tiles
        span.window.minx = 0;
        span.window.miny = 0;
        span.window.maxx = w;
@@ -2863,51 +2894,51 @@ Layer_Shape::render_shape(surface<float> *surface,int quality,
 
        //pointers for processing the bytestream
        const char *current     = &bytestream[0];
-       const char *end                 = &bytestream[bytestream.size()];       
-       
+       const char *end                 = &bytestream[bytestream.size()];
+
        int     operation       = Primitive::NONE;
        int number              = 0;
        int curnum;
-       
+
        Primitive       *curprim;
        Point           *data;
-       
+
        Real x,y,x1,y1,x2,y2;
-       
+
        while(current < end)
        {
                //get the op code safely
                curprim = (Primitive *)current;
-               
+
                //advance past indices
                current += sizeof(Primitive);
                if(current > end)
                {
                        warning("Layer_Shape::accelerated_render - Error in the byte stream, not enough space for next declaration");
-                       return false;                   
+                       return false;
                }
-               
+
                //get the relevant data
                operation       = curprim->operation;
                number          = curprim->number;
-               
+
                if(operation == Primitive::END)
                        break;
-               
+
                if(operation == Primitive::CLOSE)
                {
                        if(span.notclosed())
                        {
                                tangent[0] = span.close_x - span.cur_x;
                                tangent[1] = span.close_y - span.cur_y;
-                               span.close();                                           
+                               span.close();
                        }
                        continue;
                }
-               
+
                data = (Point*)current;
                current += sizeof(Point)*number;
-               
+
                //check data positioning
                if(current > end)
                {
@@ -2917,20 +2948,20 @@ Layer_Shape::render_shape(surface<float> *surface,int quality,
 
                //transfer all the data
                for(curnum=0; curnum < number;)
-               {                       
+               {
                        switch(operation)
                        {
                                case Primitive::MOVE_TO:
                                {
                                        x = data[curnum][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        if(curnum == 0)
                                        {
                                                span.move_to(x,y);
-                                               
+
                                                tangent[0] = 0;
                                                tangent[1] = 0;
                                        }
@@ -2938,125 +2969,125 @@ Layer_Shape::render_shape(surface<float> *surface,int quality,
                                        {
                                                tangent[0] = x - span.cur_x;
                                                tangent[1] = y - span.cur_y;
-                                               
+
                                                span.line_to(x,y);
                                        }
-                                       
+
                                        curnum++; //only advance one point
-                                       
+
                                        break;
                                }
-                               
+
                                case Primitive::LINE_TO:
                                {
                                        x = data[curnum][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        tangent[0] = x - span.cur_x;
                                        tangent[1] = y - span.cur_y;
-                                       
+
                                        span.line_to(x,y);
                                        curnum++;
                                        break;
                                }
-                               
+
                                case Primitive::CONIC_TO:
                                {
                                        x = data[curnum+1][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum+1][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        x1 = data[curnum][0];
-                                       x1 = (x1 - tl[0] + offset[0])*pw;
+                                       x1 = (x1 - tl[0] + origin[0])*pw;
                                        y1 = data[curnum][1];
-                                       y1 = (y1 - tl[1] + offset[1])*ph;
-                                       
+                                       y1 = (y1 - tl[1] + origin[1])*ph;
+
                                        tangent[0] = 2*(x - x1);
                                        tangent[1] = 2*(y - y1);
-                                       
+
                                        span.conic_to(x1,y1,x,y);
                                        curnum += 2;
                                        break;
                                }
-                               
+
                                case Primitive::CONIC_TO_SMOOTH:
                                {
                                        x = data[curnum][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        x1 = span.cur_x + tangent[0]/2;
                                        y1 = span.cur_y + tangent[1]/2;
 
                                        tangent[0] = 2*(x - x1);
                                        tangent[1] = 2*(y - y1);
-                                       
+
                                        span.conic_to(x1,y1,x,y);
                                        curnum ++;
-                                       
+
                                        break;
                                }
-                               
+
                                case Primitive::CUBIC_TO:
                                {
                                        x = data[curnum+2][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum+2][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        x2 = data[curnum+1][0];
-                                       x2 = (x2 - tl[0] + offset[0])*pw;
+                                       x2 = (x2 - tl[0] + origin[0])*pw;
                                        y2 = data[curnum+1][1];
-                                       y2 = (y2 - tl[1] + offset[1])*ph;
-                                       
+                                       y2 = (y2 - tl[1] + origin[1])*ph;
+
                                        x1 = data[curnum][0];
-                                       x1 = (x1 - tl[0] + offset[0])*pw;
+                                       x1 = (x1 - tl[0] + origin[0])*pw;
                                        y1 = data[curnum][1];
-                                       y1 = (y1 - tl[1] + offset[1])*ph;
-                                       
+                                       y1 = (y1 - tl[1] + origin[1])*ph;
+
                                        tangent[0] = 2*(x - x2);
                                        tangent[1] = 2*(y - y2);
-                                       
+
                                        span.cubic_to(x1,y1,x2,y2,x,y);
                                        curnum += 3;
-                                       
+
                                        break;
                                }
-                               
+
                                case Primitive::CUBIC_TO_SMOOTH:
                                {
                                        x = data[curnum+1][0];
-                                       x = (x - tl[0] + offset[0])*pw;
+                                       x = (x - tl[0] + origin[0])*pw;
                                        y = data[curnum+1][1];
-                                       y = (y - tl[1] + offset[1])*ph;
-                                       
+                                       y = (y - tl[1] + origin[1])*ph;
+
                                        x2 = data[curnum][0];
-                                       x2 = (x2 - tl[0] + offset[0])*pw;
+                                       x2 = (x2 - tl[0] + origin[0])*pw;
                                        y2 = data[curnum][1];
-                                       y2 = (y2 - tl[1] + offset[1])*ph;
-                                       
-                                       x1 = span.cur_x + tangent[0]/3.0;                                       
+                                       y2 = (y2 - tl[1] + origin[1])*ph;
+
+                                       x1 = span.cur_x + tangent[0]/3.0;
                                        y1 = span.cur_y + tangent[1]/3.0;
-                                       
+
                                        tangent[0] = 2*(x - x2);
                                        tangent[1] = 2*(y - y2);
-                                       
+
                                        span.cubic_to(x1,y1,x2,y2,x,y);
                                        curnum += 2;
-                                       
+
                                        break;
                                }
                        }
                }
        }
-       
+
        //sort the bastards so we can render everything
        span.sort_marks();
-       
+
        return render_polyspan(surface, span);
 }
 
@@ -3066,9 +3097,12 @@ Layer_Shape::get_bounding_rect()const
        if(invert)
                return Rect::full_plane();
 
-       Rect bounds(edge_table->aabb+offset);
-       bounds.expand(max((bounds.get_min()-bounds.get_max()).mag()*0.01,feather));
-       
-       
+       if (edge_table->initaabb)
+               return Rect::zero();
+
+       Rect bounds(edge_table->aabb+origin);
+       bounds.expand(max((bounds.get_min() - bounds.get_max()).mag()*0.01,
+                                         feather));
+
        return bounds;
 }