static void st_collections_group_parts_part_description_text_text_source(void);
static void st_collections_group_parts_part_description_text_ellipsis(void);
static void st_collections_group_parts_part_description_text_filter(void);
+static void st_collections_group_parts_part_description_text_filter_source(void);
static void st_collections_group_parts_part_description_box_layout(void);
static void st_collections_group_parts_part_description_box_align(void);
static void st_collections_group_parts_part_description_box_padding(void);
{"collections.group.parts.part.description.text.elipsis", st_collections_group_parts_part_description_text_ellipsis},
{"collections.group.parts.part.description.text.ellipsis", st_collections_group_parts_part_description_text_ellipsis},
{"collections.group.parts.part.description.text.filter", st_collections_group_parts_part_description_text_filter},
+ {"collections.group.parts.part.description.text.filter.code", st_collections_group_parts_part_description_text_filter}, /* dup */
+ {"collections.group.parts.part.description.text.filter.source", st_collections_group_parts_part_description_text_filter_source},
{"collections.group.parts.part.description.box.layout", st_collections_group_parts_part_description_box_layout},
{"collections.group.parts.part.description.box.align", st_collections_group_parts_part_description_box_align},
{"collections.group.parts.part.description.box.padding", st_collections_group_parts_part_description_box_padding},
ted->text.domain = STRDUP(ted->text.domain);
ted->text.text_class = STRDUP(ted->text.text_class);
ted->text.font.str = STRDUP(ted->text.font.str);
- ted->text.filter.code = STRDUP(ted->text.filter.code);
- {
- Eina_List *l;
- Eina_Stringshare *name;
- static int part_key = 0;
- EINA_LIST_FOREACH(ted->text.filter.sources, l, name)
- data_queue_part_lookup(pc, name, &part_key);
- }
+ /* Filters stuff */
+ ted->text.filter.code = STRDUP(ted->text.filter.code);
+ if (ted->text.filter.code)
+ {
+ Eina_List *list, *l;
+ const char *name;
+ list = ted->text.filter.sources;
+ ted->text.filter.sources = NULL;
+ EINA_LIST_FOREACH(list, l, name)
+ ted->text.filter.sources = eina_list_append(ted->text.filter.sources, STRDUP(name));
+ }
data_queue_copied_part_nest_lookup(pc, &(tparent->text.id_source), &(ted->text.id_source), &ted->text.id_source_part);
data_queue_copied_part_nest_lookup(pc, &(tparent->text.id_text_source), &(ted->text.id_text_source), &ted->text.id_text_source_part);
/**
@page edcref
+ @context
+ part {
+ type: TEXT; // or IMAGE
+ description {
+ ..
+ text {
+ ..
+ filter {
+ code: "blend {} -- ..."
+ source: "part1" "buf";
+ source: "part2" "otherbuf";
+ source: "part3";
+ }
+ // or as short form:
+ filter: "blend {} -- ..."
+ }
+ ..
+ }
+ }
@property
- filter
+ filter.code
@parameters
[filter program as a string]
@effect
- Applies a series of filtering operations to the text.
- EXPERIMENTAL FEATURE. TO BE DOCUMENTED.
+ Applies a series of image filters to a TEXT or IMAGE part. The argument
+ to this field is the source code of a Lua program invoking various
+ filter operations. For more information, please refer to the page
+ "Evas filters reference".
+ @see evasfiltersref
@endproperty
*/
static void
st_collections_group_parts_part_description_text_filter(void)
{
Edje_Part_Description_Text *ed;
- Eina_List *sources = NULL;
- Eina_Stringshare *name;
- char *token, *code;
- Eina_Bool valid = EINA_TRUE;
- Edje_Part_Collection *pc;
- static int part_key = 0;
+ check_arg_count(1);
+
+ if (current_part->type != EDJE_PART_TYPE_TEXT)
+ {
+ ERR("parse error %s:%i. text attributes in non-TEXT part.",
+ file_in, line - 1);
+ exit(-1);
+ }
+
+ ed = (Edje_Part_Description_Text*) current_desc;
+
+ free((void*) ed->text.filter.code);
+ ed->text.filter.code = parse_str(0);
+}
+
+/**
+ @page edcref
+
+ @property
+ filter.source
+ @parameters
+ [another part's name] [(optional) buffer name for filter program]
+ @effect
+ Binds another part as an image source (like a proxy source) for a
+ text or image filter operation. Optionally, a buffer name may be
+ specified, so the same filter code can be used with different sources.
+ For more information, please refer to the page "Evas filters reference".
+ @see evasfiltersref
+ @endproperty
+*/
+static void
+st_collections_group_parts_part_description_text_filter_source(void)
+{
+ Edje_Part_Description_Text *ed;
+ Edje_Part_Collection *pc;
+ char *name = NULL, *part, *str;
+ size_t sn = 0, sp;
+ int *part_key;
static const char *allowed_name_chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHJIKLMNOPQRSTUVWXYZ0123456789_";
- check_arg_count(1);
+ /* 1 or 2 args only */
+ check_min_arg_count(1);
+ if (get_arg_count() > 1)
+ check_arg_count(2);
if (current_part->type != EDJE_PART_TYPE_TEXT)
{
ed = (Edje_Part_Description_Text*) current_desc;
pc = eina_list_data_get(eina_list_last(edje_collections));
- if (ed->text.filter.code)
+
+ part = parse_str(0);
+ sp = strlen(part);
+
+ if (get_arg_count() > 1)
{
- EINA_LIST_FREE(ed->text.filter.sources, name)
+ name = parse_str(1);
+ if (name) sn = strlen(name);
+ if (!name || (strspn(name, allowed_name_chars) != sn))
{
- part_lookup_delete(pc, name, &part_key, NULL);
- eina_stringshare_del(name);
+ ERR("parse error %s:%i. invalid name for a filter buffer: %s",
+ file_in, line - 1, name);
+ exit(-1);
}
- free((void*)ed->text.filter.code);
}
- ed->text.filter.sources = NULL;
-
- ed->text.filter.code = parse_str(0);
- if (!ed->text.filter.code) return;
- // Parse list of buffers that have a source
- // note: does not support comments
- code = strdup(ed->text.filter.code);
- for (token = strtok(code, ";"); token; token = strtok(NULL, ";"))
+ if (!name && (strspn(part, allowed_name_chars) == sp))
+ str = strdup(part);
+ else
{
- size_t len;
-
- len = strspn(token, " \n\t");
- token += len;
-
- if (!strncasecmp("buffer", token, 6))
+ if (!name)
{
- // note: a valid string won't necessary compile at runtime
-
- token = strchr(token, ':');
- if (!token)
- {
- valid = EINA_FALSE;
- break;
- }
- token = strchr(token, '(');
- if (!token)
- {
- valid = EINA_FALSE;
- break;
- }
- token = strcasestr(token, "src");
- if (!token) continue;
- token += 3;
- len = strspn(token, " =\n\t");
- if (!len || !token[len])
+ // name = part so we replace all invalid chars by '_'
+ size_t k;
+ name = strdup(part);
+ sn = strlen(name);
+ for (k = 0; k < sn; k++)
{
- valid = EINA_FALSE;
- break;
- }
- token += len;
- len = strspn(token, allowed_name_chars);
- if (!len || !token[len])
- {
- valid = EINA_FALSE;
- break;
+ if (!index(allowed_name_chars, name[k]))
+ name[k] = '_';
}
- token[len] = '\0';
- name = eina_stringshare_add(token);
-
- sources = eina_list_append(sources, name);
- data_queue_part_lookup(pc, name, &part_key);
}
- }
- free(code);
-
- if (valid) ed->text.filter.sources = sources;
+ sn += sp + 1;
+ str = malloc(sn + 1);
+ if (!str) exit(-1);
+ strncpy(str, name, sn);
+ strncat(str, ":", sn);
+ strncat(str, part, sn);
+ str[sn] = '\0';
+ }
+ ed->text.filter.sources = eina_list_append(ed->text.filter.sources, str);
+
+ // note: this is leaked. not a big deal.
+ part_key = malloc(sizeof(int));
+ *part_key = -1;
+ data_queue_part_lookup(pc, part, part_key);
+
+ free(part);
+ free(name);
}
char *font2 = NULL;
char *sfont = NULL;
int size;
- const char *filter, *source_name;
- Eina_List *filter_sources = NULL, *prev_sources = NULL, *li;
+ const char *filter;
+ Eina_List *filter_sources = NULL, *prev_sources = NULL;
Evas_Coord tw, th;
Evas_Coord sw, sh;
int inlined_font = 0, free_text = 0;
/* filters */
if (filter)
{
- eo_do(ep->object,
- EINA_LIST_FOREACH(prev_sources, li, source_name)
- evas_obj_text_filter_source_set(source_name, NULL);
+ const char *src1, *src2, *part;
+ Eina_List *li1, *li2;
- EINA_LIST_FOREACH(filter_sources, li, source_name)
+ eo_do(ep->object,
+ evas_obj_text_filter_program_set(filter);
+ /* update sources. really not optimal. lots of strxxx and loops */
+ if (prev_sources != filter_sources)
{
- Edje_Real_Part *rp = _edje_real_part_get(ed, source_name);
- evas_obj_text_filter_source_set(source_name, rp ? rp->object : NULL);
- };
+ /* remove sources that are not there anymore
+ * this O(n^2) loop assumes a very small number of sources */
+ EINA_LIST_FOREACH(prev_sources, li1, src1)
+ {
+ Eina_Bool found = 0;
+ EINA_LIST_FOREACH(filter_sources, li2, src2)
+ {
+ if (!strcmp(src1, src2))
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ {
+ part = strchr(src1, ':');
+ if (!part)
+ evas_obj_text_filter_source_set(src1, NULL);
+ else
+ {
+ char *name = strdup(src1);
+ name[part - src1] = 0;
+ evas_obj_text_filter_source_set(name, NULL);
+ free(name);
+ }
+ }
+ }
+ /* add all sources by part name */
+ EINA_LIST_FOREACH(filter_sources, li1, src1)
+ {
+ Edje_Real_Part *rp;
+ char *name = NULL;
+ if ((part = strchr(src1, ':')) != NULL)
+ {
+ name = strdup(src1);
+ name[part - src1] = 0;
+ part++;
+ }
+ else
+ part = src1;
+ rp = _edje_real_part_get(ed, part);
+ evas_obj_text_filter_source_set(name ? name : part, rp ? rp->object : NULL);
+ free(name);
+ }
+ }
+ /* pass edje state for transitions */
if (ep->param2)
{
evas_obj_text_filter_state_set(chosen_desc->common.state.name, chosen_desc->common.state.value,
evas_obj_text_filter_state_set(chosen_desc->common.state.name, chosen_desc->common.state.value,
NULL, 0.0, state_val);
}
- evas_obj_text_filter_program_set(filter));
+ );
}
else
eo_do(ep->object, evas_obj_text_filter_program_set(NULL));
if (!source && !o->cur.filter->sources)
return;
+ if (o->cur.filter->sources)
+ {
+ pb_old = eina_hash_find(o->cur.filter->sources, name);
+ if (pb_old && (pb_old->eo_source == eo_source)) return;
+ }
+
fcow = eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&o->cur.filter);
if (!fcow->sources)
fcow->sources = eina_hash_string_small_new
(EINA_FREE_CB(_filter_source_hash_free_cb));
}
- else
- {
- pb_old = eina_hash_find(fcow->sources, name);
- if (pb_old)
- {
- if (pb_old->eo_source == eo_source) goto update;
- eina_hash_del(fcow->sources, name, pb_old);
- }
- }
+ else if (pb_old)
+ eina_hash_del(fcow->sources, name, pb_old);
if (!source)
{
pb->eo_source = eo_source;
pb->name = eina_stringshare_add(name);
- EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy,
- Evas_Object_Proxy_Data, source_write)
- if (!eina_list_data_find(source_write->proxies, eo_obj))
- source_write->proxies = eina_list_append(source_write->proxies, eo_obj);
- EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
+ if (!eina_list_data_find(source->proxy->proxies, eo_obj))
+ {
+ EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy, Evas_Object_Proxy_Data, source_write)
+ source_write->proxies = eina_list_append(source_write->proxies, eo_obj);
+ EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
+ }
- EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy,
- Evas_Object_Proxy_Data, proxy_write)
- proxy_write->is_proxy = EINA_TRUE;
- EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write)
+ if (!obj->proxy->is_proxy)
+ {
+ EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
+ proxy_write->is_proxy = EINA_TRUE;
+ EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write)
+ }
eina_hash_add(fcow->sources, pb->name, pb);
evas_filter_program_source_set_all(fcow->chain, fcow->sources);