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.
This commit is contained in:
Jean-Philippe Andre 2016-12-22 19:41:04 +09:00
parent ffbc0645e5
commit b2a4039bda
10 changed files with 146 additions and 106 deletions

View File

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

View File

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

View File

@ -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;
}
}

View File

@ -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);

View File

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

View File

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

View File

@ -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; }
}
}

View File

@ -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;
}

View File

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

View File

@ -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);