Evas filters: Pass text colors to the parser

This does not implement the full feature yet (Lua variable
is not set). This commit also brings various fixes.
This commit is contained in:
Jean-Philippe Andre 2015-05-26 19:37:21 +09:00
parent d148c0f0d2
commit ffea07a049
4 changed files with 329 additions and 209 deletions

View File

@ -13,6 +13,8 @@
/* save typing */ /* save typing */
#define ENFN obj->layer->evas->engine.func #define ENFN obj->layer->evas->engine.func
#define ENDT obj->layer->evas->engine.data.output #define ENDT obj->layer->evas->engine.data.output
#define COL_OBJECT(obj, sub) ARGB_JOIN(obj->sub->color.a, obj->sub->color.r, obj->sub->color.g, obj->sub->color.b)
#define COL_JOIN(o, sub, color) ARGB_JOIN(o->sub.color.a, o->sub.color.r, o->sub.color.g, o->sub.color.b)
/* private magic number for text objects */ /* private magic number for text objects */
static const char o_type[] = "text"; static const char o_type[] = "text";
@ -1766,16 +1768,15 @@ evas_object_text_render(Evas_Object *eo_obj,
Y = obj->cur->geometry.y; Y = obj->cur->geometry.y;
// Prepare color multiplier // Prepare color multiplier
ENFN->context_color_set(ENDT, context, 255, 255, 255, 255); COLOR_ONLY_SET(obj, cur->cache, clip);
if ((obj->cur->cache.clip.r == 255) && (obj->cur->cache.clip.g == 255) && if (obj->cur->clipper)
(obj->cur->cache.clip.b == 255) && (obj->cur->cache.clip.a == 255)) ENFN->context_multiplier_set(output, context,
ENFN->context_multiplier_unset(ENDT, context); obj->cur->clipper->cur->cache.clip.r,
obj->cur->clipper->cur->cache.clip.g,
obj->cur->clipper->cur->cache.clip.b,
obj->cur->clipper->cur->cache.clip.a);
else else
ENFN->context_multiplier_set(ENDT, context, ENFN->context_multiplier_unset(output, context);
obj->cur->cache.clip.r,
obj->cur->cache.clip.g,
obj->cur->cache.clip.b,
obj->cur->cache.clip.a);
if (!fcow->chain) if (!fcow->chain)
{ {
@ -1794,10 +1795,15 @@ evas_object_text_render(Evas_Object *eo_obj,
} }
fcow->chain = pgm; fcow->chain = pgm;
fcow->invalid = EINA_FALSE; fcow->invalid = EINA_FALSE;
evas_filter_program_state_set(fcow->chain, eo_obj, obj);
} }
else if (previous) else if (previous && !fcow->changed)
{ {
Eina_Bool redraw = fcow->changed; Eina_Bool redraw;
redraw = evas_filter_program_state_set(fcow->chain, eo_obj, obj);
if (redraw)
DBG("Filter redraw by state change!");
// Scan proxies to find if any changed // Scan proxies to find if any changed
if (!redraw && fcow->sources) if (!redraw && fcow->sources)
@ -1834,8 +1840,12 @@ evas_object_text_render(Evas_Object *eo_obj,
return; return;
} }
} }
else
evas_filter_program_state_set(fcow->chain, eo_obj, obj);
filter = evas_filter_context_new(obj->layer->evas, do_async); filter = evas_filter_context_new(obj->layer->evas, do_async);
// Run script
ok = evas_filter_context_program_use(filter, fcow->chain); ok = evas_filter_context_program_use(filter, fcow->chain);
if (!filter || !ok) if (!filter || !ok)
{ {
@ -2372,8 +2382,6 @@ _evas_object_text_recalc(Evas_Object *eo_obj, Eina_Unicode *text)
o->last_computed.h = obj->cur->geometry.h; o->last_computed.h = obj->cur->geometry.h;
} }
/* EXPERIMENTAL CODE BEGIN */
EOLIAN static void EOLIAN static void
_evas_text_filter_program_set(Eo *eo_obj, Evas_Text_Data *o, const char *arg) _evas_text_filter_program_set(Eo *eo_obj, Evas_Text_Data *o, const char *arg)
{ {
@ -2393,7 +2401,7 @@ _evas_text_filter_program_set(Eo *eo_obj, Evas_Text_Data *o, const char *arg)
{ {
pgm = evas_filter_program_new("Evas_Text", EINA_TRUE); pgm = evas_filter_program_new("Evas_Text", EINA_TRUE);
evas_filter_program_source_set_all(pgm, fcow->sources); evas_filter_program_source_set_all(pgm, fcow->sources);
evas_filter_program_state_set(pgm, obj->cur->geometry.w, obj->cur->geometry.h); evas_filter_program_state_set(pgm, eo_obj, obj);
if (!evas_filter_program_parse(pgm, arg)) if (!evas_filter_program_parse(pgm, arg))
{ {
ERR("Parsing failed!"); ERR("Parsing failed!");
@ -2543,8 +2551,6 @@ update:
evas_object_inform_call_resize(eo_obj); evas_object_inform_call_resize(eo_obj);
} }
/* EXPERIMENTAL CODE END */
EAPI void EAPI void
evas_object_text_font_source_set(Eo *obj, const char *font_source) evas_object_text_font_source_set(Eo *obj, const char *font_source)
{ {

View File

@ -493,6 +493,7 @@ evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only)
fb->transient = EINA_FALSE; fb->transient = EINA_FALSE;
DBG("Created context buffer %d", fb->id);
return fb->id; return fb->id;
} }
@ -741,12 +742,8 @@ evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h,
Evas_Filter_Buffer *buf = NULL; Evas_Filter_Buffer *buf = NULL;
Eina_List *l; Eina_List *l;
DBG("Want temp buffer: %dx%d %s", w, h, alpha_only ? "alpha" : "rgba");
EINA_LIST_FOREACH(ctx->buffers, l, buf) EINA_LIST_FOREACH(ctx->buffers, l, buf)
{ {
DBG("Try buffer #%d: temp:%d %dx%d %s (lock:%d)",
buf->id, buf->transient,
buf->w, buf->h, buf->alpha_only ? "alpha" : "rgba", buf->locked);
if (buf->transient && !buf->locked && (buf->alpha_only == alpha_only)) if (buf->transient && !buf->locked && (buf->alpha_only == alpha_only))
{ {
if ((!w || (w == buf->w)) if ((!w || (w == buf->w))
@ -766,7 +763,6 @@ evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h,
buf = _buffer_new(ctx, w, h, alpha_only); buf = _buffer_new(ctx, w, h, alpha_only);
buf->locked = EINA_TRUE; buf->locked = EINA_TRUE;
DBG("Created temporary buffer: %d (%s)", buf->id, alpha_only ? "Alpha" : "RGBA");
return buf; return buf;
} }

View File

@ -18,6 +18,10 @@
#define EVAS_FILTER_MODE_GROW (EVAS_FILTER_MODE_LAST+1) #define EVAS_FILTER_MODE_GROW (EVAS_FILTER_MODE_LAST+1)
#define EVAS_FILTER_MODE_BUFFER (EVAS_FILTER_MODE_LAST+2) #define EVAS_FILTER_MODE_BUFFER (EVAS_FILTER_MODE_LAST+2)
#define INSTR_PARAM_CHECK(a) do { if (!(a)) { \
ERR("Argument %s can not be nil in %s!", #a, instr->name); return -1; } \
} while (0)
/* Note on the documentation: /* Note on the documentation:
* To keep it simple, I'm not using any fancy features, only <ul>/<li> lists * To keep it simple, I'm not using any fancy features, only <ul>/<li> lists
* and @a, @b, @c flags from Doxygen. * and @a, @b, @c flags from Doxygen.
@ -286,6 +290,7 @@ typedef struct _Buffer
} pad; } pad;
int w, h; int w, h;
Eina_Bool alpha : 1; Eina_Bool alpha : 1;
Eina_Bool manual : 1; // created by "buffer" instruction
} Buffer; } Buffer;
typedef struct _Instruction_Param typedef struct _Instruction_Param
@ -316,11 +321,23 @@ struct _Evas_Filter_Instruction
Eina_Bool (* parse_run) (lua_State *L, Evas_Filter_Program *, Evas_Filter_Instruction *); Eina_Bool (* parse_run) (lua_State *L, Evas_Filter_Program *, Evas_Filter_Instruction *);
struct struct
{ {
void (* update) (Evas_Filter_Program *, Evas_Filter_Instruction *, int *, int *, int *, int *); int (* update) (Evas_Filter_Program *, Evas_Filter_Instruction *, int *, int *, int *, int *);
} pad; } pad;
Eina_Bool valid : 1; 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;
int w, h;
};
struct _Evas_Filter_Program struct _Evas_Filter_Program
{ {
Eina_Stringshare *name; // Optional for now Eina_Stringshare *name; // Optional for now
@ -328,11 +345,13 @@ struct _Evas_Filter_Program
Eina_Inlist /* Evas_Filter_Instruction */ *instructions; Eina_Inlist /* Evas_Filter_Instruction */ *instructions;
Eina_Inlist /* Buffer */ *buffers; Eina_Inlist /* Buffer */ *buffers;
struct { struct {
// Note: padding can't be in the state as it's calculated after running Lua
int l, r, t, b; int l, r, t, b;
} pad; } pad;
int w, h; Evas_Filter_Program_State state;
lua_State *L; lua_State *L;
int lua_func; int lua_func;
int last_bufid;
Eina_Bool valid : 1; Eina_Bool valid : 1;
Eina_Bool padding_calc : 1; // Padding has been calculated Eina_Bool padding_calc : 1; // Padding has been calculated
Eina_Bool padding_set : 1; // Padding has been forced Eina_Bool padding_set : 1; // Padding has been forced
@ -602,7 +621,6 @@ static Buffer *
_buffer_get(Evas_Filter_Program *pgm, const char *name) _buffer_get(Evas_Filter_Program *pgm, const char *name)
{ {
Buffer *buf; Buffer *buf;
Evas_Object *source;
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
@ -611,22 +629,6 @@ _buffer_get(Evas_Filter_Program *pgm, const char *name)
if (!strcmp(buf->name, name)) if (!strcmp(buf->name, name))
return buf; return buf;
// Auto proxies
if (pgm->proxies)
{
source = eina_hash_find(pgm->proxies, name);
if (!source) return NULL;
buf = calloc(1, sizeof(Buffer));
if (!buf) return NULL;
buf->name = eina_stringshare_add(name);
buf->proxy = eina_stringshare_add(name);
buf->alpha = EINA_FALSE;
pgm->buffers = eina_inlist_append(pgm->buffers, EINA_INLIST_GET(buf));
return buf;
}
return NULL; return NULL;
} }
@ -636,18 +638,11 @@ _lua_buffer_push(lua_State *L, Buffer *buf)
Buffer **ptr; Buffer **ptr;
lua_getglobal(L, buf->name); lua_getglobal(L, buf->name);
if (lua_isnil(L, -1)) ptr = lua_newuserdata(L, sizeof(Buffer **));
{ *ptr = buf;
ptr = lua_newuserdata(L, sizeof(Buffer **)); luaL_getmetatable(L, _lua_buffer_meta);
*ptr = buf; lua_setmetatable(L, -2);
luaL_getmetatable(L, _lua_buffer_meta); lua_setglobal(L, buf->name);
lua_setmetatable(L, -2);
lua_setglobal(L, buf->name);
}
else
{
ERR("to do");
}
return EINA_TRUE; return EINA_TRUE;
} }
@ -727,7 +722,7 @@ _lua_buffer_source(lua_State *L)
static Buffer * static Buffer *
_buffer_add(Evas_Filter_Program *pgm, const char *name, Eina_Bool alpha, _buffer_add(Evas_Filter_Program *pgm, const char *name, Eina_Bool alpha,
const char *src) const char *src, Eina_Bool manual)
{ {
Buffer *buf; Buffer *buf;
@ -746,11 +741,20 @@ _buffer_add(Evas_Filter_Program *pgm, const char *name, Eina_Bool alpha,
buf = calloc(1, sizeof(Buffer)); buf = calloc(1, sizeof(Buffer));
if (!buf) return NULL; if (!buf) return NULL;
buf->name = eina_stringshare_add(name); buf->manual = manual;
if (!name)
{
char bufname[32];
snprintf(bufname, sizeof(bufname), "__buffer%02d", ++pgm->last_bufid);
buf->name = eina_stringshare_add(bufname);
}
else
buf->name = eina_stringshare_add(name);
buf->proxy = eina_stringshare_add(src); buf->proxy = eina_stringshare_add(src);
buf->alpha = alpha; buf->alpha = alpha;
buf->w = pgm->w; buf->w = pgm->state.w;
buf->h = pgm->h; buf->h = pgm->state.h;
pgm->buffers = eina_inlist_append(pgm->buffers, EINA_INLIST_GET(buf)); pgm->buffers = eina_inlist_append(pgm->buffers, EINA_INLIST_GET(buf));
_lua_buffer_push(pgm->L, buf); _lua_buffer_push(pgm->L, buf);
@ -810,7 +814,6 @@ _buffer_instruction_parse_run(lua_State *L,
char bufname[32] = {0}; char bufname[32] = {0};
const char *src, *rgba; const char *src, *rgba;
Eina_Bool ok, alpha = EINA_FALSE; Eina_Bool ok, alpha = EINA_FALSE;
int cnt;
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(instr, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(instr, EINA_FALSE);
@ -823,9 +826,8 @@ _buffer_instruction_parse_run(lua_State *L,
alpha = (rgba && !strcasecmp(rgba, "alpha")); alpha = (rgba && !strcasecmp(rgba, "alpha"));
cnt = (pgm->buffers ? eina_inlist_count(pgm->buffers) : 0) + 1; snprintf(bufname, sizeof(bufname), "__buffer%02d", ++pgm->last_bufid);
snprintf(bufname, sizeof(bufname), "__buffer%02d", cnt); ok = (_buffer_add(pgm, bufname, alpha, src, EINA_TRUE) != NULL);
ok = (_buffer_add(pgm, bufname, alpha, src) != NULL);
if (!ok) return EINA_FALSE; if (!ok) return EINA_FALSE;
@ -851,45 +853,44 @@ _buffer_instruction_prepare(Evas_Filter_Program *pgm EINA_UNUSED,
return EINA_TRUE; return EINA_TRUE;
} }
static void static int
_blend_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr, _blend_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb) int *padl, int *padr, int *padt, int *padb)
{ {
const char *inbuf, *outbuf;
Evas_Filter_Fill_Mode fillmode; Evas_Filter_Fill_Mode fillmode;
Buffer *in, *out; Buffer *src, *dst;
int ox, oy, l = 0, r = 0, t = 0, b = 0; int ox, oy, l = 0, r = 0, t = 0, b = 0;
ox = _instruction_param_geti(instr, "ox", NULL); ox = _instruction_param_geti(instr, "ox", NULL);
oy = _instruction_param_geti(instr, "oy", NULL); oy = _instruction_param_geti(instr, "oy", NULL);
inbuf = _instruction_param_gets(instr, "src", NULL); src = _instruction_param_getbuf(instr, "src", NULL);
in = _buffer_get(pgm, inbuf); dst = _instruction_param_getbuf(instr, "dst", NULL);
EINA_SAFETY_ON_NULL_RETURN(in); INSTR_PARAM_CHECK(src);
INSTR_PARAM_CHECK(dst);
outbuf = _instruction_param_gets(instr, "dst", NULL);
out = _buffer_get(pgm, outbuf);
EINA_SAFETY_ON_NULL_RETURN(out);
fillmode = _fill_mode_get(instr); fillmode = _fill_mode_get(instr);
if (fillmode & (EVAS_FILTER_FILL_MODE_STRETCH_X | EVAS_FILTER_FILL_MODE_REPEAT_X)) ox = 0; if (fillmode & (EVAS_FILTER_FILL_MODE_STRETCH_X | EVAS_FILTER_FILL_MODE_REPEAT_X)) ox = 0;
if (fillmode & (EVAS_FILTER_FILL_MODE_STRETCH_Y | EVAS_FILTER_FILL_MODE_REPEAT_Y)) oy = 0; if (fillmode & (EVAS_FILTER_FILL_MODE_STRETCH_Y | EVAS_FILTER_FILL_MODE_REPEAT_Y)) oy = 0;
if (ox < 0) l = (-ox) + in->pad.l; if (ox < 0) l = (-ox) + src->pad.l;
else r = ox + in->pad.r; else r = ox + src->pad.r;
if (oy < 0) t = (-oy) + in->pad.t; if (oy < 0) t = (-oy) + src->pad.t;
else b = oy + in->pad.b; else b = oy + src->pad.b;
if (out->pad.l < l) out->pad.l = l; if (dst->pad.l < l) dst->pad.l = l;
if (out->pad.r < r) out->pad.r = r; if (dst->pad.r < r) dst->pad.r = r;
if (out->pad.t < t) out->pad.t = t; if (dst->pad.t < t) dst->pad.t = t;
if (out->pad.b < b) out->pad.b = b; if (dst->pad.b < b) dst->pad.b = b;
if (padl) *padl = l; if (padl) *padl = l;
if (padr) *padr = r; if (padr) *padr = r;
if (padt) *padt = t; if (padt) *padt = t;
if (padb) *padb = b; if (padb) *padb = b;
return 0;
} }
/** /**
@ -955,33 +956,32 @@ _blend_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction *in
return EINA_TRUE; return EINA_TRUE;
} }
static void static int
_blur_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr, _blur_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb) int *padl, int *padr, int *padt, int *padb)
{ {
Eina_Bool yset = EINA_FALSE; Eina_Bool yset = EINA_FALSE;
int rx, ry, ox, oy, l, r, t, b, count; int rx, ry, ox, oy, l, r, t, b, count;
const char *inbuf, *outbuf, *typestr; const char *typestr;
Evas_Filter_Blur_Type type = EVAS_FILTER_BLUR_DEFAULT; Evas_Filter_Blur_Type type = EVAS_FILTER_BLUR_DEFAULT;
Buffer *in, *out; Buffer *src, *dst;
rx = _instruction_param_geti(instr, "rx", NULL); rx = _instruction_param_geti(instr, "rx", NULL);
ry = _instruction_param_geti(instr, "ry", &yset); ry = _instruction_param_geti(instr, "ry", &yset);
ox = _instruction_param_geti(instr, "ox", NULL); ox = _instruction_param_geti(instr, "ox", NULL);
oy = _instruction_param_geti(instr, "oy", NULL); oy = _instruction_param_geti(instr, "oy", NULL);
inbuf = _instruction_param_gets(instr, "src", NULL);
outbuf = _instruction_param_gets(instr, "dst", NULL);
count = _instruction_param_geti(instr, "count", NULL); count = _instruction_param_geti(instr, "count", NULL);
typestr = _instruction_param_gets(instr, "type", NULL); typestr = _instruction_param_gets(instr, "type", NULL);
src = _instruction_param_getbuf(instr, "src", NULL);
dst = _instruction_param_getbuf(instr, "dst", NULL);
INSTR_PARAM_CHECK(src);
INSTR_PARAM_CHECK(dst);
if (typestr && !strcasecmp(typestr, "box")) if (typestr && !strcasecmp(typestr, "box"))
type = EVAS_FILTER_BLUR_BOX; type = EVAS_FILTER_BLUR_BOX;
in = _buffer_get(pgm, inbuf);
out = _buffer_get(pgm, outbuf);
EINA_SAFETY_ON_NULL_RETURN(in);
EINA_SAFETY_ON_NULL_RETURN(out);
if (!yset) ry = rx; if (!yset) ry = rx;
if (rx < 0) rx = 0; if (rx < 0) rx = 0;
if (ry < 0) ry = 0; if (ry < 0) ry = 0;
@ -997,20 +997,22 @@ _blur_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
rx *= count; rx *= count;
ry *= count; ry *= count;
l = rx + in->pad.l + ((ox < 0) ? (-ox) : 0); l = rx + src->pad.l + ((ox < 0) ? (-ox) : 0);
r = rx + in->pad.r + ((ox > 0) ? ox : 0); r = rx + src->pad.r + ((ox > 0) ? ox : 0);
t = ry + in->pad.t + ((oy < 0) ? (-oy) : 0); t = ry + src->pad.t + ((oy < 0) ? (-oy) : 0);
b = ry + in->pad.b + ((oy > 0) ? oy : 0); b = ry + src->pad.b + ((oy > 0) ? oy : 0);
if (out->pad.l < l) out->pad.l = l; if (dst->pad.l < l) dst->pad.l = l;
if (out->pad.r < r) out->pad.r = r; if (dst->pad.r < r) dst->pad.r = r;
if (out->pad.t < t) out->pad.t = t; if (dst->pad.t < t) dst->pad.t = t;
if (out->pad.b < b) out->pad.b = b; if (dst->pad.b < b) dst->pad.b = b;
if (padl) *padl = l; if (padl) *padl = l;
if (padr) *padr = r; if (padr) *padr = r;
if (padt) *padt = t; if (padt) *padt = t;
if (padb) *padb = b; if (padb) *padb = b;
return 0;
} }
/** /**
@ -1212,39 +1214,37 @@ _curve_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction *in
return EINA_TRUE; return EINA_TRUE;
} }
static void static int
_displace_padding_update(Evas_Filter_Program *pgm, _displace_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr, Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb) int *padl, int *padr, int *padt, int *padb)
{ {
int intensity = 0; int intensity = 0;
int l, r, t, b; int l, r, t, b;
const char *inbuf, *outbuf; Buffer *src, *dst;
Buffer *in, *out;
intensity = _instruction_param_geti(instr, "intensity", NULL); intensity = _instruction_param_geti(instr, "intensity", NULL);
inbuf = _instruction_param_gets(instr, "src", NULL); src = _instruction_param_getbuf(instr, "src", NULL);
outbuf = _instruction_param_gets(instr, "dst", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL);
INSTR_PARAM_CHECK(src);
INSTR_PARAM_CHECK(dst);
in = _buffer_get(pgm, inbuf); l = intensity + src->pad.l;
out = _buffer_get(pgm, outbuf); r = intensity + src->pad.r;
EINA_SAFETY_ON_NULL_RETURN(in); t = intensity + src->pad.t;
EINA_SAFETY_ON_NULL_RETURN(out); b = intensity + src->pad.b;
l = intensity + in->pad.l; if (dst->pad.l < l) dst->pad.l = l;
r = intensity + in->pad.r; if (dst->pad.r < r) dst->pad.r = r;
t = intensity + in->pad.t; if (dst->pad.t < t) dst->pad.t = t;
b = intensity + in->pad.b; if (dst->pad.b < b) dst->pad.b = b;
if (out->pad.l < l) out->pad.l = l;
if (out->pad.r < r) out->pad.r = r;
if (out->pad.t < t) out->pad.t = t;
if (out->pad.b < b) out->pad.b = b;
if (padl) *padl = l; if (padl) *padl = l;
if (padr) *padr = r; if (padr) *padr = r;
if (padt) *padt = t; if (padt) *padt = t;
if (padb) *padb = b; if (padb) *padb = b;
return 0;
} }
/** /**
@ -1361,40 +1361,39 @@ _fill_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction *ins
return EINA_TRUE; return EINA_TRUE;
} }
static void static int
_grow_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr, _grow_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb) int *padl, int *padr, int *padt, int *padb)
{ {
const char *inbuf, *outbuf; Buffer *src, *dst;
Buffer *in, *out;
int l, r, t, b; int l, r, t, b;
int radius; int radius;
radius = _instruction_param_geti(instr, "radius", NULL); radius = _instruction_param_geti(instr, "radius", NULL);
inbuf = _instruction_param_gets(instr, "src", NULL); src = _instruction_param_getbuf(instr, "src", NULL);
outbuf = _instruction_param_gets(instr, "dst", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL);
INSTR_PARAM_CHECK(src);
in = _buffer_get(pgm, inbuf); INSTR_PARAM_CHECK(dst);
out = _buffer_get(pgm, outbuf);
EINA_SAFETY_ON_NULL_RETURN(in);
EINA_SAFETY_ON_NULL_RETURN(out);
if (radius < 0) radius = 0; if (radius < 0) radius = 0;
l = radius + in->pad.l; l = radius + src->pad.l;
r = radius + in->pad.r; r = radius + src->pad.r;
t = radius + in->pad.t; t = radius + src->pad.t;
b = radius + in->pad.b; b = radius + src->pad.b;
if (padl) *padl = l; if (padl) *padl = l;
if (padr) *padr = r; if (padr) *padr = r;
if (padt) *padt = t; if (padt) *padt = t;
if (padb) *padb = b; if (padb) *padb = b;
if (out->pad.l < l) out->pad.l = l; if (dst->pad.l < l) dst->pad.l = l;
if (out->pad.r < r) out->pad.r = r; if (dst->pad.r < r) dst->pad.r = r;
if (out->pad.t < t) out->pad.t = t; if (dst->pad.t < t) dst->pad.t = t;
if (out->pad.b < b) out->pad.b = b; if (dst->pad.b < b) dst->pad.b = b;
return 0;
} }
/** /**
@ -1494,22 +1493,19 @@ _mask_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction *ins
return EINA_TRUE; return EINA_TRUE;
} }
static void static int
_transform_padding_update(Evas_Filter_Program *pgm, _transform_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr, Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb) int *padl, int *padr, int *padt, int *padb)
{ {
const char *outbuf; Buffer *dst;
Buffer *out;
int ox, oy, l = 0, r = 0, t = 0, b = 0; int ox, oy, l = 0, r = 0, t = 0, b = 0;
//ox = _instruction_param_geti(instr, "ox", NULL); //ox = _instruction_param_geti(instr, "ox", NULL);
ox = 0; ox = 0;
oy = _instruction_param_geti(instr, "oy", NULL); oy = _instruction_param_geti(instr, "oy", NULL);
dst = _instruction_param_getbuf(instr, "dst", NULL);
outbuf = _instruction_param_gets(instr, "dst", NULL); INSTR_PARAM_CHECK(dst);
out = _buffer_get(pgm, outbuf);
EINA_SAFETY_ON_NULL_RETURN(out);
if (ox < 0) l = (-ox) * 2; if (ox < 0) l = (-ox) * 2;
else r = ox * 2; else r = ox * 2;
@ -1517,15 +1513,17 @@ _transform_padding_update(Evas_Filter_Program *pgm,
if (oy < 0) t = (-oy) * 2; if (oy < 0) t = (-oy) * 2;
else b = oy * 2; else b = oy * 2;
if (out->pad.l < l) out->pad.l = l; if (dst->pad.l < l) dst->pad.l = l;
if (out->pad.r < r) out->pad.r = r; if (dst->pad.r < r) dst->pad.r = r;
if (out->pad.t < t) out->pad.t = t; if (dst->pad.t < t) dst->pad.t = t;
if (out->pad.b < b) out->pad.b = b; if (dst->pad.b < b) dst->pad.b = b;
if (padl) *padl = l; if (padl) *padl = l;
if (padr) *padr = r; if (padr) *padr = r;
if (padt) *padt = t; if (padt) *padt = t;
if (padb) *padb = b; if (padb) *padb = b;
return 0;
} }
/** /**
@ -1580,7 +1578,7 @@ _transform_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction
return EINA_TRUE; return EINA_TRUE;
} }
static void static int
_padding_set_padding_update(Evas_Filter_Program *pgm, _padding_set_padding_update(Evas_Filter_Program *pgm,
Evas_Filter_Instruction *instr, Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb) int *padl, int *padr, int *padt, int *padb)
@ -1614,6 +1612,8 @@ _padding_set_padding_update(Evas_Filter_Program *pgm,
if (padt) *padt = t; if (padt) *padt = t;
if (padb) *padb = b; if (padb) *padb = b;
pgm->padding_set = EINA_TRUE; pgm->padding_set = EINA_TRUE;
return 0;
} }
/** /**
@ -1717,6 +1717,7 @@ _lua_program_get(lua_State *L)
static Eina_Bool static Eina_Bool
_lua_parameter_parse(Evas_Filter_Program *pgm, lua_State *L, _lua_parameter_parse(Evas_Filter_Program *pgm, lua_State *L,
Evas_Filter_Instruction *instr,
Instruction_Param *param, int i) Instruction_Param *param, int i)
{ {
if (!param) return EINA_FALSE; if (!param) return EINA_FALSE;
@ -1761,22 +1762,33 @@ _lua_parameter_parse(Evas_Filter_Program *pgm, lua_State *L,
param->value.s = strdup(lua_tostring(L, i)); param->value.s = strdup(lua_tostring(L, i));
break; break;
case VT_COLOR: case VT_COLOR:
if (lua_isnumber(L, i)) if ((lua_isnumber(L, i)) || (lua_type(L, i) == LUA_TSTRING))
{ {
DATA32 color = (DATA32) lua_tonumber(L, i); int A, R, G, B;
int A = A_VAL(&color); DATA32 color;
int R = R_VAL(&color);
int G = G_VAL(&color); if (lua_isnumber(L, i))
int B = B_VAL(&color); color = (DATA32) lua_tonumber(L, i);
if (!A && (R || B || G)) A = 0xFF; else
evas_color_argb_premul(A, &R, &G, &B); {
if (!_color_parse(lua_tostring(L, i), &color))
goto fail;
}
A = A_VAL(&color);
R = R_VAL(&color);
G = G_VAL(&color);
B = B_VAL(&color);
if (!A && (R || G || B)) A = 0xFF;
if ((A < R) || (A < G) || (A < B))
{
ERR("Argument '%s' of function '%s' is not a valid premultiplied RGBA value!",
param->name, instr->name);
evas_color_argb_premul(A, &R, &G, &B);
//goto fail;
}
param->value.c = ARGB_JOIN(A, R, G, B); param->value.c = ARGB_JOIN(A, R, G, B);
} }
else if (lua_type(L, i) == LUA_TSTRING)
{
if (!_color_parse(lua_tostring(L, i), &param->value.c))
goto fail;
}
else else
goto fail; goto fail;
break; break;
@ -1889,7 +1901,7 @@ _lua_instruction_run(lua_State *L, Evas_Filter_Instruction *instr)
goto fail; goto fail;
} }
if (!_lua_parameter_parse(pgm, L, param, -1)) if (!_lua_parameter_parse(pgm, L, instr, param, -1))
goto fail; goto fail;
lua_pop(L, 1); lua_pop(L, 1);
} }
@ -1899,7 +1911,7 @@ _lua_instruction_run(lua_State *L, Evas_Filter_Instruction *instr)
EINA_INLIST_FOREACH(instr->params, param) EINA_INLIST_FOREACH(instr->params, param)
{ {
if ((++i) > argc) break; if ((++i) > argc) break;
if (!_lua_parameter_parse(pgm, L, param, i)) if (!_lua_parameter_parse(pgm, L, instr, param, i))
goto fail; goto fail;
} }
} }
@ -2043,11 +2055,30 @@ static const luaL_Reg buffer_meta[] = {
{ NULL, NULL } { NULL, NULL }
}; };
static void
_filter_program_buffers_set(Evas_Filter_Program *pgm)
{
// Standard buffers
_buffer_add(pgm, "input", pgm->input_alpha, NULL, EINA_FALSE);
_buffer_add(pgm, "output", EINA_FALSE, NULL, EINA_FALSE);
// Register proxies
if (pgm->proxies)
{
Eina_Iterator *it = eina_hash_iterator_key_new(pgm->proxies);
const char *source;
EINA_ITERATOR_FOREACH(it, source)
_buffer_add(pgm, source, EINA_FALSE, source, EINA_FALSE);
eina_iterator_free(it);
}
}
static lua_State * static lua_State *
_lua_state_create(Evas_Filter_Program *pgm) _lua_state_create(Evas_Filter_Program *pgm)
{ {
lua_State *L; lua_State *L;
Buffer *buf;
pgm->L = L = luaL_newstate(); pgm->L = L = luaL_newstate();
if (!L) if (!L)
@ -2136,29 +2167,6 @@ _lua_state_create(Evas_Filter_Program *pgm)
lua_rawset(L, -3); lua_rawset(L, -3);
lua_pop(L, 1); lua_pop(L, 1);
_buffer_add(pgm, "input", pgm->input_alpha, NULL);
_buffer_add(pgm, "output", EINA_FALSE, NULL);
// Register proxies
if (pgm->proxies)
{
Eina_Iterator *it = eina_hash_iterator_key_new(pgm->proxies);
const char *source;
EINA_ITERATOR_FOREACH(it, source)
{
buf = calloc(1, sizeof(Buffer));
if (!buf) break;
buf->name = eina_stringshare_add(source);
buf->proxy = eina_stringshare_ref(buf->name);
buf->alpha = EINA_FALSE;
pgm->buffers = eina_inlist_append(pgm->buffers, EINA_INLIST_GET(buf));
_lua_buffer_push(L, buf);
}
eina_iterator_free(it);
}
return L; return L;
} }
@ -2284,6 +2292,78 @@ _legacy_strdup(const char *str)
} }
#endif #endif
static void
_filter_program_state_set(Evas_Filter_Program *pgm)
{
lua_State *L = pgm->L;
// TODO:
// text properties: colors, font size, ascent/descent, style (enum)
/* State is defined as follow:
* state = {
* text = {
* outline = COL
* shadow = COL
* glow = COL
* glow2 = COL
* }
* color = COL
* }
*/
#define JOINC(k) ARGB_JOIN(pgm->state.k.a, pgm->state.k.r, pgm->state.k.g, pgm->state.k.b)
#define SETFIELD(name, val) do { lua_pushinteger(L, val); lua_setfield(L, -2, name); } while(0)
lua_newtable(L); // "state"
{
SETFIELD("color", JOINC(color));
lua_newtable(L); // "text"
{
SETFIELD("outline", JOINC(text.outline));
SETFIELD("shadow", JOINC(text.shadow));
SETFIELD("glow", JOINC(text.glow));
SETFIELD("glow2", JOINC(text.glow2));
lua_setfield(L, -2, "text");
}
}
lua_setglobal(L, "state");
#undef JOINC
#undef SETFIELD
}
static void
_filter_program_reset(Evas_Filter_Program *pgm)
{
Evas_Filter_Instruction *instr;
lua_State *L = pgm->L;
Eina_Inlist *il;
Buffer *buf;
// Clear out commands
EINA_INLIST_FREE(pgm->instructions, instr)
{
pgm->instructions = eina_inlist_remove(pgm->instructions, EINA_INLIST_GET(instr));
_instruction_del(instr);
}
// Clear out buffers
EINA_INLIST_FOREACH_SAFE(pgm->buffers, il, buf)
{
lua_pushnil(L);
lua_setglobal(L, buf->name);
pgm->buffers = eina_inlist_remove(pgm->buffers, EINA_INLIST_GET(buf));
_buffer_del(buf);
}
// Re-create buffers
_filter_program_buffers_set(pgm);
// Reset state table
_filter_program_state_set(pgm);
}
/** Parse a style program */ /** Parse a style program */
EAPI Eina_Bool EAPI Eina_Bool
@ -2314,6 +2394,7 @@ evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
if (ok) if (ok)
{ {
pgm->lua_func = luaL_ref(L, LUA_REGISTRYINDEX); pgm->lua_func = luaL_ref(L, LUA_REGISTRYINDEX);
_filter_program_reset(pgm);
lua_rawgeti(L, LUA_REGISTRYINDEX, pgm->lua_func); lua_rawgeti(L, LUA_REGISTRYINDEX, pgm->lua_func);
ok = !lua_pcall(L, 0, LUA_MULTRET, 0); ok = !lua_pcall(L, 0, LUA_MULTRET, 0);
} }
@ -2334,6 +2415,7 @@ evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
} }
pgm->valid = ok; pgm->valid = ok;
pgm->padding_calc = EINA_FALSE; pgm->padding_calc = EINA_FALSE;
pgm->changed = EINA_FALSE;
return ok; return ok;
} }
@ -2371,12 +2453,12 @@ _buffers_update(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm)
} }
else else
{ {
if ((buf->w != pgm->w) || (buf->h != pgm->h)) if ((buf->w != pgm->state.w) || (buf->h != pgm->state.h))
pgm->changed = EINA_TRUE; pgm->changed = EINA_TRUE;
buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha); buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha);
fb = _filter_buffer_get(ctx, buf->cid); fb = _filter_buffer_get(ctx, buf->cid);
fb->w = buf->w = pgm->w; fb->w = buf->w = pgm->state.w;
fb->h = buf->h = pgm->h; fb->h = buf->h = pgm->state.h;
} }
} }
} }
@ -2450,23 +2532,61 @@ evas_filter_program_new(const char *name, Eina_Bool input_alpha)
if (!pgm) return NULL; if (!pgm) return NULL;
pgm->name = eina_stringshare_add(name); pgm->name = eina_stringshare_add(name);
pgm->input_alpha = input_alpha; 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;
return pgm; return pgm;
} }
EAPI void EAPI Eina_Bool
evas_filter_program_state_set(Evas_Filter_Program *pgm, int w, int h) evas_filter_program_state_set(Evas_Filter_Program *pgm, Evas_Object *eo_obj,
Evas_Object_Protected_Data *obj)
{ {
Eina_Bool changed = EINA_FALSE; Evas_Filter_Program_State old_state;
#define SET(a) do { if (pgm->a != a) { changed = 1; pgm->a = a; } } while (0)
EINA_SAFETY_ON_NULL_RETURN(pgm); EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
SET(w); memcpy(&old_state, &pgm->state, sizeof(Evas_Filter_Program_State));
SET(h);
pgm->changed |= changed;
#undef SET pgm->state.w = obj->cur->geometry.w;
pgm->state.h = obj->cur->geometry.h;
eo_do(eo_obj,
efl_gfx_color_get(&pgm->state.color.r,
&pgm->state.color.g,
&pgm->state.color.b,
&pgm->state.color.a));
if (eo_isa(eo_obj, EVAS_TEXT_CLASS))
{
eo_do(eo_obj,
evas_obj_text_shadow_color_get(&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(&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(&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(&pgm->state.text.glow2.r,
&pgm->state.text.glow2.g,
&pgm->state.text.glow2.b,
&pgm->state.text.glow2.a));
}
if (memcmp(&old_state, &pgm->state, sizeof(Evas_Filter_Program_State)) != 0)
pgm->changed = EINA_TRUE;
if (pgm->changed)
pgm->padding_calc = EINA_FALSE;
return pgm->changed;
} }
/** Bind objects for proxy rendering */ /** Bind objects for proxy rendering */
@ -2494,10 +2614,6 @@ evas_filter_program_source_set_all(Evas_Filter_Program *pgm,
ENFN->context_clip_set(ENDT, dc, l, r, t, b); } while (0) ENFN->context_clip_set(ENDT, dc, l, r, t, b); } while (0)
#define RESETCLIP() do { ENFN->context_clip_set(ENDT, dc, _l, _r, _t, _b); } while (0) #define RESETCLIP() do { ENFN->context_clip_set(ENDT, dc, _l, _r, _t, _b); } while (0)
#define INSTR_PARAM_CHECK(a) do { if (!(a)) { \
ERR("Argument %s can not be nil in %s!", #a, instr->name); return -1; } \
} while (0)
static Evas_Filter_Fill_Mode static Evas_Filter_Fill_Mode
_fill_mode_get(Evas_Filter_Instruction *instr) _fill_mode_get(Evas_Filter_Instruction *instr)
{ {
@ -3006,15 +3122,16 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
DBG("Using program '%s' for context %p", pgm->name, ctx); DBG("Using program '%s' for context %p", pgm->name, ctx);
// Copy current state (size, edje state val, color class, etc...) // Copy current state (size, edje state val, color class, etc...)
ctx->w = pgm->w; ctx->w = pgm->state.w;
ctx->h = pgm->h; ctx->h = pgm->state.h;
// Create empty context with all required buffers // Create empty context with all required buffers
evas_filter_context_clear(ctx); evas_filter_context_clear(ctx);
_buffers_update(ctx, pgm);
if (pgm->changed) if (pgm->changed)
{ {
pgm->changed = EINA_FALSE;
_filter_program_reset(pgm);
lua_rawgeti(pgm->L, LUA_REGISTRYINDEX, pgm->lua_func); lua_rawgeti(pgm->L, LUA_REGISTRYINDEX, pgm->lua_func);
success = !lua_pcall(pgm->L, 0, LUA_MULTRET, 0); success = !lua_pcall(pgm->L, 0, LUA_MULTRET, 0);
if (!success) if (!success)
@ -3024,7 +3141,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
goto end; goto end;
} }
} }
pgm->changed = EINA_FALSE; _buffers_update(ctx, pgm);
// Compute and save padding info // Compute and save padding info
evas_filter_program_padding_get(pgm, &ctx->padl, &ctx->padr, &ctx->padt, &ctx->padb); evas_filter_program_padding_get(pgm, &ctx->padl, &ctx->padr, &ctx->padt, &ctx->padb);

View File

@ -35,6 +35,7 @@ typedef struct _Evas_Filter_Command Evas_Filter_Command;
typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction; typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction;
typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer; typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer;
typedef struct _Evas_Filter_Proxy_Binding Evas_Filter_Proxy_Binding; 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_Mode Evas_Filter_Mode;
typedef enum _Evas_Filter_Blur_Type Evas_Filter_Blur_Type; typedef enum _Evas_Filter_Blur_Type Evas_Filter_Blur_Type;
typedef enum _Evas_Filter_Channel Evas_Filter_Channel; typedef enum _Evas_Filter_Channel Evas_Filter_Channel;
@ -125,7 +126,7 @@ enum _Evas_Filter_Transform_Flags
/* Parser stuff (high level API) */ /* Parser stuff (high level API) */
EAPI Evas_Filter_Program *evas_filter_program_new(const char *name, Eina_Bool input_alpha); EAPI Evas_Filter_Program *evas_filter_program_new(const char *name, Eina_Bool input_alpha);
EAPI void evas_filter_program_state_set(Evas_Filter_Program *pgm, int w, int h); EAPI Eina_Bool evas_filter_program_state_set(Evas_Filter_Program *pgm, Evas_Object *eo_obj, Evas_Object_Protected_Data *obj);
EAPI Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str); EAPI Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str);
EAPI void evas_filter_program_del(Evas_Filter_Program *pgm); 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); Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);