From b2a4039bda21989ab9f9316579750f48a83e052a Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 22 Dec 2016 19:41:04 +0900 Subject: [PATCH] evas: Refactor evas filters a bit This is a preparation step for (experimental) textblock support. Textblock objects won't have a single filter, and the buffer's geometry wouldn't be that of of the object itself. Thus a few internal APIs need to be reworked first. --- src/Makefile_Evas.am | 1 + .../evas/canvas/efl_canvas_filter_internal.eo | 57 ++++++++++++++-- .../evas/canvas/efl_canvas_image_internal.eo | 3 +- src/lib/evas/canvas/evas_filter_mixin.c | 45 +++++++------ src/lib/evas/canvas/evas_object_image.c | 27 ++++++-- src/lib/evas/canvas/evas_object_text.c | 26 +++++++- src/lib/evas/canvas/evas_text.eo | 5 +- src/lib/evas/filters/evas_filter.c | 15 ++--- src/lib/evas/filters/evas_filter_parser.c | 66 +++---------------- src/lib/evas/include/evas_filter.h | 7 +- 10 files changed, 146 insertions(+), 106 deletions(-) diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 8b8186b4fd..c78a3982dd 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -2353,6 +2353,7 @@ tests/evas/evas_suite.h tests_evas_evas_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ -I$(top_srcdir)/src/lib/ecore_evas \ +-I$(top_builddir)/src/lib/evas/canvas \ -DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/evas\" \ -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/evas\" \ @CHECK_CFLAGS@ \ diff --git a/src/lib/evas/canvas/efl_canvas_filter_internal.eo b/src/lib/evas/canvas/efl_canvas_filter_internal.eo index 48bfd2685d..1f612701c5 100644 --- a/src/lib/evas/canvas/efl_canvas_filter_internal.eo +++ b/src/lib/evas/canvas/efl_canvas_filter_internal.eo @@ -1,3 +1,43 @@ +// import efl_gfx_types -> need to add Efl.Gfx.Color + +/* Everything in this file is internal to Evas. It is not meant to be used + from outside EFL itself! */ + +struct Efl.Gfx.Color32 +{ + r: uint8; + g: uint8; + b: uint8; + a: uint8; +} + +struct Efl.Canvas.Filter.State_Name +{ + name: string; + value: double; +} + +struct Efl.Canvas.Filter.State_Text +{ + outline: Efl.Gfx.Color32; + shadow: Efl.Gfx.Color32; + glow: Efl.Gfx.Color32; + glow2: Efl.Gfx.Color32; +} + +struct Efl.Canvas.Filter.State +{ + [[Internal structure representing the state of a Gfx Filter]] + text: Efl.Canvas.Filter.State_Text; + color: Efl.Gfx.Color32; + cur: Efl.Canvas.Filter.State_Name; + next: Efl.Canvas.Filter.State_Name; + w: int; + h: int; + scale: double; + pos: double; +} + mixin Efl.Canvas.Filter.Internal (Efl.Gfx.Filter, Efl.Object) { [[Evas internal implementation of filters.]] @@ -26,14 +66,21 @@ mixin Efl.Canvas.Filter.Internal (Efl.Gfx.Filter, Efl.Object) [[Called by Efl.Canvas.Filter.Internal to determine whether the input is alpha or rgba.]] return: bool; [[$true on success, $false otherwise]] } + filter_state_prepare @protected @pure_virtual { + [[Called by Efl.Canvas.Filter.Internal to request the parent class + for state information (color, etc...).]] + params { + @out state: Efl.Canvas.Filter.State; [[State info to fill in]] + @in data: void_ptr; [[Private data for the class]] + } + } filter_input_render @protected @pure_virtual { - [[Called by Efl.Canvas.Filter.Internal when the parent class must render the input. - ; - ]] + [[Called by Efl.Canvas.Filter.Internal when the parent class must render the input.]] return: bool; [[Indicates success from the object render function.]] params { - filter: void_ptr; [[Evas_Filter_Context]] - drawctx: void_ptr; [[Draw context]] + filter: void_ptr; [[Current filter context]] + drawctx: void_ptr; [[Draw context (for evas engine)]] + data: void_ptr; [[Arbitrary private data]] l: int; [[Left]] r: int; [[Right]] t: int; [[Top]] diff --git a/src/lib/evas/canvas/efl_canvas_image_internal.eo b/src/lib/evas/canvas/efl_canvas_image_internal.eo index 2101a564f0..420743ecd8 100644 --- a/src/lib/evas/canvas/efl_canvas_image_internal.eo +++ b/src/lib/evas/canvas/efl_canvas_image_internal.eo @@ -28,8 +28,9 @@ abstract Efl.Canvas.Image.Internal (Efl.Canvas.Object, Efl.Canvas.Filter.Interna Efl.Gfx.Fill.fill_auto { get; set; } Efl.Gfx.Filter.filter_program { set; } Efl.Gfx.View.view_size { get; } + Efl.Canvas.Filter.Internal.filter_dirty; Efl.Canvas.Filter.Internal.filter_input_alpha; Efl.Canvas.Filter.Internal.filter_input_render; - Efl.Canvas.Filter.Internal.filter_dirty; + Efl.Canvas.Filter.Internal.filter_state_prepare; } } diff --git a/src/lib/evas/canvas/evas_filter_mixin.c b/src/lib/evas/canvas/evas_filter_mixin.c index 94070ca331..3f211a4fab 100644 --- a/src/lib/evas/canvas/evas_filter_mixin.c +++ b/src/lib/evas/canvas/evas_filter_mixin.c @@ -150,6 +150,21 @@ _filter_source_hash_free_cb(void *data) free(pb); } +static inline Eina_Bool +_evas_filter_state_set_internal(Evas_Filter_Program *pgm, Evas_Filter_Data *pd) +{ + Efl_Canvas_Filter_State state = EFL_CANVAS_FILTER_STATE_DEFAULT; + + evas_filter_state_prepare(pd->obj->object, &state, NULL); + state.cur.name = pd->data->state.cur.name; + state.cur.value = pd->data->state.cur.value; + state.next.name = pd->data->state.next.name; + state.next.value = pd->data->state.next.value; + state.pos = pd->data->state.pos; + + return evas_filter_program_state_set(pgm, &state); +} + Eina_Bool evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, void *output, void *context, void *surface, @@ -196,13 +211,11 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, if (!pd->data->chain) { Evas_Filter_Program *pgm; + pgm = evas_filter_program_new(pd->data->name, alpha); evas_filter_program_source_set_all(pgm, pd->data->sources); evas_filter_program_data_set_all(pgm, pd->data->data); - evas_filter_program_state_set(pgm, eo_obj, obj, - pd->data->state.cur.name, pd->data->state.cur.value, - pd->data->state.next.name, pd->data->state.next.value, - pd->data->state.pos); + _evas_filter_state_set_internal(pgm, pd); if (!evas_filter_program_parse(pgm, pd->data->code)) { ERR("Filter program parsing failed"); @@ -226,10 +239,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, { Eina_Bool redraw; - redraw = evas_filter_program_state_set(pd->data->chain, eo_obj, obj, - pd->data->state.cur.name, pd->data->state.cur.value, - pd->data->state.next.name, pd->data->state.next.value, - pd->data->state.pos); + redraw = _evas_filter_state_set_internal(pd->data->chain, pd); if (redraw) DBG("Filter redraw by state change!"); else if (obj->changed) @@ -280,10 +290,9 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, } } else - evas_filter_program_state_set(pd->data->chain, eo_obj, obj, - pd->data->state.cur.name, pd->data->state.cur.value, - pd->data->state.next.name, pd->data->state.next.value, - pd->data->state.pos); + { + _evas_filter_state_set_internal(pd->data->chain, pd); + } filter = evas_filter_context_new(obj->layer->evas, do_async); @@ -316,7 +325,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, // Request rendering from the object itself (child class) evas_filter_program_padding_get(pd->data->chain, &l, &r, &t, &b); - ok = evas_filter_input_render(eo_obj, filter, drawctx, l, r, t, b, do_async); + ok = evas_filter_input_render(eo_obj, filter, drawctx, NULL, l, r, t, b, do_async); if (!ok) ERR("Filter input render failed."); ENFN->context_free(ENDT, drawctx); @@ -377,10 +386,7 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_F pgm = evas_filter_program_new(fcow->name, alpha); evas_filter_program_source_set_all(pgm, fcow->sources); evas_filter_program_data_set_all(pgm, fcow->data); - evas_filter_program_state_set(pgm, eo_obj, obj, - fcow->state.cur.name, fcow->state.cur.value, - fcow->state.next.name, fcow->state.next.value, - fcow->state.pos); + _evas_filter_state_set_internal(pgm, pd); if (!evas_filter_program_parse(pgm, code)) { ERR("Parsing failed!"); @@ -523,10 +529,7 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_state_set(Eo *eo_obj, Evas_Fil if (pd->data->chain) { - evas_filter_program_state_set(pd->data->chain, eo_obj, obj, - pd->data->state.cur.name, pd->data->state.cur.value, - pd->data->state.next.name, pd->data->state.next.value, - pd->data->state.pos); + _evas_filter_state_set_internal(pd->data->chain, pd); } evas_filter_dirty(eo_obj); diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 427359e2f9..1a93fafb5b 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -1717,7 +1717,8 @@ _efl_canvas_image_internal_efl_canvas_filter_internal_filter_dirty(Eo *eo_obj, E } EOLIAN static Eina_Bool -_efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_alpha(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o EINA_UNUSED) +_efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_alpha( + Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o EINA_UNUSED) { return EINA_FALSE; } @@ -1730,11 +1731,27 @@ _efl_canvas_image_internal_efl_gfx_filter_filter_program_set(Eo *obj, Evas_Image efl_gfx_filter_program_set(efl_super(obj, MY_CLASS), code, name); } +EOLIAN static void +_efl_canvas_image_internal_efl_canvas_filter_internal_filter_state_prepare( + Eo *eo_obj, Evas_Image_Data *o EINA_UNUSED, Efl_Canvas_Filter_State *state, void *data EINA_UNUSED) +{ + Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); + + memset(&state->text, 0, sizeof(state->text)); +#define STATE_COLOR(dst, src) dst.r = src.r; dst.g = src.g; dst.b = src.b; dst.a = src.a + STATE_COLOR(state->color, obj->cur->color); +#undef STATE_COLOR + + state->w = obj->cur->geometry.w; + state->h = obj->cur->geometry.h; + state->scale = obj->cur->scale; +} + EOLIAN static Eina_Bool -_efl_canvas_image_internal_efl_canvas_filter_internal_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) +_efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_render( + Eo *eo_obj, Evas_Image_Data *o, void *_filter, void *context, + void *data EINA_UNUSED, int l, int r EINA_UNUSED, int t, int b EINA_UNUSED, + Eina_Bool do_async) { Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); Evas_Filter_Context *filter = _filter; diff --git a/src/lib/evas/canvas/evas_object_text.c b/src/lib/evas/canvas/evas_object_text.c index ce383dac52..7329e78d82 100644 --- a/src/lib/evas/canvas/evas_object_text.c +++ b/src/lib/evas/canvas/evas_object_text.c @@ -1698,11 +1698,31 @@ _evas_text_efl_canvas_filter_internal_filter_input_alpha(Eo *eo_obj EINA_UNUSED, return EINA_TRUE; } +EOLIAN static void +_evas_text_efl_canvas_filter_internal_filter_state_prepare(Eo *eo_obj, Evas_Text_Data *o, + Efl_Canvas_Filter_State *state, void *data EINA_UNUSED) +{ + Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); + +#define STATE_COLOR(dst, src) dst.r = src.r; dst.g = src.g; dst.b = src.b; dst.a = src.a + STATE_COLOR(state->color, obj->cur->color); + STATE_COLOR(state->text.glow, o->cur.glow); + STATE_COLOR(state->text.glow2, o->cur.glow2); + STATE_COLOR(state->text.shadow, o->cur.shadow); + STATE_COLOR(state->text.outline, o->cur.outline); +#undef STATE_COLOR + + state->w = obj->cur->geometry.w; + state->h = obj->cur->geometry.h; + state->scale = obj->cur->scale; +} + EOLIAN static Eina_Bool _evas_text_efl_canvas_filter_internal_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) + void *_filter, void *drawctx, + void *data EINA_UNUSED, + 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; diff --git a/src/lib/evas/canvas/evas_text.eo b/src/lib/evas/canvas/evas_text.eo index f2e2b46612..8cce0edd66 100644 --- a/src/lib/evas/canvas/evas_text.eo +++ b/src/lib/evas/canvas/evas_text.eo @@ -267,9 +267,10 @@ class Evas.Text (Efl.Canvas.Object, Efl.Text, Efl.Text.Properties, Efl.Canvas.Fi Efl.Text.Properties.font { get; set; } Efl.Text.Properties.font_source { get; set; } Efl.Gfx.Filter.filter_program { set; } + Efl.Canvas.Filter.Internal.filter_dirty; Efl.Canvas.Filter.Internal.filter_input_alpha; Efl.Canvas.Filter.Internal.filter_input_render; - Efl.Canvas.Filter.Internal.filter_dirty; - Efl.Canvas.Object.paragraph_direction { get; set; } + Efl.Canvas.Filter.Internal.filter_state_prepare; + Efl.Canvas.Object.paragraph_direction { set; get; } } } diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index 5440105a28..e4008d5600 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -1314,17 +1314,13 @@ _filter_target_render(Evas_Filter_Context *ctx) ctx->target.r, ctx->target.g, ctx->target.b, ctx->target.a); } - else - { - ENFN->context_multiplier_unset(ENDT, drawctx); - } if (ctx->target.mask) - ENFN->context_clip_image_set(ENDT, drawctx, - ctx->target.mask, ctx->target.mask_x, ctx->target.mask_y, - ctx->evas, EINA_FALSE); - else - ENFN->context_clip_image_unset(ENDT, drawctx); + { + ENFN->context_clip_image_set(ENDT, drawctx, ctx->target.mask, + ctx->target.mask_x, ctx->target.mask_y, + ctx->evas, EINA_FALSE); + } ENFN->image_draw(ENDT, drawctx, surface, image, 0, 0, src->w, src->h, @@ -1359,6 +1355,7 @@ evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, evas_common_font_glyphs_ref(text_props->glyphs); evas_unref_queue_glyph_put(ctx->evas, text_props->glyphs); } + //evas_common_save_image_to_file(surface, "/tmp/input.png", 0, 100, 0 ,0); return EINA_TRUE; } diff --git a/src/lib/evas/filters/evas_filter_parser.c b/src/lib/evas/filters/evas_filter_parser.c index 6ccb649b39..8fce7c57a9 100644 --- a/src/lib/evas/filters/evas_filter_parser.c +++ b/src/lib/evas/filters/evas_filter_parser.c @@ -316,30 +316,6 @@ struct _Evas_Filter_Instruction Eina_Bool valid : 1; }; -struct _Evas_Filter_Program_State -{ - struct { - struct { int a, r, g, b; } outline; - struct { int a, r, g, b; } shadow; - struct { int a, r, g, b; } glow; - struct { int a, r, g, b; } glow2; - } text; - struct { - int a, r, g, b; - } color; - struct { - const char *name; - double value; - } cur; - struct { - const char *name; - double value; - } next; - int w, h; - double scale; - double pos; -}; - struct _Evas_Filter_Program { Eina_Stringshare *name; // Optional for now @@ -350,7 +326,7 @@ struct _Evas_Filter_Program // Note: padding can't be in the state as it's calculated after running Lua int l, r, t, b; } pad; - Evas_Filter_Program_State state; + Efl_Canvas_Filter_State state; Eina_Inlist *data; // Evas_Filter_Data_Binding lua_State *L; int lua_func; @@ -2967,50 +2943,24 @@ evas_filter_program_new(const char *name, Eina_Bool input_alpha) if (!pgm) return NULL; pgm->name = eina_stringshare_add(name); pgm->input_alpha = input_alpha; - pgm->state.color.r = 255; - pgm->state.color.g = 255; - pgm->state.color.b = 255; - pgm->state.color.a = 255; - pgm->state.scale = 1.0; + pgm->state = (Efl_Canvas_Filter_State) EFL_CANVAS_FILTER_STATE_DEFAULT; return pgm; } EAPI Eina_Bool -evas_filter_program_state_set(Evas_Filter_Program *pgm, Evas_Object *eo_obj, - Evas_Object_Protected_Data *obj, - const char *cur_state, double cur_val, - const char *next_state, double next_val, - double pos) +evas_filter_program_state_set(Evas_Filter_Program *pgm, + const Efl_Canvas_Filter_State *state) { - Evas_Filter_Program_State old_state; - EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(state, EINA_FALSE); - memcpy(&old_state, &pgm->state, sizeof(Evas_Filter_Program_State)); - - pgm->state.w = obj->cur->geometry.w; - pgm->state.h = obj->cur->geometry.h; - pgm->state.scale = obj->cur->scale; - pgm->state.pos = pos; - pgm->state.cur.name = cur_state; - pgm->state.cur.value = cur_val; - pgm->state.next.name = next_state; - pgm->state.next.value = next_val; - - efl_gfx_color_get(eo_obj, &pgm->state.color.r, &pgm->state.color.g, &pgm->state.color.b, &pgm->state.color.a); - - if (efl_isa(eo_obj, EVAS_TEXT_CLASS)) + if (memcmp(&pgm->state, state, sizeof(Efl_Canvas_Filter_State)) != 0) { - evas_obj_text_shadow_color_get(eo_obj, &pgm->state.text.shadow.r, &pgm->state.text.shadow.g, &pgm->state.text.shadow.b, &pgm->state.text.shadow.a); - evas_obj_text_outline_color_get(eo_obj, &pgm->state.text.outline.r, &pgm->state.text.outline.g, &pgm->state.text.outline.b, &pgm->state.text.outline.a); - evas_obj_text_glow_color_get(eo_obj, &pgm->state.text.glow.r, &pgm->state.text.glow.g, &pgm->state.text.glow.b, &pgm->state.text.glow.a); - evas_obj_text_glow2_color_get(eo_obj, &pgm->state.text.glow2.r, &pgm->state.text.glow2.g, &pgm->state.text.glow2.b, &pgm->state.text.glow2.a); + pgm->changed = EINA_TRUE; + memcpy(&pgm->state, state, sizeof(Efl_Canvas_Filter_State)); } - if (memcmp(&old_state, &pgm->state, sizeof(Evas_Filter_Program_State)) != 0) - pgm->changed = EINA_TRUE; - if (pgm->changed) pgm->padding_calc = EINA_FALSE; diff --git a/src/lib/evas/include/evas_filter.h b/src/lib/evas/include/evas_filter.h index bb7a32d287..60d946fddc 100644 --- a/src/lib/evas/include/evas_filter.h +++ b/src/lib/evas/include/evas_filter.h @@ -4,6 +4,8 @@ #include "evas_common_private.h" #include "evas_private.h" +#include "efl_canvas_filter_internal.eo.h" + #ifdef EAPI # undef EAPI #endif @@ -35,7 +37,6 @@ typedef struct _Evas_Filter_Command Evas_Filter_Command; typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction; typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer; typedef struct _Evas_Filter_Proxy_Binding Evas_Filter_Proxy_Binding; -typedef struct _Evas_Filter_Program_State Evas_Filter_Program_State; typedef enum _Evas_Filter_Mode Evas_Filter_Mode; typedef enum _Evas_Filter_Blur_Type Evas_Filter_Blur_Type; typedef enum _Evas_Filter_Channel Evas_Filter_Channel; @@ -124,9 +125,11 @@ enum _Evas_Filter_Transform_Flags EVAS_FILTER_TRANSFORM_VFLIP = 1 }; +#define EFL_CANVAS_FILTER_STATE_DEFAULT { {}, { 255, 255, 255, 255 }, { "default", 0.0 }, {}, 0, 0, 1.0, 0.0 } + /* Parser stuff (high level API) */ EAPI Evas_Filter_Program *evas_filter_program_new(const char *name, Eina_Bool input_alpha); -EAPI Eina_Bool evas_filter_program_state_set(Evas_Filter_Program *pgm, Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, const char *cur_state, double cur_val, const char *next_state, double next_val, double pos); +EAPI Eina_Bool evas_filter_program_state_set(Evas_Filter_Program *pgm, const Efl_Canvas_Filter_State *state); EAPI Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str); EAPI void evas_filter_program_del(Evas_Filter_Program *pgm); Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);