Author: Carlos Lopez <[email protected]>
Date: Sat Jul 21 11:19:44 2012 +0200
Rectangle: initial version of accelerated_cairorender. It works fine for non
inverted rectangles but doesn't work properly for inverted rectangles yet.
Blending modes not fully supported.
---
synfig-core/src/modules/mod_geometry/rectangle.cpp | 189 ++++++++++++++++++++
synfig-core/src/modules/mod_geometry/rectangle.h | 1 +
2 files changed, 190 insertions(+), 0 deletions(-)
diff --git a/synfig-core/src/modules/mod_geometry/rectangle.cpp
b/synfig-core/src/modules/mod_geometry/rectangle.cpp
index 9ec1f01..e953acd 100644
--- a/synfig-core/src/modules/mod_geometry/rectangle.cpp
+++ b/synfig-core/src/modules/mod_geometry/rectangle.cpp
@@ -559,6 +559,195 @@ Rectangle::accelerated_render(Context context,Surface
*surface,int quality, cons
return true;
}
+//////
+
+bool
+Rectangle::accelerated_cairorender(Context context,cairo_surface_t
*surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
+{
+ if(is_disabled())
+ return
context.accelerated_cairorender(surface,quality,renddesc,cb);
+
+ Color dcolor(color/*.premult_alpha()*/);
+ const float r(dcolor.get_r());
+ const float g(dcolor.get_g());
+ const float b(dcolor.get_b());
+ const float a(dcolor.get_a());
+
+ 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;
+ Point min(point1), max(point2);
+
+ // if x max, min are swaped then swap the x coordinate
+ if(min[0] > max[0]) swap(min[0],max[0]);
+ // if y max min are swaped then swap the y coordinate
+ if(min[1] > max[1]) swap(min[1],max[1]);
+ // min is the lower left corner and max is the upper right corner
+ // now we need to expand the edges
+ min[0]-=expand;
+ max[0]+=expand;
+ min[1]-=expand;
+ max[1]+=expand;
+ //
+ //synfig::info("min=%f, %f max=%f, %f", min[0], min[1], max[0],
max[1]);
+ //
+ cairo_t* cr=cairo_create(surface);
+ // This is a rectangle with the same dimensions of the rectangle
+ const Rect shape(min, max);
+ // This is a rectangle with the same dimensions of the canvas
+ const Rect dest(tl, br);
+ Rect inter(dest);
+ // inter holds the intersection rectangle of both rectangles.
+ inter&=shape;
+
+ Point inter_min(inter.get_min());
+ Point inter_max(inter.get_max());
+ //
+ //synfig::info("intermin=%f, %f intermax=%f, %f", inter_min[0],
inter_min[1], inter_max[0], inter_max[1]);
+ //
+ if(invert)
+ {
+ if(is_solid_color())
+ {
+ // The rectangle is inverted and is solid color
+ // Let's do this:
+ // Fill the surface with the color intially
+ cairo_save(cr);
+ cairo_set_source_rgba(cr, r, g, b, a); // a=1.0
+ cairo_paint(cr);
+ cairo_restore(cr);
+
+ // Check for the case where there is nothing to render
+ if (inter.area()<0.00000001)
+ {
+ cairo_destroy(cr);
+ return true;
+ }
+ // Modify the Render Description to render on the
intersection.
+ // this will modify the w and h values in pixels.
+ RendDesc desc(renddesc);
+ //desc.set_flags(0);
+ desc.set_tl(Point(inter.get_min()[0],
inter.get_max()[1]));
+ desc.set_br(Point(inter.get_max()[0],
inter.get_min()[1]));
+ // create a new similar surface with the wxh dimensions
+ cairo_surface_t*
subimage=cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR_ALPHA,
desc.get_w(), desc.get_h());
+ synfig::info("w=%d, h=%d", desc.get_w(), desc.get_h());
+ synfig::info("tl=%f,%f br=%f,%f", desc.get_tl()[0],
desc.get_tl()[1], desc.get_br()[0], desc.get_br()[1] );
+ // Render what is behind us
+
if(!context.accelerated_cairorender(subimage,quality,desc,cb))
+ {
+ if(cb)cb->error(strprintf(__FILE__"%d:
Accelerated Cairo Renderer Failure",__LINE__));
+ {
+ cairo_surface_destroy(subimage);
+ cairo_destroy(cr);
+ return false;
+ }
+ }
+ cairo_save(cr);
+ double width (inter_max[0]-inter_min[0]);
+ double height(inter_max[1]-inter_min[1]);
+ double tx((br[0]-tl[0])/2/pw);
+ double ty((br[1]-tl[1])/2/ph);
+ double sx(1/pw);
+ double sy(1/ph);
+ cairo_translate(cr, tx , ty);
+ cairo_scale(cr, sx, sy);
+ cairo_rectangle(cr, inter_min[0], inter_min[1], width,
height);
+ cairo_clip(cr);
+ cairo_set_source_surface(cr, subimage, 0, 0
/*inter_min[0], inter_min[1]*/);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(cr);
+ cairo_restore(cr);
+ cairo_surface_destroy(subimage);
+ cairo_destroy(cr);
+ return true;
+ }
+ else // not solid color so we need to render what's behind
+ {
+ // Initially render what's behind us
+
if(!context.accelerated_cairorender(surface,quality,renddesc,cb))
+ {
+ if(cb)cb->error(strprintf(__FILE__"%d:
Accelerated Cairo Renderer Failure",__LINE__));
+ cairo_destroy(cr);
+ return false;
+ }
+ // Now let's render the rectangle 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_t* subcr=cairo_create(subimage);
+ cairo_set_source_rgba(subcr, r, g, b, a);
+ cairo_paint(subcr);
+ // now remove the area of the intersection rectangle
+ cairo_rectangle(subcr, inter_min[0], inter_min[1],
inter_max[0]-inter_min[0], inter_max[1]-inter_min[1]);
+ cairo_set_operator(subcr, CAIRO_OPERATOR_CLEAR);
+ cairo_fill(cr);
+ // now let's paint the inverted rectangle with the hole
on the rendered context
+ cairo_save(cr);
+ cairo_set_source_surface(cr, subimage, 0, 0);
+ 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;
+ }
+ }
+
+ // not inverted
+ // optimization - if the whole canvas is covered by this rectangle,
+ // and the rectangle is a solid color, we don't need to render
+ // what's behind us
+ if (is_solid_color() && inter==Rect(tl, br))
+ {
+ cairo_set_source_rgba(cr, r, g, b, a);
+ cairo_paint(cr);
+ cairo_destroy(cr);
+ return true;
+ }
+ // The rectangle intersects the canvas partially
+ // Render what is behind us
+ if(!context.accelerated_cairorender(surface,quality,renddesc,cb))
+ {
+ if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Cairo
Renderer Failure",__LINE__));
+ cairo_destroy(cr);
+ return false;
+ }
+
+ // In the case where there is nothing to render...
+ if (inter.area()<0.00000001)
+ return true;
+
+ cairo_set_source_rgba(cr, r, g, b, a);
+ double width (inter_max[0]-inter_min[0]);
+ double height(inter_max[1]-inter_min[1]);
+ double tx((br[0]-tl[0])/2/pw);
+ double ty((br[1]-tl[1])/2/ph);
+ double sx(1/pw);
+ double sy(1/ph);
+ cairo_translate(cr, tx , ty);
+ cairo_scale(cr, sx, sy);
+ cairo_rectangle(cr, inter_min[0], inter_min[1], width, height);
+ cairo_clip(cr);
+ if(is_solid_color())
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ else
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER); // TODO this has
to be the real operator
+ cairo_paint_with_alpha(cr, get_amount());
+ cairo_destroy(cr);
+ return true;
+}
+
+
+//////
+
Rect
Rectangle::get_bounding_rect()const
{
diff --git a/synfig-core/src/modules/mod_geometry/rectangle.h
b/synfig-core/src/modules/mod_geometry/rectangle.h
index add217c..ab7a4a4 100644
--- a/synfig-core/src/modules/mod_geometry/rectangle.h
+++ b/synfig-core/src/modules/mod_geometry/rectangle.h
@@ -67,6 +67,7 @@ public:
virtual synfig::Color get_color(synfig::Context context, const
synfig::Point &pos)const;
virtual bool accelerated_render(synfig::Context context,synfig::Surface
*surface,int quality, const synfig::RendDesc &renddesc,
synfig::ProgressCallback *cb)const;
+ virtual bool accelerated_cairorender(synfig::Context context,
cairo_surface_t *surface,int quality, const synfig::RendDesc &renddesc,
synfig::ProgressCallback *cb)const;
synfig::Layer::Handle hit_check(synfig::Context context, const
synfig::Point &point)const;
------------------------------------------------------------------------------
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