Author: Carlos Lopez <genet...@gmail.com>
Date:   Tue Aug 14 10:08:28 2012 +0200

Region: add support for Cairo render.

---

 synfig-core/src/modules/mod_geometry/region.cpp |  215 +++++++++++++++++++++++
 synfig-core/src/modules/mod_geometry/region.h   |    2 +-
 2 files changed, 216 insertions(+), 1 deletions(-)

diff --git a/synfig-core/src/modules/mod_geometry/region.cpp 
b/synfig-core/src/modules/mod_geometry/region.cpp
index e765373..c536325 100644
--- a/synfig-core/src/modules/mod_geometry/region.cpp
+++ b/synfig-core/src/modules/mod_geometry/region.cpp
@@ -251,3 +251,218 @@ Region::set_time(Context context, Time time, Vector 
pos)const
        const_cast<Region*>(this)->sync();
        context.set_time(time,pos);
 }
+
+/////////
+bool
+Region::accelerated_cairorender(Context context,cairo_surface_t *surface,int 
quality, const RendDesc &renddesc, ProgressCallback *cb)const
+{
+       synfig::info("rendering Cairo Region");
+       std::vector<synfig::Segment> segments;
+
+       // Grab the rgba values
+       const float r(color.get_r());
+       const float g(color.get_g());
+       const float b(color.get_b());
+       const float a(color.get_a());
+       
+       // Window Boundaries
+       const Point     tl(renddesc.get_tl());
+       const Point br(renddesc.get_br());
+       const int       w(renddesc.get_w());
+       const int       h(renddesc.get_h());
+       
+       // Width and Height of a pixel
+       const Real pw = (br[0] - tl[0]) / w;
+       const Real ph = (br[1] - tl[1]) / h;
+       
+       // These are the scale and translation values
+       const double sx(1/pw);
+       const double sy(1/ph);
+       const double tx((-tl[0]+origin[0])*sx);
+       const double ty((-tl[1]+origin[1])*sy);
+       
+       if(bline.get_contained_type()==ValueBase::TYPE_BLINEPOINT)
+               segments=convert_bline_to_segment_list(bline);
+       else if(bline.get_contained_type()==ValueBase::TYPE_SEGMENT)
+               segments=vector<synfig::Segment>(bline.get_list().begin(), 
bline.get_list().end());
+       else
+       {
+               synfig::warning("Region: incorrect type on bline, layer 
disabled");
+               return false;
+       }
+       
+       if(segments.empty())
+       {
+               synfig::warning("Region: segment_list is empty, layer 
disabled");
+               return false;
+       }
+               
+       cairo_t* cr=cairo_create(surface);
+       // Let's render the region in other surface
+       // Initially I'll fill it completely with the alpha color
+       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);
+       // Now let's check if it is inverted
+       if(invert)
+       {
+               cairo_paint(subcr);
+       }
+       // Draw the region
+       cairo_translate(subcr, tx , ty);
+       cairo_scale(subcr, sx, sy);
+
+       vector<Segment>::const_iterator iter=segments.begin();
+       double t1x;
+       double t1y;
+       double t2x;
+       double t2y;
+       double p2x;
+       double p2y;
+       double p1x=iter->p1[0];
+       double p1y=iter->p1[1];
+       cairo_move_to(subcr, p1x, p1y);
+       for(;iter!=segments.end();++iter)
+       {
+               t1x=iter->t1[0];
+               t1y=iter->t1[1];
+               t2x=iter->t2[0];
+               t2y=iter->t2[1];
+               p1x=iter->p1[0];
+               p1y=iter->p1[1];
+               p2x=iter->p2[0];
+               p2y=iter->p2[1];
+               cairo_curve_to(subcr, p1x+t1x/3, p1y+t1y/3, p2x-t2x/3, 
p2y-t2y/3, p2x, p2y);
+       }
+       
+       cairo_close_path(subcr);
+       if(invert)
+               cairo_set_operator(subcr, CAIRO_OPERATOR_CLEAR);
+       else
+               cairo_set_operator(subcr, CAIRO_OPERATOR_OVER);
+       switch(winding_style)
+       {
+               case WINDING_NON_ZERO:
+                       cairo_set_fill_rule(subcr, CAIRO_FILL_RULE_WINDING);
+                       break;
+               default:
+                       cairo_set_fill_rule(subcr, CAIRO_FILL_RULE_EVEN_ODD);
+                       break;
+       }
+       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
+               Color ccolor(color);
+               for(y=0; y<wh; y++)
+                       for(x=0;x<ww;x++)
+                       {
+                               float a=shapesurface[y][x];
+                               ccolor.set_a(a);
+                               ccolor.clamped();
+                               
cairosubimage[y][x]=CairoColor(ccolor).premult_alpha();
+                       }
+               
+               cairosubimage.unmap_cairo_image();
+       }
+       
+       // Put the (feathered) region on the surface
+       if(!is_solid_color()) // we need to render the context before
+               
if(!context.accelerated_cairorender(surface,quality,renddesc,cb))
+               {
+                       if(cb)
+                               cb->error(strprintf(__FILE__"%d: Accelerated 
Cairo Renderer Failure",__LINE__));
+                       cairo_destroy(cr);
+                       cairo_destroy(subcr);
+                       cairo_surface_destroy(subimage);
+                       return false;
+               }
+       double px(tl[0]-workdesc.get_tl()[0]);
+       double py(tl[1]-workdesc.get_tl()[1]);
+       cairo_save(cr);
+       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);
+       cairo_surface_destroy(subimage);
+       cairo_destroy(subcr);
+       cairo_destroy(cr);
+       
+       return true;
+}
+
+/////////
diff --git a/synfig-core/src/modules/mod_geometry/region.h 
b/synfig-core/src/modules/mod_geometry/region.h
index 38e33f3..4694fc5 100644
--- a/synfig-core/src/modules/mod_geometry/region.h
+++ b/synfig-core/src/modules/mod_geometry/region.h
@@ -65,7 +65,7 @@ public:
        virtual Vocab get_param_vocab()const;
        virtual void set_time(Context context, Time time)const;
        virtual void set_time(Context context, Time time, Vector pos)const;
-
+       virtual bool accelerated_cairorender(Context context,cairo_surface_t 
*surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const;
 };
 
 /* === E N D =============================================================== */


------------------------------------------------------------------------------
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
Synfig-devl@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/synfig-devl

Reply via email to