Added copyright lines for files I've edited this year.
[synfig.git] / synfig-core / trunk / src / synfig / layer_shape.cpp
index 7845d0a..539d715 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$
 **
 **     \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,8 +60,8 @@ 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$");
 
@@ -233,7 +234,7 @@ struct MonoSegment
 
        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;
@@ -244,11 +245,13 @@ struct MonoSegment
                //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)
@@ -316,7 +319,7 @@ struct CurveArray
                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;
@@ -330,17 +333,17 @@ struct CurveArray
 
                //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
@@ -381,7 +384,7 @@ struct CurveArray
                }
 
                //calculate number of intersections
-               if(t1 >= 0 & t1 <= 1)
+               if(t1 >= 0 && t1 <= 1)
                {
                        const Real t = t1;
                        const Real invt = 1 - t;
@@ -396,7 +399,7 @@ struct CurveArray
                        }
                }
 
-               if(t2 >= 0 & t2 <= 1)
+               if(t2 >= 0 && t2 <= 1)
                {
                        const Real t = t2;
                        const Real invt = 1 - t;
@@ -440,7 +443,7 @@ struct CurveArray
                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];
@@ -471,7 +474,7 @@ struct CurveArray
                }
        }
 
-       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;
@@ -504,7 +507,7 @@ struct CurveArray
                //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];
@@ -582,7 +585,7 @@ struct CurveArray
                                        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;
@@ -604,7 +607,7 @@ struct CurveArray
                //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;
 
@@ -622,7 +625,7 @@ 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;
 
@@ -640,7 +643,7 @@ 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;
 
@@ -660,7 +663,7 @@ struct CurveArray
 
        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();
@@ -711,6 +714,8 @@ struct CurveArray
 struct Layer_Shape::Intersector
 {
        Rect    aabb;
+
+       //! true iff aabb hasn't been initialized yet
        bool    initaabb;
 
        int     flags;
@@ -743,7 +748,7 @@ struct Layer_Shape::Intersector
 
        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)
@@ -769,7 +774,7 @@ struct Layer_Shape::Intersector
                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);
@@ -790,7 +795,7 @@ struct Layer_Shape::Intersector
 
                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;
@@ -992,7 +997,7 @@ public:
 
        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
@@ -1017,7 +1022,7 @@ public:
        //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);
@@ -1087,19 +1092,27 @@ public:
        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)
+       Real ExtractAlpha(Real area, WindingStyle winding_style)
        {
-               //non-zero winding style
-               if(area < 0) area = -area;
-               if(area > 1) area = 1;
+               if (area < 0)
+                       area = -area;
 
-               //even-odd 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;
 
-               while(area > 2) area -= 2;
-               if(area > 1) area = 1-area; //want pyramid like thing
-               */
-               //broken? - yep broken
+                       // want pyramid like thing
+                       if (area < 0)
+                               area = -area;
+               }
 
                return area;
        }
@@ -1116,6 +1129,7 @@ Layer_Shape::Layer_Shape(const Real &a, const Color::BlendMethod m):
        antialias               (true),
        blurtype                (Blur::FASTGAUSSIAN),
        feather                 (0),
+       winding_style   (WINDING_NON_ZERO),
        bytestream              (0),
        lastbyteop              (Primitive::NONE),
        lastoppos               (-1)
@@ -1137,12 +1151,15 @@ Layer_Shape::clear()
 bool
 Layer_Shape::set_param(const String & param, const ValueBase &value)
 {
-       IMPORT(color);
+       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(offset);
        IMPORT(invert);
        IMPORT(antialias);
        IMPORT(feather);
        IMPORT(blurtype);
+       IMPORT(winding_style);
 
        return Layer_Composite::set_param(param,value);
 }
@@ -1156,6 +1173,7 @@ Layer_Shape::get_param(const String &param)const
        EXPORT(antialias);
        EXPORT(feather);
        EXPORT(blurtype);
+       EXPORT(winding_style);
 
        EXPORT_NAME();
        EXPORT_VERSION();
@@ -1173,7 +1191,7 @@ Layer_Shape::get_param_vocab()const
                .set_description(_("Layer_Shape Color"))
        );
        ret.push_back(ParamDesc("offset")
-               .set_local_name(_("Position"))
+               .set_local_name(_("Offset"))
        );
        ret.push_back(ParamDesc("invert")
                .set_local_name(_("Invert"))
@@ -1195,6 +1213,13 @@ 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;
 }
@@ -1270,7 +1295,7 @@ 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];
+       Real n[4] = {0,0,0,0};
        bool afterx = false;
 
        const Real xin(x), yin(y);
@@ -1281,8 +1306,8 @@ void Layer_Shape::PolySpan::line_to(Real x, Real 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;
@@ -1307,7 +1332,7 @@ void Layer_Shape::PolySpan::line_to(Real x, Real y)
                        //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
@@ -1331,7 +1356,7 @@ void Layer_Shape::PolySpan::line_to(Real x, Real y)
                        //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
@@ -1381,7 +1406,7 @@ void Layer_Shape::PolySpan::line_to(Real x, Real y)
                                //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;
@@ -1410,7 +1435,7 @@ void Layer_Shape::PolySpan::line_to(Real x, Real y)
                                //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;
@@ -1448,9 +1473,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);
 }
 
@@ -1466,10 +1491,10 @@ static inline bool clip_cubic(const Point *const p, const ContextRect &r)
                        (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)
@@ -1527,7 +1552,7 @@ void Layer_Shape::PolySpan::conic_to(Real x1, Real y1, Real x, Real y)
        {
                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);
@@ -1600,7 +1625,7 @@ void Layer_Shape::PolySpan::cubic_to(Real x1, Real y1, Real x2, Real y2, Real x,
        {
                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);
@@ -1678,7 +1703,7 @@ void Layer_Shape::PolySpan::draw_scanline(int y, Real x1, Real fy1, Real x2, Rea
        //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;
        }
 
@@ -1692,7 +1717,7 @@ void Layer_Shape::PolySpan::draw_scanline(int y, Real x1, Real fy1, Real x2, Rea
                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;
@@ -1728,7 +1753,7 @@ void Layer_Shape::PolySpan::draw_scanline(int y, Real x1, Real fy1, Real x2, Rea
                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;
@@ -1856,7 +1881,7 @@ void Layer_Shape::PolySpan::draw_line(Real x1, Real y1, Real x2, Real y2)
 
                mult = (1 - fy1) * dxdy;
 
-               //x interset scanline
+               //x intersect scanline
                x_from = x1 + mult;
                draw_scanline(iy1,x1,fy1,x_from,1);
 
@@ -1886,7 +1911,7 @@ void Layer_Shape::PolySpan::draw_line(Real x1, Real y1, Real x2, Real y2)
 
                mult = fy1 * dxdy;
 
-               //x interset scanline
+               //x intersect scanline
                x_from = x1 + mult;
                draw_scanline(iy1,x1,fy1,x_from,0);
 
@@ -1965,7 +1990,7 @@ void Layer_Shape::endpath()
        op.operation = Primitive::END;
        op.number = 0;
 
-       if(lastbyteop == Primitive::END | lastbyteop == Primitive::NONE)
+       if(lastbyteop == Primitive::END || lastbyteop == Primitive::NONE)
        {
        }else
        {
@@ -1986,7 +2011,7 @@ void Layer_Shape::line_to(Real x, Real 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));
@@ -2183,7 +2208,7 @@ bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan,
                //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;
@@ -2193,7 +2218,7 @@ bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan,
                //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)
@@ -2230,7 +2255,7 @@ bool Layer_Shape::render_polyspan(Surface *surface, PolySpan &polyspan,
                //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)
@@ -2309,7 +2334,7 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                        //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;
@@ -2319,7 +2344,7 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                        //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();
@@ -2351,7 +2376,7 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                        //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);
@@ -2381,7 +2406,7 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                        //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;
@@ -2391,7 +2416,7 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                        //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();
@@ -2416,7 +2441,7 @@ bool Layer_Shape::render_polyspan(etl::surface<float> *surface, PolySpan &polysp
                        //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);
@@ -2456,8 +2481,8 @@ Layer_Shape::accelerated_render(Context context,Surface *surface,int quality, co
 
                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);
@@ -2498,7 +2523,7 @@ Layer_Shape::accelerated_render(Context context,Surface *surface,int quality, co
 
        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
 
@@ -2594,7 +2619,7 @@ 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);
@@ -2619,7 +2644,11 @@ Layer_Shape::render_shape(Surface *surface,bool useblend,int quality,
 
        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;
@@ -2834,8 +2863,8 @@ Layer_Shape::render_shape(Surface *surface,bool useblend,int quality,
 }
 
 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())
@@ -2855,7 +2884,7 @@ Layer_Shape::render_shape(surface<float> *surface,int quality,
 
        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;
@@ -3066,9 +3095,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+offset);
+       bounds.expand(max((bounds.get_min() - bounds.get_max()).mag()*0.01,
+                                         feather));
 
        return bounds;
 }