summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2016-12-22 19:43:45 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-01-17 14:35:28 +0900
commitcb294320dc68c54ac0562362fd6bc97e291ec5ba (patch)
tree88e1bd34357504a198d178f30ab5147b599ac936 /src
parent301e80a10a7246c6aa4112088c91b91d1e45553f (diff)
evas: Experimental textblock support for gfx filters
This is only for testing purposes for now. Eventually we need to fix the following things: - terrible performance (cache buffers) - force redraws based on filter padding - expand textblock padding based on max filter padding - add sources, data and a filter name/code hash - test! :)
Diffstat (limited to 'src')
-rw-r--r--src/bin/elementary/test_gfx_filters.c33
-rw-r--r--src/lib/evas/canvas/efl_canvas_text.eo6
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c345
3 files changed, 351 insertions, 33 deletions
diff --git a/src/bin/elementary/test_gfx_filters.c b/src/bin/elementary/test_gfx_filters.c
index 04ac8e1785..3612e69e47 100644
--- a/src/bin/elementary/test_gfx_filters.c
+++ b/src/bin/elementary/test_gfx_filters.c
@@ -199,6 +199,15 @@ _text_resize(void *data EINA_UNUSED, const Efl_Event *ev)
199 efl_gfx_size_hint_min_set(ev->object, w, h); 199 efl_gfx_size_hint_min_set(ev->object, w, h);
200} 200}
201 201
202static void
203_textblock_resize(void *data EINA_UNUSED, const Efl_Event *ev)
204{
205 int w = 0, h = 0;
206
207 evas_object_textblock_size_native_get(ev->object, &w, &h);
208 efl_gfx_size_hint_min_set(ev->object, w + 1, h + 1);
209}
210
202static Evas_Object * 211static Evas_Object *
203_img_tooltip(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, Evas_Object *tt) 212_img_tooltip(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, Evas_Object *tt)
204{ 213{
@@ -245,7 +254,7 @@ _font_size_change(void *data, const Efl_Event *ev)
245void 254void
246test_gfx_filters(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) 255test_gfx_filters(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
247{ 256{
248 Eo *win, *box, *box2, *o, *text, *spinner, *code, *split; 257 Eo *win, *box, *box2, *o, *text = NULL, *spinner, *code, *split;
249 258
250 win = efl_add(EFL_UI_WIN_STANDARD_CLASS, NULL, 259 win = efl_add(EFL_UI_WIN_STANDARD_CLASS, NULL,
251 efl_text_set(efl_added, "Gfx Filter Editor"), 260 efl_text_set(efl_added, "Gfx Filter Editor"),
@@ -342,6 +351,7 @@ test_gfx_filters(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *eve
342 efl_content_set(efl_part(split, "top"), box2); 351 efl_content_set(efl_part(split, "top"), box2);
343 352
344 /* FIXME: No textblock support! TEXT is not part of EO public API. */ 353 /* FIXME: No textblock support! TEXT is not part of EO public API. */
354 /*
345 o = text = evas_object_text_add(evas_object_evas_get(win)); 355 o = text = evas_object_text_add(evas_object_evas_get(win));
346 efl_event_callback_add(o, EFL_GFX_EVENT_RESIZE, _text_resize, NULL); 356 efl_event_callback_add(o, EFL_GFX_EVENT_RESIZE, _text_resize, NULL);
347 efl_text_properties_font_set(o, "Sans:style=Bold", default_font_size); 357 efl_text_properties_font_set(o, "Sans:style=Bold", default_font_size);
@@ -349,6 +359,27 @@ test_gfx_filters(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *eve
349 efl_text_set(o, "EFL"); 359 efl_text_set(o, "EFL");
350 efl_gfx_visible_set(o, 1); 360 efl_gfx_visible_set(o, 1);
351 efl_pack(box2, o); 361 efl_pack(box2, o);
362 // */
363
364 const char *tbtxt =
365 "Hey dude, "
366 "<gfx_filter='fill{color=\"#0033\"} padding_set{20} blur{3} blend{}'>hello</>"
367 " world!<br>"
368 "<gfx_filter='blur{15,color=\"red\"}blend{}'>Wanna dance?</><br>"
369 "What's going on here???";
370
371 /* EXPERIMENTAL TEXTBLOCK FILTER */
372 o = evas_object_textblock_add(evas_object_evas_get(win));
373 efl_event_callback_add(o, EFL_GFX_EVENT_RESIZE, _textblock_resize, NULL);
374 Evas_Textblock_Style *st = evas_textblock_style_new();
375 evas_textblock_style_set(st, "DEFAULT='font=Sans font_size=24 color=#FFF wrap=word'");
376 evas_object_textblock_style_set(o, st);
377 evas_object_textblock_text_markup_set(o, tbtxt);
378 efl_canvas_object_scale_set(o, elm_config_scale_get());
379 efl_pack(box2, o);
380 evas_object_resize(o, 1, 1);
381 efl_gfx_visible_set(o, 1);
382 // */
352 } 383 }
353 384
354 { 385 {
diff --git a/src/lib/evas/canvas/efl_canvas_text.eo b/src/lib/evas/canvas/efl_canvas_text.eo
index 1e9fd76300..df926bd575 100644
--- a/src/lib/evas/canvas/efl_canvas_text.eo
+++ b/src/lib/evas/canvas/efl_canvas_text.eo
@@ -1,6 +1,6 @@
1struct Efl.Canvas.Text.Style; [[EFL text style data structure]] 1struct Efl.Canvas.Text.Style; [[EFL text style data structure]]
2 2
3class Efl.Canvas.Text (Efl.Canvas.Object, Efl.Text) 3class Efl.Canvas.Text (Efl.Canvas.Object, Efl.Text, Efl.Canvas.Filter.Internal)
4{ 4{
5 [[Efl canvas text class]] 5 [[Efl canvas text class]]
6 legacy_prefix: evas_object_textblock; 6 legacy_prefix: evas_object_textblock;
@@ -367,6 +367,10 @@ class Efl.Canvas.Text (Efl.Canvas.Object, Efl.Text)
367 Efl.Object.dbg_info_get; 367 Efl.Object.dbg_info_get;
368 Efl.Canvas.Object.paragraph_direction { get; set; } 368 Efl.Canvas.Object.paragraph_direction { get; set; }
369 Efl.Text.text { get; set; } 369 Efl.Text.text { get; set; }
370 Efl.Gfx.Filter.filter_program { get; set; }
371 Efl.Canvas.Filter.Internal.filter_dirty;
372 Efl.Canvas.Filter.Internal.filter_input_render;
373 Efl.Canvas.Filter.Internal.filter_state_prepare;
370 } 374 }
371 events { 375 events {
372 changed; [[Called when the content (text or annotations) changed.]] 376 changed; [[Called when the content (text or annotations) changed.]]
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index 00b796cac0..0d8ce5dc86 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -63,6 +63,7 @@
63 */ 63 */
64 64
65#define EFL_CANVAS_OBJECT_BETA 65#define EFL_CANVAS_OBJECT_BETA
66#define EFL_CANVAS_FILTER_INTERNAL_PROTECTED
66 67
67#include "evas_common_private.h" 68#include "evas_common_private.h"
68#include "evas_private.h" 69#include "evas_private.h"
@@ -77,6 +78,9 @@
77#include "linebreak.h" 78#include "linebreak.h"
78#include "wordbreak.h" 79#include "wordbreak.h"
79 80
81#include "evas_filter.h"
82#include "efl_canvas_filter_internal.eo.h"
83
80/* save typing */ 84/* save typing */
81#define ENFN obj->layer->evas->engine.func 85#define ENFN obj->layer->evas->engine.func
82#define ENDT obj->layer->evas->engine.data.output 86#define ENDT obj->layer->evas->engine.data.output
@@ -217,6 +221,18 @@ typedef struct _Evas_Textblock_Selection_Iterator Evas_Textblock_Selection_Itera
217typedef struct _Efl_Canvas_Text_Annotation_Iterator Efl_Canvas_Text_Annotation_Iterator; 221typedef struct _Efl_Canvas_Text_Annotation_Iterator Efl_Canvas_Text_Annotation_Iterator;
218/** 222/**
219 * @internal 223 * @internal
224 * @typedef Evas_Object_Textblock_Filter
225 * A structure holding gfx filter information for a text item
226 */
227typedef struct _Evas_Object_Textblock_Filter Evas_Object_Textblock_Filter;
228/**
229 * @internal
230 * @typedef Evas_Object_Textblock_Filter_Post_Render
231 * Post-render data for async rendering of gfx filters
232 */
233typedef struct _Evas_Object_Textblock_Filter_Post_Render Evas_Object_Textblock_Filter_Post_Render;
234/**
235 * @internal
220 * @def IS_AT_END(ti, ind) 236 * @def IS_AT_END(ti, ind)
221 * Return true if ind is at the end of the text item, false otherwise. 237 * Return true if ind is at the end of the text item, false otherwise.
222 */ 238 */
@@ -408,6 +424,7 @@ struct _Evas_Object_Textblock_Item
408 Evas_Coord yoff; /**< y offset. */ 424 Evas_Coord yoff; /**< y offset. */
409 Eina_Bool merge : 1; /**< Indicates whether this item should merge to the previous item or not */ 425 Eina_Bool merge : 1; /**< Indicates whether this item should merge to the previous item or not */
410 Eina_Bool visually_deleted : 1; /**< Indicates whether this item is used in the visual layout or not. */ 426 Eina_Bool visually_deleted : 1; /**< Indicates whether this item is used in the visual layout or not. */
427 Eina_Bool has_gfx_filter : 1; /**< True if this item should be rendered with a gfx filter */
411}; 428};
412 429
413struct _Evas_Object_Textblock_Text_Item 430struct _Evas_Object_Textblock_Text_Item
@@ -429,6 +446,30 @@ struct _Evas_Object_Textblock_Format_Item
429 Eina_Bool formatme : 1; /**< EINA_TRUE if format required, else EINA_FALSE */ 446 Eina_Bool formatme : 1; /**< EINA_TRUE if format required, else EINA_FALSE */
430}; 447};
431 448
449struct _Evas_Object_Textblock_Filter
450{
451 // FIXME: sources not handled! --> global to the textblock
452 // FIXME: data not handled! --> global to the textblock
453 // FIXME: filters need names! --> global to the textblock
454 Eina_Stringshare *code; // only name! and reference to textblock's list of filters
455 Evas_Filter_Program *pgm;
456 Evas_Filter_Context *ctx;
457 Evas_Object *eo_obj;
458 Evas_Public_Data *evas;
459 void *dc; /* draw context */
460 struct {
461 int l, r, t, b;
462 } pad;
463 Eina_Bool invalid;
464 Eina_Bool async;
465};
466
467struct _Evas_Object_Textblock_Filter_Post_Render
468{
469 Evas_Object_Textblock_Filter *filter;
470 Eina_Bool success;
471};
472
432struct _Evas_Object_Textblock_Format 473struct _Evas_Object_Textblock_Format
433{ 474{
434 Evas_Object_Textblock_Node_Format *fnode; /**< Pointer to textblock format node. */ 475 Evas_Object_Textblock_Node_Format *fnode; /**< Pointer to textblock format node. */
@@ -449,6 +490,7 @@ struct _Evas_Object_Textblock_Format
449 struct { 490 struct {
450 int l, r; 491 int l, r;
451 } margin; /**< Left and right margin width. */ 492 } margin; /**< Left and right margin width. */
493 Evas_Object_Textblock_Filter *gfx_filter; /**< Gfx Filter to apply to this node */
452 int ref; /**< Value of the ref. */ 494 int ref; /**< Value of the ref. */
453 int tabstops; /**< Value of the size of the tab character. */ 495 int tabstops; /**< Value of the size of the tab character. */
454 int linesize; /**< Value of the size of the line of the text. */ 496 int linesize; /**< Value of the size of the line of the text. */
@@ -878,6 +920,13 @@ _format_unref_free(const Evas_Object *eo_obj, Evas_Object_Textblock_Format *fmt)
878 if (fmt->ref > 0) return; 920 if (fmt->ref > 0) return;
879 if (fmt->font.fdesc) evas_font_desc_unref(fmt->font.fdesc); 921 if (fmt->font.fdesc) evas_font_desc_unref(fmt->font.fdesc);
880 if (fmt->font.source) eina_stringshare_del(fmt->font.source); 922 if (fmt->font.source) eina_stringshare_del(fmt->font.source);
923 if (fmt->gfx_filter)
924 {
925 eina_stringshare_del(fmt->gfx_filter->code);
926 if (fmt->gfx_filter->dc)
927 ENFN->context_free(ENDT, fmt->gfx_filter->dc);
928 free(fmt->gfx_filter);
929 }
881 if ((obj->layer) && (obj->layer->evas)) 930 if ((obj->layer) && (obj->layer->evas))
882 evas_font_free(obj->layer->evas->evas, fmt->font.font); 931 evas_font_free(obj->layer->evas->evas, fmt->font.font);
883 free(fmt); 932 free(fmt);
@@ -1202,6 +1251,7 @@ static const char *replacement_charstr = NULL;
1202static const char *underline_dash_widthstr = NULL; 1251static const char *underline_dash_widthstr = NULL;
1203static const char *underline_dash_gapstr = NULL; 1252static const char *underline_dash_gapstr = NULL;
1204static const char *underline_heightstr = NULL; 1253static const char *underline_heightstr = NULL;
1254static const char *gfx_filter = NULL;
1205 1255
1206/** 1256/**
1207 * @page evas_textblock_style_page Evas Textblock Style Options 1257 * @page evas_textblock_style_page Evas Textblock Style Options
@@ -1307,6 +1357,7 @@ _format_command_init(void)
1307 underline_dash_widthstr = eina_stringshare_add("underline_dash_width"); 1357 underline_dash_widthstr = eina_stringshare_add("underline_dash_width");
1308 underline_dash_gapstr = eina_stringshare_add("underline_dash_gap"); 1358 underline_dash_gapstr = eina_stringshare_add("underline_dash_gap");
1309 underline_heightstr = eina_stringshare_add("underline_height"); 1359 underline_heightstr = eina_stringshare_add("underline_height");
1360 gfx_filter = eina_stringshare_add("gfx_filter"); // FIXME: bg, fg filters
1310 } 1361 }
1311 format_refcount++; 1362 format_refcount++;
1312} 1363}
@@ -1361,6 +1412,7 @@ _format_command_shutdown(void)
1361 eina_stringshare_del(underline_dash_widthstr); 1412 eina_stringshare_del(underline_dash_widthstr);
1362 eina_stringshare_del(underline_dash_gapstr); 1413 eina_stringshare_del(underline_dash_gapstr);
1363 eina_stringshare_del(underline_heightstr); 1414 eina_stringshare_del(underline_heightstr);
1415 eina_stringshare_del(gfx_filter);
1364} 1416}
1365 1417
1366/** 1418/**
@@ -2450,6 +2502,22 @@ _format_command(Evas_Object *eo_obj, Evas_Object_Textblock_Format *fmt, const ch
2450 fmt->underline_height = atof(param); 2502 fmt->underline_height = atof(param);
2451 if (fmt->underline_height <= 0.0) fmt->underline_height = 1.0; 2503 if (fmt->underline_height <= 0.0) fmt->underline_height = 1.0;
2452 } 2504 }
2505 else if (cmd == gfx_filter)
2506 {
2507 /**
2508 * @page evas_textblock_style_page Evas Textblock Style Options
2509 *
2510 * @subsection evas_textblock_style_gfx_filter Gfx Filter
2511 *
2512 * Experimental filter, see efl_gfx_filter for more information.
2513 * @code
2514 * gfx_filter='lua code'
2515 * @endcode
2516 */
2517 if (!fmt->gfx_filter)
2518 fmt->gfx_filter = calloc(1, sizeof(Evas_Object_Textblock_Filter));
2519 eina_stringshare_replace(&fmt->gfx_filter->code, param);
2520 }
2453} 2521}
2454 2522
2455/** 2523/**
@@ -12728,6 +12796,43 @@ evas_object_textblock_free(Evas_Object *eo_obj)
12728} 12796}
12729 12797
12730static void 12798static void
12799_filter_sync_end(Evas_Object_Textblock_Filter *filter, Eina_Bool success)
12800{
12801 evas_filter_context_destroy(filter->ctx);
12802 filter->invalid = !success;
12803 filter->ctx = NULL;
12804}
12805
12806static void
12807_filter_post_render_cb(void *data)
12808{
12809 Evas_Object_Textblock_Filter_Post_Render *post_data = data;
12810
12811 _filter_sync_end(post_data->filter, post_data->success);
12812 free(post_data);
12813}
12814
12815static void
12816_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
12817{
12818 Evas_Object_Textblock_Filter_Post_Render *post_data;
12819 Evas_Object_Textblock_Filter *filter = data;
12820
12821 EINA_SAFETY_ON_FALSE_RETURN(filter->ctx == ctx);
12822
12823 if (!filter->async)
12824 {
12825 _filter_sync_end(filter, success);
12826 return;
12827 }
12828
12829 post_data = calloc(1, sizeof(*post_data));
12830 post_data->success = success;
12831 post_data->filter = filter;
12832 evas_post_render_job_add(filter->evas, _filter_post_render_cb, post_data);
12833}
12834
12835static void
12731evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, 12836evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
12732 Evas_Object_Protected_Data *obj, 12837 Evas_Object_Protected_Data *obj,
12733 void *type_private_data, 12838 void *type_private_data,
@@ -12741,6 +12846,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
12741 Eina_List *shadows = NULL; 12846 Eina_List *shadows = NULL;
12742 Eina_List *glows = NULL; 12847 Eina_List *glows = NULL;
12743 Eina_List *outlines = NULL; 12848 Eina_List *outlines = NULL;
12849 Eina_List *gfx_filters = NULL, *li;
12850 void *context_save = context;
12744 int strikethrough_thickness, underline_thickness, underline_position; 12851 int strikethrough_thickness, underline_thickness, underline_position;
12745 int i, j; 12852 int i, j;
12746 int cx, cy, cw, ch, clip; 12853 int cx, cy, cw, ch, clip;
@@ -12839,6 +12946,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
12839 } \ 12946 } \
12840 } \ 12947 } \
12841 do {} while(0) 12948 do {} while(0)
12949
12842#define COLOR_SET(col) \ 12950#define COLOR_SET(col) \
12843 nr = obj->cur->cache.clip.r * ti->parent.format->color.col.r; \ 12951 nr = obj->cur->cache.clip.r * ti->parent.format->color.col.r; \
12844 ng = obj->cur->cache.clip.g * ti->parent.format->color.col.g; \ 12952 ng = obj->cur->cache.clip.g * ti->parent.format->color.col.g; \
@@ -12850,6 +12958,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
12850 nr / 255, ng / 255, nb / 255, na / 255); \ 12958 nr / 255, ng / 255, nb / 255, na / 255); \
12851 cr = nr; cg = ng; cb = nb; ca = na; \ 12959 cr = nr; cg = ng; cb = nb; ca = na; \
12852 } 12960 }
12961
12853#define COLOR_SET_AMUL(col, amul) \ 12962#define COLOR_SET_AMUL(col, amul) \
12854 nr = obj->cur->cache.clip.r * ti->parent.format->color.col.r * (amul); \ 12963 nr = obj->cur->cache.clip.r * ti->parent.format->color.col.r * (amul); \
12855 ng = obj->cur->cache.clip.g * ti->parent.format->color.col.g * (amul); \ 12964 ng = obj->cur->cache.clip.g * ti->parent.format->color.col.g * (amul); \
@@ -12861,6 +12970,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
12861 nr / 65025, ng / 65025, nb / 65025, na / 65025); \ 12970 nr / 65025, ng / 65025, nb / 65025, na / 65025); \
12862 cr = nr; cg = ng; cb = nb; ca = na; \ 12971 cr = nr; cg = ng; cb = nb; ca = na; \
12863 } 12972 }
12973/*
12864#define DRAW_TEXT(ox, oy) \ 12974#define DRAW_TEXT(ox, oy) \
12865 if (ti->parent.format->font.font) { \ 12975 if (ti->parent.format->font.font) { \
12866 ENFN->context_cutout_target(output, context, \ 12976 ENFN->context_cutout_target(output, context, \
@@ -12874,6 +12984,29 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
12874 ti->parent.w, ti->parent.h, ti->parent.w, ti->parent.h, \ 12984 ti->parent.w, ti->parent.h, ti->parent.w, ti->parent.h, \
12875 &ti->text_props, do_async); \ 12985 &ti->text_props, do_async); \
12876 } 12986 }
12987*/
12988
12989#define DRAW_TEXT_FILTER(gfx_f, ox, oy) \
12990 evas_filter_input_render(eo_obj, gfx_f->ctx, gfx_f->dc, ti, \
12991 gfx_f->pad.l, gfx_f->pad.r, \
12992 gfx_f->pad.t, gfx_f->pad.b, do_async)
12993
12994#define DRAW_TEXT_NOFILTER(ox, oy) \
12995 evas_font_draw_async_check(obj, output, context, surface, \
12996 ti->parent.format->font.font, \
12997 obj->cur->geometry.x + ln->x + ti->parent.x + x + (ox), \
12998 obj->cur->geometry.y + ln->par->y + ln->y + yoff + y + (oy), \
12999 ti->parent.w, ti->parent.h, ti->parent.w, ti->parent.h, \
13000 &ti->text_props, do_async) \
13001
13002#define DRAW_TEXT(ox, oy) do { \
13003 if (ti->parent.format->font.font) \
13004 { \
13005 if (EINA_LIKELY(!itr->has_gfx_filter)) \
13006 DRAW_TEXT_NOFILTER(ox, oy); \
13007 else \
13008 DRAW_TEXT_FILTER(ti->parent.format->gfx_filter, ox, oy); \
13009 } } while(0)
12877 13010
12878 /* backing */ 13011 /* backing */
12879#define DRAW_RECT(ox, oy, ow, oh, or, og, ob, oa) \ 13012#define DRAW_RECT(ox, oy, ow, oh, or, og, ob, oa) \
@@ -12889,11 +13022,6 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
12889 nr / 255, ng / 255, nb / 255, na / 255); \ 13022 nr / 255, ng / 255, nb / 255, na / 255); \
12890 cr = nr; cg = ng; cb = nb; ca = na; \ 13023 cr = nr; cg = ng; cb = nb; ca = na; \
12891 } \ 13024 } \
12892 ENFN->context_cutout_target(output, context, \
12893 obj->cur->geometry.x + ln->x + x + (ox), \
12894 obj->cur->geometry.y + ln->par->y + ln->y + y + (oy), \
12895 (ow), \
12896 (oh)); \
12897 ENFN->rectangle_draw(output, \ 13025 ENFN->rectangle_draw(output, \
12898 context, \ 13026 context, \
12899 surface, \ 13027 surface, \
@@ -12971,33 +13099,37 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
12971 ITEM_WALK() 13099 ITEM_WALK()
12972 { 13100 {
12973 /* Check which other pass are necessary to avoid useless WALK */ 13101 /* Check which other pass are necessary to avoid useless WALK */
12974 Evas_Object_Textblock_Text_Item *ti; 13102 Evas_Object_Textblock_Text_Item *ti;
12975 13103
12976 ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL; 13104 ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL;
12977 if (ti) 13105 if (ti)
12978 { 13106 {
12979 if (ti->parent.format->style & (EVAS_TEXT_STYLE_SHADOW | 13107 if (ti->parent.format->style & (EVAS_TEXT_STYLE_SHADOW |
12980 EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW | 13108 EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW |
12981 EVAS_TEXT_STYLE_OUTLINE_SHADOW | 13109 EVAS_TEXT_STYLE_OUTLINE_SHADOW |
12982 EVAS_TEXT_STYLE_FAR_SHADOW | 13110 EVAS_TEXT_STYLE_FAR_SHADOW |
12983 EVAS_TEXT_STYLE_FAR_SOFT_SHADOW | 13111 EVAS_TEXT_STYLE_FAR_SOFT_SHADOW |
12984 EVAS_TEXT_STYLE_SOFT_SHADOW)) 13112 EVAS_TEXT_STYLE_SOFT_SHADOW))
12985 { 13113 {
12986 shadows = eina_list_append(shadows, itr); 13114 shadows = eina_list_append(shadows, itr);
12987 } 13115 }
12988 if ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == 13116 if ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) ==
12989 EVAS_TEXT_STYLE_GLOW) 13117 EVAS_TEXT_STYLE_GLOW)
12990 { 13118 {
12991 glows = eina_list_append(glows, itr); 13119 glows = eina_list_append(glows, itr);
12992 } 13120 }
12993 if (((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE) || 13121 if (((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE) ||
12994 ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || 13122 ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SHADOW) ||
12995 ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW) || 13123 ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW) ||
12996 (ti->parent.format->style == EVAS_TEXT_STYLE_SOFT_OUTLINE)) 13124 (ti->parent.format->style == EVAS_TEXT_STYLE_SOFT_OUTLINE))
12997 { 13125 {
12998 outlines = eina_list_append(outlines, itr); 13126 outlines = eina_list_append(outlines, itr);
12999 } 13127 }
13000 } 13128 if (ti->parent.format->gfx_filter)
13129 {
13130 gfx_filters = eina_list_append(gfx_filters, itr);
13131 }
13132 }
13001 13133
13002 /* Draw background */ 13134 /* Draw background */
13003 DRAW_FORMAT(backing, 0, ln->h); 13135 DRAW_FORMAT(backing, 0, ln->h);
@@ -13009,6 +13141,83 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13009 13141
13010 /* prepare everything for text draw */ 13142 /* prepare everything for text draw */
13011 13143
13144 /* gfx filters preparation */
13145 EINA_LIST_FOREACH(gfx_filters, li, itr)
13146 {
13147 Efl_Canvas_Filter_State state = EFL_CANVAS_FILTER_STATE_DEFAULT;
13148 Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(itr);
13149 Evas_Object_Textblock_Filter *filter;
13150 Evas_Filter_Program *pgm;
13151 Evas_Filter_Context *ctx;
13152 Eina_Bool ok;
13153
13154 filter = ti->parent.format->gfx_filter;
13155 if (!filter->code || filter->invalid)
13156 {
13157 itr->has_gfx_filter = EINA_FALSE;
13158 continue;
13159 }
13160
13161 pgm = filter->pgm;
13162 if (!pgm)
13163 {
13164 pgm = evas_filter_program_new(NULL, EINA_FALSE);
13165 ok = evas_filter_program_parse(pgm, filter->code);
13166 if (!ok)
13167 {
13168 evas_filter_program_del(pgm);
13169 filter->invalid = EINA_TRUE;
13170 itr->has_gfx_filter = EINA_FALSE;
13171 continue;
13172 }
13173 filter->pgm = pgm;
13174 }
13175
13176#ifdef DEBUG
13177 if (filter->ctx) WRN("Previous filter context was not deleted");
13178#endif
13179
13180 ctx = evas_filter_context_new(obj->layer->evas, do_async);
13181 evas_filter_state_prepare(eo_obj, &state, ti);
13182 evas_filter_program_state_set(pgm, &state);
13183 ok = evas_filter_context_program_use(ctx, pgm);
13184 if (!ok)
13185 {
13186 evas_filter_context_destroy(ctx);
13187 evas_filter_program_del(pgm);
13188 filter->pgm = NULL;
13189 filter->invalid = EINA_TRUE;
13190 itr->has_gfx_filter = EINA_FALSE;
13191 continue;
13192 }
13193 filter->ctx = ctx;
13194
13195 ln = ti->parent.ln;
13196 ENFN->context_color_set(ENDT, context, 255, 255, 255, 255);
13197 ENFN->context_multiplier_set(ENDT, context,
13198 obj->cur->cache.clip.r, obj->cur->cache.clip.g,
13199 obj->cur->cache.clip.b, obj->cur->cache.clip.a);
13200 evas_filter_program_padding_get(pgm,
13201 &filter->pad.l, &filter->pad.r,
13202 &filter->pad.t, &filter->pad.b);
13203 evas_filter_context_buffers_allocate_all(ctx);
13204 evas_filter_target_set(ctx, context, surface,
13205 obj->cur->geometry.x + ti->parent.x + x - filter->pad.l,
13206 obj->cur->geometry.y + ln->par->y + y - filter->pad.t);
13207 if (!filter->dc)
13208 {
13209 filter->dc = ENFN->context_new(ENDT);
13210 ENFN->context_color_set(ENDT, filter->dc, 255, 255, 255, 255);
13211 }
13212 filter->eo_obj = eo_obj;
13213 filter->evas = obj->layer->evas;
13214 filter->async = do_async;
13215
13216 itr->has_gfx_filter = EINA_TRUE;
13217
13218 ENFN->context_multiplier_unset(ENDT, context);
13219 }
13220
13012 /* shadows */ 13221 /* shadows */
13013 EINA_LIST_FREE(shadows, itr) 13222 EINA_LIST_FREE(shadows, itr)
13014 { 13223 {
@@ -13022,6 +13231,9 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13022 yoff = itr->yoff; 13231 yoff = itr->yoff;
13023 ln = itr->ln; 13232 ln = itr->ln;
13024 13233
13234 if (EINA_UNLIKELY(itr->has_gfx_filter))
13235 context = ti->parent.format->gfx_filter->dc;
13236
13025 shad_dst = shad_sz = dx = dy = haveshad = 0; 13237 shad_dst = shad_sz = dx = dy = haveshad = 0;
13026 switch (ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) 13238 switch (ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC)
13027 { 13239 {
@@ -13118,6 +13330,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13118 break; 13330 break;
13119 } 13331 }
13120 } 13332 }
13333
13334 context = context_save;
13121 } 13335 }
13122 13336
13123 /* glows */ 13337 /* glows */
@@ -13132,6 +13346,9 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13132 yoff = itr->yoff; 13346 yoff = itr->yoff;
13133 ln = itr->ln; 13347 ln = itr->ln;
13134 13348
13349 if (EINA_UNLIKELY(itr->has_gfx_filter))
13350 context = ti->parent.format->gfx_filter->dc;
13351
13135 if ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_GLOW) 13352 if ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_GLOW)
13136 { 13353 {
13137 for (j = 0; j < 5; j++) 13354 for (j = 0; j < 5; j++)
@@ -13151,6 +13368,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13151 DRAW_TEXT(0, -1); 13368 DRAW_TEXT(0, -1);
13152 DRAW_TEXT(0, 1); 13369 DRAW_TEXT(0, 1);
13153 } 13370 }
13371
13372 context = context_save;
13154 } 13373 }
13155 13374
13156 /* outlines */ 13375 /* outlines */
@@ -13165,6 +13384,9 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13165 yoff = itr->yoff; 13384 yoff = itr->yoff;
13166 ln = itr->ln; 13385 ln = itr->ln;
13167 13386
13387 if (EINA_UNLIKELY(itr->has_gfx_filter))
13388 context = ti->parent.format->gfx_filter->dc;
13389
13168 if (((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE) || 13390 if (((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE) ||
13169 ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || 13391 ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SHADOW) ||
13170 ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW)) 13392 ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW))
@@ -13189,6 +13411,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13189 } 13411 }
13190 } 13412 }
13191 } 13413 }
13414
13415 context = context_save;
13192 } 13416 }
13193 13417
13194 /* normal text and lines */ 13418 /* normal text and lines */
@@ -13239,14 +13463,30 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13239 } 13463 }
13240 13464
13241 ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL; 13465 ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL;
13466
13242 /* NORMAL TEXT */ 13467 /* NORMAL TEXT */
13243 if (ti) 13468 if (ti)
13244 { 13469 {
13245 void *fi = _ITEM_TEXT(itr)->text_props.font_instance; 13470 void *fi = _ITEM_TEXT(itr)->text_props.font_instance;
13471
13472 if (EINA_UNLIKELY(itr->has_gfx_filter))
13473 context = ti->parent.format->gfx_filter->dc;
13474
13246 COLOR_SET(normal); 13475 COLOR_SET(normal);
13247 DRAW_TEXT(0, 0); 13476 DRAW_TEXT(0, 0);
13248 strikethrough_thickness = 13477 strikethrough_thickness =
13249 evas_common_font_instance_underline_thickness_get(fi); 13478 evas_common_font_instance_underline_thickness_get(fi);
13479
13480 context = context_save;
13481
13482 if (EINA_UNLIKELY(itr->has_gfx_filter))
13483 {
13484 Evas_Object_Textblock_Filter *filter = ti->parent.format->gfx_filter;
13485 Evas_Filter_Context *ctx = filter->ctx;
13486
13487 evas_filter_context_post_run_callback_set(ctx, _filter_cb, filter);
13488 evas_filter_run(ctx);
13489 }
13250 } 13490 }
13251 13491
13252 /* STRIKETHROUGH */ 13492 /* STRIKETHROUGH */
@@ -13270,6 +13510,49 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
13270 ENFN->context_multiplier_unset(output, context); 13510 ENFN->context_multiplier_unset(output, context);
13271} 13511}
13272 13512
13513EOLIAN static void
13514_efl_canvas_text_efl_canvas_filter_internal_filter_state_prepare(
13515 Eo *eo_obj, Efl_Canvas_Text_Data *pd EINA_UNUSED, Efl_Canvas_Filter_State *state, void *data)
13516{
13517 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
13518 Evas_Object_Textblock_Text_Item *ti = data;
13519 int l, r, t, b;
13520
13521#define STATE_COLOR(dst, src) dst.r = src.r; dst.g = src.g; dst.b = src.b; dst.a = src.a
13522 STATE_COLOR(state->color, ti->parent.format->color.normal);
13523 STATE_COLOR(state->text.glow, ti->parent.format->color.glow);
13524 STATE_COLOR(state->text.glow2, ti->parent.format->color.glow2);
13525 STATE_COLOR(state->text.shadow, ti->parent.format->color.shadow);
13526 STATE_COLOR(state->text.outline, ti->parent.format->color.outline);
13527#undef STATE_COLOR
13528
13529 evas_filter_program_padding_get(ti->parent.format->gfx_filter->pgm, &l, &r, &t, &b);
13530 state->w = ti->parent.w + l + r;
13531 state->h = ti->parent.h + t + b;
13532 state->scale = obj->cur->scale;
13533}
13534
13535EOLIAN static Eina_Bool
13536_efl_canvas_text_efl_canvas_filter_internal_filter_input_render(
13537 Eo *obj EINA_UNUSED, Efl_Canvas_Text_Data *pd EINA_UNUSED, void *filter, void *drawctx,
13538 void *data, int l, int r EINA_UNUSED, int t, int b EINA_UNUSED, Eina_Bool do_async)
13539{
13540 Evas_Object_Textblock_Text_Item *ti = data;
13541
13542 return evas_filter_font_draw(filter, drawctx,
13543 EVAS_FILTER_BUFFER_INPUT_ID,
13544 ti->parent.format->font.font,
13545 l, t + ti->parent.ln->y + ti->parent.yoff,
13546 &ti->text_props, do_async);
13547}
13548
13549EOLIAN static void
13550_efl_canvas_text_efl_canvas_filter_internal_filter_dirty(
13551 Eo *obj EINA_UNUSED, Efl_Canvas_Text_Data *pd EINA_UNUSED)
13552{
13553 WRN("Filter marked as dirty. NOT IMPLEMENTED!");
13554}
13555
13273static void 13556static void
13274evas_object_textblock_coords_recalc(Evas_Object *eo_obj, 13557evas_object_textblock_coords_recalc(Evas_Object *eo_obj,
13275 Evas_Object_Protected_Data *obj, 13558 Evas_Object_Protected_Data *obj,