Author: Carlos Lopez <[email protected]>
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/synfig-devl