From 24f19dc770093e9c7d67887502a384cbe894c47f Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Mon, 29 Feb 2016 15:23:18 +0900 Subject: [PATCH] Efl.Gfx.Filter: Rework APIs and mark as stable - Remove @beta flags, - Update @since to match stabilization, - Change methods to properties with keys, - Use eo_prefix and add filter_ prefix to all properties since they use very generic names, The filter API stays under Efl.Gfx since there are other kinds of filters, and this one is the particular "graphical filter" or "effect" API. The EO API mostly not change from an application point of view, except for "source_get" which now returns a string directly. Also, state and data can now be queried. --- src/lib/efl/interfaces/efl_gfx_filter.eo | 107 +++++++++++++++++++------------ src/lib/evas/canvas/evas_filter.eo | 39 ++++++----- src/lib/evas/canvas/evas_filter_mixin.c | 88 ++++++++++++++++++------- src/lib/evas/canvas/evas_image.eo | 8 +-- src/lib/evas/canvas/evas_object_image.c | 15 +++-- src/lib/evas/canvas/evas_object_text.c | 14 ++-- src/lib/evas/canvas/evas_text.eo | 8 +-- src/tests/edje/edje_test_edje.c | 2 +- 8 files changed, 177 insertions(+), 104 deletions(-) diff --git a/src/lib/efl/interfaces/efl_gfx_filter.eo b/src/lib/efl/interfaces/efl_gfx_filter.eo index f9cf35f..f4aabf0 100644 --- a/src/lib/efl/interfaces/efl_gfx_filter.eo +++ b/src/lib/efl/interfaces/efl_gfx_filter.eo @@ -1,45 +1,69 @@ interface Efl.Gfx.Filter { + [[Graphical filters can be applied to any object implementing this interface. + + Filters are programmable effects that run whenever the object is rendered + on its canvas. The program language is Lua and a complete reference can + be found under "EFL Graphics Filters". + + This was a beta feature since 1.15. + + @since 1.18 + ]] + eo_prefix: efl_gfx; legacy_prefix: null; - /* @since 1.15 */ methods { - @property program @beta { + @property filter_program { set { - [[Set an evas filter program on this object. + [[Set a graphical filter program on this object. Valid for Text and Image objects at the moment. - The argument passed to this function is a string - containing a valid Lua program based on the filters - API as described in the "Evas filters reference" - page. + The argument passed to this function is a string containing + a valid Lua program based on the filters API as described in + the "EFL Graphics Filters" reference page. - Set to null to disable filtering. + Set to $null to disable filtering. ]] } get { [[Gets the code of the filter program set on this object. - May be null. + May be $null. ]] } values { - code: const(char)*; [[filter program source code]] - name: const(char)*(0); [[filter name (optional)]] + code: const(char)*; [[The Lua program source code.]] + name: const(char)* @optional; [[An optional name for this filter.]] } } - @property state @beta { - set { - [[Set the current state of the filter (for use from Edje).]] - } + @property filter_state { + [[Set the current state of the filter. + + This should be used by Edje (EFL's internal layout engine), but + could also be used when implementing animations programmatically. + + A full state is defined by two states (name + value): origin state + and target state of an ongoing animation, as well as the $pos + progress (from 0 to 1) of that animation timeline. The second state + can be omitted if there is no ongoing animation. + ]] + get {} + set {} values { cur_state: const(char)*; - cur_val: double(0.0); - next_state: const(char)*; - next_val: double(0.0); - pos: double(0.0); + cur_val: double; + next_state: const(char)* @optional; + next_val: double @optional; + pos: double @optional; } } - @property padding @beta { + @property filter_padding { + [[Required padding to apply this filter without cropping. + + Read-only property that can be used to calculate the object's final + geometry. This can be overriden (set) from inside the filter program + by using the function 'padding_set' in the Lua program. + ]] get { [[Gets the padding required to apply this filter.]] } @@ -50,34 +74,37 @@ interface Efl.Gfx.Filter b: int; } } - source_set @beta { - [[Bind an object to use as a mask or texture with Evas Filters. + @property filter_source { + [[Bind an object to use as a mask or texture in a filter program. This will create automatically a new RGBA buffer containing the source object's pixels (as it is rendered). ]] - params { - @in name: const(char)*; [[buffer name as used in the program]] - @in source: Efl.Gfx.Base*; [[object to use as a proxy source]] + set {} + get {} + keys { + name: const(char)*; [[Buffer name as used in the program.]] } - } - source_get @const @beta { - [[Retrieve which object is attached to this filter given its - buffer name. - ]] - params { - @in name: const(char)*; [[buffer name as used in the program]] - @out source: Efl.Gfx.Base*; [[object used as a proxy source]] + values { + source: Efl.Gfx.Base*; [[Object to use as a source of pixels.]] } } - data_set @beta { - [[Pass extra data to the filter program. + @property filter_data { + [[Extra data used by the filter program. - This sets a global value as a string.]] - params { - @in name: const(char)*; [[Name of the global variable]] - @in value: const(char)*; [[String value to use as data]] - @in execute: bool; [[If true, execute 'name = value']] + Each data element is a string ($value) stored as a global variable + $name. The program is then responsible for conversion to numbers, + tables, etc... + + If the $execute flag is set, then the $value can be complex and + run, as if the original Lua program contained a line 'name = value'. + ]] + keys { + name: const(char)*; [[Name of the global variable]] + } + values { + value: const(char)*; [[String value to use as data]] + execute: bool(false); [[If $true, execute 'name = value']] } } } diff --git a/src/lib/evas/canvas/evas_filter.eo b/src/lib/evas/canvas/evas_filter.eo index 18a4d28..8383567 100644 --- a/src/lib/evas/canvas/evas_filter.eo +++ b/src/lib/evas/canvas/evas_filter.eo @@ -1,9 +1,12 @@ mixin Evas.Filter (Efl.Gfx.Filter, Eo.Base) { - // Evas internal implementation + [[Evas internal implementation of filters.]] + + eo_prefix: evas; legacy_prefix: null; + methods { - @property changed @protected { + @property filter_changed @protected { set { [[Marks this filter as changed.]] } @@ -11,7 +14,7 @@ mixin Evas.Filter (Efl.Gfx.Filter, Eo.Base) val: bool; } } - @property invalid @protected { + @property filter_invalid @protected { set { [[Marks this filter as invalid.]] } @@ -19,11 +22,11 @@ mixin Evas.Filter (Efl.Gfx.Filter, Eo.Base) val: bool; } } - input_alpha @protected { + filter_input_alpha @protected { [[Called by Evas.Filter to determine whether the input is alpha or rgba.]] return: bool; } - input_render @protected { + filter_input_render @protected { [[Called by Evas.Filter when the parent class must render the input. ; ]] @@ -38,13 +41,13 @@ mixin Evas.Filter (Efl.Gfx.Filter, Eo.Base) do_async: bool; } } - dirty @protected { + filter_dirty @protected { [[Called when the filter changes must trigger a redraw of the object. Virtual, to be implemented in the parent class. ]] } - @property output_buffer @protected { + @property filter_output_buffer @protected { get { [[Retrieve cached output buffer, if any. @@ -59,15 +62,17 @@ mixin Evas.Filter (Efl.Gfx.Filter, Eo.Base) implements { Eo.Base.constructor; Eo.Base.destructor; - Efl.Gfx.Filter.program.set; - Efl.Gfx.Filter.program.get; - Efl.Gfx.Filter.state.set; - Efl.Gfx.Filter.padding.get; - Efl.Gfx.Filter.source_set; - Efl.Gfx.Filter.source_get; - Efl.Gfx.Filter.data_set; - @virtual .input_alpha; - @virtual .input_render; - @virtual .dirty; + Efl.Gfx.Filter.filter_program.set; + Efl.Gfx.Filter.filter_program.get; + Efl.Gfx.Filter.filter_state.get; + Efl.Gfx.Filter.filter_state.set; + Efl.Gfx.Filter.filter_padding.get; + Efl.Gfx.Filter.filter_source.set; + Efl.Gfx.Filter.filter_source.get; + Efl.Gfx.Filter.filter_data.get; + Efl.Gfx.Filter.filter_data.set; + @virtual .filter_input_alpha; + @virtual .filter_input_render; + @virtual .filter_dirty; } } diff --git a/src/lib/evas/canvas/evas_filter_mixin.c b/src/lib/evas/canvas/evas_filter_mixin.c index 643f5ad..eb2f557 100644 --- a/src/lib/evas/canvas/evas_filter_mixin.c +++ b/src/lib/evas/canvas/evas_filter_mixin.c @@ -352,8 +352,8 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, } EOLIAN static void -_evas_filter_efl_gfx_filter_program_set(Eo *eo_obj, Evas_Filter_Data *pd, - const char *code, const char *name) +_evas_filter_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_Filter_Data *pd, + const char *code, const char *name) { Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); Evas_Filter_Program *pgm = NULL; @@ -404,15 +404,15 @@ _evas_filter_efl_gfx_filter_program_set(Eo *eo_obj, Evas_Filter_Data *pd, } EOLIAN static void -_evas_filter_efl_gfx_filter_program_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, const char **code, const char **name) +_evas_filter_efl_gfx_filter_filter_program_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, const char **code, const char **name) { if (code) *code = pd->data->code; if (name) *name = pd->data->name; } EOLIAN static void -_evas_filter_efl_gfx_filter_source_set(Eo *eo_obj, Evas_Filter_Data *pd, - const char *name, Efl_Gfx_Base *eo_source) +_evas_filter_efl_gfx_filter_filter_source_set(Eo *eo_obj, Evas_Filter_Data *pd, + const char *name, Efl_Gfx_Base *eo_source) { Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); Evas_Filter_Proxy_Binding *pb, *pb_old = NULL; @@ -497,19 +497,20 @@ update: evas_object_inform_call_resize(eo_obj); } -EOLIAN static void -_evas_filter_efl_gfx_filter_source_get(const Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, - const char *name, Efl_Gfx_Base **source) +EOLIAN static Efl_Gfx_Base * +_evas_filter_efl_gfx_filter_filter_source_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd, + const char * name) { - if (!source) return; - *source = eina_hash_find(pd->data->sources, name); + Evas_Filter_Proxy_Binding *pb = eina_hash_find(pd->data->sources, name); + if (!pb) return NULL; + return pb->eo_source; } EOLIAN static void -_evas_filter_efl_gfx_filter_state_set(Eo *eo_obj, Evas_Filter_Data *pd, - const char *cur_state, double cur_val, - const char *next_state, double next_val, - double pos) +_evas_filter_efl_gfx_filter_filter_state_set(Eo *eo_obj, Evas_Filter_Data *pd, + const char *cur_state, double cur_val, + const char *next_state, double next_val, + double pos) { Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); @@ -520,9 +521,9 @@ _evas_filter_efl_gfx_filter_state_set(Eo *eo_obj, Evas_Filter_Data *pd, { Evas_Object_Filter_Data *fcow = FCOW_BEGIN(pd); fcow->changed = 1; - fcow->state.cur.name = cur_state; + eina_stringshare_replace(&fcow->state.cur.name, cur_state); fcow->state.cur.value = cur_val; - fcow->state.next.name = next_state; + eina_stringshare_replace(&fcow->state.next.name, next_state); fcow->state.next.value = next_val; fcow->state.pos = pos; FCOW_END(fcow, pd); @@ -545,8 +546,21 @@ _evas_filter_efl_gfx_filter_state_set(Eo *eo_obj, Evas_Filter_Data *pd, } EOLIAN static void -_evas_filter_efl_gfx_filter_padding_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, - int *l, int *r, int *t, int *b) +_evas_filter_efl_gfx_filter_filter_state_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd, + const char **cur_state, double *cur_val, + const char **next_state, double *next_val, + double *pos) +{ + if (cur_state) *cur_state = pd->data->state.cur.name; + if (cur_val) *cur_val = pd->data->state.cur.value; + if (next_state) *next_state = pd->data->state.next.name; + if (next_val) *next_val = pd->data->state.next.value; + if (pos) *pos = pd->data->state.pos; +} + +EOLIAN static void +_evas_filter_efl_gfx_filter_filter_padding_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, + int *l, int *r, int *t, int *b) { if (!pd->data->chain) { @@ -560,7 +574,7 @@ _evas_filter_efl_gfx_filter_padding_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data } EOLIAN static void -_evas_filter_changed_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val) +_evas_filter_filter_changed_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val) { if ((evas_object_filter_cow_default != pd->data) && (pd->data->changed != val)) { @@ -571,7 +585,7 @@ _evas_filter_changed_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool } EOLIAN static void -_evas_filter_invalid_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val) +_evas_filter_filter_invalid_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val) { if (pd->data->invalid != val) { @@ -619,6 +633,8 @@ _evas_filter_eo_base_destructor(Eo *eo_obj, Evas_Filter_Data *pd) } evas_filter_program_del(pd->data->chain); eina_stringshare_del(pd->data->code); + eina_stringshare_del(pd->data->state.cur.name); + eina_stringshare_del(pd->data->state.next.name); finish: eina_cow_free(evas_object_filter_cow, (const Eina_Cow_Data **) &pd->data); @@ -634,9 +650,9 @@ finish: } EOLIAN static void -_evas_filter_efl_gfx_filter_data_set(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd, - const char *name, const char *value, - Eina_Bool execute) +_evas_filter_efl_gfx_filter_filter_data_set(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd, + const char *name, const char *value, + Eina_Bool execute) { Evas_Filter_Data_Binding *db, *found = NULL; Evas_Object_Filter_Data *fcow; @@ -680,8 +696,32 @@ _evas_filter_efl_gfx_filter_data_set(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd, FCOW_END(fcow, pd); } +EOLIAN static void +_evas_filter_efl_gfx_filter_filter_data_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd, + const char *name, const char **value, + Eina_Bool *execute) +{ + Evas_Filter_Data_Binding *db; + + if (!value && !execute) return; + EINA_SAFETY_ON_NULL_RETURN(pd->data); + + EINA_INLIST_FOREACH(pd->data->data, db) + { + if (!strcmp(name, db->name)) + { + if (value) *value = db->value; + if (execute) *execute = db->execute; + return; + } + } + + if (value) *value = NULL; + if (execute) *execute = EINA_FALSE; +} + EOLIAN static void * -_evas_filter_output_buffer_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd) +_evas_filter_filter_output_buffer_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd) { return pd->data->output; } diff --git a/src/lib/evas/canvas/evas_image.eo b/src/lib/evas/canvas/evas_image.eo index a14f183..7eff63a 100644 --- a/src/lib/evas/canvas/evas_image.eo +++ b/src/lib/evas/canvas/evas_image.eo @@ -784,9 +784,9 @@ class Evas.Image (Evas.Object, Efl.File, Efl.Image, Efl.Gfx.Fill, Efl.Gfx.View, Efl.Gfx.Fill.fill.get; Efl.Gfx.View.size.set; Efl.Gfx.View.size.get; - Efl.Gfx.Filter.program.set; - Evas.Filter.input_alpha; - Evas.Filter.input_render; - Evas.Filter.dirty; + Efl.Gfx.Filter.filter_program.set; + Evas.Filter.filter_input_alpha; + Evas.Filter.filter_input_render; + Evas.Filter.filter_dirty; } } diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 474386f..ed2e604 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -3208,22 +3208,22 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, } EOLIAN static void -_evas_image_evas_filter_dirty(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o) +_evas_image_evas_filter_filter_dirty(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o) { o->changed = 1; } EOLIAN static Eina_Bool -_evas_image_evas_filter_input_alpha(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o EINA_UNUSED) +_evas_image_evas_filter_filter_input_alpha(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o EINA_UNUSED) { return EINA_FALSE; } EOLIAN static Eina_Bool -_evas_image_evas_filter_input_render(Eo *eo_obj, Evas_Image_Data *o, - void *_filter, void *context, - int l, int r EINA_UNUSED, int t, int b EINA_UNUSED, - Eina_Bool do_async) +_evas_image_evas_filter_filter_input_render(Eo *eo_obj, Evas_Image_Data *o, + void *_filter, void *context, + int l, int r EINA_UNUSED, int t, int b EINA_UNUSED, + Eina_Bool do_async) { Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); Evas_Filter_Context *filter = _filter; @@ -4974,7 +4974,8 @@ evas_object_image_smooth_scale_get(const Eo *obj) } EOLIAN static void -_evas_image_efl_gfx_filter_program_set(Eo *obj, Evas_Image_Data *pd EINA_UNUSED, const char *code, const char *name) +_evas_image_efl_gfx_filter_filter_program_set(Eo *obj, Evas_Image_Data *pd EINA_UNUSED, + const char *code, const char *name) { pd->has_filter = (code != NULL); eo_do_super(obj, MY_CLASS, efl_gfx_filter_program_set(code, name)); diff --git a/src/lib/evas/canvas/evas_object_text.c b/src/lib/evas/canvas/evas_object_text.c index 28e756c..70f527f 100644 --- a/src/lib/evas/canvas/evas_object_text.c +++ b/src/lib/evas/canvas/evas_object_text.c @@ -1664,7 +1664,7 @@ evas_font_draw_async_check(Evas_Object_Protected_Data *obj, /* ugly binding between evas_fitler_mixin.c and this object */ EOLIAN static void -_evas_text_evas_filter_dirty(Eo *eo_obj, Evas_Text_Data *o) +_evas_text_evas_filter_filter_dirty(Eo *eo_obj, Evas_Text_Data *o) { _evas_object_text_items_clear(o); o->changed = 1; @@ -1672,16 +1672,16 @@ _evas_text_evas_filter_dirty(Eo *eo_obj, Evas_Text_Data *o) } EOLIAN static Eina_Bool -_evas_text_evas_filter_input_alpha(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o EINA_UNUSED) +_evas_text_evas_filter_filter_input_alpha(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o EINA_UNUSED) { return EINA_TRUE; } EOLIAN static Eina_Bool -_evas_text_evas_filter_input_render(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o, - void *_filter, void *drawctx, - int l, int r EINA_UNUSED, int t, int b EINA_UNUSED, - Eina_Bool do_async) +_evas_text_evas_filter_filter_input_render(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o, + void *_filter, void *drawctx, + int l, int r EINA_UNUSED, int t, int b EINA_UNUSED, + Eina_Bool do_async) { Evas_Filter_Context *filter = _filter; Evas_Object_Text_Item *it; @@ -2336,7 +2336,7 @@ evas_object_text_text_get(const Eo *obj) } EOLIAN static void -_evas_text_efl_gfx_filter_program_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, const char *code, const char *name) +_evas_text_efl_gfx_filter_filter_program_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, const char *code, const char *name) { pd->has_filter = (code != NULL); eo_do_super(obj, MY_CLASS, efl_gfx_filter_program_set(code, name)); diff --git a/src/lib/evas/canvas/evas_text.eo b/src/lib/evas/canvas/evas_text.eo index e26c561..9e326a21 100644 --- a/src/lib/evas/canvas/evas_text.eo +++ b/src/lib/evas/canvas/evas_text.eo @@ -260,10 +260,10 @@ class Evas.Text (Evas.Object, Efl.Text, Efl.Text_Properties, Evas.Filter) Efl.Text_Properties.font.set; Efl.Text_Properties.font_source.get; Efl.Text_Properties.font_source.set; - Efl.Gfx.Filter.program.set; - Evas.Filter.input_alpha; - Evas.Filter.input_render; - Evas.Filter.dirty; + Efl.Gfx.Filter.filter_program.set; + Evas.Filter.filter_input_alpha; + Evas.Filter.filter_input_render; + Evas.Filter.filter_dirty; Evas.Object.paragraph_direction.set; Evas.Object.paragraph_direction.get; } diff --git a/src/tests/edje/edje_test_edje.c b/src/tests/edje/edje_test_edje.c index 8d5f725..b406bad 100644 --- a/src/tests/edje/edje_test_edje.c +++ b/src/tests/edje/edje_test_edje.c @@ -240,7 +240,7 @@ START_TEST(edje_test_filters) fail_if(!prg); fail_if(!name || strcmp(name, "filterfile")); - eo_do(text, efl_gfx_filter_source_get("mask", &src)); + eo_do(text, src = efl_gfx_filter_source_get("mask")); fail_if(!src); // TODO: Verify properly that the filter runs well -- 2.7.4