Author: Carlos Lopez <[email protected]>
Date: Fri Sep 28 20:00:32 2012 +0200
Shade layer: Add support for Cairo render
---
synfig-core/src/modules/lyr_std/shade.cpp | 183 +++++++++++++++++++++++++++++
synfig-core/src/modules/lyr_std/shade.h | 1 +
2 files changed, 184 insertions(+), 0 deletions(-)
diff --git a/synfig-core/src/modules/lyr_std/shade.cpp
b/synfig-core/src/modules/lyr_std/shade.cpp
index d0f0686..b0529f2 100644
--- a/synfig-core/src/modules/lyr_std/shade.cpp
+++ b/synfig-core/src/modules/lyr_std/shade.cpp
@@ -368,6 +368,189 @@ Layer_Shade::accelerated_render(Context context,Surface
*surface,int quality, co
return true;
}
+
+///
+bool
+Layer_Shade::accelerated_cairorender(Context context,cairo_surface_t
*surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
+{
+ int x,y;
+
+ const int w = renddesc.get_w(),
+ h = renddesc.get_h();
+ const Real pw = renddesc.get_pw(),
+ ph = renddesc.get_ph();
+
+ RendDesc workdesc(renddesc);
+ cairo_surface_t *worksurface;
+ etl::surface<float> blurred;
+
+ //expand the working surface to accommodate the blur
+ //the expanded size = 1/2 the size in each direction rounded up
+ int halfsizex = (int) (abs(size[0]*.5/pw) + 3),
+ halfsizey = (int) (abs(size[1]*.5/ph) + 3);
+
+ int
origin_u(-round_to_int(origin[0]/pw)),origin_v(-round_to_int(origin[1]/ph));
+
+ int origin_w(w+abs(origin_u)),origin_h(h+abs(origin_v));
+
+ workdesc.set_subwindow(
+ origin_u<0?origin_u:0,
+ origin_v<0?origin_v:0,
+ (origin_u>0?origin_u:0)+w,
+ (origin_v>0?origin_v:0)+h
+ );
+
+ if(quality >= 10)
+ {
+ halfsizex=1;
+ halfsizey=1;
+ }
+ else if (quality == 9)
+ {
+ halfsizex/=4;
+ halfsizey/=4;
+ }
+#define SCALE_FACTOR (64.0)
+ //expand by 1/2 size in each direction on either side
+ switch(type)
+ {
+ case Blur::DISC:
+ case Blur::BOX:
+ case Blur::CROSS:
+ {
+ // If passed a certain size don't expand more
+ halfsizex=halfsizex>SCALE_FACTOR?SCALE_FACTOR:halfsizex;
+ halfsizey=halfsizey>SCALE_FACTOR?SCALE_FACTOR:halfsizey;
+
workdesc.set_subwindow(-max(1,halfsizex),-max(1,halfsizey),origin_w+2*max(1,halfsizex),origin_h+2*max(1,halfsizey));
+ break;
+ }
+ case Blur::FASTGAUSSIAN:
+ {
+ if(quality < 4)
+ {
+ halfsizex*=2;
+ halfsizey*=2;
+ }
+ // If passed a certain size don't expand more
+ halfsizex=halfsizex>SCALE_FACTOR?SCALE_FACTOR:halfsizex;
+ halfsizey=halfsizey>SCALE_FACTOR?SCALE_FACTOR:halfsizey;
+
workdesc.set_subwindow(-max(1,halfsizex),-max(1,halfsizey),origin_w+2*max(1,halfsizex),origin_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)*size[0]*GAUSSIAN_ADJUSTMENT+0.5);
+ halfsizey =
(int)(abs(ph)*size[1]*GAUSSIAN_ADJUSTMENT+0.5);
+
+ halfsizex = (halfsizex + 1)/2;
+ halfsizey = (halfsizey + 1)/2;
+ // If passed a certain size don't expand more
+ halfsizex=halfsizex>SCALE_FACTOR?SCALE_FACTOR:halfsizex;
+ halfsizey=halfsizey>SCALE_FACTOR?SCALE_FACTOR:halfsizey;
+ workdesc.set_subwindow( -halfsizex, -halfsizey,
origin_w+2*halfsizex, origin_h+2*halfsizey );
+
+ break;
+ }
+ }
+ SuperCallback stageone(cb,0,5000,10000);
+ SuperCallback stagetwo(cb,5000,10000,10000);
+
+ //callbacks depend on how long the blur takes
+ if(size[0] || size[1])
+ {
+ if(type == Blur::DISC)
+ {
+ stageone = SuperCallback(cb,0,5000,10000);
+ stagetwo = SuperCallback(cb,5000,10000,10000);
+ }
+ else
+ {
+ stageone = SuperCallback(cb,0,9000,10000);
+ stagetwo = SuperCallback(cb,9000,10000,10000);
+ }
+ }
+ else
+ {
+ stageone = SuperCallback(cb,0,9999,10000);
+ stagetwo = SuperCallback(cb,9999,10000,10000);
+ }
+
+
+ // setup the worksurface
+ worksurface=cairo_surface_create_similar(surface,
CAIRO_CONTENT_COLOR_ALPHA, workdesc.get_w(), workdesc.get_h());
+
+ //render the background onto the expanded surface
+
if(!context.accelerated_cairorender(worksurface,quality,workdesc,&stageone))
+ return false;
+ // copy the background on the target surface if applies
+ if(!is_solid_color())
+ {
+ cairo_t *cr=cairo_create(surface);
+ cairo_set_source_surface(cr, worksurface,
-halfsizex+(origin_u<0?origin_u:0), -halfsizey+(origin_v<0?origin_v:0));
+ cairo_paint(cr);
+ cairo_destroy(cr);
+ }
+
+ // Extract the CairoSurface from the cairo_surface_t
+ CairoSurface cairoworksurface(worksurface);
+ if(!cairoworksurface.map_cairo_image())
+ {
+ synfig::info("map cairo image failed");
+ return false;
+ }
+ // Extract the alpha
+ blurred.set_wh(workdesc.get_w(),workdesc.get_h());
+ for(int j=0;j<workdesc.get_h();j++)
+ for(int i=0;i<workdesc.get_w();i++)
+
blurred[j][i]=cairoworksurface[j][i].get_a()/CairoColor::ceil;
+
+ //blur the image
+
Blur(size,type,&stagetwo)(blurred,workdesc.get_br()-workdesc.get_tl(),blurred);
+
+ // repaint the cairosubimage with the result. Use the layer's amount
here (is faster)
+ Color ccolor(color);
+ float am=get_amount();
+ for(y=0; y<workdesc.get_h(); y++)
+ for(x=0;x<workdesc.get_w();x++)
+ {
+ float a=blurred[y][x];
+ ccolor.set_a(a*am);
+ ccolor.clamped();
+
cairoworksurface[y][x]=CairoColor(ccolor).premult_alpha();
+ }
+
+ cairoworksurface.unmap_cairo_image();
+
+ // Now lets blend the result in the output surface
+ cairo_t *cr=cairo_create(surface);
+ cairo_set_source_surface(cr, worksurface,
-halfsizex+(origin_u<0?origin_u:0)-origin_u,
-halfsizey+(origin_v<0?origin_v:0)-origin_v);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER); // TODO this has to be the
real operator
+ cairo_paint(cr); // not need to paint with alpha because it is already
included
+ cairo_destroy(cr);
+
+ cairo_surface_destroy(worksurface);
+
+#undef GAUSSIAN_ADJUSTMENT
+#undef SCALE_FACTOR
+
+ if(cb && !cb->amount_complete(10000,10000))
+ {
+ //if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer
Failure",__LINE__));
+ return false;
+ }
+
+ return true;
+}
+
+///
+
Layer::Vocab
Layer_Shade::get_param_vocab(void)const
{
diff --git a/synfig-core/src/modules/lyr_std/shade.h
b/synfig-core/src/modules/lyr_std/shade.h
index ec16ad1..13867b0 100644
--- a/synfig-core/src/modules/lyr_std/shade.h
+++ b/synfig-core/src/modules/lyr_std/shade.h
@@ -57,6 +57,7 @@ public:
virtual Color get_color(Context context, const Point &pos)const;
virtual bool accelerated_render(Context context,Surface *surface,int
quality, const RendDesc &renddesc, ProgressCallback *cb)const;
+ virtual bool accelerated_cairorender(Context context,cairo_surface_t
*surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const;
virtual Rect get_full_bounding_rect(Context context)const;
virtual Vocab get_param_vocab()const;
virtual bool reads_context()const { return true; }
------------------------------------------------------------------------------
Got visibility?
Most devs has no idea what their production app looks like.
Find out how fast your code is with AppDynamics Lite.
http://ad.doubleclick.net/clk;262219671;13503038;y?
http://info.appdynamics.com/FreeJavaPerformanceDownload.html
_______________________________________________
Synfig-devl mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/synfig-devl