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 */
#define ENFN obj->layer->evas->engine.func
#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 */
static const char o_type[] = "text";
@ -1766,16 +1768,15 @@ evas_object_text_render(Evas_Object *eo_obj,
Y = obj->cur->geometry.y;
// Prepare color multiplier
ENFN->context_color_set(ENDT, context, 255, 255, 255, 255);
if ((obj->cur->cache.clip.r == 255) && (obj->cur->cache.clip.g == 255) &&
(obj->cur->cache.clip.b == 255) && (obj->cur->cache.clip.a == 255))
ENFN->context_multiplier_unset(ENDT, context);
COLOR_ONLY_SET(obj, cur->cache, clip);
if (obj->cur->clipper)
ENFN->context_multiplier_set(output, 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
ENFN->context_multiplier_set(ENDT, context,
obj->cur->cache.clip.r,
obj->cur->cache.clip.g,
obj->cur->cache.clip.b,
obj->cur->cache.clip.a);
ENFN->context_multiplier_unset(output, context);
if (!fcow->chain)
{
@ -1794,10 +1795,15 @@ evas_object_text_render(Evas_Object *eo_obj,
}
fcow->chain = pgm;
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
if (!redraw && fcow->sources)
@ -1834,8 +1840,12 @@ evas_object_text_render(Evas_Object *eo_obj,
return;
}
}
else
evas_filter_program_state_set(fcow->chain, eo_obj, obj);
filter = evas_filter_context_new(obj->layer->evas, do_async);
// Run script
ok = evas_filter_context_program_use(filter, fcow->chain);
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;
}
/* EXPERIMENTAL CODE BEGIN */
EOLIAN static void
_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);
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))
{
ERR("Parsing failed!");
@ -2543,8 +2551,6 @@ update:
evas_object_inform_call_resize(eo_obj);
}
/* EXPERIMENTAL CODE END */
EAPI void
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;
DBG("Created context buffer %d", 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;
Eina_List *l;
DBG("Want temp buffer: %dx%d %s", w, h, alpha_only ? "alpha" : "rgba");
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 ((!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->locked = EINA_TRUE;
DBG("Created temporary buffer: %d (%s)", buf->id, alpha_only ? "Alpha" : "RGBA");
return buf;
}

View File

@ -18,6 +18,10 @@
#define EVAS_FILTER_MODE_GROW (EVAS_FILTER_MODE_LAST+1)
#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:
* To keep it simple, I'm not using any fancy features, only <ul>/<li> lists
* and @a, @b, @c flags from Doxygen.
@ -286,6 +290,7 @@ typedef struct _Buffer
} pad;
int w, h;
Eina_Bool alpha : 1;
Eina_Bool manual : 1; // created by "buffer" instruction
} Buffer;
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 *);
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;
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
{
Eina_Stringshare *name; // Optional for now
@ -328,11 +345,13 @@ struct _Evas_Filter_Program
Eina_Inlist /* Evas_Filter_Instruction */ *instructions;
Eina_Inlist /* Buffer */ *buffers;
struct {
// Note: padding can't be in the state as it's calculated after running Lua
int l, r, t, b;
} pad;
int w, h;
Evas_Filter_Program_State state;
lua_State *L;
int lua_func;
int last_bufid;
Eina_Bool valid : 1;
Eina_Bool padding_calc : 1; // Padding has been calculated
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 *buf;
Evas_Object *source;
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, 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))
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;
}
@ -636,18 +638,11 @@ _lua_buffer_push(lua_State *L, Buffer *buf)
Buffer **ptr;
lua_getglobal(L, buf->name);
if (lua_isnil(L, -1))
{
ptr = lua_newuserdata(L, sizeof(Buffer **));
*ptr = buf;
luaL_getmetatable(L, _lua_buffer_meta);
lua_setmetatable(L, -2);
lua_setglobal(L, buf->name);
}
else
{
ERR("to do");
}
ptr = lua_newuserdata(L, sizeof(Buffer **));
*ptr = buf;
luaL_getmetatable(L, _lua_buffer_meta);
lua_setmetatable(L, -2);
lua_setglobal(L, buf->name);
return EINA_TRUE;
}
@ -727,7 +722,7 @@ _lua_buffer_source(lua_State *L)
static Buffer *
_buffer_add(Evas_Filter_Program *pgm, const char *name, Eina_Bool alpha,
const char *src)
const char *src, Eina_Bool manual)
{
Buffer *buf;
@ -746,11 +741,20 @@ _buffer_add(Evas_Filter_Program *pgm, const char *name, Eina_Bool alpha,
buf = calloc(1, sizeof(Buffer));
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->alpha = alpha;
buf->w = pgm->w;
buf->h = pgm->h;
buf->w = pgm->state.w;
buf->h = pgm->state.h;
pgm->buffers = eina_inlist_append(pgm->buffers, EINA_INLIST_GET(buf));
_lua_buffer_push(pgm->L, buf);
@ -810,7 +814,6 @@ _buffer_instruction_parse_run(lua_State *L,
char bufname[32] = {0};
const char *src, *rgba;
Eina_Bool ok, alpha = EINA_FALSE;
int cnt;
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, 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"));
cnt = (pgm->buffers ? eina_inlist_count(pgm->buffers) : 0) + 1;
snprintf(bufname, sizeof(bufname), "__buffer%02d", cnt);
ok = (_buffer_add(pgm, bufname, alpha, src) != NULL);
snprintf(bufname, sizeof(bufname), "__buffer%02d", ++pgm->last_bufid);
ok = (_buffer_add(pgm, bufname, alpha, src, EINA_TRUE) != NULL);
if (!ok) return EINA_FALSE;
@ -851,45 +853,44 @@ _buffer_instruction_prepare(Evas_Filter_Program *pgm EINA_UNUSED,
return EINA_TRUE;
}
static void
_blend_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
static int
_blend_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb)
{
const char *inbuf, *outbuf;
Evas_Filter_Fill_Mode fillmode;
Buffer *in, *out;
Buffer *src, *dst;
int ox, oy, l = 0, r = 0, t = 0, b = 0;
ox = _instruction_param_geti(instr, "ox", NULL);
oy = _instruction_param_geti(instr, "oy", NULL);
inbuf = _instruction_param_gets(instr, "src", NULL);
in = _buffer_get(pgm, inbuf);
EINA_SAFETY_ON_NULL_RETURN(in);
outbuf = _instruction_param_gets(instr, "dst", NULL);
out = _buffer_get(pgm, outbuf);
EINA_SAFETY_ON_NULL_RETURN(out);
src = _instruction_param_getbuf(instr, "src", NULL);
dst = _instruction_param_getbuf(instr, "dst", NULL);
INSTR_PARAM_CHECK(src);
INSTR_PARAM_CHECK(dst);
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_Y | EVAS_FILTER_FILL_MODE_REPEAT_Y)) oy = 0;
if (ox < 0) l = (-ox) + in->pad.l;
else r = ox + in->pad.r;
if (ox < 0) l = (-ox) + src->pad.l;
else r = ox + src->pad.r;
if (oy < 0) t = (-oy) + in->pad.t;
else b = oy + in->pad.b;
if (oy < 0) t = (-oy) + src->pad.t;
else b = oy + src->pad.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 (dst->pad.l < l) dst->pad.l = l;
if (dst->pad.r < r) dst->pad.r = r;
if (dst->pad.t < t) dst->pad.t = t;
if (dst->pad.b < b) dst->pad.b = b;
if (padl) *padl = l;
if (padr) *padr = r;
if (padt) *padt = t;
if (padb) *padb = b;
return 0;
}
/**
@ -955,33 +956,32 @@ _blend_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction *in
return EINA_TRUE;
}
static void
_blur_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
static int
_blur_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb)
{
Eina_Bool yset = EINA_FALSE;
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;
Buffer *in, *out;
Buffer *src, *dst;
rx = _instruction_param_geti(instr, "rx", NULL);
ry = _instruction_param_geti(instr, "ry", &yset);
ox = _instruction_param_geti(instr, "ox", 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);
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"))
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 (rx < 0) rx = 0;
if (ry < 0) ry = 0;
@ -997,20 +997,22 @@ _blur_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
rx *= count;
ry *= count;
l = rx + in->pad.l + ((ox < 0) ? (-ox) : 0);
r = rx + in->pad.r + ((ox > 0) ? ox : 0);
t = ry + in->pad.t + ((oy < 0) ? (-oy) : 0);
b = ry + in->pad.b + ((oy > 0) ? oy : 0);
l = rx + src->pad.l + ((ox < 0) ? (-ox) : 0);
r = rx + src->pad.r + ((ox > 0) ? ox : 0);
t = ry + src->pad.t + ((oy < 0) ? (-oy) : 0);
b = ry + src->pad.b + ((oy > 0) ? oy : 0);
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 (dst->pad.l < l) dst->pad.l = l;
if (dst->pad.r < r) dst->pad.r = r;
if (dst->pad.t < t) dst->pad.t = t;
if (dst->pad.b < b) dst->pad.b = b;
if (padl) *padl = l;
if (padr) *padr = r;
if (padt) *padt = t;
if (padb) *padb = b;
return 0;
}
/**
@ -1212,39 +1214,37 @@ _curve_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction *in
return EINA_TRUE;
}
static void
_displace_padding_update(Evas_Filter_Program *pgm,
static int
_displace_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb)
{
int intensity = 0;
int l, r, t, b;
const char *inbuf, *outbuf;
Buffer *in, *out;
Buffer *src, *dst;
intensity = _instruction_param_geti(instr, "intensity", NULL);
inbuf = _instruction_param_gets(instr, "src", NULL);
outbuf = _instruction_param_gets(instr, "dst", NULL);
src = _instruction_param_getbuf(instr, "src", NULL);
dst = _instruction_param_getbuf(instr, "dst", NULL);
INSTR_PARAM_CHECK(src);
INSTR_PARAM_CHECK(dst);
in = _buffer_get(pgm, inbuf);
out = _buffer_get(pgm, outbuf);
EINA_SAFETY_ON_NULL_RETURN(in);
EINA_SAFETY_ON_NULL_RETURN(out);
l = intensity + src->pad.l;
r = intensity + src->pad.r;
t = intensity + src->pad.t;
b = intensity + src->pad.b;
l = intensity + in->pad.l;
r = intensity + in->pad.r;
t = intensity + in->pad.t;
b = intensity + in->pad.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 (dst->pad.l < l) dst->pad.l = l;
if (dst->pad.r < r) dst->pad.r = r;
if (dst->pad.t < t) dst->pad.t = t;
if (dst->pad.b < b) dst->pad.b = b;
if (padl) *padl = l;
if (padr) *padr = r;
if (padt) *padt = t;
if (padb) *padb = b;
return 0;
}
/**
@ -1361,40 +1361,39 @@ _fill_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction *ins
return EINA_TRUE;
}
static void
_grow_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
static int
_grow_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb)
{
const char *inbuf, *outbuf;
Buffer *in, *out;
Buffer *src, *dst;
int l, r, t, b;
int radius;
radius = _instruction_param_geti(instr, "radius", NULL);
inbuf = _instruction_param_gets(instr, "src", NULL);
outbuf = _instruction_param_gets(instr, "dst", NULL);
in = _buffer_get(pgm, inbuf);
out = _buffer_get(pgm, outbuf);
EINA_SAFETY_ON_NULL_RETURN(in);
EINA_SAFETY_ON_NULL_RETURN(out);
src = _instruction_param_getbuf(instr, "src", NULL);
dst = _instruction_param_getbuf(instr, "dst", NULL);
INSTR_PARAM_CHECK(src);
INSTR_PARAM_CHECK(dst);
if (radius < 0) radius = 0;
l = radius + in->pad.l;
r = radius + in->pad.r;
t = radius + in->pad.t;
b = radius + in->pad.b;
l = radius + src->pad.l;
r = radius + src->pad.r;
t = radius + src->pad.t;
b = radius + src->pad.b;
if (padl) *padl = l;
if (padr) *padr = r;
if (padt) *padt = t;
if (padb) *padb = 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 (dst->pad.l < l) dst->pad.l = l;
if (dst->pad.r < r) dst->pad.r = r;
if (dst->pad.t < t) dst->pad.t = t;
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;
}
static void
_transform_padding_update(Evas_Filter_Program *pgm,
static int
_transform_padding_update(Evas_Filter_Program *pgm EINA_UNUSED,
Evas_Filter_Instruction *instr,
int *padl, int *padr, int *padt, int *padb)
{
const char *outbuf;
Buffer *out;
Buffer *dst;
int ox, oy, l = 0, r = 0, t = 0, b = 0;
//ox = _instruction_param_geti(instr, "ox", NULL);
ox = 0;
oy = _instruction_param_geti(instr, "oy", NULL);
outbuf = _instruction_param_gets(instr, "dst", NULL);
out = _buffer_get(pgm, outbuf);
EINA_SAFETY_ON_NULL_RETURN(out);
dst = _instruction_param_getbuf(instr, "dst", NULL);
INSTR_PARAM_CHECK(dst);
if (ox < 0) l = (-ox) * 2;
else r = ox * 2;
@ -1517,15 +1513,17 @@ _transform_padding_update(Evas_Filter_Program *pgm,
if (oy < 0) t = (-oy) * 2;
else b = oy * 2;
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 (dst->pad.l < l) dst->pad.l = l;
if (dst->pad.r < r) dst->pad.r = r;
if (dst->pad.t < t) dst->pad.t = t;
if (dst->pad.b < b) dst->pad.b = b;
if (padl) *padl = l;
if (padr) *padr = r;
if (padt) *padt = t;
if (padb) *padb = b;
return 0;
}
/**
@ -1580,7 +1578,7 @@ _transform_instruction_prepare(Evas_Filter_Program *pgm, Evas_Filter_Instruction
return EINA_TRUE;
}
static void
static int
_padding_set_padding_update(Evas_Filter_Program *pgm,
Evas_Filter_Instruction *instr,
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 (padb) *padb = b;
pgm->padding_set = EINA_TRUE;
return 0;
}
/**
@ -1717,6 +1717,7 @@ _lua_program_get(lua_State *L)
static Eina_Bool
_lua_parameter_parse(Evas_Filter_Program *pgm, lua_State *L,
Evas_Filter_Instruction *instr,
Instruction_Param *param, int i)
{
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));
break;
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 = A_VAL(&color);
int R = R_VAL(&color);
int G = G_VAL(&color);
int B = B_VAL(&color);
if (!A && (R || B || G)) A = 0xFF;
evas_color_argb_premul(A, &R, &G, &B);
int A, R, G, B;
DATA32 color;
if (lua_isnumber(L, i))
color = (DATA32) lua_tonumber(L, i);
else
{
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);
}
else if (lua_type(L, i) == LUA_TSTRING)
{
if (!_color_parse(lua_tostring(L, i), &param->value.c))
goto fail;
}
else
goto fail;
break;
@ -1889,7 +1901,7 @@ _lua_instruction_run(lua_State *L, Evas_Filter_Instruction *instr)
goto fail;
}
if (!_lua_parameter_parse(pgm, L, param, -1))
if (!_lua_parameter_parse(pgm, L, instr, param, -1))
goto fail;
lua_pop(L, 1);
}
@ -1899,7 +1911,7 @@ _lua_instruction_run(lua_State *L, Evas_Filter_Instruction *instr)
EINA_INLIST_FOREACH(instr->params, param)
{
if ((++i) > argc) break;
if (!_lua_parameter_parse(pgm, L, param, i))
if (!_lua_parameter_parse(pgm, L, instr, param, i))
goto fail;
}
}
@ -2043,11 +2055,30 @@ static const luaL_Reg buffer_meta[] = {
{ 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 *
_lua_state_create(Evas_Filter_Program *pgm)
{
lua_State *L;
Buffer *buf;
pgm->L = L = luaL_newstate();
if (!L)
@ -2136,29 +2167,6 @@ _lua_state_create(Evas_Filter_Program *pgm)
lua_rawset(L, -3);
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;
}
@ -2284,6 +2292,78 @@ _legacy_strdup(const char *str)
}
#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 */
EAPI Eina_Bool
@ -2314,6 +2394,7 @@ evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
if (ok)
{
pgm->lua_func = luaL_ref(L, LUA_REGISTRYINDEX);
_filter_program_reset(pgm);
lua_rawgeti(L, LUA_REGISTRYINDEX, pgm->lua_func);
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->padding_calc = EINA_FALSE;
pgm->changed = EINA_FALSE;
return ok;
}
@ -2371,12 +2453,12 @@ _buffers_update(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm)
}
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;
buf->cid = evas_filter_buffer_empty_new(ctx, buf->alpha);
fb = _filter_buffer_get(ctx, buf->cid);
fb->w = buf->w = pgm->w;
fb->h = buf->h = pgm->h;
fb->w = buf->w = pgm->state.w;
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;
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;
return pgm;
}
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)
{
Eina_Bool changed = EINA_FALSE;
#define SET(a) do { if (pgm->a != a) { changed = 1; pgm->a = a; } } while (0)
Evas_Filter_Program_State old_state;
EINA_SAFETY_ON_NULL_RETURN(pgm);
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
SET(w);
SET(h);
pgm->changed |= changed;
memcpy(&old_state, &pgm->state, sizeof(Evas_Filter_Program_State));
#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 */
@ -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)
#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
_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);
// Copy current state (size, edje state val, color class, etc...)
ctx->w = pgm->w;
ctx->h = pgm->h;
ctx->w = pgm->state.w;
ctx->h = pgm->state.h;
// Create empty context with all required buffers
evas_filter_context_clear(ctx);
_buffers_update(ctx, pgm);
if (pgm->changed)
{
pgm->changed = EINA_FALSE;
_filter_program_reset(pgm);
lua_rawgeti(pgm->L, LUA_REGISTRYINDEX, pgm->lua_func);
success = !lua_pcall(pgm->L, 0, LUA_MULTRET, 0);
if (!success)
@ -3024,7 +3141,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
goto end;
}
}
pgm->changed = EINA_FALSE;
_buffers_update(ctx, pgm);
// Compute and save padding info
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_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;
@ -125,7 +126,7 @@ enum _Evas_Filter_Transform_Flags
/* Parser stuff (high level API) */
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 void evas_filter_program_del(Evas_Filter_Program *pgm);
Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);