Author: Carlos Lopez <[email protected]>
Date:   Sat Aug 11 17:50:02 2012 +0200

Circle Layer: Add support for feathered circles. Only falloff linear at the 
moment.

---

 synfig-core/src/modules/mod_geometry/circle.cpp |  159 +++++++++++++++++++++-
 1 files changed, 151 insertions(+), 8 deletions(-)

diff --git a/synfig-core/src/modules/mod_geometry/circle.cpp 
b/synfig-core/src/modules/mod_geometry/circle.cpp
index 604e8ea..5231776 100644
--- a/synfig-core/src/modules/mod_geometry/circle.cpp
+++ b/synfig-core/src/modules/mod_geometry/circle.cpp
@@ -1016,11 +1016,18 @@ Circle::accelerated_cairorender(Context 
context,cairo_surface_t *surface,int qua
        {
                if(invert)
                {
-                       // Draw the inverted feathered circle
+                       if(
+                          is_solid_color()
+                          ||
+                          (get_blend_method() == Color::BLEND_COMPOSITE &&
+                               get_amount() == 1.0f &&
+                               color.get_a() == 1.0f)
+                          )
+                       {
+                               // Draw the inverted feathered circle
                                cairo_pattern_t* 
gradient=cairo_pattern_create_radial(origin[0], origin[1], out_radius, 
origin[0], origin[1], in_radius);
-                               cairo_pattern_add_color_stop_rgba(gradient, 
0.0, r, g, b, a);
-                               cairo_pattern_add_color_stop_rgba(gradient, 
1.0, r, g, b, 0);
-                               // Now draw the circle with the out_radius
+                               cairo_pattern_add_color_stop_rgba(gradient, 
0.0, r, g, b, falloff_func(cache,out_radius*out_radius));
+                               cairo_pattern_add_color_stop_rgba(gradient, 
1.0, r, g, b, falloff_func(cache,in_radius*in_radius));
                                cairo_save(cr);
                                // This is the scale and translation values
                                double tx(-tl[0]/pw);
@@ -1032,17 +1039,153 @@ Circle::accelerated_cairorender(Context 
context,cairo_surface_t *surface,int qua
                                cairo_scale(cr, sx, sy);
                                cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
                                cairo_set_source(cr, gradient);
+                               cairo_paint(cr);
+                               cairo_pattern_destroy(gradient); // Not needed 
more
+                               cairo_restore(cr);
+                               // Check for the case where there is nothing 
else to render
+                               if (degenerated)
+                               {
+                                       cairo_destroy(cr);
+                                       return true;
+                               }
+                               if(!is_solid_color())  // this means that it is 
just opaque.
+                               {
+                                       // Since it is opaque it means that we 
don't
+                                       // need to render the context beyond 
the outer radius
+                                       // So first, modify the Render 
Description to render on
+                                       // the intersection only.
+                                       RendDesc desc(renddesc);
+                                       //desc.set_flags(0);
+                                       // this will modify the w and h values 
in pixels.
+                                       desc.set_tl(Point(inter_out_min[0], 
inter_out_max[1]));
+                                       desc.set_br(Point(inter_out_max[0], 
inter_out_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());
+                                       // 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;
+                                               }
+                                       }
+                                       // Now, place the rendered surface 
behind the inverted circle.
+                                       // remember that the circle has 
Composite blend method at
+                                       // this point
+                                       double width 
(inter_out_max[0]-inter_out_min[0]);
+                                       double 
height(inter_out_max[1]-inter_out_min[1]);
+                                       // This is the scale and translation 
values
+                                       double tx(-tl[0]/pw);
+                                       double ty(-tl[1]/ph);
+                                       double sx(1/pw);
+                                       double sy(1/ph);
+                                       
+                                       cairo_save(cr);
+                                       cairo_set_source_surface(cr, subimage, 
(inter_out_min[0]-tl[0])/pw, (inter_out_max[1]-tl[1])/ph);
+                                       cairo_translate(cr, tx , ty);
+                                       cairo_scale(cr, sx, sy);
+                                       cairo_rectangle(cr, inter_out_min[0], 
inter_out_min[1], width, height);
+                                       cairo_clip(cr);
+                                       cairo_set_operator(cr, 
CAIRO_OPERATOR_DEST_OVER);
+                                       cairo_paint(cr);
+                                       cairo_restore(cr);
+                                       cairo_surface_destroy(subimage);
+                                       cairo_pattern_destroy(gradient);
+                                       cairo_destroy(cr);
+                                       return true;
+                               }
+                       }
+                       else //inverted and semi transparent
+                       {
+                               // 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;
+                               }
+                               // Draw the inverted feathered circle
+                               cairo_pattern_t* 
gradient=cairo_pattern_create_radial(origin[0], origin[1], out_radius, 
origin[0], origin[1], in_radius);
+                               cairo_pattern_add_color_stop_rgba(gradient, 
0.0, r, g, b, falloff_func(cache,out_radius*out_radius));
+                               cairo_pattern_add_color_stop_rgba(gradient, 
1.0, r, g, b, falloff_func(cache,in_radius*in_radius));
+                               cairo_save(cr);
+                               // This is the scale and translation values
+                               double tx(-tl[0]/pw);
+                               double ty(-tl[1]/ph);
+                               double sx(1/pw);
+                               double sy(1/ph);
+                               
+                               cairo_translate(cr, tx , ty);
+                               cairo_scale(cr, sx, sy);
+                               cairo_set_operator(cr, CAIRO_OPERATOR_OVER); // 
TODO: this has to be the real operator
+                               cairo_set_source(cr, gradient);
                                cairo_paint_with_alpha(cr, get_amount());
+                               cairo_pattern_destroy(gradient); // Not needed 
more
                                cairo_restore(cr);
-                               cairo_pattern_destroy(gradient);
                                cairo_destroy(cr);
                                return true;
-
+                       }
                        
                }
-               else
+               else // not inverted
                {
-                       
+                       // check if the circle covers completely the canvas
+                       // and it is full opaque
+                       if(
+                          (
+                               is_solid_color()
+                               ||
+                               (get_blend_method() == Color::BLEND_COMPOSITE &&
+                                get_amount() == 1.0f &&
+                                color.get_a() == 1.0f)
+                               )
+                          &&
+                          inter_in==dest
+                          )
+                       {
+                               // Fill the surface with the color
+                               cairo_save(cr);
+                               cairo_set_source_rgba(cr, r, g, b, a); // a=1.0
+                               cairo_paint(cr);
+                               cairo_restore(cr);
+                               cairo_destroy(cr);
+                               // Mark our progress as finished
+                               if(cb && !cb->amount_complete(10000,10000))
+                                       return false;
+                               return true;    
+                       }
+                       else
+                       {
+                               // 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;
+                               }
+                               // Draw the feathered circle
+                               cairo_pattern_t* 
gradient=cairo_pattern_create_radial(origin[0], origin[1], out_radius, 
origin[0], origin[1], in_radius);
+                               cairo_pattern_add_color_stop_rgba(gradient, 
0.0, r, g, b, falloff_func(cache,out_radius*out_radius));
+                               cairo_pattern_add_color_stop_rgba(gradient, 
1.0, r, g, b, falloff_func(cache,in_radius*in_radius));
+                               cairo_save(cr);
+                               // This is the scale and translation values
+                               double tx(-tl[0]/pw);
+                               double ty(-tl[1]/ph);
+                               double sx(1/pw);
+                               double sy(1/ph);
+                               
+                               cairo_translate(cr, tx , ty);
+                               cairo_scale(cr, sx, sy);
+                               cairo_set_operator(cr, CAIRO_OPERATOR_OVER); // 
TODO: this has to be the real operator
+                               cairo_set_source(cr, gradient);
+                               cairo_paint_with_alpha(cr, get_amount());
+                               cairo_pattern_destroy(gradient); // Not needed 
more
+                               cairo_restore(cr);
+                               cairo_destroy(cr);
+                               return true;
+                       }
                }
                
        }


------------------------------------------------------------------------------
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