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