jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=de47187dde8374a61ef4082048f6d87339b7ebf5

commit de47187dde8374a61ef4082048f6d87339b7ebf5
Author: Jean-Philippe Andre <[email protected]>
Date:   Wed Jan 4 16:50:09 2017 +0900

    evas: Fix tb filters spanning over multiple items
    
    If a gfx filter was applied to a block of text spanning over
    multiple text items, then it would improperly render as the
    filter context was stored in the format, rather than the text
    item. This is fixed by using a list of contexts in the format
    node rather than a single context.
---
 src/lib/evas/canvas/evas_filter_mixin.c     |  2 +-
 src/lib/evas/canvas/evas_object_textblock.c | 86 ++++++++++++++++++-----------
 src/lib/evas/filters/evas_filter.c          | 11 +++-
 src/lib/evas/filters/evas_filter_private.h  |  1 +
 src/lib/evas/include/evas_filter.h          |  7 ++-
 5 files changed, 69 insertions(+), 38 deletions(-)

diff --git a/src/lib/evas/canvas/evas_filter_mixin.c 
b/src/lib/evas/canvas/evas_filter_mixin.c
index f4f2265..6f43129 100644
--- a/src/lib/evas/canvas/evas_filter_mixin.c
+++ b/src/lib/evas/canvas/evas_filter_mixin.c
@@ -278,7 +278,7 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
              _evas_filter_state_set_internal(pd->data->chain, pd);
           }
 
-        filter = evas_filter_context_new(obj->layer->evas, do_async);
+        filter = evas_filter_context_new(obj->layer->evas, do_async, 0);
 
         // Run script
         ok = evas_filter_context_program_use(filter, pd->data->chain);
diff --git a/src/lib/evas/canvas/evas_object_textblock.c 
b/src/lib/evas/canvas/evas_object_textblock.c
index 5038649..f08bc98 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -430,7 +430,6 @@ struct _Evas_Object_Textblock_Item
    Evas_Coord                           yoff;  /**< y offset. */
    Eina_Bool                            merge : 1; /**< Indicates whether this 
item should merge to the previous item or not */
    Eina_Bool                            visually_deleted : 1; /**< Indicates 
whether this item is used in the visual layout or not. */
-   Eina_Bool                            has_gfx_filter : 1; /**< True if this 
item should be rendered with a gfx filter */
 };
 
 struct _Evas_Object_Textblock_Text_Item
@@ -439,6 +438,7 @@ struct _Evas_Object_Textblock_Text_Item
    Evas_Text_Props                  text_props;  /**< Props for this item. */
    Evas_Coord                       inset;  /**< Inset of text item. */
    Evas_Coord                       x_adjustment; /**< Used to indicate by how 
much we adjusted sizes */
+   int                              gfx_filter_id; /**< Index for the filter 
context in parent.format->gfx_filter */
 };
 
 struct _Evas_Object_Textblock_Format_Item
@@ -456,15 +456,15 @@ struct _Efl_Canvas_Text_Filter
 {
    // FIXME: sources not handled! --> global to the textblock
    // FIXME: data not handled! --> global to the textblock
-   // FIXME: filters need names! --> global to the textblock
    Eina_Stringshare     *name;
-   Evas_Filter_Context  *ctx;
+   Eina_Array           *contexts; /* contains Evas_Filter_Context items for 
each sub text item */
    Evas_Object          *eo_obj;
    Evas_Public_Data     *evas;
-   void                 *dc; /* draw context */
+   void                 *dc; /* draw context - no clip, white, no colmul... */
    struct {
       int                l, r, t, b;
    } pad;
+   int                   pending_ctx;
    Eina_Bool             invalid;
    Eina_Bool             async;
 };
@@ -472,7 +472,8 @@ struct _Efl_Canvas_Text_Filter
 struct _Efl_Canvas_Text_Filter_Post_Render
 {
    Efl_Canvas_Text_Filter *filter;
-   Eina_Bool success;
+   int                     ctx_id;
+   Eina_Bool               success;
 };
 
 struct _Efl_Canvas_Text_Filter_Program
@@ -504,7 +505,7 @@ struct _Evas_Object_Textblock_Format
    struct {
       int               l, r;
    } margin;  /**< Left and right margin width. */
-   Efl_Canvas_Text_Filter *gfx_filter; /**< Gfx Filter to apply to this node */
+   Efl_Canvas_Text_Filter *gfx_filter; /**< Gfx Filter to apply to the 
children text items */
    int                  ref;  /**< Value of the ref. */
    int                  tabstops;  /**< Value of the size of the tab 
character. */
    int                  linesize;  /**< Value of the size of the line of the 
text. */
@@ -12813,11 +12814,21 @@ evas_object_textblock_free(Evas_Object *eo_obj)
 }
 
 static void
-_filter_sync_end(Efl_Canvas_Text_Filter *filter, Eina_Bool success)
+_filter_sync_end(Efl_Canvas_Text_Filter *filter, int id, Eina_Bool success)
 {
-   evas_filter_context_destroy(filter->ctx);
+   Evas_Filter_Context *ctx;
+
+   EINA_SAFETY_ON_NULL_RETURN(filter->contexts);
+   ctx = eina_array_data_get(filter->contexts, id);
+   eina_array_data_set(filter->contexts, id, NULL);
+   evas_filter_context_destroy(ctx);
    filter->invalid = !success;
-   filter->ctx = NULL;
+
+   if ((--filter->pending_ctx) == 0)
+     {
+        eina_array_free(filter->contexts);
+        filter->contexts = NULL;
+     }
 }
 
 static void
@@ -12825,7 +12836,7 @@ _filter_post_render_cb(void *data)
 {
    Efl_Canvas_Text_Filter_Post_Render *post_data = data;
 
-   _filter_sync_end(post_data->filter, post_data->success);
+   _filter_sync_end(post_data->filter, post_data->ctx_id, post_data->success);
    free(post_data);
 }
 
@@ -12834,18 +12845,20 @@ _filter_cb(Evas_Filter_Context *ctx, void *data, 
Eina_Bool success)
 {
    Efl_Canvas_Text_Filter_Post_Render *post_data;
    Efl_Canvas_Text_Filter *filter = data;
+   int ctx_id;
 
-   EINA_SAFETY_ON_FALSE_RETURN(filter->ctx == ctx);
+   ctx_id = evas_filter_context_id_get(ctx);
 
    if (!filter->async)
      {
-        _filter_sync_end(filter, success);
+        _filter_sync_end(filter, ctx_id, success);
         return;
      }
 
    post_data = calloc(1, sizeof(*post_data));
    post_data->success = success;
    post_data->filter = filter;
+   post_data->ctx_id = ctx_id;
    evas_post_render_job_add(filter->evas, _filter_post_render_cb, post_data);
 }
 
@@ -13002,10 +13015,11 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
         cr = nr; cg = ng; cb = nb; ca = na;                             \
      }
 
-#define DRAW_TEXT_FILTER(gfx_f, ox, oy) do {                            \
-   evas_filter_input_render(eo_obj, gfx_f->ctx, gfx_f->dc, ti,          \
-                            gfx_f->pad.l, gfx_f->pad.r,                 \
-                            gfx_f->pad.t, gfx_f->pad.b, do_async);      \
+#define DRAW_TEXT_FILTER(gf, gf_id, ox, oy) do {                        \
+   Evas_Filter_Context *ctx = eina_array_data_get(gf->contexts, gf_id); \
+   evas_filter_input_render(eo_obj, ctx, gf->dc, ti,                    \
+                            gf->pad.l, gf->pad.r,                       \
+                            gf->pad.t, gf->pad.b, do_async);            \
    } while (0)
 
 #define DRAW_TEXT_NOFILTER(ox, oy) do {                                 \
@@ -13024,10 +13038,10 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
 #define DRAW_TEXT(ox, oy) do {                                          \
    if (ti->parent.format->font.font)                                    \
      {                                                                  \
-        if (EINA_LIKELY(!itr->has_gfx_filter))                          \
+        if (EINA_LIKELY(!ti->gfx_filter_id))                            \
           DRAW_TEXT_NOFILTER(ox, oy);                                   \
         else                                                            \
-          DRAW_TEXT_FILTER(ti->parent.format->gfx_filter, ox, oy);      \
+          DRAW_TEXT_FILTER(ti->parent.format->gfx_filter, ti->gfx_filter_id - 
1, ox, oy); \
      } } while(0)
 
    /* backing */
@@ -13172,12 +13186,13 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
         Efl_Canvas_Text_Filter *filter;
         Evas_Filter_Program *pgm;
         Evas_Filter_Context *ctx;
+        int filter_id;
         Eina_Bool ok;
 
         filter = ti->parent.format->gfx_filter;
         if (!filter->name || filter->invalid)
           {
-             itr->has_gfx_filter = EINA_FALSE;
+             ti->gfx_filter_id = 0;
              continue;
           }
 
@@ -13185,7 +13200,7 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
         if (!program)
           {
              WRN("Filter '%s' not found on this object", filter->name);
-             itr->has_gfx_filter = EINA_FALSE;
+             ti->gfx_filter_id = 0;
              continue;
           }
 
@@ -13199,18 +13214,22 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
                {
                   evas_filter_program_del(pgm);
                   filter->invalid = EINA_TRUE;
-                  itr->has_gfx_filter = EINA_FALSE;
+                  ti->gfx_filter_id = 0;
                   continue;
                }
              program->pgm = pgm;
           }
 
 #ifdef DEBUG
-        if (filter->ctx) WRN("Previous filter context was not deleted");
+        if (filter->contexts) WRN("Previous filter context was not deleted");
 #endif
 
+        if (!filter->contexts)
+          filter->contexts = eina_array_new(8);
+        filter_id = eina_array_count(filter->contexts);
+
         // TODO: sources set
-        ctx = evas_filter_context_new(obj->layer->evas, do_async);
+        ctx = evas_filter_context_new(obj->layer->evas, do_async, filter_id);
         evas_filter_state_prepare(eo_obj, &state, ti);
         evas_filter_program_state_set(pgm, &state);
         ok = evas_filter_context_program_use(ctx, pgm);
@@ -13218,10 +13237,12 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
           {
              evas_filter_context_destroy(ctx);
              filter->invalid = EINA_TRUE;
-             itr->has_gfx_filter = EINA_FALSE;
+             ti->gfx_filter_id = 0;
              continue;
           }
-        filter->ctx = ctx;
+
+        eina_array_push(filter->contexts, ctx);
+        ti->gfx_filter_id = filter_id + 1;
 
         ln = ti->parent.ln;
         ENFN->context_color_set(ENDT, context, 255, 255, 255, 255);
@@ -13243,8 +13264,7 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
         filter->eo_obj = eo_obj;
         filter->evas = obj->layer->evas;
         filter->async = do_async;
-
-        itr->has_gfx_filter = EINA_TRUE;
+        filter->pending_ctx++;
 
         ENFN->context_multiplier_unset(ENDT, context);
      }
@@ -13262,7 +13282,7 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
         yoff = itr->yoff;
         ln = itr->ln;
 
-        if (EINA_UNLIKELY(itr->has_gfx_filter))
+        if (EINA_UNLIKELY(ti->gfx_filter_id))
           context = ti->parent.format->gfx_filter->dc;
 
         shad_dst = shad_sz = dx = dy = haveshad = 0;
@@ -13377,7 +13397,7 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
         yoff = itr->yoff;
         ln = itr->ln;
 
-        if (EINA_UNLIKELY(itr->has_gfx_filter))
+        if (EINA_UNLIKELY(ti->gfx_filter_id))
           context = ti->parent.format->gfx_filter->dc;
 
         if ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == 
EVAS_TEXT_STYLE_GLOW)
@@ -13415,7 +13435,7 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
         yoff = itr->yoff;
         ln = itr->ln;
 
-        if (EINA_UNLIKELY(itr->has_gfx_filter))
+        if (EINA_UNLIKELY(ti->gfx_filter_id))
           context = ti->parent.format->gfx_filter->dc;
 
         if (((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == 
EVAS_TEXT_STYLE_OUTLINE) ||
@@ -13500,7 +13520,7 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
           {
              void *fi = _ITEM_TEXT(itr)->text_props.font_instance;
 
-             if (EINA_UNLIKELY(itr->has_gfx_filter))
+             if (EINA_UNLIKELY(ti->gfx_filter_id))
                context = ti->parent.format->gfx_filter->dc;
 
              COLOR_SET(normal);
@@ -13510,10 +13530,10 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
 
              context = context_save;
 
-             if (EINA_UNLIKELY(itr->has_gfx_filter))
+             if (EINA_UNLIKELY(ti->gfx_filter_id))
                {
                   Efl_Canvas_Text_Filter *filter = 
ti->parent.format->gfx_filter;
-                  Evas_Filter_Context *ctx = filter->ctx;
+                  Evas_Filter_Context *ctx = 
eina_array_data_get(filter->contexts, ti->gfx_filter_id - 1);
 
                   evas_filter_context_post_run_callback_set(ctx, _filter_cb, 
filter);
                   evas_filter_run(ctx);
diff --git a/src/lib/evas/filters/evas_filter.c 
b/src/lib/evas/filters/evas_filter.c
index e4008d5..2b6fbae 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -49,7 +49,7 @@ _evas_image_get(Ector_Buffer *buf)
 /* Main functions */
 
 Evas_Filter_Context *
-evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async)
+evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, int id)
 {
    Evas_Filter_Context *ctx;
 
@@ -60,10 +60,19 @@ evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool 
async)
 
    ctx->evas = evas;
    ctx->async = async;
+   ctx->context_id = id;
 
    return ctx;
 }
 
+int
+evas_filter_context_id_get(Evas_Filter_Context *ctx)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
+
+   return ctx->context_id;
+}
+
 /* Private function to reset the filter context. Used from parser.c */
 void
 evas_filter_context_clear(Evas_Filter_Context *ctx)
diff --git a/src/lib/evas/filters/evas_filter_private.h 
b/src/lib/evas/filters/evas_filter_private.h
index 5ebc981..4c54c96 100644
--- a/src/lib/evas/filters/evas_filter_private.h
+++ b/src/lib/evas/filters/evas_filter_private.h
@@ -116,6 +116,7 @@ struct _Evas_Filter_Context
    Eina_List *buffers; // Evas_Filter_Buffer *
    int last_buffer_id;
    int last_command_id;
+   int context_id; // used by textblock
 
    // Variables changing at each run
    int w, h; // Dimensions of the input/output buffers
diff --git a/src/lib/evas/include/evas_filter.h 
b/src/lib/evas/include/evas_filter.h
index 60d946f..75a80a9 100644
--- a/src/lib/evas/include/evas_filter.h
+++ b/src/lib/evas/include/evas_filter.h
@@ -132,15 +132,16 @@ EAPI Evas_Filter_Program *evas_filter_program_new(const 
char *name, Eina_Bool in
 EAPI Eina_Bool           evas_filter_program_state_set(Evas_Filter_Program 
*pgm, const Efl_Canvas_Filter_State *state);
 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);
 EAPI Eina_Bool           evas_filter_program_padding_get(Evas_Filter_Program 
*pgm, int *l, int *r, int *t, int *b);
 EAPI void                
evas_filter_program_source_set_all(Evas_Filter_Program *pgm, Eina_Hash 
*sources);
-void                     
evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, 
Eina_Bool do_async);
 void                     evas_filter_program_data_set_all(Evas_Filter_Program 
*pgm, Eina_Inlist *data);
 
 /* Filter context (low level) */
-Evas_Filter_Context     *evas_filter_context_new(Evas_Public_Data *evas, 
Eina_Bool async);
+Evas_Filter_Context     *evas_filter_context_new(Evas_Public_Data *evas, 
Eina_Bool async, int id);
+int                      evas_filter_context_id_get(Evas_Filter_Context *ctx);
 void                     evas_filter_context_destroy(Evas_Filter_Context *ctx);
+Eina_Bool                evas_filter_context_program_use(Evas_Filter_Context 
*ctx, Evas_Filter_Program *pgm);
+void                     
evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, 
Eina_Bool do_async);
 void                     
evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, 
Evas_Filter_Cb cb, void *data);
 #define                  evas_filter_context_autodestroy(ctx) 
evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) 
evas_filter_context_destroy), ctx)
 Eina_Bool                
evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx);

-- 


Reply via email to