Author: Carlos Lopez <[email protected]>
Date:   Sat Aug 11 19:33:03 2012 +0200

Circle Layer: add full support for feathered circles. It needs some improvement 
on the number of stops in the gradients. Sigmoind and Cosine feathers doesn't 
have good result though. Probable optimization for linear feather.

---

 synfig-core/src/modules/mod_geometry/circle.cpp |   53 +++++++++++++++++++----
 synfig-core/src/modules/mod_geometry/circle.h   |    1 +
 2 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/synfig-core/src/modules/mod_geometry/circle.cpp 
b/synfig-core/src/modules/mod_geometry/circle.cpp
index 69405f4..ff26c55 100644
--- a/synfig-core/src/modules/mod_geometry/circle.cpp
+++ b/synfig-core/src/modules/mod_geometry/circle.cpp
@@ -803,6 +803,26 @@ Circle::accelerated_cairorender(Context 
context,cairo_surface_t *surface,int qua
 
        const Real in_radius=radius-newfeather>0?radius-newfeather:0;
        const Real out_radius=radius+newfeather;
+
+       const Real inner_radius = radius-newfeather>0 ? radius-newfeather : 0;
+       const Real outer_radius = radius+newfeather;
+       
+       const Real inner_radius_sqd = inner_radius*inner_radius;
+       const Real outer_radius_sqd = outer_radius*outer_radius;
+       
+       const Real diff_radii_sqd = 
4*newfeather*std::max(newfeather,radius);//4.0*radius*newfeather;
+       const Real double_feather = newfeather * 2.0;
+       
+       //Compile the temporary cache for the falloff calculations
+       FALLOFF_FUNC *func = GetFalloffFunc();
+       
+       const CircleDataCache cache =
+       {
+               inner_radius,outer_radius,
+               inner_radius_sqd,outer_radius_sqd,
+               diff_radii_sqd,double_feather
+       };
+       
        const Point
                        out_bl(origin-Point(out_radius, out_radius)),
                        out_tr(origin+Point(out_radius, out_radius)),
@@ -1007,9 +1027,8 @@ Circle::accelerated_cairorender(Context 
context,cairo_surface_t *surface,int qua
                           )
                        {
                                // 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_pattern_t* 
gradient=cairo_pattern_create_radial(origin[0], origin[1], in_radius, 
origin[0], origin[1], out_radius);
+                               compile_gradient(gradient, cache, func);
                                cairo_save(cr);
                                cairo_translate(cr, tx , ty);
                                cairo_scale(cr, sx, sy);
@@ -1077,9 +1096,8 @@ Circle::accelerated_cairorender(Context 
context,cairo_surface_t *surface,int qua
                                        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_pattern_t* 
gradient=cairo_pattern_create_radial(origin[0], origin[1], in_radius, 
origin[0], origin[1], out_radius);
+                               compile_gradient(gradient, cache, func);
                                cairo_save(cr);
                                cairo_translate(cr, tx , ty);
                                cairo_scale(cr, sx, sy);
@@ -1130,9 +1148,8 @@ Circle::accelerated_cairorender(Context 
context,cairo_surface_t *surface,int qua
                                        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_pattern_t* 
gradient=cairo_pattern_create_radial(origin[0], origin[1], in_radius, 
origin[0], origin[1], out_radius);
+                               compile_gradient(gradient, cache, func);
                                cairo_save(cr);
                                cairo_translate(cr, tx , ty);
                                cairo_scale(cr, sx, sy);
@@ -1151,6 +1168,24 @@ Circle::accelerated_cairorender(Context 
context,cairo_surface_t *surface,int qua
 }
 
 
+void
+Circle::compile_gradient(cairo_pattern_t* gradient, CircleDataCache mycache, 
FALLOFF_FUNC *func)const
+{
+       double index;
+       const float r(color.get_r());
+       const float g(color.get_g());
+       const float b(color.get_b());
+       const float a(color.get_a());
+       for(index=0.0;index<=1.0;index+=0.1)
+       {
+               double 
radius=mycache.inner_radius+index*(mycache.outer_radius-mycache.inner_radius);
+               double alpha=func(mycache, radius*radius);
+               if(alpha>1.0) alpha =1.0;
+               if(alpha<0.0) alpha =0.0;
+               cairo_pattern_add_color_stop_rgba(gradient, index, r, g, b, 
a*alpha);
+       }
+}
+
 ///////////
 
 
diff --git a/synfig-core/src/modules/mod_geometry/circle.h 
b/synfig-core/src/modules/mod_geometry/circle.h
index 451aa24..46662de 100644
--- a/synfig-core/src/modules/mod_geometry/circle.h
+++ b/synfig-core/src/modules/mod_geometry/circle.h
@@ -115,6 +115,7 @@ public:
        synfig::Layer::Handle hit_check(synfig::Context context, const 
synfig::Point &point)const;
 
        virtual Vocab get_param_vocab()const;
+       void compile_gradient(cairo_pattern_t* gradient, CircleDataCache cache, 
FALLOFF_FUNC *func)const;
 };
 
 /* -- E X T E R N S --------------------------------------------------------- 
*/


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