Evas filters: Allow calling program_set and source_set in any order
authorJean-Philippe Andre <jp.andre@samsung.com>
Fri, 7 Feb 2014 05:23:29 +0000 (14:23 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Fri, 7 Feb 2014 08:59:18 +0000 (17:59 +0900)
If source_set was called after program_set, then parsing would fail.
It used to work because the program was re-parsed at source_set.
Now, save the code, mark the filter as changed, and reparse again
if the source changed (keep track of invalid programs to avoid
excessive parsing).

src/lib/evas/canvas/evas_object_text.c
src/lib/evas/filters/evas_filter_parser.c

index 9b58a69c94b3bce122471c5f2d5b6ed9172a0904..fd962bb422b2a2824c12f5612302c9019df145d6 100644 (file)
@@ -53,6 +53,7 @@ struct _Evas_Object_Text
          int                  sources_count;
          void                *output;
          Eina_Bool            changed : 1;
+         Eina_Bool            invalid : 1; // Code parse failed
       } filter;
    } cur, prev;
 
@@ -2129,7 +2130,7 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
     * remotely similar to its final form. You've been warned :)
     */
 
-   if (o->cur.filter.chain)
+   if (o->cur.filter.chain || (o->cur.filter.code && !o->cur.filter.invalid))
      {
         int X, Y, W, H;
         Evas_Filter_Context *filter;
@@ -2152,7 +2153,22 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
         X = obj->cur->geometry.x;
         Y = obj->cur->geometry.y;
 
-        if (previous)
+        if (!o->cur.filter.chain)
+          {
+             Evas_Filter_Program *pgm;
+             pgm = evas_filter_program_new("Evas_Text");
+             evas_filter_program_source_set_all(pgm, o->cur.filter.sources);
+             if (!evas_filter_program_parse(pgm, o->cur.filter.code))
+               {
+                  ERR("Filter program parsing failed");
+                  evas_filter_program_del(pgm);
+                  o->cur.filter.invalid = EINA_TRUE;
+                  goto normal_render;
+               }
+             o->cur.filter.chain = pgm;
+             o->cur.filter.invalid = EINA_FALSE;
+          }
+        else if (previous)
           {
              Eina_Bool redraw = o->cur.filter.changed;
 
@@ -2719,6 +2735,7 @@ _filter_program_set(Eo *eo_obj, void *_pd, va_list *list)
      }
    o->cur.filter.chain = pgm;
    o->cur.filter.changed = EINA_TRUE;
+   o->cur.filter.invalid = (pgm == NULL);
    eina_stringshare_replace(&o->cur.filter.code, arg);
 
    // Update object
@@ -2777,7 +2794,10 @@ _filter_source_set(Eo *eo_obj, void *_pd, va_list *list)
    const char *name = va_arg(list, const char *);
    Evas_Object *eo_source = va_arg(list, Evas_Object *);
    Evas_Filter_Proxy_Binding *pb, *pb_old = NULL;
-   Evas_Object_Protected_Data *source;
+   Evas_Object_Protected_Data *source = NULL;
+
+   obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
+   if (eo_source) source = eo_data_scope_get(eo_source, EVAS_OBJ_CLASS);
 
    if (!o->cur.filter.sources)
      {
@@ -2787,13 +2807,20 @@ _filter_source_set(Eo *eo_obj, void *_pd, va_list *list)
    else
      {
         pb_old = eina_hash_find(o->cur.filter.sources, name);
-        if (pb_old && (pb_old->eo_source == eo_source)) return;
-        eina_hash_del(o->cur.filter.sources, name, pb_old);
+        if (pb_old)
+          {
+             if (pb_old->eo_source == eo_source) goto update;
+             eina_hash_del(o->cur.filter.sources, name, pb_old);
+          }
      }
 
-   obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
-   source = eo_data_scope_get(eo_source, EVAS_OBJ_CLASS);
-   if (!source) return;
+   if (!source)
+     {
+        pb_old = eina_hash_find(o->cur.filter.sources, name);
+        if (!pb_old) return;
+        eina_hash_del_by_key(o->cur.filter.sources, name);
+        goto update;
+     }
 
    pb = calloc(1, sizeof(*pb));
    pb->eo_proxy = eo_obj;
@@ -2817,7 +2844,9 @@ _filter_source_set(Eo *eo_obj, void *_pd, va_list *list)
    evas_filter_program_source_set_all(pgm, o->cur.filter.sources);
 
    // Update object
+update:
    o->cur.filter.changed = EINA_TRUE;
+   o->cur.filter.invalid = EINA_FALSE;
    _evas_object_text_items_clear(o);
    o->changed = 1;
    _evas_object_text_recalc(eo_obj, o->cur.text);
index 1b41a9b41eae5377de27652d883b7ffcf2d786f4..e24dfbc3b45a5668665ba01eb3368b8d9c55ee2b 100644 (file)
@@ -635,6 +635,7 @@ static Buffer *
 _buffer_get(Evas_Filter_Program *pgm, const char *name)
 {
    Buffer *buf;
+   Eo *source;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, NULL);
    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
@@ -643,6 +644,22 @@ _buffer_get(Evas_Filter_Program *pgm, const char *name)
      if (!strcasecmp(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;
 }