forked from enlightenment/efl
Evas filters: switch script language to Lua
It was a pretty stupid idea to write a parser for a custom language when we already have Lua as a dependency and it's so beautiful and easy. There is a fallback function to allow for compatibility with legacy filters. But that broken syntax is not recommended. I'll probably remove it soon. All the test cases I have in my example app work fine with this compatibily layer.
This commit is contained in:
parent
72b959239d
commit
103d8d08fa
|
@ -1,7 +1,22 @@
|
||||||
#include "evas_filter_private.h"
|
#include "evas_filter_private.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
#if LUA_VERSION_NUM == 502
|
||||||
|
# define LUA52 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#ifdef DEBUG
|
||||||
|
# define FILTERS_DEBUG
|
||||||
|
//#endif
|
||||||
|
|
||||||
#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)
|
||||||
|
|
||||||
|
// FIXME: The documentation must be updated to respect the Lua language
|
||||||
|
|
||||||
/* 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
|
||||||
|
@ -181,35 +196,6 @@
|
||||||
by rendering the Evas Object into this buffer. This is how it will be
|
by rendering the Evas Object into this buffer. This is how it will be
|
||||||
possible to load external images, textures and even animations into a buffer.
|
possible to load external images, textures and even animations into a buffer.
|
||||||
|
|
||||||
|
|
||||||
@subsection sec_buffers_cmd Buffer command
|
|
||||||
|
|
||||||
@code
|
|
||||||
buffer : name;
|
|
||||||
buffer : name (alpha);
|
|
||||||
buffer : name (rgba);
|
|
||||||
buffer : name (src = partname);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
The "buffer" instruction is a @a special command used to declare a new buffer
|
|
||||||
in the filters context. This buffer can be either ALPHA, RGBA or based on
|
|
||||||
an other Evas Object (proxy source).
|
|
||||||
If no option is given, an RGBA buffer will be created.
|
|
||||||
|
|
||||||
@param name An alpha-numerical name, starting with a letter (a-z, A-Z).
|
|
||||||
Can not be @c input or @c output, as these are reserved names.
|
|
||||||
Must be unique.
|
|
||||||
|
|
||||||
@param (args) [alpha] OR [rgba] OR [src = partname] <br>
|
|
||||||
Create a new named buffer, specify its colorspace or source. Possible options:
|
|
||||||
@li @c alpha: Create an alpha-only buffer (1 channel, no color)
|
|
||||||
@li @c rgba: Create an RGBA buffer (4 channels, full color)
|
|
||||||
@li <tt>src = partname</tt>: Use another <tt>Evas Object</tt> as source for this
|
|
||||||
buffer's pixels. The name can either be an Edje part name or the one
|
|
||||||
specified in evas_obj_text_filter_source_set.
|
|
||||||
|
|
||||||
@see evas_obj_text_filter_source_set
|
|
||||||
|
|
||||||
@since 1.9
|
@since 1.9
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -303,8 +289,10 @@ struct _Evas_Filter_Instruction
|
||||||
{
|
{
|
||||||
EINA_INLIST;
|
EINA_INLIST;
|
||||||
Eina_Stringshare *name;
|
Eina_Stringshare *name;
|
||||||
int /* Evas_Filter_Mode */ type;
|
int /*Evas_Filter_Mode*/ type;
|
||||||
Eina_Inlist /* Instruction_Param */ *params;
|
Eina_Inlist /* Instruction_Param */ *params;
|
||||||
|
int return_count;
|
||||||
|
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 *);
|
void (* update) (Evas_Filter_Program *, Evas_Filter_Instruction *, int *, int *, int *, int *);
|
||||||
|
@ -411,6 +399,18 @@ _instruction_del(Evas_Filter_Instruction *instr)
|
||||||
free(instr);
|
free(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Instruction_Param *
|
||||||
|
_instruction_param_get(Evas_Filter_Instruction *instr, const char *name)
|
||||||
|
{
|
||||||
|
Instruction_Param *param;
|
||||||
|
|
||||||
|
EINA_INLIST_FOREACH(instr->params, param)
|
||||||
|
if (!strcasecmp(name, param->name))
|
||||||
|
return param;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_instruction_param_geti(Evas_Filter_Instruction *instr, const char *name,
|
_instruction_param_geti(Evas_Filter_Instruction *instr, const char *name,
|
||||||
Eina_Bool *isset)
|
Eina_Bool *isset)
|
||||||
|
@ -501,6 +501,7 @@ _instruction_param_gets(Evas_Filter_Instruction *instr, const char *name,
|
||||||
|
|
||||||
/* Parsing format: func ( arg , arg2 , argname=val1, argname2 = val2 ) */
|
/* Parsing format: func ( arg , arg2 , argname=val1, argname2 = val2 ) */
|
||||||
|
|
||||||
|
#if 0
|
||||||
#define CHARS_ALPHABET "abcdefghijklmnopqrstuvwxyzABCDEFGHJIKLMNOPQRSTUVWXYZ"
|
#define CHARS_ALPHABET "abcdefghijklmnopqrstuvwxyzABCDEFGHJIKLMNOPQRSTUVWXYZ"
|
||||||
#define CHARS_NUMS "0123456789"
|
#define CHARS_NUMS "0123456789"
|
||||||
#define CHARS_DELIMS "=-(),;#.:_"
|
#define CHARS_DELIMS "=-(),;#.:_"
|
||||||
|
@ -636,6 +637,7 @@ _is_valid_keyval(const char *str)
|
||||||
*equal = '=';
|
*equal = '=';
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_bool_parse(const char *str, Eina_Bool *b)
|
_bool_parse(const char *str, Eina_Bool *b)
|
||||||
|
@ -709,6 +711,7 @@ end:
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_value_parse(Instruction_Param *param, const char *value)
|
_value_parse(Instruction_Param *param, const char *value)
|
||||||
{
|
{
|
||||||
|
@ -847,6 +850,7 @@ end:
|
||||||
instr->valid = success;
|
instr->valid = success;
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Buffers */
|
/* Buffers */
|
||||||
static Buffer *
|
static Buffer *
|
||||||
|
@ -921,6 +925,87 @@ _buffer_del(Buffer *buf)
|
||||||
|
|
||||||
/* Instruction definitions */
|
/* Instruction definitions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
@page evasfiltersref
|
||||||
|
|
||||||
|
@subsection sec_buffers_cmd Buffer command
|
||||||
|
|
||||||
|
Create a new buffer.
|
||||||
|
|
||||||
|
@code
|
||||||
|
name1 = buffer();
|
||||||
|
name2 = buffer("alpha");
|
||||||
|
name3 = buffer("rgba");
|
||||||
|
name4 = buffer{src = "partname"};
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@param type Buffer type: @c rgba (default) or @c alpha
|
||||||
|
@param src An optional source. If set, @a type will be @c rgba.
|
||||||
|
@return A new buffer. This value must not be saved to a variable.
|
||||||
|
|
||||||
|
This creates a new named buffer, specify its colorspace or source. Possible options:
|
||||||
|
@li @c alpha: Create an alpha-only buffer (1 channel, no color)
|
||||||
|
@li @c rgba: Create an RGBA buffer (4 channels, full color)
|
||||||
|
@li <tt>{src = "partname"}</tt>: Use another <tt>Evas Object</tt> as source for this
|
||||||
|
buffer's pixels. The name can either be an Edje part name or the one
|
||||||
|
specified in @c evas_obj_text_filter_source_set.
|
||||||
|
|
||||||
|
If no option is given, an RGBA buffer will be created. All buffers have the
|
||||||
|
same size, unless they are based on an external source.
|
||||||
|
|
||||||
|
@see evas_obj_text_filter_source_set
|
||||||
|
|
||||||
|
@since 1.10
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_buffer_instruction_parse_run(lua_State *L,
|
||||||
|
Evas_Filter_Program *pgm,
|
||||||
|
Evas_Filter_Instruction *instr)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
// FIXME: Buffers are still referred to internally by name.
|
||||||
|
// This is pretty bad with the switch to Lua.
|
||||||
|
|
||||||
|
rgba = _instruction_param_gets(instr, "type", NULL);
|
||||||
|
src = _instruction_param_gets(instr, "src", NULL);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!ok) return EINA_FALSE;
|
||||||
|
|
||||||
|
lua_pushstring(L, bufname);
|
||||||
|
instr->return_count = 1;
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_buffer_instruction_prepare(Evas_Filter_Instruction *instr)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(instr, EINA_FALSE);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(instr->name, EINA_FALSE);
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(!strcmp(instr->name, "buffer"), EINA_FALSE);
|
||||||
|
|
||||||
|
instr->type = EVAS_FILTER_MODE_BUFFER;
|
||||||
|
instr->parse_run = _buffer_instruction_parse_run;
|
||||||
|
_instruction_param_seq_add(instr, "type", VT_BUFFER, "rgba");
|
||||||
|
_instruction_param_seq_add(instr, "src", VT_BUFFER, NULL);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_blend_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
|
_blend_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
|
||||||
int *padl, int *padr, int *padt, int *padb)
|
int *padl, int *padr, int *padt, int *padb)
|
||||||
|
@ -1727,6 +1812,7 @@ _padding_set_instruction_prepare(Evas_Filter_Instruction *instr)
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static Evas_Filter_Instruction *
|
static Evas_Filter_Instruction *
|
||||||
_instruction_create(const char *name)
|
_instruction_create(const char *name)
|
||||||
{
|
{
|
||||||
|
@ -1735,7 +1821,9 @@ _instruction_create(const char *name)
|
||||||
|
|
||||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(name && *name, NULL);
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(name && *name, NULL);
|
||||||
|
|
||||||
if (!strcasecmp(name, "blend"))
|
if (!strcasecmp(name, "buffer"))
|
||||||
|
prepare = _buffer_instruction_prepare;
|
||||||
|
else if (!strcasecmp(name, "blend"))
|
||||||
prepare = _blend_instruction_prepare;
|
prepare = _blend_instruction_prepare;
|
||||||
else if (!strcasecmp(name, "blur"))
|
else if (!strcasecmp(name, "blur"))
|
||||||
prepare = _blur_instruction_prepare;
|
prepare = _blur_instruction_prepare;
|
||||||
|
@ -1773,6 +1861,7 @@ _instruction_create(const char *name)
|
||||||
}
|
}
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Evas_Filter_Parser entry points */
|
/* Evas_Filter_Parser entry points */
|
||||||
|
|
||||||
|
@ -1803,6 +1892,7 @@ evas_filter_program_del(Evas_Filter_Program *pgm)
|
||||||
free(pgm);
|
free(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_instruction_buffer_parse(Evas_Filter_Program *pgm, char *command)
|
_instruction_buffer_parse(Evas_Filter_Program *pgm, char *command)
|
||||||
{
|
{
|
||||||
|
@ -1849,23 +1939,474 @@ _instruction_buffer_parse(Evas_Filter_Program *pgm, char *command)
|
||||||
end:
|
end:
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const int this_is_not_a_cat = 42;
|
||||||
|
|
||||||
|
static Evas_Filter_Program *
|
||||||
|
_lua_program_get(lua_State *L)
|
||||||
|
{
|
||||||
|
Evas_Filter_Program *pgm;
|
||||||
|
lua_pushlightuserdata(L, (void *) &this_is_not_a_cat);
|
||||||
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||||
|
pgm = lua_touserdata(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return pgm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_lua_parameter_parse(lua_State *L, Instruction_Param *param, int i)
|
||||||
|
{
|
||||||
|
Eina_Bool ok;
|
||||||
|
int retc = 0;
|
||||||
|
|
||||||
|
if (!param) goto fail;
|
||||||
|
if (param->set)
|
||||||
|
{
|
||||||
|
ERR("Parameter %s has already been set", param->name);
|
||||||
|
luaL_error(L, "Parameter %s has already been set", param->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (param->type)
|
||||||
|
{
|
||||||
|
case VT_BOOL:
|
||||||
|
if (lua_type(L, i) == LUA_TSTRING)
|
||||||
|
{
|
||||||
|
const char *str = lua_tostring(L, i);
|
||||||
|
Eina_Bool val = _bool_parse(str, &ok);
|
||||||
|
if (!ok) goto fail;
|
||||||
|
eina_value_set(param->value, val);
|
||||||
|
}
|
||||||
|
else if (lua_isboolean(L, i) || lua_isnumber(L, i))
|
||||||
|
eina_value_set(param->value, lua_toboolean(L, i));
|
||||||
|
else goto fail;
|
||||||
|
break;
|
||||||
|
case VT_INT:
|
||||||
|
if (!lua_isnumber(L, i)) goto fail;
|
||||||
|
eina_value_set(param->value, lua_tointeger(L, i));
|
||||||
|
break;
|
||||||
|
case VT_REAL:
|
||||||
|
if (!lua_isnumber(L, i)) goto fail;
|
||||||
|
eina_value_set(param->value, lua_tonumber(L, i));
|
||||||
|
break;
|
||||||
|
case VT_STRING:
|
||||||
|
if (lua_type(L, i) != LUA_TSTRING) goto fail;
|
||||||
|
eina_value_set(param->value, lua_tostring(L, i));
|
||||||
|
break;
|
||||||
|
case VT_COLOR:
|
||||||
|
if (lua_isnumber(L, i))
|
||||||
|
eina_value_set(param->value, (DATA32) lua_tonumber(L, i));
|
||||||
|
else if (lua_type(L, i) == LUA_TSTRING)
|
||||||
|
{
|
||||||
|
DATA32 color;
|
||||||
|
ok = _color_parse(lua_tostring(L, i), &color);
|
||||||
|
if (!ok) goto fail;
|
||||||
|
eina_value_set(param->value, color);
|
||||||
|
}
|
||||||
|
else goto fail;
|
||||||
|
break;
|
||||||
|
case VT_BUFFER:
|
||||||
|
if (lua_type(L, i) != LUA_TSTRING) goto fail;
|
||||||
|
eina_value_set(param->value, lua_tostring(L, i));
|
||||||
|
break;
|
||||||
|
case VT_NONE:
|
||||||
|
default:
|
||||||
|
// This should not happen
|
||||||
|
CRI("Invalid function declaration");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
param->set = EINA_TRUE;
|
||||||
|
|
||||||
|
return retc;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ERR("Invalid value for parameter %s", param->name);
|
||||||
|
luaL_error(L, "Invalid value for parameter %s", param->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_lua_instruction_run(lua_State *L, Evas_Filter_Instruction *instr)
|
||||||
|
{
|
||||||
|
const unsigned int argc = lua_gettop(L);
|
||||||
|
Evas_Filter_Program *pgm = _lua_program_get(L);
|
||||||
|
Instruction_Param *param;
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
if (!instr) goto fail;
|
||||||
|
|
||||||
|
if (eina_inlist_count(instr->params) < argc)
|
||||||
|
{
|
||||||
|
ERR("Too many arguments passed to the instruction %s", instr->name);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_istable(L, 1))
|
||||||
|
{
|
||||||
|
Eina_Bool seqmode = EINA_TRUE;
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
ERR("Too many arguments passed to the instruction %s (in table mode)", instr->name);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
lua_pushnil(L);
|
||||||
|
param = EINA_INLIST_CONTAINER_GET(instr->params, Instruction_Param);
|
||||||
|
|
||||||
|
while (lua_next(L, 1))
|
||||||
|
{
|
||||||
|
if (!lua_isnumber(L, -2) && (lua_type(L, -2) == LUA_TSTRING))
|
||||||
|
{
|
||||||
|
const char *name = lua_tostring(L, -2);
|
||||||
|
seqmode = EINA_FALSE;
|
||||||
|
param = _instruction_param_get(instr, name);
|
||||||
|
if (!param)
|
||||||
|
{
|
||||||
|
ERR("Parameter %s does not exist", name);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!seqmode)
|
||||||
|
{
|
||||||
|
ERR("Unnamed parameter can not come after a named parameter");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else if (param && !param->allow_seq)
|
||||||
|
{
|
||||||
|
ERR("The parameter %s must be refered to by name", param->name);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lua_parameter_parse(L, param, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
if (seqmode)
|
||||||
|
param = EINA_INLIST_GET(param)->next ?
|
||||||
|
_EINA_INLIST_CONTAINER(param, EINA_INLIST_GET(param)->next) :
|
||||||
|
NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EINA_INLIST_FOREACH(instr->params, param)
|
||||||
|
{
|
||||||
|
if ((++i) >= argc) break;
|
||||||
|
_lua_parameter_parse(L, param, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instr->parse_run)
|
||||||
|
{
|
||||||
|
if (!instr->parse_run(L, pgm, instr))
|
||||||
|
{
|
||||||
|
ERR("Failed to run instruction '%s'", instr->name);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ERR("Invalid parameters for instruction %s", instr->name);
|
||||||
|
luaL_error(L, "Invalid parameters for instruction %s", instr->name);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_lua_generic_function(lua_State *L, const char *name,
|
||||||
|
Eina_Bool (* prepare) (Evas_Filter_Instruction *))
|
||||||
|
{
|
||||||
|
Evas_Filter_Program *pgm = _lua_program_get(L);
|
||||||
|
Evas_Filter_Instruction *instr;
|
||||||
|
Eina_Bool ok;
|
||||||
|
|
||||||
|
instr = _instruction_new(name);
|
||||||
|
prepare(instr);
|
||||||
|
ok = _lua_instruction_run(L, instr);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
ERR("Instruction parsing failed");
|
||||||
|
_instruction_del(instr);
|
||||||
|
lua_error(L);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pgm->instructions = eina_inlist_append(pgm->instructions, EINA_INLIST_GET(instr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return instr->return_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LUA_GENERIC_FUNCTION(name) \
|
||||||
|
static int \
|
||||||
|
_lua_##name(lua_State *L) \
|
||||||
|
{ \
|
||||||
|
return _lua_generic_function(L, #name, _##name##_instruction_prepare); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PUSH_LUA_FUNCTION(name) \
|
||||||
|
lua_pushcfunction(L, _lua_##name); \
|
||||||
|
lua_setglobal(L, #name);
|
||||||
|
|
||||||
|
LUA_GENERIC_FUNCTION(buffer)
|
||||||
|
LUA_GENERIC_FUNCTION(blend)
|
||||||
|
LUA_GENERIC_FUNCTION(blur)
|
||||||
|
LUA_GENERIC_FUNCTION(bump)
|
||||||
|
LUA_GENERIC_FUNCTION(curve)
|
||||||
|
LUA_GENERIC_FUNCTION(displace)
|
||||||
|
LUA_GENERIC_FUNCTION(fill)
|
||||||
|
LUA_GENERIC_FUNCTION(grow)
|
||||||
|
LUA_GENERIC_FUNCTION(mask)
|
||||||
|
LUA_GENERIC_FUNCTION(padding_set)
|
||||||
|
LUA_GENERIC_FUNCTION(transform)
|
||||||
|
|
||||||
|
static lua_State *
|
||||||
|
_lua_state_create(Evas_Filter_Program *pgm)
|
||||||
|
{
|
||||||
|
lua_State *L;
|
||||||
|
|
||||||
|
L = luaL_newstate();
|
||||||
|
if (!L)
|
||||||
|
{
|
||||||
|
ERR("Could not create a new Lua state");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
luaopen_base(L);
|
||||||
|
luaopen_table(L);
|
||||||
|
luaopen_string(L);
|
||||||
|
luaopen_math(L);
|
||||||
|
|
||||||
|
// Store program
|
||||||
|
lua_pushlightuserdata(L, (void *) &this_is_not_a_cat);
|
||||||
|
lua_pushlightuserdata(L, pgm);
|
||||||
|
lua_settable(L, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
|
// Register functions
|
||||||
|
PUSH_LUA_FUNCTION(buffer)
|
||||||
|
PUSH_LUA_FUNCTION(blend)
|
||||||
|
PUSH_LUA_FUNCTION(blur)
|
||||||
|
PUSH_LUA_FUNCTION(bump)
|
||||||
|
PUSH_LUA_FUNCTION(curve)
|
||||||
|
PUSH_LUA_FUNCTION(displace)
|
||||||
|
PUSH_LUA_FUNCTION(fill)
|
||||||
|
PUSH_LUA_FUNCTION(grow)
|
||||||
|
PUSH_LUA_FUNCTION(mask)
|
||||||
|
PUSH_LUA_FUNCTION(padding_set)
|
||||||
|
PUSH_LUA_FUNCTION(transform)
|
||||||
|
|
||||||
|
// Register special variables
|
||||||
|
for (unsigned k = 0; k < (sizeof(color_map) / sizeof(color_map[0])); k++)
|
||||||
|
{
|
||||||
|
lua_pushnumber(L, color_map[k].value);
|
||||||
|
lua_setglobal(L, color_map[k].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned k = 0; k < (sizeof(fill_modes) / sizeof(fill_modes[0])); k++)
|
||||||
|
{
|
||||||
|
if (strcmp("repeat", fill_modes[k].name))
|
||||||
|
{
|
||||||
|
lua_pushstring(L, fill_modes[k].name);
|
||||||
|
lua_setglobal(L, fill_modes[k].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushstring(L, "rgba");
|
||||||
|
lua_setglobal(L, "rgba");
|
||||||
|
|
||||||
|
lua_pushstring(L, "alpha");
|
||||||
|
lua_setglobal(L, "alpha");
|
||||||
|
|
||||||
|
static const struct { Eina_Bool b; const char *name; } booleans[] =
|
||||||
|
{
|
||||||
|
{ EINA_TRUE, "on" },
|
||||||
|
{ EINA_TRUE, "yes" },
|
||||||
|
{ EINA_TRUE, "enable" },
|
||||||
|
{ EINA_TRUE, "enabled" },
|
||||||
|
{ EINA_FALSE, "off" },
|
||||||
|
{ EINA_FALSE, "no" },
|
||||||
|
{ EINA_FALSE, "disnable" },
|
||||||
|
{ EINA_FALSE, "disabled" }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned k = 0; k < (sizeof(booleans) / sizeof(booleans[0])); k++)
|
||||||
|
{
|
||||||
|
lua_pushnumber(L, booleans[k].b);
|
||||||
|
lua_setglobal(L, booleans[k].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register proxies
|
||||||
|
if (pgm->proxies)
|
||||||
|
{
|
||||||
|
Eina_Iterator *it = eina_hash_iterator_key_new(pgm->proxies);
|
||||||
|
const char *source;
|
||||||
|
|
||||||
|
EINA_ITERATOR_FOREACH(it, source)
|
||||||
|
if (_buffer_get(pgm, source))
|
||||||
|
{
|
||||||
|
lua_pushstring(L, source);
|
||||||
|
lua_setglobal(L, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_iterator_free(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is here to avoid breaking the ABI too much.
|
||||||
|
// It should not stay here long, only until all client apps have changed the filters' code to Lua.
|
||||||
|
static char *
|
||||||
|
_legacy_strdup(const char *str)
|
||||||
|
{
|
||||||
|
Eina_Strbuf *dst;
|
||||||
|
|
||||||
|
dst = eina_strbuf_new();
|
||||||
|
for (const char *ptr = str; ptr && *ptr; ptr++)
|
||||||
|
{
|
||||||
|
if (ptr[0] == '/' && ptr[1] == '/')
|
||||||
|
// Comments
|
||||||
|
ptr = strchr(ptr, '\n');
|
||||||
|
else if (ptr[0] == '/' && ptr[1] == '*')
|
||||||
|
{
|
||||||
|
/* Comments */
|
||||||
|
ptr = strstr(ptr + 2, "*/");
|
||||||
|
if (ptr) ptr++;
|
||||||
|
}
|
||||||
|
else if (*ptr == '(')
|
||||||
|
eina_strbuf_append_char(dst, '{');
|
||||||
|
else if (*ptr == ')')
|
||||||
|
eina_strbuf_append_char(dst, '}');
|
||||||
|
else if (*ptr == '#')
|
||||||
|
{
|
||||||
|
// Colors: #RGBA becomes "#RGBA"
|
||||||
|
ptr++;
|
||||||
|
eina_strbuf_append_length(dst, "\"#", 2);
|
||||||
|
while (*ptr && *ptr != ',' && *ptr != ')')
|
||||||
|
eina_strbuf_append_char(dst, *ptr++);
|
||||||
|
eina_strbuf_append_char(dst, '"');
|
||||||
|
ptr--;
|
||||||
|
}
|
||||||
|
else if (!strncasecmp("buffer", ptr, 6))
|
||||||
|
{
|
||||||
|
// Buffers: "buffer : a (rgba)" into "local a = buffer (rgba)"
|
||||||
|
ptr = strchr(ptr, ':');
|
||||||
|
if (!ptr) break;
|
||||||
|
eina_strbuf_append(dst, "local ");
|
||||||
|
for (ptr++; ptr && *ptr; ptr++)
|
||||||
|
{
|
||||||
|
if (*ptr != '(')
|
||||||
|
eina_strbuf_append_char(dst, *ptr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eina_strbuf_append(dst, " = buffer{");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strncasecmp("points", ptr, 6))
|
||||||
|
{
|
||||||
|
// Color curves: points = 0:0 - 255:255 becomes points = "0:0-255:255"
|
||||||
|
ptr = strchr(ptr, '=');
|
||||||
|
if (!ptr) break;
|
||||||
|
ptr++;
|
||||||
|
eina_strbuf_append(dst, "points = \"");
|
||||||
|
while (*ptr && *ptr != ',' && *ptr != ')')
|
||||||
|
{
|
||||||
|
if (isspace(*ptr))
|
||||||
|
{
|
||||||
|
ptr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
eina_strbuf_append_char(dst, *ptr++);
|
||||||
|
}
|
||||||
|
eina_strbuf_append_char(dst, '"');
|
||||||
|
ptr--;
|
||||||
|
}
|
||||||
|
else if (!strncasecmp("curve", ptr, 5))
|
||||||
|
{
|
||||||
|
// Color curves: curve (0:0 - 255:255, becomes curve { points = "0:0-255:255",
|
||||||
|
const char *end = strchr(ptr, ')');
|
||||||
|
const char *points = strstr(ptr, "points");
|
||||||
|
if (!end || (points > end)) break;
|
||||||
|
if (!points)
|
||||||
|
{
|
||||||
|
while (*ptr != '(') ptr++;
|
||||||
|
ptr++;
|
||||||
|
eina_strbuf_append(dst, "curve { points = \"");
|
||||||
|
while (*ptr && *ptr != ',' && *ptr != ')')
|
||||||
|
{
|
||||||
|
if (isspace(*ptr))
|
||||||
|
{
|
||||||
|
ptr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
eina_strbuf_append_char(dst, *ptr++);
|
||||||
|
}
|
||||||
|
eina_strbuf_append_char(dst, '"');
|
||||||
|
ptr--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strncasecmp("repeat", ptr, 6))
|
||||||
|
{
|
||||||
|
// repeat is a Lua keyword, replace all occurences by "repeat_xy"
|
||||||
|
if (ptr[-1] != '_' && ptr[6] != '_')
|
||||||
|
{
|
||||||
|
eina_strbuf_append(dst, "\"repeat_xy\"");
|
||||||
|
ptr += 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eina_strbuf_append_char(dst, *ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eina_strbuf_append_char(dst, *ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return eina_strbuf_string_steal(dst);
|
||||||
|
}
|
||||||
|
|
||||||
/** Parse a style program */
|
/** Parse a style program */
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
|
evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
|
||||||
{
|
{
|
||||||
Evas_Filter_Instruction *instr = NULL;
|
// Evas_Filter_Instruction *instr = NULL;
|
||||||
Instruction_Param *param;
|
// Instruction_Param *param;
|
||||||
Eina_Bool success = EINA_FALSE, ok;
|
// Eina_Bool success = EINA_FALSE, ok;
|
||||||
char *token, *next, *code, *instrname;
|
// char *token, *next, *code, *instrname;
|
||||||
int count = 0;
|
// int count = 0;
|
||||||
size_t spn;
|
// size_t spn;
|
||||||
|
lua_State *L;
|
||||||
|
Eina_Bool ok;
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
|
||||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(*str != 0, EINA_FALSE);
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(*str != 0, EINA_FALSE);
|
||||||
|
|
||||||
|
L = _lua_state_create(pgm);
|
||||||
|
if (!L) return EINA_FALSE;
|
||||||
|
|
||||||
|
ok = !luaL_loadstring(L, str);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
char *code = _legacy_strdup(str);
|
||||||
|
INF("Fallback to transformed legacy code:\n%s", code);
|
||||||
|
ok = !luaL_loadstring(L, code);
|
||||||
|
free(code);
|
||||||
|
}
|
||||||
|
if (ok) ok = !lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||||
|
lua_close(L);
|
||||||
|
|
||||||
|
pgm->valid = ok;
|
||||||
|
pgm->padding_calc = EINA_FALSE;
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
|
||||||
|
#if 0
|
||||||
code = _whitespace_ignore_strdup(str);
|
code = _whitespace_ignore_strdup(str);
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(code, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(code, EINA_FALSE);
|
||||||
|
|
||||||
|
@ -1939,6 +2480,7 @@ end:
|
||||||
|
|
||||||
pgm->valid = success;
|
pgm->valid = success;
|
||||||
return success;
|
return success;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Evaluate required padding to correctly apply an effect */
|
/** Evaluate required padding to correctly apply an effect */
|
||||||
|
@ -2048,6 +2590,7 @@ _fill_mode_get(Evas_Filter_Instruction *instr)
|
||||||
|
|
||||||
if (!instr) return EVAS_FILTER_FILL_MODE_NONE;
|
if (!instr) return EVAS_FILTER_FILL_MODE_NONE;
|
||||||
fill = _instruction_param_gets(instr, "fillmode", NULL);
|
fill = _instruction_param_gets(instr, "fillmode", NULL);
|
||||||
|
if (!fill) return EVAS_FILTER_FILL_MODE_NONE;
|
||||||
|
|
||||||
for (k = 0; k < sizeof(fill_modes) / sizeof(fill_modes[0]); k++)
|
for (k = 0; k < sizeof(fill_modes) / sizeof(fill_modes[0]); k++)
|
||||||
{
|
{
|
||||||
|
@ -2077,6 +2620,8 @@ _instr2cmd_blend(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
fillmode = _fill_mode_get(instr);
|
fillmode = _fill_mode_get(instr);
|
||||||
in = _buffer_get(pgm, src);
|
in = _buffer_get(pgm, src);
|
||||||
out = _buffer_get(pgm, dst);
|
out = _buffer_get(pgm, dst);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(out, -1);
|
||||||
|
|
||||||
if (isset) SETCOLOR(color);
|
if (isset) SETCOLOR(color);
|
||||||
cmdid = evas_filter_command_blend_add(ctx, dc, in->cid, out->cid, ox, oy,
|
cmdid = evas_filter_command_blend_add(ctx, dc, in->cid, out->cid, ox, oy,
|
||||||
|
@ -2109,6 +2654,8 @@ _instr2cmd_blur(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
count = _instruction_param_geti(instr, "count", &cntset);
|
count = _instruction_param_geti(instr, "count", &cntset);
|
||||||
in = _buffer_get(pgm, src);
|
in = _buffer_get(pgm, src);
|
||||||
out = _buffer_get(pgm, dst);
|
out = _buffer_get(pgm, dst);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(out, -1);
|
||||||
|
|
||||||
if (typestr)
|
if (typestr)
|
||||||
{
|
{
|
||||||
|
@ -2175,6 +2722,9 @@ _instr2cmd_bump(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
in = _buffer_get(pgm, src);
|
in = _buffer_get(pgm, src);
|
||||||
out = _buffer_get(pgm, dst);
|
out = _buffer_get(pgm, dst);
|
||||||
bump = _buffer_get(pgm, map);
|
bump = _buffer_get(pgm, map);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(out, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(bump, -1);
|
||||||
|
|
||||||
cmdid = evas_filter_command_bump_map_add(ctx, dc, in->cid, bump->cid, out->cid,
|
cmdid = evas_filter_command_bump_map_add(ctx, dc, in->cid, bump->cid, out->cid,
|
||||||
azimuth, elevation, depth, specular,
|
azimuth, elevation, depth, specular,
|
||||||
|
@ -2218,6 +2768,9 @@ _instr2cmd_displace(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
in = _buffer_get(pgm, src);
|
in = _buffer_get(pgm, src);
|
||||||
out = _buffer_get(pgm, dst);
|
out = _buffer_get(pgm, dst);
|
||||||
mask = _buffer_get(pgm, map);
|
mask = _buffer_get(pgm, map);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(out, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(mask, -1);
|
||||||
|
|
||||||
cmdid = evas_filter_command_displacement_map_add(ctx, dc, in->cid, out->cid,
|
cmdid = evas_filter_command_displacement_map_add(ctx, dc, in->cid, out->cid,
|
||||||
mask->cid, flags, intensity,
|
mask->cid, flags, intensity,
|
||||||
|
@ -2246,6 +2799,7 @@ _instr2cmd_fill(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
b = _instruction_param_geti(instr, "b", NULL);
|
b = _instruction_param_geti(instr, "b", NULL);
|
||||||
|
|
||||||
buf = _buffer_get(pgm, bufname);
|
buf = _buffer_get(pgm, bufname);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(buf, -1);
|
||||||
|
|
||||||
SETCOLOR(color);
|
SETCOLOR(color);
|
||||||
cmdid = evas_filter_command_fill_add(ctx, dc, buf->cid);
|
cmdid = evas_filter_command_fill_add(ctx, dc, buf->cid);
|
||||||
|
@ -2282,6 +2836,8 @@ _instr2cmd_grow(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
|
|
||||||
in = _buffer_get(pgm, src);
|
in = _buffer_get(pgm, src);
|
||||||
out = _buffer_get(pgm, dst);
|
out = _buffer_get(pgm, dst);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(out, -1);
|
||||||
|
|
||||||
cmdid = evas_filter_command_grow_add(ctx, dc, in->cid, out->cid,
|
cmdid = evas_filter_command_grow_add(ctx, dc, in->cid, out->cid,
|
||||||
radius, smooth);
|
radius, smooth);
|
||||||
|
@ -2311,6 +2867,9 @@ _instr2cmd_mask(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
in = _buffer_get(pgm, src);
|
in = _buffer_get(pgm, src);
|
||||||
out = _buffer_get(pgm, dst);
|
out = _buffer_get(pgm, dst);
|
||||||
mask = _buffer_get(pgm, msk);
|
mask = _buffer_get(pgm, msk);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(out, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(mask, -1);
|
||||||
|
|
||||||
SETCOLOR(color);
|
SETCOLOR(color);
|
||||||
cmdid = evas_filter_command_mask_add(ctx, dc, in->cid, mask->cid, out->cid, fillmode);
|
cmdid = evas_filter_command_mask_add(ctx, dc, in->cid, mask->cid, out->cid, fillmode);
|
||||||
|
@ -2398,6 +2957,9 @@ interpolated:
|
||||||
|
|
||||||
in = _buffer_get(pgm, src);
|
in = _buffer_get(pgm, src);
|
||||||
out = _buffer_get(pgm, dst);
|
out = _buffer_get(pgm, dst);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(out, -1);
|
||||||
|
|
||||||
cmdid = evas_filter_command_curve_add(ctx, dc, in->cid, out->cid, values, channel);
|
cmdid = evas_filter_command_curve_add(ctx, dc, in->cid, out->cid, values, channel);
|
||||||
|
|
||||||
return cmdid;
|
return cmdid;
|
||||||
|
@ -2428,6 +2990,9 @@ _instr2cmd_transform(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
|
|
||||||
in = _buffer_get(pgm, src);
|
in = _buffer_get(pgm, src);
|
||||||
out = _buffer_get(pgm, dst);
|
out = _buffer_get(pgm, dst);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(out, -1);
|
||||||
|
|
||||||
return evas_filter_command_transform_add(ctx, dc, in->cid, out->cid, flags, ox, oy);
|
return evas_filter_command_transform_add(ctx, dc, in->cid, out->cid, flags, ox, oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2468,6 +3033,7 @@ _command_from_instruction(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
instr2cmd = _instr2cmd_transform;
|
instr2cmd = _instr2cmd_transform;
|
||||||
break;
|
break;
|
||||||
case EVAS_FILTER_MODE_PADDING_SET:
|
case EVAS_FILTER_MODE_PADDING_SET:
|
||||||
|
case EVAS_FILTER_MODE_BUFFER:
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
default:
|
default:
|
||||||
CRI("Invalid instruction type: %d", instr->type);
|
CRI("Invalid instruction type: %d", instr->type);
|
||||||
|
@ -2477,6 +3043,63 @@ _command_from_instruction(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
return instr2cmd(ctx, pgm, instr, dc);
|
return instr2cmd(ctx, pgm, instr, dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FILTERS_DEBUG
|
||||||
|
static void
|
||||||
|
_instruction_dump(Evas_Filter_Instruction *instr)
|
||||||
|
{
|
||||||
|
Eina_Strbuf *str;
|
||||||
|
const char *comma = "";
|
||||||
|
Instruction_Param *param;
|
||||||
|
|
||||||
|
if (!instr) return;
|
||||||
|
|
||||||
|
str = eina_strbuf_new();
|
||||||
|
eina_strbuf_append(str, instr->name);
|
||||||
|
eina_strbuf_append(str, "({ ");
|
||||||
|
EINA_INLIST_FOREACH(instr->params, param)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
DATA32 c;
|
||||||
|
const char *s;
|
||||||
|
double d;
|
||||||
|
|
||||||
|
switch (param->type)
|
||||||
|
{
|
||||||
|
case VT_BOOL:
|
||||||
|
case VT_INT:
|
||||||
|
eina_value_get(param->value, &i);
|
||||||
|
eina_strbuf_append_printf(str, "%s%s = %d", comma, param->name, i);
|
||||||
|
break;
|
||||||
|
case VT_COLOR:
|
||||||
|
eina_value_get(param->value, &c);
|
||||||
|
eina_strbuf_append_printf(str, "%s%s = 0x%08x", comma, param->name, c);
|
||||||
|
break;
|
||||||
|
case VT_REAL:
|
||||||
|
eina_value_get(param->value, &d);
|
||||||
|
eina_strbuf_append_printf(str, "%s%s = %f", comma, param->name, d);
|
||||||
|
break;
|
||||||
|
case VT_STRING:
|
||||||
|
case VT_BUFFER:
|
||||||
|
eina_value_get(param->value, &s);
|
||||||
|
if (s) eina_strbuf_append_printf(str, "%s%s = \"%s\"", comma, param->name, s);
|
||||||
|
else eina_strbuf_append_printf(str, "%s%s = nil", comma, param->name);
|
||||||
|
break;
|
||||||
|
case VT_NONE:
|
||||||
|
default:
|
||||||
|
eina_strbuf_append_printf(str, "%s%s = <INVALID>", comma, param->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
comma = ", ";
|
||||||
|
}
|
||||||
|
eina_strbuf_append(str, "})");
|
||||||
|
DBG("%s", eina_strbuf_string_get(str));
|
||||||
|
eina_strbuf_free(str);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define _instruction_dump(a) do {} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
Eina_Bool
|
Eina_Bool
|
||||||
evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
||||||
Evas_Filter_Program *pgm)
|
Evas_Filter_Program *pgm)
|
||||||
|
@ -2523,6 +3146,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
|
||||||
// Apply all commands
|
// Apply all commands
|
||||||
EINA_INLIST_FOREACH(pgm->instructions, instr)
|
EINA_INLIST_FOREACH(pgm->instructions, instr)
|
||||||
{
|
{
|
||||||
|
_instruction_dump(instr);
|
||||||
cmdid = _command_from_instruction(ctx, pgm, instr, dc);
|
cmdid = _command_from_instruction(ctx, pgm, instr, dc);
|
||||||
if (cmdid <= 0)
|
if (cmdid <= 0)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
Loading…
Reference in New Issue