Add 'winding style' control, allowing the user to specify how regions are filled in.
authordooglus <dooglus@1f10aa63-cdf2-0310-b900-c93c546f37ac>
Mon, 9 Apr 2007 16:07:16 +0000 (16:07 +0000)
committerdooglus <dooglus@1f10aa63-cdf2-0310-b900-c93c546f37ac>
Mon, 9 Apr 2007 16:07:16 +0000 (16:07 +0000)
git-svn-id: http://svn.voria.com/code@447 1f10aa63-cdf2-0310-b900-c93c546f37ac

synfig-core/trunk/src/synfig/layer_shape.cpp
synfig-core/trunk/src/synfig/layer_shape.h

index 0c980aa..2c2d71d 100644 (file)
@@ -1089,19 +1089,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;
        }
@@ -1118,6 +1126,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)
@@ -1145,6 +1154,7 @@ Layer_Shape::set_param(const String & param, const ValueBase &value)
        IMPORT(antialias);
        IMPORT(feather);
        IMPORT(blurtype);
+       IMPORT(winding_style);
 
        return Layer_Composite::set_param(param,value);
 }
@@ -1158,6 +1168,7 @@ Layer_Shape::get_param(const String &param)const
        EXPORT(antialias);
        EXPORT(feather);
        EXPORT(blurtype);
+       EXPORT(winding_style);
 
        EXPORT_NAME();
        EXPORT_VERSION();
@@ -1197,6 +1208,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;
 }
@@ -2195,7 +2213,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)
@@ -2232,7 +2250,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)
@@ -2321,7 +2339,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();
@@ -2353,7 +2371,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);
@@ -2393,7 +2411,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();
@@ -2418,7 +2436,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);
index 69a285b..d083cee 100644 (file)
@@ -48,6 +48,14 @@ class Layer_Shape : public Layer_Composite, public Layer_NoDeform
 {
        SYNFIG_LAYER_MODULE_EXT
 
+       enum WindingStyle
+       {
+           WINDING_NON_ZERO=0,                 //!< less than -1 --> 1;  -1 --> 1;   0 --> 0;   1 --> 1;  greater than 1 --> 1
+           WINDING_EVEN_ODD=1,                 //!< add or subtract multiples of 2 to get into range -1:1, then as above
+
+           WINDING_END=2                               //!< \internal
+       };
+
 private:
 
        //internal cacheing
@@ -63,6 +71,7 @@ private:
 
        int             blurtype;
        Real    feather;
+       WindingStyle winding_style;
 
        std::vector< char >     bytestream;