Author: Carlos Lopez <[email protected]>
Date:   Mon Aug 13 20:44:31 2012 +0200

Layer_Polygon: add support for feather. Results lacks of current Software 
render method smoothness because the blur is alpha based and in Cairo alpha has 
values of discrete 1/255 steps.

---

 synfig-core/src/synfig/layer_polygon.cpp |   94 ++++++++++++++++++++++++++++--
 1 files changed, 88 insertions(+), 6 deletions(-)

diff --git a/synfig-core/src/synfig/layer_polygon.cpp 
b/synfig-core/src/synfig/layer_polygon.cpp
index 89e4614..4059f9a 100644
--- a/synfig-core/src/synfig/layer_polygon.cpp
+++ b/synfig-core/src/synfig/layer_polygon.cpp
@@ -212,8 +212,58 @@ Layer_Polygon::accelerated_cairorender(Context 
context,cairo_surface_t *surface,
        cairo_t* cr=cairo_create(surface);
        // Let's render the polygon in other surface
        // Initially I'll fill it completely with the alpha color
-       // Create a similar image with the same dimensions than the current 
renddesc
-       cairo_surface_t* subimage=cairo_surface_create_similar(surface, 
CAIRO_CONTENT_COLOR_ALPHA, renddesc.get_w(), renddesc.get_h());
+       cairo_surface_t* subimage;
+       // Let's calculate the subimage dimensions based on the feather value
+       //so make a separate surface
+       RendDesc        workdesc(renddesc);
+       int halfsizex(0), halfsizey(0);
+       if(feather && quality != 10)
+       {
+               //the expanded size = 1/2 the size in each direction rounded up
+               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)
+               {
+                       case Blur::DISC:
+                       case Blur::BOX:
+                       case Blur::CROSS:
+                       {
+                               
workdesc.set_subwindow(-max(1,halfsizex),-max(1,halfsizey),w+2*max(1,halfsizex),h+2*max(1,halfsizey));
+                               break;
+                       }
+                       case Blur::FASTGAUSSIAN:
+                       {
+                               if(quality < 4)
+                               {
+                                       halfsizex*=2;
+                                       halfsizey*=2;
+                               }
+                               
workdesc.set_subwindow(-max(1,halfsizex),-max(1,halfsizey),w+2*max(1,halfsizex),h+2*max(1,halfsizey));
+                               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;
+#undef GAUSSIAN_ADJUSTMENT
+                       }
+               }
+       }
+       subimage=cairo_surface_create_similar(surface, 
CAIRO_CONTENT_COLOR_ALPHA, workdesc.get_w(), workdesc.get_h());
        cairo_t* subcr=cairo_create(subimage);
        cairo_save(subcr);
        cairo_set_source_rgba(subcr, r, g, b, a);
@@ -247,12 +297,42 @@ Layer_Polygon::accelerated_cairorender(Context 
context,cairo_surface_t *surface,
        }
        if(!antialias)
                cairo_set_antialias(subcr, CAIRO_ANTIALIAS_NONE);
+
        cairo_fill(subcr);
        cairo_restore(subcr);
+       if(feather && quality!=10)
+       {
+               etl::surface<float>     shapesurface;
+               shapesurface.set_wh(workdesc.get_w(),workdesc.get_h());
+               shapesurface.clear();
+
+               CairoSurface cairosubimage(subimage);
+               if(!cairosubimage.map_cairo_image())
+               {
+                       synfig::info("map cairo image failed");
+                       return false;
+               }
+               // Extract the alpha values:
+               int x, y;
+               int wh(workdesc.get_h()), ww(workdesc.get_w());
+               for(y=0; y<wh; y++)
+                       for(x=0;x<ww;x++)
+                               
shapesurface[y][x]=cairosubimage[y][x].get_a()/CairoColor::ceil;
+               // Blue the alpha values
+               
Blur(feather,feather,blurtype,cb)(shapesurface,workdesc.get_br()-workdesc.get_tl(),shapesurface);
+               // repaint the cairosubimage with the result
+               CairoColor ccolor(color);
+               for(y=0; y<wh; y++)
+                       for(x=0;x<ww;x++)
+                       {
+                               float a=shapesurface[y][x];
+                               cairosubimage[y][x]=(ccolor*a).set_a((unsigned 
char)a/Color::ceil);
+                       }
+               
+               cairosubimage.unmap_cairo_image();
+       }
        
-       // ADD FEATHER HERE
-       
-       // Put the polygon on the surface
+       // Put the (feathered) polygon on the surface
        if(!is_solid_color()) // we need to render the context before
                
if(!context.accelerated_cairorender(surface,quality,renddesc,cb))
                {
@@ -263,7 +343,9 @@ Layer_Polygon::accelerated_cairorender(Context 
context,cairo_surface_t *surface,
                        cairo_surface_destroy(subimage);
                        return false;
                }
-       cairo_set_source_surface(cr, subimage, 0, 0);
+       double px(tl[0]-workdesc.get_tl()[0]);
+       double py(tl[1]-workdesc.get_tl()[1]);
+       cairo_set_source_surface(cr, subimage, px, py );
        cairo_set_operator(cr, CAIRO_OPERATOR_OVER); // TODO: this has to be 
the real operator
        cairo_paint_with_alpha(cr, get_amount());
        cairo_restore(cr);


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Synfig-devl mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/synfig-devl

Reply via email to