From a6d428334f7b1f50b7d49a1b57579138c90f5bab Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Wed, 28 Jul 2010 12:00:41 +0000 Subject: [PATCH] Evas: Changing the font engine to work with Eina_Unicode instead of utf8. Changing textblock and text objects to work with Eina_Unicode instead of utf8 (internally, API remains intact). Started relying on new fribidi 0.19.2 instead of the old fribidi. A lot of fixes to the font engine. Renaming of evas_common_font_utf8_* to evas_common_encoding_utf8_* This relies on new Eina changes and types: Eina_Unicode, Eina_UStrbuf and Eina_UStringshare. SVN revision: 50595 --- legacy/evas/configure.ac | 2 +- legacy/evas/src/lib/canvas/evas_object_text.c | 118 ++- .../src/lib/canvas/evas_object_textblock.c | 676 +++++++++++------- .../evas/src/lib/engines/common/Makefile.am | 6 +- .../src/lib/engines/common/evas_bidi_utils.c | 202 ++++++ .../src/lib/engines/common/evas_bidi_utils.h | 105 +++ .../src/lib/engines/common/evas_encoding.c | 211 ++++++ .../src/lib/engines/common/evas_encoding.h | 26 + .../evas/src/lib/engines/common/evas_font.h | 23 +- .../src/lib/engines/common/evas_font_draw.c | 187 ++--- .../src/lib/engines/common/evas_font_main.c | 124 +--- .../src/lib/engines/common/evas_font_query.c | 537 ++++++++------ .../common/evas_intl/evas_intl_arabic.c | 0 .../common/evas_intl/evas_intl_arabic.h | 0 .../src/lib/engines/common/evas_intl_utils.c | 124 ---- .../src/lib/engines/common/evas_intl_utils.h | 42 -- .../evas/src/lib/engines/common/evas_pipe.c | 7 +- .../evas/src/lib/engines/common/evas_pipe.h | 3 +- legacy/evas/src/lib/imaging/evas_imaging.c | 60 +- legacy/evas/src/lib/include/evas_common.h | 9 +- legacy/evas/src/lib/include/evas_private.h | 17 +- .../modules/engines/direct3d/evas_engine.c | 5 +- .../modules/engines/directfb/evas_engine.c | 5 +- .../src/modules/engines/gl_glew/evas_engine.c | 5 +- .../src/modules/engines/gl_sdl/evas_engine.c | 6 +- .../src/modules/engines/gl_x11/evas_engine.c | 5 +- .../src/modules/engines/quartz/evas_engine.c | 20 +- .../engines/quartz/evas_quartz_private.h | 3 +- .../modules/engines/software_16/evas_engine.c | 32 +- .../engines/software_16_sdl/evas_engine.c | 6 +- .../engines/software_generic/evas_engine.c | 34 +- .../engines/software_sdl/evas_engine.c | 6 +- .../modules/engines/xrender_x11/evas_engine.c | 6 +- 33 files changed, 1637 insertions(+), 975 deletions(-) create mode 100644 legacy/evas/src/lib/engines/common/evas_bidi_utils.c create mode 100644 legacy/evas/src/lib/engines/common/evas_bidi_utils.h create mode 100644 legacy/evas/src/lib/engines/common/evas_encoding.c create mode 100644 legacy/evas/src/lib/engines/common/evas_encoding.h delete mode 100644 legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.c delete mode 100644 legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.h delete mode 100644 legacy/evas/src/lib/engines/common/evas_intl_utils.c delete mode 100644 legacy/evas/src/lib/engines/common/evas_intl_utils.h diff --git a/legacy/evas/configure.ac b/legacy/evas/configure.ac index ce24f37b40..31a6a7d1cd 100644 --- a/legacy/evas/configure.ac +++ b/legacy/evas/configure.ac @@ -280,7 +280,7 @@ AC_ARG_ENABLE([fribidi], if test "x${want_fribidi}" = "xyes" -o "x${want_fribidi}" = "xauto" ; then PKG_CHECK_MODULES([FRIBIDI], - [fribidi], + [fribidi >= 0.19.2], [ have_fribidi="yes" AC_DEFINE(HAVE_FRIBIDI, 1, [have fribidi support]) diff --git a/legacy/evas/src/lib/canvas/evas_object_text.c b/legacy/evas/src/lib/canvas/evas_object_text.c index 49053013a8..de41599215 100644 --- a/legacy/evas/src/lib/canvas/evas_object_text.c +++ b/legacy/evas/src/lib/canvas/evas_object_text.c @@ -1,4 +1,4 @@ -#include "evas_common.h" +#include "evas_common.h" /* Includes evas_bidi_utils stuff. */ #include "evas_private.h" /* save typing */ @@ -16,15 +16,17 @@ struct _Evas_Object_Text DATA32 magic; struct { - const char *text; - const char *font; - const char *source; - Evas_Font_Size size; + const Eina_Unicode *text; /*The shaped text */ + const char *utf8_text; /* The text exposed to the API */ + const char *font; + const char *source; + Evas_Font_Size size; struct { unsigned char r, g, b, a; } outline, shadow, glow, glow2; unsigned char style; + Evas_BiDi_Props intl_props; } cur, prev; float ascent, descent; @@ -227,8 +229,11 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz { int w, h; - ENFN->font_string_size_get(ENDT, o->engine_data, o->cur.text, &w, &h); - o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data); + o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data); + ENFN->font_string_size_get(ENDT, + o->engine_data, + o->cur.text, &o->cur.intl_props, + &w, &h); o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data); o->descent = ENFN->font_descent_get(ENDT, o->engine_data); o->max_ascent = ENFN->font_max_ascent_get(ENDT, o->engine_data); o->max_descent = ENFN->font_max_descent_get(ENDT, o->engine_data); @@ -316,12 +321,12 @@ evas_object_text_font_get(const Evas_Object *obj, const char **font, Evas_Font_S * @param text Text to display. */ EAPI void -evas_object_text_text_set(Evas_Object *obj, const char *text) +evas_object_text_text_set(Evas_Object *obj, const char *_text) { Evas_Object_Text *o; int is, was; - - if (!text) text = ""; + Eina_Unicode *text; + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); return; MAGIC_CHECK_END(); @@ -329,24 +334,48 @@ evas_object_text_text_set(Evas_Object *obj, const char *text) MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT); return; MAGIC_CHECK_END(); - if ((o->cur.text) && (text) && (!strcmp(o->cur.text, text))) return; + + text = evas_common_encoding_utf8_to_unicode(_text, NULL); + + if (!text) text = eina_unicode_strdup(EINA_UNICODE_EMPTY_STRING); + if ((o->cur.text) && (text) && (!eina_unicode_strcmp(o->cur.text, text))) + { + free(text); + return; + } was = evas_object_is_in_output_rect(obj, obj->layer->evas->pointer.x, obj->layer->evas->pointer.y, 1, 1); /* DO II */ - /* - if (o->cur.text) eina_stringshare_del(o->cur.text); - if ((text) && (*text)) o->cur.text = eina_stringshare_add(text); - else o->cur.text = NULL; - */ - eina_stringshare_replace(&o->cur.text, text); + /*Update intl_props*/ +#ifdef BIDI_SUPPORT + evas_bidi_update_props(text, &o->cur.intl_props); +#endif + if (o->cur.text) eina_ustringshare_del(o->cur.text); + if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text); + + if ((text) && (*text)) + { + o->cur.text = eina_ustringshare_add(text); + o->cur.utf8_text = eina_stringshare_add(_text); + } + else + { + o->cur.text = NULL; + o->cur.utf8_text = NULL; + } + o->prev.text = NULL; + if ((o->engine_data) && (o->cur.text)) { int w, h; int l = 0, r = 0, t = 0, b = 0; - ENFN->font_string_size_get(ENDT, o->engine_data, o->cur.text, &w, &h); + ENFN->font_string_size_get(ENDT, + o->engine_data, + o->cur.text, &o->cur.intl_props, + &w, &h); evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); obj->cur.geometry.w = w + l + r; obj->cur.geometry.h = h + t + b; @@ -375,6 +404,7 @@ evas_object_text_text_set(Evas_Object *obj, const char *text) obj->layer->evas->last_timestamp, NULL); evas_object_inform_call_resize(obj); + if (text) free(text); } /** @@ -394,7 +424,7 @@ evas_object_text_text_get(const Evas_Object *obj) MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT); return NULL; MAGIC_CHECK_END(); - return o->cur.text; + return o->cur.utf8_text; } /** @@ -524,7 +554,7 @@ evas_object_text_horiz_advance_get(const Evas_Object *obj) MAGIC_CHECK_END(); if (!o->engine_data) return 0; if (!o->cur.text) return 0; - return ENFN->font_h_advance_get(ENDT, o->engine_data, o->cur.text); + return ENFN->font_h_advance_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props); } /** @@ -547,7 +577,7 @@ evas_object_text_vert_advance_get(const Evas_Object *obj) MAGIC_CHECK_END(); if (!o->engine_data) return 0; if (!o->cur.text) return o->ascent + o->descent; - return ENFN->font_v_advance_get(ENDT, o->engine_data, o->cur.text); + return ENFN->font_v_advance_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props); } /** @@ -587,7 +617,7 @@ evas_object_text_char_pos_get(const Evas_Object *obj, int pos, Evas_Coord *cx, E if (!o->cur.text) return EINA_FALSE; inset = ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text); - ret = ENFN->font_char_coords_get(ENDT, o->engine_data, o->cur.text, + ret = ENFN->font_char_coords_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props, pos, &x, &y, &w, &h); evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); y += o->max_ascent - t; @@ -640,8 +670,11 @@ evas_object_text_last_up_to_pos(const Evas_Object *obj, Evas_Coord x, Evas_Coord if (!o->cur.text) return -1; inset = ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text); - return ENFN->font_last_up_to_pos(ENDT, o->engine_data, o->cur.text, - x + inset, y - o->max_ascent); + return ENFN->font_last_up_to_pos(ENDT, + o->engine_data, + o->cur.text, &o->cur.intl_props, + x + inset, + y - o->max_ascent); } /** @@ -669,9 +702,13 @@ evas_object_text_char_coords_get(const Evas_Object *obj, Evas_Coord x, Evas_Coor if (!o->cur.text) return -1; inset = ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text); - ret = ENFN->font_char_at_coords_get(ENDT, o->engine_data, o->cur.text, - x + inset, y - o->max_ascent, - &rx, &ry, &rw, &rh); + ret = ENFN->font_char_at_coords_get(ENDT, + o->engine_data, + o->cur.text, &o->cur.intl_props, + x + inset, + y - o->max_ascent, + &rx, &ry, + &rw, &rh); evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); ry += o->max_ascent - t; rx -= inset + l; @@ -1258,7 +1295,7 @@ evas_string_char_next_get(const char *str, int pos, int *decoded) if (decoded) *decoded = 0; if ((!str) || (pos < 0)) return 0; p = pos; - d = evas_common_font_utf8_get_next((unsigned char *)str, &p); + d = evas_common_encoding_utf8_get_next((unsigned char *)str, &p); if (decoded) *decoded = d; return p; } @@ -1278,7 +1315,7 @@ evas_string_char_prev_get(const char *str, int pos, int *decoded) if (decoded) *decoded = 0; if ((!str) || (pos < 1)) return 0; p = pos; - d = evas_common_font_utf8_get_prev((unsigned char *)str, &p); + d = evas_common_encoding_utf8_get_prev((unsigned char *)str, &p); if (decoded) *decoded = d; return p; } @@ -1293,7 +1330,7 @@ EAPI int evas_string_char_len_get(const char *str) { if (!str) return 0; - return evas_common_font_utf8_get_len((const unsigned char *) str); + return evas_common_encoding_utf8_get_len((const unsigned char *) str); } /** @@ -1417,6 +1454,9 @@ evas_object_text_new(void) o = calloc(1, sizeof(Evas_Object_Text)); o->magic = MAGIC_OBJ_TEXT; o->prev = o->cur; +#ifdef BIDI_SUPPORT + o->cur.intl_props.direction = FRIBIDI_PAR_ON; +#endif return o; } @@ -1431,10 +1471,13 @@ evas_object_text_free(Evas_Object *obj) return; MAGIC_CHECK_END(); /* free obj */ - if (o->cur.text) eina_stringshare_del(o->cur.text); + if (o->cur.text) eina_ustringshare_del(o->cur.text); + if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text); if (o->cur.font) eina_stringshare_del(o->cur.font); if (o->cur.source) eina_stringshare_del(o->cur.source); if (o->engine_data) evas_font_free(obj->layer->evas, o->engine_data); + if (o->cur.intl_props.embedding_levels) free(o->cur.intl_props.embedding_levels); + if (o->cur.intl_props.char_types) free(o->cur.intl_props.char_types); o->magic = 0; free(o); } @@ -1520,7 +1563,7 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur obj->cur.geometry.h, \ obj->cur.geometry.w, \ obj->cur.geometry.h, \ - o->cur.text); + o->cur.text, &o->cur.intl_props); #if 0 #define DRAW_TEXT(ox, oy) \ if ((o->engine_data) && (o->cur.text)) \ @@ -1537,7 +1580,7 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur obj->cur.cache.geometry.h, \ obj->cur.geometry.w, \ obj->cur.geometry.h, \ - o->cur.text); + o->cur.text, &o->cur.intl_props); #endif /* shadows */ if (o->cur.style == EVAS_TEXT_STYLE_SHADOW) @@ -1724,8 +1767,8 @@ evas_object_text_render_pre(Evas_Object *obj) (strcmp(o->cur.font, o->prev.font))) || ((o->cur.font) && (!o->prev.font)) || ((!o->cur.font) && (o->prev.font)) || - ((o->cur.text) && (o->prev.text) && - (strcmp(o->cur.text, o->prev.text))) || + ((o->cur.text) && (o->prev.text) && + (eina_unicode_strcmp(o->cur.text, o->prev.text))) || ((o->cur.text) && (!o->prev.text)) || ((!o->cur.text) && (o->prev.text)) || ((o->cur.style != o->prev.style)) || @@ -1860,7 +1903,10 @@ _evas_object_text_rehint(Evas_Object *obj) int w, h; int l = 0, r = 0, t = 0, b = 0; - ENFN->font_string_size_get(ENDT, o->engine_data, o->cur.text, &w, &h); + ENFN->font_string_size_get(ENDT, + o->engine_data, + o->cur.text, &o->cur.intl_props, + &w, &h); evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); obj->cur.geometry.w = w + l + r; obj->cur.geometry.h = h + t + b; diff --git a/legacy/evas/src/lib/canvas/evas_object_textblock.c b/legacy/evas/src/lib/canvas/evas_object_textblock.c index c19a91ba9e..e2095f0b05 100644 --- a/legacy/evas/src/lib/canvas/evas_object_textblock.c +++ b/legacy/evas/src/lib/canvas/evas_object_textblock.c @@ -2,6 +2,10 @@ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 */ +/* FIXME: Write an intro + explanation about all of this object, including + * the internal types and functions. It's time consuming to understand what's + * going on here without a reasonable amount of help. */ + #include "evas_common.h" #include "evas_private.h" @@ -15,16 +19,23 @@ static const char o_type[] = "textblock"; /* private struct for textblock object internal data */ typedef struct _Evas_Object_Textblock Evas_Object_Textblock; typedef struct _Evas_Object_Style_Tag Evas_Object_Style_Tag; +typedef enum _Evas_Object_Textblock_Node_Type Evas_Object_Textblock_Node_Type; typedef struct _Evas_Object_Textblock_Node Evas_Object_Textblock_Node; +typedef struct _Evas_Object_Textblock_Paragraph Evas_Object_Textblock_Paragraph; typedef struct _Evas_Object_Textblock_Line Evas_Object_Textblock_Line; typedef struct _Evas_Object_Textblock_Item Evas_Object_Textblock_Item; typedef struct _Evas_Object_Textblock_Format_Item Evas_Object_Textblock_Format_Item; typedef struct _Evas_Object_Textblock_Format Evas_Object_Textblock_Format; /* the current state of the formatting */ +#define GET_PREV(text, ind) (((ind) > 0) ? (text[(ind)--]) : (text[ind])) +#define GET_NEXT(text, ind) ((text[ind]) ? (text[(ind)++]) : (text[ind])) -#define NODE_TEXT 0 -#define NODE_FORMAT 1 +enum _Evas_Object_Textblock_Node_Type +{ + NODE_TEXT, + NODE_FORMAT +}; struct _Evas_Object_Style_Tag { @@ -38,10 +49,29 @@ struct _Evas_Object_Style_Tag struct _Evas_Object_Textblock_Node { EINA_INLIST; - Eina_Strbuf *text; - int type; + Evas_Object_Textblock_Node_Type type; + union { + struct { + Eina_UStrbuf *unicode; + char * utf8; + } text; + Eina_Strbuf *format; + } data; }; +#define _NODE_STRBUF_FREE(x) \ + do { \ + if (x->type == NODE_FORMAT) \ + { \ + if (x->data.format) eina_strbuf_free(x->data.format); \ + } \ + else \ + { \ + if (x->data.text.unicode) eina_ustrbuf_free(x->data.text.unicode);\ + if (x->data.text.utf8) free(x->data.text.utf8); \ + } \ + } while(0) + struct _Evas_Object_Textblock_Line { EINA_INLIST; @@ -55,13 +85,14 @@ struct _Evas_Object_Textblock_Line struct _Evas_Object_Textblock_Item { EINA_INLIST; - char *text; + Eina_Unicode *text; Evas_Object_Textblock_Format *format; Evas_Object_Textblock_Node *source_node; int x, w, h; int inset, baseline; int source_pos; unsigned char type; + Evas_BiDi_Props intl_props; }; struct _Evas_Object_Textblock_Format_Item @@ -294,13 +325,13 @@ _nodes_clear(const Evas_Object *obj) n = (Evas_Object_Textblock_Node *)o->nodes; o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); - if (n->text) eina_strbuf_free(n->text); + _NODE_STRBUF_FREE(n); free(n); } } static void -_format_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt) +_format_unref_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt) { fmt->ref--; if (fmt->ref > 0) return; @@ -321,7 +352,10 @@ _line_free(const Evas_Object *obj, Evas_Object_Textblock_Line *ln) it = (Evas_Object_Textblock_Item *)ln->items; ln->items = (Evas_Object_Textblock_Item *)eina_inlist_remove(EINA_INLIST_GET(ln->items), EINA_INLIST_GET(ln->items)); if (it->text) free(it->text); - _format_free(obj, it->format); +#ifdef BIDI_SUPPORT + evas_bidi_props_clean(&it->intl_props); +#endif + _format_unref_free(obj, it->format); free(it); } while (ln->format_items) @@ -365,9 +399,9 @@ _nodes_adjacent_merge(const Evas_Object *obj, Evas_Object_Textblock_Node *n1) n2 = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->next; if ((n0) && (n0->type == NODE_TEXT)) { - plen = eina_strbuf_length_get(n0->text); - eina_strbuf_append_length(n0->text, eina_strbuf_string_get(n1->text), - eina_strbuf_length_get(n1->text)); + plen = eina_ustrbuf_length_get(n0->data.text.unicode); + eina_ustrbuf_append_length(n0->data.text.unicode, eina_ustrbuf_string_get(n1->data.text.unicode), + eina_ustrbuf_length_get(n1->data.text.unicode)); o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove (EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n1)); // (EINA_INLIST_GET(n0))->next = EINA_INLIST_GET(n2); @@ -386,7 +420,8 @@ _nodes_adjacent_merge(const Evas_Object *obj, Evas_Object_Textblock_Node *n1) data->pos += plen; } } - if (n1->text) eina_strbuf_free(n1->text); + if (n1->data.text.unicode) eina_ustrbuf_free(n1->data.text.unicode); + if (n1->data.text.utf8) free(n1->data.text.utf8); free(n1); n1 = n0; n2 = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->next; @@ -396,9 +431,9 @@ _nodes_adjacent_merge(const Evas_Object *obj, Evas_Object_Textblock_Node *n1) n0 = n1; n1 = n2; n2 = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->next; - plen = eina_strbuf_length_get(n0->text); - eina_strbuf_append_length(n0->text, eina_strbuf_string_get(n1->text), - eina_strbuf_length_get(n1->text)); + plen = eina_ustrbuf_length_get(n0->data.text.unicode); + eina_ustrbuf_append_length(n0->data.text.unicode, eina_ustrbuf_string_get(n1->data.text.unicode), + eina_ustrbuf_length_get(n1->data.text.unicode)); o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove (EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n1)); // (EINA_INLIST_GET(n0))->next = EINA_INLIST_GET(n2); @@ -417,7 +452,8 @@ _nodes_adjacent_merge(const Evas_Object *obj, Evas_Object_Textblock_Node *n1) data->pos += plen; } } - if (n1->text) eina_strbuf_free(n1->text); + if (n1->data.text.unicode) eina_ustrbuf_free(n1->data.text.unicode); + if (n1->data.text.utf8) free(n1->data.text.utf8); free(n1); } } @@ -634,7 +670,7 @@ _clean_white(int clean_start, int clean_end, char *str) while (*p != 0) { pwhite = white; - if (isspace(*p) || _is_white(*p)) white = 1; + if (_is_white(*p)) white = 1; else white = 0; if ((pwhite) && (white)) ok = 0; else @@ -675,8 +711,9 @@ _clean_white(int clean_start, int clean_end, char *str) return str2; } +/* Appends the text between s and p to the current cursor */ static void -_append_text_run(Evas_Object_Textblock *o, char *s, char *p) +_append_text_run(Evas_Object_Textblock *o, const char *s, const char *p) { if ((s) && (p > s)) { @@ -691,7 +728,7 @@ _append_text_run(Evas_Object_Textblock *o, char *s, char *p) } static void -_prepend_text_run(Evas_Object_Textblock *o, char *s, char *p) +_prepend_text_run(Evas_Object_Textblock *o, const char *s, const char *p) { if ((s) && (p > s)) { @@ -828,6 +865,11 @@ _format_command_init(void) linefillstr = eina_stringshare_add("linefill"); } +/* FIXME: ATM we don't really use shutdown and init in a sane way + * we just call init EVERY TIME and shutdown the same, and hope for the best. + * There's currently a hack returning on both if already init, more correct would + * be reffing/unreffing or even better, don't init/deinit all the time! + */ static void _format_command_shutdown(void) { @@ -1440,7 +1482,7 @@ _layout_format_pop(Ctxt *c, Evas_Object_Textblock_Format *fmt) { if ((c->format_stack) && (c->format_stack->next)) { - _format_free(c->obj, fmt); + _format_unref_free(c->obj, fmt); c->format_stack = eina_list_remove_list(c->format_stack, c->format_stack); fmt = c->format_stack->data; } @@ -1570,23 +1612,28 @@ _layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt) } static Evas_Object_Textblock_Item * -_layout_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt, char *str) +_layout_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt, const Eina_Unicode *str) { Evas_Object_Textblock_Item *it; it = calloc(1, sizeof(Evas_Object_Textblock_Item)); it->format = fmt; it->format->ref++; - it->text = strdup(str); + it->text = eina_unicode_strdup(str); + it->intl_props.char_types = NULL; + it->intl_props.embedding_levels = NULL; +#ifdef BIDI_SUPPORT + it->intl_props.direction = FRIBIDI_PAR_ON; + evas_bidi_update_props(it->text, &it->intl_props); +#endif return it; } static int _layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Item *it) { - if (fmt->font.font) - return c->ENFN->font_last_up_to_pos(c->ENDT, fmt->font.font, it->text, + return c->ENFN->font_last_up_to_pos(c->ENDT, fmt->font.font, it->text, &it->intl_props, c->w - c->o->style_pad.l - c->o->style_pad.r - @@ -1600,28 +1647,32 @@ _layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_ static void _layout_item_text_cutoff(Ctxt *c __UNUSED__, Evas_Object_Textblock_Item *it, int cut) { - char *ts; + Eina_Unicode *ts; ts = it->text; ts[cut] = 0; - it->text = strdup(ts); + it->text = eina_unicode_strdup(ts); free(ts); + +#ifdef BIDI_SUPPORT + evas_bidi_update_props(it->text, &it->intl_props); +#endif } static int -_layout_word_start(char *str, int start) +_layout_word_start(const Eina_Unicode *str, int start) { int p, tp, chr = 0; p = start; - chr = evas_common_font_utf8_get_next((unsigned char *)(str), &p); + chr = GET_NEXT(str, p); if (_is_white(chr)) { tp = p; while (_is_white(chr) && (p >= 0)) { tp = p; - chr = evas_common_font_utf8_get_next((unsigned char *)(str), &p); + chr = GET_NEXT(str, p); } return tp; } @@ -1629,24 +1680,26 @@ _layout_word_start(char *str, int start) tp = p; while (p > 0) { - chr = evas_common_font_utf8_get_prev((unsigned char *)(str), &p); + chr = GET_PREV(str, p); if (_is_white(chr)) break; tp = p; } if (p < 0) p = 0; if ((p >= 0) && (_is_white(chr))) - evas_common_font_utf8_get_next((unsigned char *)(str), &p); + { + GET_NEXT(str, p); + } return p; } static int -_layout_ends_with_space(char *str) +_str_ends_with_whitespace(const Eina_Unicode *str) { int p, chr; - p = evas_common_font_utf8_get_last((unsigned char *)(str), strlen(str)); + p = eina_unicode_strlen(str) - 1; if (p < 0) return 0; - chr = evas_common_font_utf8_get_next((unsigned char *)(str), &p); + chr = GET_NEXT(str, p); return _is_white(chr); } @@ -1655,20 +1708,20 @@ _layout_strip_trailing_whitespace(Ctxt *c, Evas_Object_Textblock_Format *fmt __U { int p, tp, chr, adv, tw, th; - p = evas_common_font_utf8_get_last((unsigned char *)(it->text), strlen(it->text)); + p = eina_unicode_strlen(it->text) - 1; tp = p; if (p >= 0) { - chr = evas_common_font_utf8_get_prev((unsigned char *)(it->text), &p); + chr = GET_PREV(it->text, p); if (_is_white(chr)) { _layout_item_text_cutoff(c, it, tp); adv = 0; if (it->format->font.font) - adv = c->ENFN->font_h_advance_get(c->ENDT, it->format->font.font, it->text); + adv = c->ENFN->font_h_advance_get(c->ENDT, it->format->font.font, it->text, &it->intl_props); tw = th = 0; if (it->format->font.font) - c->ENFN->font_string_size_get(c->ENDT, it->format->font.font, it->text, &tw, &th); + c->ENFN->font_string_size_get(c->ENDT, it->format->font.font, it->text, &it->intl_props, &tw, &th); it->w = tw; it->h = th; c->x = it->x + adv; @@ -1682,7 +1735,10 @@ static int _layout_item_abort(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Item *it) { if (it->text) free(it->text); - _format_free(c->obj, it->format); + _format_unref_free(c->obj, it->format); +#ifdef BIDI_SUPPORT + evas_bidi_props_clean(&it->intl_props); +#endif free(it); if (c->ln->items) { @@ -1712,48 +1768,48 @@ _layout_next_char_jump(Ctxt *c, Evas_Object_Textblock_Item *it, char *str) #endif static int -_layout_last_item_ends_in_whitespace(Ctxt *c) +_layout_last_item_ends_with_whitespace(Ctxt *c) { Evas_Object_Textblock_Item *it; if (!c->ln->items) return 1; it = (Evas_Object_Textblock_Item *)(EINA_INLIST_GET(c->ln->items))->last; - return _layout_ends_with_space(it->text); + return _str_ends_with_whitespace(it->text); } static int -_layout_word_end(char *str, int p) +_layout_word_end(const Eina_Unicode *str, int p) { int ch, tp; tp = p; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp); + ch = GET_NEXT(str, tp); while ((!_is_white(ch)) && (tp >= 0) && (ch != 0)) { p = tp; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp); + ch = GET_NEXT(str, tp); } if (ch == 0) return -1; return p; } static int -_layout_word_next(char *str, int p) +_layout_word_next(Eina_Unicode *str, int p) { int ch, tp; tp = p; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp); + ch = GET_NEXT(str, tp); while ((!_is_white(ch)) && (tp >= 0) && (ch != 0)) { p = tp; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp); + ch = GET_NEXT(str, tp); } if (ch == 0) return -1; while ((_is_white(ch)) && (tp >= 0) && (ch != 0)) { p = tp; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp); + ch = GET_NEXT(str, tp); } if (ch == 0) return -1; return p; @@ -1770,11 +1826,12 @@ _layout_walk_back_to_item_word_redo(Ctxt *c, Evas_Object_Textblock_Item *it) /* it is not appended yet */ EINA_INLIST_REVERSE_FOREACH((EINA_INLIST_GET(c->ln->items)), pit) { - if (_layout_ends_with_space(pit->text)) + if (_str_ends_with_whitespace(pit->text)) { break; } - index = evas_common_font_utf8_get_last((unsigned char *)(pit->text), strlen(pit->text)); + index = eina_unicode_strlen(pit->text) - 1; + if (index < 0) index = 0; index = _layout_word_start(pit->text, index); if (index == 0) remove_items = eina_list_prepend(remove_items, pit); @@ -1805,7 +1862,7 @@ _layout_walk_back_to_item_word_redo(Ctxt *c, Evas_Object_Textblock_Item *it) /* append new_it */ tw = th = 0; if (new_it->format->font.font) - c->ENFN->font_string_size_get(c->ENDT, new_it->format->font.font, new_it->text, &tw, &th); + c->ENFN->font_string_size_get(c->ENDT, new_it->format->font.font, new_it->text, &it->intl_props, &tw, &th); new_it->w = tw; new_it->h = th; inset = 0; @@ -1815,7 +1872,7 @@ _layout_walk_back_to_item_word_redo(Ctxt *c, Evas_Object_Textblock_Item *it) new_it->x = c->x; adv = 0; if (new_it->format->font.font) - adv = c->ENFN->font_h_advance_get(c->ENDT, new_it->format->font.font, new_it->text); + adv = c->ENFN->font_h_advance_get(c->ENDT, new_it->format->font.font, new_it->text, &new_it->intl_props); c->x += adv; c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(new_it)); } @@ -1825,7 +1882,7 @@ _layout_walk_back_to_item_word_redo(Ctxt *c, Evas_Object_Textblock_Item *it) remove_items = eina_list_remove_list(remove_items, remove_items); /* append pit */ pit->x = c->x; - adv = c->ENFN->font_h_advance_get(c->ENDT, pit->format->font.font, pit->text); + adv = c->ENFN->font_h_advance_get(c->ENDT, pit->format->font.font, pit->text, &pit->intl_props); c->x += adv; c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(pit)); } @@ -1835,7 +1892,7 @@ _layout_walk_back_to_item_word_redo(Ctxt *c, Evas_Object_Textblock_Item *it) it->x = c->x; adv = 0; if (it->format->font.font) - adv = c->ENFN->font_h_advance_get(c->ENDT, it->format->font.font, it->text); + adv = c->ENFN->font_h_advance_get(c->ENDT, it->format->font.font, it->text, &it->intl_props); c->x += adv; c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(it)); } @@ -1846,39 +1903,42 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text { int adv, inset, tw, th, new_line, empty_item; int wrap, twrap, ch, index, white_stripped; - char *str; - const char *tbase; + const Eina_Unicode *str = EINA_UNICODE_EMPTY_STRING; + const Eina_Unicode *ustr; + const Eina_Unicode *tbase; Evas_Object_Textblock_Item *it; if (n) { - if ((repch) && (eina_strbuf_length_get(n->text))) + if ((repch) && (eina_ustrbuf_length_get(n->data.text.unicode))) { - int i, len, chlen; - char *ptr; + int i, len, ind; + Eina_Unicode *ptr; + Eina_Unicode urepch; - len = evas_common_font_utf8_get_len((unsigned char *) eina_strbuf_string_get(n->text)); - chlen = strlen(repch); - str = alloca((len * chlen) + 1); + len = eina_unicode_strlen(eina_ustrbuf_string_get(n->data.text.unicode)); + str = alloca((len + 1) * sizeof(Eina_Unicode)); tbase = str; - for (i = 0, ptr = str; i < len; ptr += chlen, i++) - memcpy(ptr, repch, chlen); + ind = 0; + urepch = evas_common_encoding_utf8_get_next(repch, &ind); + for (i = 0, ptr = (Eina_Unicode *)tbase; i < len; ptr++, i++) + *ptr = urepch; *ptr = 0; } else { - str = (char *)eina_strbuf_string_get(n->text); + str = eina_ustrbuf_string_get(n->data.text.unicode); tbase = str; } } else { - str = ""; tbase = str; } // printf("add: wrap: %i|%i, width: %i '%s'\n", fmt->wrap_word, fmt->wrap_char, c->w, str); new_line = 0; empty_item = 0; + while (str) { /* if this is the first line item and it starts with spaces - remove them */ @@ -1897,12 +1957,12 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text str = str + twrap; } */ - it = _layout_item_new(c, fmt, str); + it = _layout_item_new(c, fmt, str); it->source_node = n; it->source_pos = str - tbase; tw = th = 0; if (fmt->font.font) - c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, it->text, &tw, &th); + c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, it->text, &it->intl_props, &tw, &th); if ((c->w >= 0) && ((fmt->wrap_word) || (fmt->wrap_char)) && ((c->x + tw) > @@ -1911,19 +1971,19 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text { wrap = _layout_text_cutoff_get(c, fmt, it); if (wrap == 0) - evas_common_font_utf8_get_next((unsigned char *)str, &wrap); + GET_NEXT(str, wrap); if (wrap > 0) { if (fmt->wrap_word) { index = wrap; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &index); + ch = GET_NEXT(str, index); if (!_is_white(ch)) wrap = _layout_word_start(str, wrap); if (wrap > 0) { twrap = wrap; - ch = evas_common_font_utf8_get_prev((unsigned char *)str, &twrap); + ch = GET_PREV(str, twrap); /* the text intersects the wrap point on a whitespace char */ if (_is_white(ch)) { @@ -1933,7 +1993,7 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text * commented out. * ch = evas_common_font_utf8_get_next((unsigned char *)str, &twrap); */ - str = str + twrap; + str += twrap; } /* intersects a word */ else @@ -1943,15 +2003,15 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text if (twrap != 0) { wrap = twrap; - ch = evas_common_font_utf8_get_prev((unsigned char *)str, &twrap); + ch = GET_PREV(str, twrap); _layout_item_text_cutoff(c, it, twrap); - str = str + wrap; + str += wrap; } else { empty_item = 1; if (it->text) free(it->text); - _format_free(c->obj, it->format); + _format_unref_free(c->obj, it->format); free(it); if (c->ln->items) { @@ -1960,8 +2020,8 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text twrap = _layout_word_end(str, wrap); if (twrap >= 0) { - ch = evas_common_font_utf8_get_next((unsigned char *)str, &twrap); - str = str + twrap; + ch = GET_NEXT(str, twrap); + str += twrap; } else str = NULL; @@ -1973,9 +2033,9 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text { /* wrap now is the index of the word START */ index = wrap; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &index); + ch = GET_NEXT(str, index); if (!_is_white(ch) && - (!_layout_last_item_ends_in_whitespace(c))) + (!_layout_last_item_ends_with_whitespace(c))) { _layout_walk_back_to_item_word_redo(c, it); return; @@ -1994,11 +2054,11 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text wrap = twrap; if (twrap >= 0) { - ch = evas_common_font_utf8_get_next((unsigned char *)str, &wrap); + ch = GET_NEXT(str, wrap); _layout_item_text_cutoff(c, it, twrap); } if (wrap > 0) - str = str + wrap; + str += wrap; else str = NULL; } @@ -2010,7 +2070,7 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text else if (fmt->wrap_char) { _layout_item_text_cutoff(c, it, wrap); - str = str + wrap; + str += wrap; } new_line = 1; } @@ -2021,9 +2081,9 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text { if (wrap < 0) wrap = 0; index = wrap; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &index); + ch = GET_NEXT(str, index); if (!_is_white(ch) && - (!_layout_last_item_ends_in_whitespace(c))) + (!_layout_last_item_ends_with_whitespace(c))) { _layout_walk_back_to_item_word_redo(c, it); return; @@ -2045,7 +2105,7 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text if (twrap >= 0) _layout_item_text_cutoff(c, it, twrap); if (wrap >= 0) - str = str + wrap; + str += wrap; else str = NULL; } @@ -2058,7 +2118,7 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text { tw = th = 0; if (fmt->font.font) - c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, it->text, &tw, &th); + c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, it->text, &it->intl_props, &tw, &th); } } else @@ -2075,7 +2135,7 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text it->x = c->x; adv = 0; if (fmt->font.font) - adv = c->ENFN->font_h_advance_get(c->ENDT, fmt->font.font, it->text); + adv = c->ENFN->font_h_advance_get(c->ENDT, fmt->font.font, it->text, &it->intl_props); c->x += adv; c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(it)); } @@ -2086,7 +2146,7 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text if (!white_stripped) { index = 0; - ch = evas_common_font_utf8_get_next((unsigned char *)str, &index); + ch = GET_NEXT(str, index); if (_is_white(ch)) str += index; } } @@ -2109,6 +2169,13 @@ _layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node *n, char *item) return fi; } +/* A macro to check if the string is a new line, either the actual char or a + * relevant escape sequence */ +#define _IS_LINE_SEPARATOR(item) \ + (!strcmp(item, "\n") || !strcmp(item, "\\n")) +/* same as the above just with paragraphs */ +#define _IS_PARAGRAPH_SEPARATOR(item) \ + (!strcmp(item, "PS")) /* Paragraph separator */ static void _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ret) { @@ -2156,6 +2223,7 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ /* run through all text and format nodes generating lines */ if (!c->o->nodes) { + /* If there are no nodes and lines, do the inital creation. */ if (!c->ln) { _layout_line_new(c, fmt); @@ -2166,7 +2234,7 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ tw = th = 0; if (fmt->font.font) { - c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, "", &tw, &th); + c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, "", NULL, &tw, &th); c->ln->x = 0; c->ln->y = 0; c->ln->w = tw; @@ -2178,16 +2246,18 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ */ } } + /* FIXME: Consider splitting FORMAT NODE parsing into a different func */ EINA_INLIST_FOREACH(c->o->nodes, n) { if (!c->ln) _layout_line_new(c, fmt); - if ((n->type == NODE_FORMAT) && eina_strbuf_length_get(n->text)) + /* Handle format nodes */ + if ((n->type == NODE_FORMAT) && eina_strbuf_length_get(n->data.format)) { char *s; char *item; int handled = 0; - s = (char *)eina_strbuf_string_get(n->text); + s = (char *)eina_strbuf_string_get(n->data.format); if (!strncmp(s, "+ item ", 7)) { // one of: @@ -2312,7 +2382,15 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ } else { - if ((!strcmp(item, "\n")) || (!strcmp(item, "\\n"))) +#if 0 + if (_IS_PARAGRAPH_SEPARATOR(item)) + { + + } + else if (_IS_LINE_SEPARATOR(item)) +#else + if (_IS_LINE_SEPARATOR(item)) +#endif { Evas_Object_Textblock_Format_Item *fi; @@ -2359,7 +2437,8 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ else if (fmt->underline) c->have_underline = 1; } - else if ((n->type == NODE_TEXT) && eina_strbuf_length_get(n->text)) + /* Handle text nodes */ + else if ((n->type == NODE_TEXT) && eina_ustrbuf_length_get(n->data.text.unicode)) { _layout_text_append(c, fmt, n, o->repch); if ((c->have_underline2) || (c->have_underline)) @@ -2374,11 +2453,12 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ } if ((c->ln) && (c->ln->items) && (fmt)) _layout_line_advance(c, fmt); + /* Clean the rest of the format stack */ while (c->format_stack) { fmt = c->format_stack->data; c->format_stack = eina_list_remove_list(c->format_stack, c->format_stack); - _format_free(c->obj, fmt); + _format_unref_free(c->obj, fmt); } EINA_INLIST_FOREACH(c->lines, ln) { @@ -2463,7 +2543,7 @@ _find_layout_item_line_match(Evas_Object *obj, Evas_Object_Textblock_Node *n, in { int pos2 = pos; - evas_common_font_utf8_get_prev((unsigned char *) eina_strbuf_string_get(n->text), &pos2); + GET_PREV(eina_ustrbuf_string_get(n->data.text.unicode), pos2); if (pos2 < pos) pos = pos2; } EINA_INLIST_FOREACH(o->lines, ln) @@ -2481,7 +2561,7 @@ _find_layout_item_line_match(Evas_Object *obj, Evas_Object_Textblock_Node *n, in int p; itn = (Evas_Object_Textblock_Item *)(((Eina_Inlist *)it)->next); - p = (int)(it->source_pos + strlen(it->text)); + p = (int)(it->source_pos + eina_unicode_strlen(it->text)); if ((p >= pos) || ((p == pos) && (!lnn) && ((!itn) | @@ -2841,33 +2921,36 @@ evas_object_textblock_replace_char_get(Evas_Object *obj) return o->repch; } - +/* Advance the pointer *p_buf to point after the next null - used in the escape table */ static inline void -_advance_after_end_of_string(const char **p_buf) +_escaped_advance_after_end_of_string(const char **p_buf) { while (**p_buf != 0) (*p_buf)++; (*p_buf)++; } +/* Advance the pointer *p_buf to point after the next null - returns true if + * there is a match */ static inline int -_is_eq_and_advance(const char *s, const char *s_end, +_escaped_is_eq_and_advance(const char *s, const char *s_end, const char **p_m, const char *m_end) { for (;((s < s_end) && (*p_m < m_end)); s++, (*p_m)++) { if (*s != **p_m) { - _advance_after_end_of_string(p_m); + _escaped_advance_after_end_of_string(p_m); return 0; } } if (*p_m < m_end) - _advance_after_end_of_string(p_m); + _escaped_advance_after_end_of_string(p_m); return s == s_end; } +/* Returns a pointer to the matched espcae char */ static inline const char * _escaped_char_match(const char *s, int *adv) { @@ -2882,7 +2965,7 @@ _escaped_char_match(const char *s, int *adv) int match; escape = map_itr; - _advance_after_end_of_string(&map_itr); + _escaped_advance_after_end_of_string(&map_itr); if (map_itr >= map_end) break; mc = map_itr; @@ -2900,7 +2983,7 @@ _escaped_char_match(const char *s, int *adv) *adv = mc - map_itr; return escape; } - _advance_after_end_of_string(&map_itr); + _escaped_advance_after_end_of_string(&map_itr); } return NULL; } @@ -2915,10 +2998,10 @@ _escaped_char_get(const char *s, const char *s_end) while (map_itr < map_end) { - if (_is_eq_and_advance(s, s_end, &map_itr, map_end)) + if (_escaped_is_eq_and_advance(s, s_end, &map_itr, map_end)) return map_itr; if (map_itr < map_end) - _advance_after_end_of_string(&map_itr); + _escaped_advance_after_end_of_string(&map_itr); } return NULL; } @@ -2960,6 +3043,7 @@ evas_textblock_string_escape_get(const char *string, int *len_ret) return _escaped_char_match(string, len_ret); } +/* Appends the escaped char beteewn s and s_end to the curosr */ static inline void _append_escaped_char(Evas_Textblock_Cursor *cur, const char *s, const char *s_end) @@ -3019,14 +3103,23 @@ evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text) tag_start = tag_end = esc_start = esc_end = NULL; p = (char *)text; s = p; + /* This loop goes through all of the mark up text until it finds format + * tags, escape sequences or the terminating NULL. When it finds either + * of those, it appends the text found up until that point to the textblock + * proccesses whatever found. It repeats itself until the termainating + * NULL is reached. */ for (;;) { + /* If we got to the end of string or just finished/started tag + * or escape sequence handling. */ if ((*p == 0) || (tag_end) || (esc_end) || (tag_start) || (esc_start)) { if (tag_end) { + /* If we reached to a tag ending, analyze the tag */ + /* FIXME: Move tag analyzing to a different function */ char *ttag; size_t ttag_len = tag_end - tag_start -1; @@ -3083,6 +3176,8 @@ evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text) { if (!esc_start) { + /* Append the text prior to this to the textblock and mark + * the start of the tag */ tag_start = p; tag_end = NULL; _append_text_run(o, s, p); @@ -3101,6 +3196,8 @@ evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text) { if (!tag_start) { + /* Append the text prior to this to the textblock and mark + * the start of the escape sequence */ esc_start = p; esc_end = NULL; _append_text_run(o, s, p); @@ -3119,12 +3216,12 @@ evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text) } } { - Eina_List *l; - Evas_Textblock_Cursor *data; + Eina_List *l; + Evas_Textblock_Cursor *data; - evas_textblock_cursor_node_first(o->cursor); - EINA_LIST_FOREACH(o->cursors, l, data) - evas_textblock_cursor_node_first(data); + evas_textblock_cursor_node_first(o->cursor); + EINA_LIST_FOREACH(o->cursors, l, data) + evas_textblock_cursor_node_first(data); } } @@ -3276,11 +3373,11 @@ evas_object_textblock_text_markup_get(const Evas_Object *obj) txt = eina_strbuf_new(); EINA_INLIST_FOREACH(o->nodes, n) { - size_t replace_len = eina_strbuf_length_get(n->text); - if ((n->type == NODE_FORMAT) && replace_len) + size_t replace_len; + if ((n->type == NODE_FORMAT) && (replace_len = eina_strbuf_length_get(n->data.format))) { size_t tag_len; - const char *tag = _style_match_replace(o->style, eina_strbuf_string_get(n->text), replace_len, &tag_len); + const char *tag = _style_match_replace(o->style, eina_strbuf_string_get(n->data.format), replace_len, &tag_len); eina_strbuf_append_char(txt, '<'); if (tag) { @@ -3294,7 +3391,7 @@ evas_object_textblock_text_markup_get(const Evas_Object *obj) int pop = 0; // FIXME: need to escape - s = eina_strbuf_string_get(n->text); + s = eina_strbuf_string_get(n->data.format); if (*s == '+') push = 1; if (*s == '-') pop = 1; while ((*s == ' ') || (*s == '+') || (*s == '-')) s++; @@ -3304,10 +3401,10 @@ evas_object_textblock_text_markup_get(const Evas_Object *obj) } eina_strbuf_append_char(txt, '>'); } - else if ((n->type == NODE_TEXT) && eina_strbuf_length_get(n->text)) + else if ((n->type == NODE_TEXT) && (replace_len = eina_ustrbuf_length_get(n->data.text.unicode))) { - const char *p = eina_strbuf_string_get(n->text); - + char *p = evas_common_encoding_unicode_to_utf8(eina_ustrbuf_string_get(n->data.text.unicode), NULL); + char *base = p; while (*p) { const char *escape; @@ -3325,6 +3422,7 @@ evas_object_textblock_text_markup_get(const Evas_Object *obj) p++; } } + free(base); } } o->markup_text = eina_strbuf_string_steal(txt); @@ -3478,7 +3576,7 @@ evas_textblock_cursor_char_next(Evas_Textblock_Cursor *cur) if (!cur) return EINA_FALSE; if (!cur->node) return EINA_FALSE; if (cur->node->type == NODE_FORMAT) return EINA_FALSE; - if (!eina_strbuf_length_get(cur->node->text)) return EINA_FALSE; + if (!eina_ustrbuf_length_get(cur->node->data.text.unicode)) return EINA_FALSE; index = cur->pos; if (cur->node->type == NODE_TEXT) @@ -3497,9 +3595,9 @@ evas_textblock_cursor_char_next(Evas_Textblock_Cursor *cur) printf("TB: 'it' not found\n"); } - ch = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(cur->node->text), &index); + ch = GET_NEXT(eina_ustrbuf_string_get(cur->node->data.text.unicode), index); if ((ch == 0) || (index < 0)) return EINA_FALSE; - if (eina_strbuf_string_get(cur->node->text)[index] == 0) return EINA_FALSE; + if (eina_ustrbuf_string_get(cur->node->data.text.unicode)[index] == 0) return EINA_FALSE; cur->pos = index; cur->eol = 0; // 1 return EINA_TRUE; @@ -3520,7 +3618,7 @@ evas_textblock_cursor_char_prev(Evas_Textblock_Cursor *cur) if (!cur) return EINA_FALSE; if (!cur->node) return EINA_FALSE; if (cur->node->type == NODE_FORMAT) return EINA_FALSE; - if (!eina_strbuf_length_get(cur->node->text)) return EINA_FALSE; + if (!eina_ustrbuf_length_get(cur->node->data.text.unicode)) return EINA_FALSE; index = cur->pos; if (index == 0) return EINA_FALSE; @@ -3541,7 +3639,8 @@ evas_textblock_cursor_char_prev(Evas_Textblock_Cursor *cur) { int plast; - plast = evas_common_font_utf8_get_last((unsigned char *) it->text, strlen(it->text)); + plast = eina_unicode_strlen(it->text) - 1; + if (plast < 0) plast = 0; if ((index - it->source_pos) == plast) at_end_of_line = 1; } } @@ -3552,7 +3651,7 @@ evas_textblock_cursor_char_prev(Evas_Textblock_Cursor *cur) cur->eol = 0; return EINA_TRUE; } - evas_common_font_utf8_get_prev((unsigned char *)eina_strbuf_string_get(cur->node->text), &index); + GET_PREV(eina_ustrbuf_string_get(cur->node->data.text.unicode), index); if (/*(ch == 0) || */(index < 0)) return EINA_FALSE; cur->pos = index; if (at_start_of_line) @@ -3592,7 +3691,7 @@ evas_textblock_cursor_char_last(Evas_Textblock_Cursor *cur) cur->pos = 0; return; } - index = evas_common_font_utf8_get_last((unsigned char *)eina_strbuf_string_get(cur->node->text), eina_strbuf_length_get(cur->node->text)); + index = eina_unicode_strlen(eina_ustrbuf_string_get(cur->node->data.text.unicode)) - 1; if (index < 0) cur->pos = 0; cur->pos = index; cur->eol = 0; // 1 @@ -3683,9 +3782,10 @@ evas_textblock_cursor_line_last(Evas_Textblock_Cursor *cur) cur->pos = it->source_pos; cur->node = it->source_node; - index = evas_common_font_utf8_get_last((unsigned char *)it->text, strlen(it->text)); + index = eina_unicode_strlen(it->text) - 1; + if (index < 0) index = 0; if ((index >= 0) && (it->text[0] != 0)) - evas_common_font_utf8_get_next((unsigned char *)(it->text), &index); + GET_NEXT(it->text, index); if (index >= 0) cur->pos += index; } else if (fi) @@ -3721,7 +3821,7 @@ evas_textblock_cursor_pos_set(Evas_Textblock_Cursor *cur, int pos) if (!cur) return; if (!cur->node) return; if (cur->node->type == NODE_FORMAT) pos = 0; - len = eina_strbuf_length_get(cur->node->text); + len = eina_ustrbuf_length_get(cur->node->data.text.unicode); if (pos < 0) pos = 0; else if (pos > len) pos = len; cur->pos = pos; @@ -3838,13 +3938,15 @@ evas_textblock_cursor_copy(const Evas_Textblock_Cursor *cur, Evas_Textblock_Curs * @return Returns no value. */ EAPI void -evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) +evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *_text) { Evas_Object_Textblock *o; Evas_Object_Textblock_Node *n, *nrel; + Eina_Unicode *text; int index, ch; if (!cur) return; + text = evas_common_encoding_utf8_to_unicode(_text, NULL); o = (Evas_Object_Textblock *)(cur->obj->object_data); if (text) { @@ -3857,7 +3959,7 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) { if (o->cursor->pos > cur->pos) { - o->cursor->pos += strlen(text); + o->cursor->pos += eina_unicode_strlen(text); } } } @@ -3869,7 +3971,7 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) { if (data->pos > cur->pos) { - data->pos += strlen(text); + data->pos += eina_unicode_strlen(text); } } } @@ -3881,7 +3983,7 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) nrel = n; n = calloc(1, sizeof(Evas_Object_Textblock_Node)); n->type = NODE_TEXT; - n->text = eina_strbuf_new(); + n->data.text.unicode = eina_ustrbuf_new(); if (nrel) o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n), @@ -3891,22 +3993,26 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) } cur->node = n; index = cur->pos; - if (eina_strbuf_length_get(n->text)) + if (eina_ustrbuf_length_get(n->data.text.unicode)) { - ch = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n->text), &index); + ch = GET_NEXT(eina_ustrbuf_string_get(n->data.text.unicode), index); if (ch != 0) { cur->pos = index; } } - if (cur->pos >= (eina_strbuf_length_get(n->text) - 1)) - eina_strbuf_append(n->text, (char *)text); + if (cur->pos >= (eina_ustrbuf_length_get(n->data.text.unicode) - 1)) + { + eina_ustrbuf_append(n->data.text.unicode, text); + } else - eina_strbuf_insert(n->text, (char *)text, cur->pos); + { + eina_ustrbuf_insert(n->data.text.unicode, text, cur->pos); + } // XXX: This makes no sense? if (text) { - cur->pos += strlen(text); + cur->pos += eina_unicode_strlen(text); } o->formatted.valid = 0; o->native.valid = 0; @@ -3918,6 +4024,7 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) } _nodes_adjacent_merge(cur->obj, n); evas_object_change(cur->obj); + free(text); } /** @@ -3927,12 +4034,14 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) * @return Returns no value. */ EAPI void -evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text) +evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *_text) { Evas_Object_Textblock *o; Evas_Object_Textblock_Node *n, *nrel; + Eina_Unicode *text; if (!cur) return; + text = evas_common_encoding_utf8_to_unicode(_text, NULL); o = (Evas_Object_Textblock *)(cur->obj->object_data); { Eina_List *l; @@ -3946,7 +4055,7 @@ evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text) (o->cursor->node->type == NODE_TEXT) && (o->cursor->pos >= cur->pos)) { - o->cursor->pos += strlen(text); + o->cursor->pos += eina_unicode_strlen(text); } } } @@ -3960,7 +4069,7 @@ evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text) (data->node->type == NODE_TEXT) && (data->pos >= cur->pos)) { - data->pos += strlen(text); + data->pos += eina_unicode_strlen(text); } } } @@ -3972,7 +4081,7 @@ evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text) nrel = n; n = calloc(1, sizeof(Evas_Object_Textblock_Node)); n->type = NODE_TEXT; - n->text = eina_strbuf_new(); + n->data.text.unicode = eina_ustrbuf_new(); if (nrel) o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend_relative(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n), @@ -3980,20 +4089,20 @@ evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text) else o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); } - if (!n->text) n->text = eina_strbuf_new(); + if (!n->data.text.unicode) n->data.text.unicode = eina_ustrbuf_new(); cur->node = n; if (text) { - if (cur->pos > (eina_strbuf_length_get(n->text) - 1)) + if (cur->pos > (eina_ustrbuf_length_get(n->data.text.unicode) - 1)) { - eina_strbuf_append(n->text, (char *)text); + eina_ustrbuf_append(n->data.text.unicode, text); } else { - eina_strbuf_insert(n->text, (char *)text, cur->pos); + eina_ustrbuf_insert(n->data.text.unicode, text, cur->pos); } - cur->pos += strlen(text); + cur->pos += eina_unicode_strlen(text); } o->formatted.valid = 0; o->native.valid = 0; @@ -4005,6 +4114,7 @@ evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text) } _nodes_adjacent_merge(cur->obj, n); evas_object_change(cur->obj); + free(text); } /** @@ -4025,8 +4135,8 @@ evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *form nc = cur->node; n = calloc(1, sizeof(Evas_Object_Textblock_Node)); n->type = NODE_FORMAT; - n->text = eina_strbuf_new(); - eina_strbuf_append(n->text, format); + n->data.format = eina_strbuf_new(); + eina_strbuf_append(n->data.format, format); if (!nc) { o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); @@ -4042,26 +4152,26 @@ evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *form int index, ch = 0; index = cur->pos; - if (eina_strbuf_length_get(nc->text)) + if (eina_ustrbuf_length_get(nc->data.text.unicode)) { - ch = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(nc->text), &index); + ch = GET_NEXT(eina_ustrbuf_string_get(nc->data.text.unicode), index); if (ch != 0) cur->pos = index; } o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n), EINA_INLIST_GET(nc)); - if ((ch != 0) && (cur->pos < eina_strbuf_length_get(nc->text))) + if ((ch != 0) && (cur->pos < eina_ustrbuf_length_get(nc->data.text.unicode))) { n2 = calloc(1, sizeof(Evas_Object_Textblock_Node)); n2->type = NODE_TEXT; - n2->text = eina_strbuf_new(); - eina_strbuf_append(n2->text, (eina_strbuf_string_get(nc->text) + cur->pos)); + n2->data.text.unicode = eina_ustrbuf_new(); + eina_ustrbuf_append(n2->data.text.unicode, (eina_ustrbuf_string_get(nc->data.text.unicode) + cur->pos)); o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n2), EINA_INLIST_GET(n)); - eina_strbuf_remove(nc->text, cur->pos, eina_strbuf_length_get(nc->text)); + eina_ustrbuf_remove(nc->data.text.unicode, cur->pos, eina_ustrbuf_length_get(nc->data.text.unicode)); } } cur->node = n; @@ -4096,8 +4206,8 @@ evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *for nc = cur->node; n = calloc(1, sizeof(Evas_Object_Textblock_Node)); n->type = NODE_FORMAT; - n->text = eina_strbuf_new(); - eina_strbuf_append(n->text, format); + n->data.format = eina_strbuf_new(); + eina_strbuf_append(n->data.format, format); if (!nc) { o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); @@ -4116,7 +4226,7 @@ evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *for { int len; - len = eina_strbuf_length_get(nc->text); + len = eina_ustrbuf_length_get(nc->data.text.unicode); if (cur->pos == 0) o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend_relative(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n), @@ -4129,13 +4239,13 @@ evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *for { n2 = calloc(1, sizeof(Evas_Object_Textblock_Node)); n2->type = NODE_TEXT; - n2->text = eina_strbuf_new(); - eina_strbuf_append(n2->text, - (eina_strbuf_string_get(nc->text) + cur->pos)); + n2->data.text.unicode = eina_ustrbuf_new(); + eina_ustrbuf_append(n2->data.text.unicode, + (eina_ustrbuf_string_get(nc->data.text.unicode) + cur->pos)); o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n2), EINA_INLIST_GET(n)); - eina_strbuf_remove(nc->text, cur->pos, eina_strbuf_length_get(nc->text)); + eina_ustrbuf_remove(nc->data.text.unicode, cur->pos, eina_ustrbuf_length_get(nc->data.text.unicode)); cur->node = n2; cur->pos = 0; // cur->eol = 0; @@ -4177,11 +4287,14 @@ evas_textblock_cursor_node_delete(Evas_Textblock_Cursor *cur) { Evas_Object_Textblock *o; Evas_Object_Textblock_Node *n, *n2; + Eina_Unicode newline[2] = {'\n', 0}; if (!cur) return; o = (Evas_Object_Textblock *)(cur->obj->object_data); n = cur->node; - if (eina_strbuf_length_get(n->text) && (!strcmp(eina_strbuf_string_get(n->text), "\n")) && + if (n->type == NODE_TEXT && eina_ustrbuf_length_get(n->data.text.unicode) && (!eina_unicode_strcmp(eina_ustrbuf_string_get(n->data.text.unicode), newline)) && + (!(EINA_INLIST_GET(n))->next)) return; + else if (n->type == NODE_FORMAT && eina_strbuf_length_get(n->data.format) && (!strcmp(eina_strbuf_string_get(n->data.format), "\n")) && (!(EINA_INLIST_GET(n))->next)) return; n2 = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(n))->next); if (n2) @@ -4225,7 +4338,7 @@ evas_textblock_cursor_node_delete(Evas_Textblock_Cursor *cur) } o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); - if (n->text) eina_strbuf_free(n->text); + _NODE_STRBUF_FREE(n); free(n); if (n2) _nodes_adjacent_merge(cur->obj, n2); @@ -4262,16 +4375,16 @@ evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur) return; } index = cur->pos; - chr = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n->text), &index); + chr = GET_NEXT(eina_ustrbuf_string_get(n->data.text.unicode), index); if (chr == 0) return; ppos = cur->pos; - eina_strbuf_remove(n->text, cur->pos, index); - if (!eina_strbuf_length_get(n->text)) + eina_ustrbuf_remove(n->data.text.unicode, cur->pos, index); + if (!eina_ustrbuf_length_get(n->data.text.unicode)) { evas_textblock_cursor_node_delete(cur); return; } - if (cur->pos == eina_strbuf_length_get(n->text)) + if (cur->pos == eina_ustrbuf_length_get(n->data.text.unicode)) { n2 = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(n))->next); if (n2) @@ -4351,27 +4464,30 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C n2 = cur2->node; if ((!n1) || (!n2)) return; index = cur2->pos; - chr = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n2->text), &index); + if (n2->type == NODE_TEXT) + chr = GET_NEXT(eina_ustrbuf_string_get(n2->data.text.unicode), index); + else + chr = evas_common_encoding_utf8_get_next((unsigned char *)eina_strbuf_string_get(n2->data.format), &index); // XXX: why was this added? this stops sel to end and // if (chr == 0) return; if (n1 == n2) { if (n1->type == NODE_TEXT) - { + { if (cur1->pos == cur2->pos) { evas_textblock_cursor_char_delete(cur1); evas_textblock_cursor_copy(cur1, cur2); return; } - eina_strbuf_remove(n1->text, cur1->pos, index); - if (!eina_strbuf_length_get(n1->text)) + eina_ustrbuf_remove(n1->data.text.unicode, cur1->pos, index); + if (!eina_ustrbuf_length_get(n1->data.text.unicode)) { evas_textblock_cursor_node_delete(cur1); evas_textblock_cursor_copy(cur1, cur2); return; } - if (cur1->pos >= eina_strbuf_length_get(n1->text)) + if (cur1->pos >= eina_ustrbuf_length_get(n1->data.text.unicode)) { n2 = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(n1))->next); if (n2) @@ -4399,8 +4515,13 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C tcur.node = n2; tcur.pos = 0; index = cur2->pos; - chr = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n2->text), &index); - if ((chr == 0) || (index >= eina_strbuf_length_get(n2->text))) + if (n2->type == NODE_TEXT) + chr = GET_NEXT(eina_ustrbuf_string_get(n2->data.text.unicode), index); + else + chr = evas_common_encoding_utf8_get_next((unsigned char *)eina_strbuf_string_get(n2->data.format), &index); + if ((chr == 0) || + (n2->type == NODE_TEXT && index >= eina_ustrbuf_length_get(n2->data.text.unicode)) || + (n2->type == NODE_FORMAT && index >= eina_strbuf_length_get(n2->data.format))) { tcur.node = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n2))->next; tcur.pos = 0; @@ -4410,37 +4531,46 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C { tcur.node = n1; index = cur1->pos; - chr = evas_common_font_utf8_get_prev((unsigned char *)eina_strbuf_string_get(n2->text), &index); + + if (n2->type == NODE_TEXT) + chr = GET_PREV(eina_ustrbuf_string_get(n2->data.text.unicode), index); + else + chr = evas_common_encoding_utf8_get_prev((unsigned char *)eina_strbuf_string_get(n2->data.format), &index); tcur.pos = index; } else { tcur.node = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->prev; if ((tcur.node) && (tcur.node->type == NODE_TEXT)) - tcur.pos = evas_common_font_utf8_get_last((unsigned char *)eina_strbuf_string_get(tcur.node->text), eina_strbuf_length_get(tcur.node->text)); + { + tcur.pos = eina_unicode_strlen(eina_ustrbuf_string_get(tcur.node->data.text.unicode)) - 1; + if (tcur.pos < 0) tcur.pos = 0; + } else - tcur.pos = 0; + { + tcur.pos = 0; + } } } } - eina_strbuf_remove(n1->text, cur1->pos, eina_strbuf_length_get(n1->text)); + eina_ustrbuf_remove(n1->data.text.unicode, cur1->pos, eina_ustrbuf_length_get(n1->data.text.unicode)); removes = NULL; for (l = (EINA_INLIST_GET(n1))->next; l != EINA_INLIST_GET(n2); l = l->next) removes = eina_list_append(removes, l); format_hump = NULL; if (n1->type == NODE_TEXT) { - if (!eina_strbuf_length_get(n1->text)) + if (!eina_ustrbuf_length_get(n1->data.text.unicode)) evas_textblock_cursor_node_delete(cur1); } else { - if (eina_strbuf_length_get(n1->text) && (eina_strbuf_string_get(n1->text)[0] == '+')) + if (eina_strbuf_length_get(n1->data.format) && (eina_strbuf_string_get(n1->data.format)[0] == '+')) format_hump = eina_list_append(format_hump, n1); else { o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n1)); - if (n1->text) eina_strbuf_free(n1->text); + if (n1->data.format) eina_strbuf_free(n1->data.format); free(n1); } } @@ -4450,16 +4580,17 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C if (n->type == NODE_TEXT) { o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); - if (n->text) eina_strbuf_free(n->text); + if (n->data.text.unicode) eina_ustrbuf_free(n->data.text.unicode); + if (n->data.text.utf8) free(n->data.text.utf8); free(n); } else { - if (eina_strbuf_string_get(n->text)[0] == '+') + if (eina_strbuf_string_get(n->data.format)[0] == '+') { format_hump = eina_list_append(format_hump, n); } - else if (eina_strbuf_string_get(n->text)[0] == '-') + else if (eina_strbuf_string_get(n->data.format)[0] == '-') { tn = eina_list_data_get(eina_list_last(format_hump)); if (tn) @@ -4467,11 +4598,11 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C format_hump = eina_list_remove_list(format_hump, eina_list_last(format_hump)); o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(tn)); - if (tn->text) eina_strbuf_free(tn->text); + if (tn->data.format) eina_strbuf_free(tn->data.format); free(tn); o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); - if (n->text) eina_strbuf_free(n->text); + if (n->data.format) eina_strbuf_free(n->data.format); free(n); } } @@ -4479,7 +4610,7 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C { o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); - if (n->text) eina_strbuf_free(n->text); + if (n->data.format) eina_strbuf_free(n->data.format); free(n); } } @@ -4487,8 +4618,8 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C } if (n2->type == NODE_TEXT) { - eina_strbuf_remove(n2->text, 0, index); - if (!eina_strbuf_length_get(n2->text)) + eina_ustrbuf_remove(n2->data.text.unicode, 0, index); + if (!eina_ustrbuf_length_get(n2->data.text.unicode)) evas_textblock_cursor_node_delete(cur2); } else @@ -4506,17 +4637,22 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C if (tcur.node) { if (tcur.node->type == NODE_TEXT) - tcur.pos = evas_common_font_utf8_get_last((unsigned char *)eina_strbuf_string_get(tcur.node->text), eina_strbuf_length_get(tcur.node->text)); + { + tcur.pos = eina_unicode_strlen(eina_ustrbuf_string_get(tcur.node->data.text.unicode)) - 1; + if (tcur.pos < 0) tcur.pos = 0; + } else - tcur.pos = 0; + { + tcur.pos = 0; + } } } } - if (eina_strbuf_string_get(n2->text)[0] == '-') + if (eina_strbuf_string_get(n2->data.format)[0] == '-') { o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n2)); - if (n2->text) eina_strbuf_free(n2->text); + if (n2->data.format) eina_strbuf_free(n2->data.format); free(n2); n = eina_list_data_get(eina_list_last(format_hump)); if (n) @@ -4533,16 +4669,21 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C tcur.node = (Evas_Object_Textblock_Node *) (EINA_INLIST_GET(n))->next; if (tcur.node) { - if (tcur.node->type == NODE_TEXT) - tcur.pos = evas_common_font_utf8_get_last((unsigned char *)eina_strbuf_string_get(tcur.node->text), eina_strbuf_length_get(tcur.node->text)); - else - tcur.pos = 0; + if (tcur.node->type == NODE_TEXT) + { + tcur.pos = eina_unicode_strlen(eina_ustrbuf_string_get(tcur.node->data.text.unicode)) - 1; + if (tcur.pos < 0) tcur.pos = 0; + } + else + { + tcur.pos = 0; + } } } } o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n)); - if (n->text) eina_strbuf_free(n->text); + if (n->data.format) eina_strbuf_free(n->data.format); free(n); } } @@ -4550,7 +4691,7 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C { o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n2)); - if (n2->text) eina_strbuf_free(n2->text); + if (n2->data.format) eina_strbuf_free(n2->data.text.unicode); free(n2); } } @@ -4600,6 +4741,7 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C * @param cur to be documented. * @return to be documented. */ +/*FIXME: returns allocated space, fix it! */ EAPI const char * evas_textblock_cursor_node_text_get(const Evas_Textblock_Cursor *cur) { @@ -4607,7 +4749,13 @@ evas_textblock_cursor_node_text_get(const Evas_Textblock_Cursor *cur) if (!cur->node) return NULL; if (cur->node->type == NODE_TEXT) { - return eina_strbuf_string_get(cur->node->text); + if (cur->node->data.text.utf8) + { + free(cur->node->data.text.utf8); + } + cur->node->data.text.utf8 = evas_common_encoding_unicode_to_utf8( + eina_ustrbuf_string_get(cur->node->data.text.unicode), NULL); + return cur->node->data.text.utf8; } return NULL; } @@ -4624,7 +4772,7 @@ evas_textblock_cursor_node_text_length_get(const Evas_Textblock_Cursor *cur) if (!cur->node) return 0; if (cur->node->type == NODE_TEXT) { - return eina_strbuf_length_get(cur->node->text); + return eina_ustrbuf_length_get(cur->node->data.text.unicode); } return 0; } @@ -4641,7 +4789,7 @@ evas_textblock_cursor_node_format_get(const Evas_Textblock_Cursor *cur) if (!cur->node) return NULL; if (cur->node->type == NODE_FORMAT) { - return eina_strbuf_string_get(cur->node->text); + return eina_strbuf_string_get(cur->node->data.format); } return NULL; } @@ -4660,13 +4808,13 @@ evas_textblock_cursor_node_format_is_visible_get(const Evas_Textblock_Cursor *cu n = cur->node; if (!n) return EINA_FALSE; if (n->type != NODE_FORMAT) return EINA_FALSE; - if (!eina_strbuf_length_get(n->text)) return EINA_FALSE; + if (!eina_strbuf_length_get(n->data.format)) return EINA_FALSE; { char *s; char *item; int visible = 0; - s = (char *)eina_strbuf_string_get(n->text); + s = (char *)eina_strbuf_string_get(n->data.format); if (s[0] == '+' || s[0] == '-') { s++; @@ -4699,7 +4847,8 @@ evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Ev Evas_Object_Textblock *o; Evas_Object_Textblock_Node *n1, *n2, *n; Eina_Strbuf *txt; - char *s, *ret; + char *ret; + const Eina_Unicode *s; int index; if (!cur1) return NULL; @@ -4718,48 +4867,51 @@ evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Ev n2 = cur2->node; index = cur2->pos; if ((!n1) || (!n2)) return NULL; - if (n2->text) - evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n2->text), &index); + if (n2->data.text.unicode) + GET_NEXT(eina_ustrbuf_string_get(n2->data.text.unicode), index); txt = eina_strbuf_new(); EINA_INLIST_FOREACH(n1, n) { - if ((n->type == NODE_TEXT) && (n->text)) + if ((n->type == NODE_TEXT) && (n->data.text.unicode)) { - s = (char *)eina_strbuf_string_get(n->text); + s = eina_ustrbuf_string_get(n->data.text.unicode); if (format == EVAS_TEXTBLOCK_TEXT_MARKUP) { - const char *p, *ps, *pe; + const Eina_Unicode *p, *ps, *pe; - if (eina_strbuf_length_get(n->text)) + if (eina_ustrbuf_length_get(n->data.text.unicode)) { if ((n == n1) && (n == n2)) { - ps = eina_strbuf_string_get(n->text) + cur1->pos; + ps = eina_ustrbuf_string_get(n->data.text.unicode) + cur1->pos; pe = ps + index - cur1->pos; } else if (n == n1) { - ps = eina_strbuf_string_get(n->text) + cur1->pos; - pe = ps + strlen(ps); + ps = eina_ustrbuf_string_get(n->data.text.unicode) + cur1->pos; + pe = ps + eina_unicode_strlen(ps); } else if (n == n2) { - ps = eina_strbuf_string_get(n->text); + ps = eina_ustrbuf_string_get(n->data.text.unicode); pe = ps + cur2->pos + 1; } else { - ps = eina_strbuf_string_get(n->text); - pe = ps + strlen(ps); + ps = eina_ustrbuf_string_get(n->data.text.unicode); + pe = ps + eina_unicode_strlen(ps); } p = ps; while (p < pe) { - const char *escape; + const char *escape; + char *tmp; int adv; if (!*p) break; - escape = _escaped_char_match(p, &adv); + tmp = evas_common_encoding_unicode_to_utf8(p, NULL); + escape = _escaped_char_match(tmp, &adv); + free(tmp); if (escape) { p += adv; @@ -4775,44 +4927,49 @@ evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Ev } else { + /*FIXME: make more efficient */ + char *utf; + utf = evas_common_encoding_unicode_to_utf8(s, NULL); if ((n == n1) && (n == n2)) { s += cur1->pos; - eina_strbuf_append_n(txt, s, index - cur1->pos); + eina_strbuf_append_n(txt, utf, index - cur1->pos); } else if (n == n1) { s += cur1->pos; - eina_strbuf_append(txt, s); + eina_strbuf_append(txt, utf); } else if (n == n2) { - eina_strbuf_append_n(txt, s, index); + eina_strbuf_append_n(txt, utf, index); } else { - eina_strbuf_append(txt, s); + eina_strbuf_append(txt, utf); } + free(utf); } } - else if (n->text) + else if (n->data.format) { if (format == EVAS_TEXTBLOCK_TEXT_PLAIN) { - s = (char *)eina_strbuf_string_get(n->text); - while (*s) + const char *tmp; + tmp = eina_strbuf_string_get(n->data.format); + while (*tmp) { - if (*s == '\n') + if (*tmp == '\n') eina_strbuf_append_char(txt, '\n'); - else if (*s == '\t') + else if (*tmp == '\t') eina_strbuf_append_char(txt, '\t'); - s++; + tmp++; } } else if (format == EVAS_TEXTBLOCK_TEXT_MARKUP) { - size_t tag_len, replace_len = eina_strbuf_length_get(n->text); - const char *tag = _style_match_replace(o->style, eina_strbuf_string_get(n->text), replace_len, &tag_len); + size_t tag_len, replace_len = eina_strbuf_length_get(n->data.format); + const char *tag = _style_match_replace(o->style, eina_strbuf_string_get(n->data.format), replace_len, &tag_len); eina_strbuf_append_char(txt, '<'); if (tag) { @@ -4823,17 +4980,21 @@ evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Ev { int push = 0; int pop = 0; + const char *tmp; // FIXME: need to escape - s = (char *)eina_strbuf_string_get(n->text); - if (*s == '+') push = 1; - if (*s == '-') pop = 1; - while ((*s == ' ') || (*s == '+') || (*s == '-')) s++; + tmp = eina_strbuf_string_get(n->data.format); + if (*tmp == '+') push = 1; + if (*tmp == '-') pop = 1; + while ((*tmp == ' ') || (*tmp == '+') || (*tmp == '-')) tmp++; if (pop) eina_strbuf_append_char(txt, '/'); - if (push) eina_strbuf_append(txt, "+ "); - eina_strbuf_append(txt, s); + if (push) + { + eina_strbuf_append(txt, "+ "); + } + eina_strbuf_append(txt, tmp); } - eina_strbuf_append_char(txt, '>'); + eina_ustrbuf_append_char(txt, '>'); } } if (n == n2) break; @@ -4901,20 +5062,22 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C int pos2; pos2 = pos; - evas_common_font_utf8_get_next((unsigned char *)(it->text), &pos2); + GET_NEXT(it->text, pos2); if (pos2 > pos) pos = pos2; } if (pos < 0) pos = 0; - if (it->format->font.font) - ret = cur->ENFN->font_char_coords_get(cur->ENDT, it->format->font.font, - it->text, - pos, - &x, &y, &w, &h); + if (it->format->font.font) + { + ret = cur->ENFN->font_char_coords_get(cur->ENDT, it->format->font.font, + it->text, &it->intl_props, + pos, + &x, &y, &w, &h); + } if (ret <= 0) { if (it->format->font.font) cur->ENFN->font_string_size_get(cur->ENDT, it->format->font.font, - it->text, &w, &h); + it->text, &it->intl_props, &w, &h); x = w; y = 0; w = 0; @@ -5031,7 +5194,7 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, E if (it->format->font.font) pos = cur->ENFN->font_char_at_coords_get(cur->ENDT, it->format->font.font, - it->text, + it->text, &it->intl_props, x - it->x - ln->x, 0, &cx, &cy, &cw, &ch); if (pos < 0) @@ -5441,6 +5604,7 @@ evas_object_textblock_free(Evas_Object *obj) free(o); } + static void evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y) { @@ -5516,19 +5680,19 @@ evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void (obj->cur.cache.clip.g * it->format->color.col.g * (amul)) / 65025, \ (obj->cur.cache.clip.b * it->format->color.col.b * (amul)) / 65025, \ (obj->cur.cache.clip.a * it->format->color.col.a * (amul)) / 65025); +# define DRAW_TEXT(ox, oy) \ + if (it->format->font.font) ENFN->font_draw(output, context, surface, it->format->font.font, \ + obj->cur.geometry.x + ln->x + it->x - it->inset + x + (ox), \ + obj->cur.geometry.y + ln->y + yoff + y + (oy), \ + it->w, it->h, it->w, it->h, it->text, &it->intl_props); +# if 0 #define DRAW_TEXT(ox, oy) \ if (it->format->font.font) ENFN->font_draw(output, context, surface, it->format->font.font, \ obj->cur.geometry.x + ln->x + it->x - it->inset + x + (ox), \ obj->cur.geometry.y + ln->y + yoff + y + (oy), \ - it->w, it->h, it->w, it->h, it->text); -#if 0 -//#define DRAW_TEXT(ox, oy) \ -// if (it->format->font.font) ENFN->font_draw(output, context, surface, it->format->font.font, \ -// obj->cur.geometry.x + ln->x + it->x - it->inset + x + (ox), \ -// obj->cur.geometry.y + ln->y + yoff + y + (oy), \ -// obj->cur.cache.geometry.x + ln->x + it->x - it->inset + x + (ox), \ -// obj->cur.cache.geometry.y + ln->y + yoff + y + (oy), \ -// it->w, it->h, it->w, it->h, it->text); + obj->cur.cache.geometry.x + ln->x + it->x - it->inset + x + (ox), \ + obj->cur.cache.geometry.y + ln->y + yoff + y + (oy), \ + it->w, it->h, it->w, it->h, it->text, &it->intl_props); #endif #define ITEM_WALK_LINE_SKIP_DROP() \ if ((ln->y + ln->h) <= 0) continue; \ @@ -5592,6 +5756,8 @@ evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void } ITEM_WALK_END(); + /* prepare everything for text draw */ + /* shadows */ ITEM_WALK(); ITEM_WALK_LINE_SKIP_DROP(); diff --git a/legacy/evas/src/lib/engines/common/Makefile.am b/legacy/evas/src/lib/engines/common/Makefile.am index 5ad9142550..e1d66bf952 100644 --- a/legacy/evas/src/lib/engines/common/Makefile.am +++ b/legacy/evas/src/lib/engines/common/Makefile.am @@ -39,6 +39,7 @@ evas_convert_grypal_6.c \ evas_convert_yuv.c \ evas_cpu.c \ evas_draw_main.c \ +evas_encoding.c \ evas_font_draw.c \ evas_font_load.c \ evas_font_main.c \ @@ -67,7 +68,7 @@ evas_scale_span.c \ evas_tiler.c \ evas_regionbuf.c \ evas_pipe.c \ -evas_intl_utils.c \ +evas_bidi_utils.c \ evas_map_image.c \ evas_map_image.h @@ -87,6 +88,7 @@ evas_convert_rgb_32.h \ evas_convert_rgb_8.h \ evas_convert_yuv.h \ evas_draw.h \ +evas_encoding.h \ evas_font.h \ evas_font_private.h \ evas_gradient.h \ @@ -107,7 +109,7 @@ evas_scale_smooth_scaler_noscale.c \ evas_scale_smooth_scaler_up.c \ evas_scale_span.h \ evas_pipe.h \ -evas_intl_utils.h \ +evas_bidi_utils.h \ evas_map_image_internal.c \ evas_map_image_core.c \ evas_map_image_loop.c diff --git a/legacy/evas/src/lib/engines/common/evas_bidi_utils.c b/legacy/evas/src/lib/engines/common/evas_bidi_utils.c new file mode 100644 index 0000000000..f15f81f760 --- /dev/null +++ b/legacy/evas/src/lib/engines/common/evas_bidi_utils.c @@ -0,0 +1,202 @@ +#include +#include + +#include "evas_common.h" +#include "evas_bidi_utils.h" +#include "evas_encoding.h" + +#include "evas_font_private.h" + +#ifdef BIDI_SUPPORT +#include + +#define _SAFE_FREE(x) \ + do { \ + if (x) \ + { \ + free(x); \ + x = NULL; \ + } \ + } while(0) + +Eina_Bool +evas_bidi_is_rtl_str(const Eina_Unicode *str) +{ + int i = 0; + int ch; + EvasBiDiCharType type; + + if (!str) + return EINA_FALSE; + + for ( ; *str ; str++) + { + type = fribidi_get_bidi_type(*str); + if (FRIBIDI_IS_LETTER(type) && FRIBIDI_IS_RTL(type)) + { + return EINA_TRUE; + } + } + return EINA_FALSE; +} + +int +evas_bidi_update_props(Eina_Unicode *ustr, Evas_BiDi_Props *intl_props) +{ + EvasBiDiCharType *char_types = NULL; + EvasBiDiLevel *embedding_levels = NULL; + EvasBiDiJoiningType *join_types = NULL; + size_t len; + + if (!ustr) + return -2; + + if (!evas_bidi_is_rtl_str(ustr)) /* No need to handle bidi */ + { + len = -1; + goto cleanup; + } + + len = eina_unicode_strlen(ustr); + + /* Prep work for reordering */ + char_types = (EvasBiDiCharType *) malloc(sizeof(EvasBiDiCharType) * len); + if (!char_types) + { + len = -2; + goto cleanup; + } + fribidi_get_bidi_types(ustr, len, char_types); + + embedding_levels = (EvasBiDiLevel *)malloc(sizeof(EvasBiDiLevel) * len); + if (!embedding_levels) + { + len = -2; + goto cleanup; + } + if (!fribidi_get_par_embedding_levels(char_types, len, &intl_props->direction, embedding_levels)) + { + len = -2; + goto cleanup; + } + + join_types = (EvasBiDiJoiningType *) malloc(sizeof(EvasBiDiJoiningType) * len); + if (!join_types) + { + len = -2; + goto cleanup; + } + fribidi_get_joining_types(ustr, len, join_types); + + fribidi_join_arabic(char_types, len, embedding_levels, join_types); + + + /* Actually modify the string */ + fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC, embedding_levels, len, join_types, + ustr); + + /* clean up */ + if (intl_props->embedding_levels) + { + free(intl_props->embedding_levels); + } + intl_props->embedding_levels = embedding_levels; + + /* clean up */ + + if (intl_props->char_types) + { + free(intl_props->char_types); + } + intl_props->char_types = char_types; + + + if (join_types) free(join_types); + + return len; + +/* Cleanup */ +cleanup: + if (join_types) free(join_types); + if (char_types) free(char_types); + if (embedding_levels) free(embedding_levels); + evas_bidi_props_clean(intl_props); /*Mark that we don't need bidi handling */ + return len; +} + +int +evas_bidi_props_reorder_line(Eina_Unicode *ustr, const Evas_BiDi_Props *intl_props, EvasBiDiStrIndex **_v_to_l) +{ + EvasBiDiStrIndex *v_to_l = NULL; + size_t len; + + if (!EVAS_BIDI_IS_BIDI_PROP(intl_props)) + return 0; + + len = eina_unicode_strlen(ustr); + + if (_v_to_l) { + int i; + v_to_l = *_v_to_l = calloc(len, sizeof(EvasBiDiStrIndex)); + if (!v_to_l) + { + goto error; + } + /* init the array for fribidi */ + for (i = 0 ; i < len ; i++) + { + v_to_l[i] = i; + } + } + + /* Shaping must be done *BEFORE* breaking to lines so there's no choice but + doing it in textblock. */ + if (!fribidi_reorder_line (FRIBIDI_FLAGS_DEFAULT, intl_props->char_types, + len, 0, intl_props->direction, + intl_props->embedding_levels, ustr, v_to_l)) + { + goto error; + } + + + return 0; +/* ERROR HANDLING */ +error: + _SAFE_FREE(v_to_l); + return 1; +} + + +EvasBiDiStrIndex +evas_bidi_position_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDiStrIndex position) +{ + int i; + EvasBiDiStrIndex *ind; + if (position >= len || !v_to_l) + return position; + + for (i = 0, ind = v_to_l ; i < len ; i++, ind++) + { + if (*ind == position) + { + return i; + } + } + return position; +} + +Eina_Bool +evas_bidi_is_rtl_char(EvasBiDiLevel *embedded_level_list, EvasBiDiStrIndex index) +{ + if(!embedded_level_list || index < 0) + return EINA_FALSE; + return (FRIBIDI_IS_RTL(embedded_level_list[index])) ? EINA_TRUE : EINA_FALSE; +} + +void +evas_bidi_props_clean(Evas_BiDi_Props *intl_props) +{ + _SAFE_FREE(intl_props->embedding_levels); + _SAFE_FREE(intl_props->char_types); +} +#endif diff --git a/legacy/evas/src/lib/engines/common/evas_bidi_utils.h b/legacy/evas/src/lib/engines/common/evas_bidi_utils.h new file mode 100644 index 0000000000..3358f2097a --- /dev/null +++ b/legacy/evas/src/lib/engines/common/evas_bidi_utils.h @@ -0,0 +1,105 @@ +#ifndef _EVAS_BIDI_UTILS +#define _EVAS_BIDI_UTILS + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_FRIBIDI +# define USE_FRIBIDI +# define BIDI_SUPPORT +#endif + +#include "evas_common.h" + +#ifdef USE_FRIBIDI +# include +#endif + +/* abstract fribidi - we statically define sizes here because otherwise we would + * have to ifdef everywhere (because function decorations may change with/without + * bidi support) + * These types should only be passed as pointers! i.e do not directely use any of + * these types in function declarations. Defining as void should help ensuring that. + */ + +#ifdef USE_FRIBIDI +# define _EVAS_BIDI_TYPEDEF(type) \ + typedef FriBidi ## type EvasBiDi ## type +#else +# define _EVAS_BIDI_TYPEDEF(type) \ + typedef void EvasBiDi ## type +#endif + +#if 0 /* We are using Eina_Unicode instead */ +_EVAS_BIDI_TYPEDEF(Char); +#endif +_EVAS_BIDI_TYPEDEF(CharType); +_EVAS_BIDI_TYPEDEF(ParType); +_EVAS_BIDI_TYPEDEF(StrIndex); +_EVAS_BIDI_TYPEDEF(Level); +_EVAS_BIDI_TYPEDEF(JoiningType); + +/* This structure defines a set of properties of a BiDi string. In case of a + * non-bidi string, all values should be NULL. + * To check if a structure describes a bidi string or not, use the macro + * EVAS_BIDI_IS_BIDI_PROP. RTL-only strings are also treated as bidi ATM. + */ +struct _Evas_BiDi_Props { + EvasBiDiCharType *char_types; /* BiDi char types */ + EvasBiDiLevel *embedding_levels; /* BiDi embedding levels */ +#ifdef USE_FRIBIDI + EvasBiDiParType direction; /* The paragraph direction, FIXME-tom: should be a + pointer to the paragraph structure */ +#endif +}; + +typedef struct _Evas_BiDi_Props Evas_BiDi_Props; + + +#ifdef USE_FRIBIDI + +# define EVAS_BIDI_IS_BIDI_PROP(intl_props) ((intl_props) && (intl_props)->char_types) +# define evas_bidi_position_visual_to_logical(list, position) \ + (list) ? list[position] : position; + +/* Gets a v_to_l list, it's len and a logical character index, and returns the + * the visual index of that character. + */ +EvasBiDiStrIndex +evas_bidi_position_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDiStrIndex position); + +/* Returns true if the string has rtl characters, false otherwise */ +Eina_Bool +evas_bidi_is_rtl_str(const Eina_Unicode *str); + +/* Returns true if the embedding level of the index is rtl, false otherwise */ +Eina_Bool +evas_bidi_is_rtl_char(EvasBiDiLevel *embedded_level_list, EvasBiDiStrIndex index); + +/* Overallocates a bit, if anyone cares, he should realloc, though usually, + * the string get freed very fast so there's really no need to care about it + * (rellaoc-ing is slower than not) + */ +int +evas_bidi_props_reorder_line(Eina_Unicode *text, const Evas_BiDi_Props *intl_props, EvasBiDiStrIndex **_v_to_l); + +/* Updates the international properties according to the text. First checks to see + * if the text in question has rtl chars, if not, it cleans intl_props and returns. + * Otherwise, it essentially frees the old fields, allocates new fields, and + * populates them. + * On error, intl_props gets cleaned. + * Return value: the length of the string. + */ +int +evas_bidi_update_props(Eina_Unicode *text, Evas_BiDi_Props *intl_props) EINA_ARG_NONNULL(1, 2); + +/* Cleans and frees the international properties. - Just the content, not the + * poitner itself. + */ +void +evas_bidi_props_clean(Evas_BiDi_Props *intl_props) EINA_ARG_NONNULL(1); + +#endif + +#endif diff --git a/legacy/evas/src/lib/engines/common/evas_encoding.c b/legacy/evas/src/lib/engines/common/evas_encoding.c new file mode 100644 index 0000000000..d25c1f8576 --- /dev/null +++ b/legacy/evas/src/lib/engines/common/evas_encoding.c @@ -0,0 +1,211 @@ +#include "evas_common.h" +#include "evas_encoding.h" + +EAPI int +evas_common_encoding_utf8_get_next(const unsigned char *buf, int *iindex) +{ + /* Reads UTF8 bytes from @buf, starting at *@index and returns + * the decoded code point at iindex offset, and advances iindex + * to the next code point after this. + * + * Returns 0 to indicate there is no next char + */ + int index = *iindex, len, r; + unsigned char d, d2, d3, d4; + + /* if this char is the null terminator, exit */ + if (!buf[index]) + return 0; + + d = buf[index++]; + + while (buf[index] && ((buf[index] & 0xc0) == 0x80)) + index++; + len = index - *iindex; + + if (len == 1) + r = d; + else if (len == 2) + { + /* 2 bytes */ + d2 = buf[*iindex + 1]; + r = d & 0x1f; /* copy lower 5 */ + r <<= 6; + r |= (d2 & 0x3f); /* copy lower 6 */ + } + else if (len == 3) + { + /* 3 bytes */ + d2 = buf[*iindex + 1]; + d3 = buf[*iindex + 2]; + r = d & 0x0f; /* copy lower 4 */ + r <<= 6; + r |= (d2 & 0x3f); + r <<= 6; + r |= (d3 & 0x3f); + } + else + { + /* 4 bytes */ + d2 = buf[*iindex + 1]; + d3 = buf[*iindex + 2]; + d4 = buf[*iindex + 3]; + r = d & 0x0f; /* copy lower 4 */ + r <<= 6; + r |= (d2 & 0x3f); + r <<= 6; + r |= (d3 & 0x3f); + r <<= 6; + r |= (d4 & 0x3f); + } + + *iindex = index; + return r; +} + +EAPI int +evas_common_encoding_utf8_get_prev(const unsigned char *buf, int *iindex) +{ + /* Reads UTF8 bytes from @buf, starting at *@index and returns + * the decoded code point at iindex offset, and advances iindex + * to the prev code point after this. + * + * Returns 0 to indicate there is no prev char + */ + + int r; + int index = *iindex; + /* although when index == 0 there's no previous char, we still want to get + * the current char */ + if (index < 0) + return 0; + + /* First obtain the codepoint at iindex */ + r = evas_common_encoding_utf8_get_next(buf, &index); + + /* Next advance iindex to previous codepoint */ + index = *iindex; + index--; + while ((index > 0) && ((buf[index] & 0xc0) == 0x80)) + index--; + + *iindex = index; + return r; +} + +EAPI int +evas_common_encoding_utf8_get_last(const unsigned char *buf, int buflen) +{ + /* jumps to the nul byte at the buffer end and decodes backwards and + * returns the offset index byte in the buffer where the last character + * in the buffer begins. + * + * Returns -1 to indicate an error + */ + int index; + unsigned char d; + + if (buflen < 1) return 0; + index = buflen - 1; + d = buf[index]; + if (!(d & 0x80)) + return index; + else + { + while (index > 0) + { + index--; + d = buf[index]; + if ((d & 0xc0) != 0x80) + return index; + } + } + return 0; +} + +EAPI int +evas_common_encoding_utf8_get_len(const unsigned char *buf) +{ + /* returns the number of utf8 characters (not bytes) in the string */ + int index = 0, len = 0; + + while (buf[index]) + { + if ((buf[index] & 0xc0) != 0x80) + len++; + index++; + } + return len; +} + +/* FIXME: Should optimize! */ +EAPI Eina_Unicode * +evas_common_encoding_utf8_to_unicode(const unsigned char *utf, int *_len) +{ + int len, i; + int index; + Eina_Unicode *buf, *ind; + + len = evas_common_encoding_utf8_get_len(utf); + if (_len) + *_len = len; + buf = (Eina_Unicode *) calloc(sizeof(Eina_Unicode), (len + 1)); + if (!buf) return buf; + + for (i = 0, index = 0, ind = buf ; i < len ; i++, ind++) + { + *ind = evas_common_encoding_utf8_get_next(utf, &index); + } + + return buf; +} + +EAPI char * +evas_common_encoding_unicode_to_utf8(const Eina_Unicode *uni, int *_len) +{ + char *buf; + const Eina_Unicode *uind; + char *ind; + int ulen, len; + + ulen = eina_unicode_strlen(uni); + buf = (char *) calloc(ulen + 1, EVAS_ENCODING_UTF8_BYTES_PER_CHAR); + + len = 0; + for (uind = uni, ind = buf ; *uind ; uind++) + { + if (*uind <= 0x7F) /* 1 byte char */ + { + *ind++ = *uind; + len += 1; + } + else if (*uind <= 0x7FF) /* 2 byte char */ + { + *ind++ = 0xC0 | (unsigned char) (*uind >> 6); + *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); + len += 2; + } + else if (*uind <= 0xFFFF) /* 3 byte char */ + { + *ind++ = 0xE0 | (unsigned char) (*uind >> 12); + *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F); + *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); + len += 3; + } + else /* 4 byte char */ + { + *ind++ = 0xF0 | (unsigned char) ((*uind >> 18) & 0x07); + *ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F); + *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F); + *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); + len += 4; + } + } + buf = realloc(buf, len + 1); + buf[len] = '\0'; + if (_len) + *_len = len; + return buf; +} + + diff --git a/legacy/evas/src/lib/engines/common/evas_encoding.h b/legacy/evas/src/lib/engines/common/evas_encoding.h new file mode 100644 index 0000000000..4095b63d48 --- /dev/null +++ b/legacy/evas/src/lib/engines/common/evas_encoding.h @@ -0,0 +1,26 @@ +#ifndef EVAS_ENCODING_H +#define EVAS_ENCODING_H +#include + +/* FIXME: An assumption that will probably break in the future */ +#define EVAS_ENCODING_UTF8_BYTES_PER_CHAR 4 + +EAPI int +evas_common_encoding_utf8_get_next(const unsigned char *buf, int *iindex); + +EAPI int +evas_common_encoding_utf8_get_prev(const unsigned char *buf, int *iindex); + +EAPI int +evas_common_encoding_utf8_get_last(const unsigned char *buf, int buflen); + +EAPI int +evas_common_encoding_utf8_get_len(const unsigned char *buf); + +EAPI Eina_Unicode * +evas_common_encoding_utf8_to_unicode(const unsigned char *utf, int *_len) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC; + +EAPI char * +evas_common_encoding_unicode_to_utf8(const Eina_Unicode *uni, int *_len) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC; + +#endif diff --git a/legacy/evas/src/lib/engines/common/evas_font.h b/legacy/evas/src/lib/engines/common/evas_font.h index e776fe4929..5d320a94fc 100644 --- a/legacy/evas/src/lib/engines/common/evas_font.h +++ b/legacy/evas/src/lib/engines/common/evas_font.h @@ -4,6 +4,7 @@ #ifndef _EVAS_FONT_H #define _EVAS_FONT_H +#include "evas_bidi_utils.h" /* main */ @@ -18,14 +19,14 @@ EAPI int evas_common_font_max_ascent_get (RGBA_Font *fn); EAPI int evas_common_font_max_descent_get (RGBA_Font *fn); EAPI int evas_common_font_get_line_advance (RGBA_Font *fn); -EAPI int evas_common_font_utf8_get_next (const unsigned char *buf, int *iindex); -EAPI int evas_common_font_utf8_get_prev (const unsigned char *buf, int *iindex); -EAPI int evas_common_font_utf8_get_last (const unsigned char *buf, int buflen); -EAPI int evas_common_font_utf8_get_len (const unsigned char *buf); +EINA_DEPRECATED EAPI int evas_common_font_utf8_get_next (const unsigned char *buf, int *iindex); +EINA_DEPRECATED EAPI int evas_common_font_utf8_get_prev (const unsigned char *buf, int *iindex); +EINA_DEPRECATED EAPI int evas_common_font_utf8_get_last (const unsigned char *buf, int buflen); +EINA_DEPRECATED EAPI int evas_common_font_utf8_get_len (const unsigned char *buf); /* draw */ -EAPI void evas_common_font_draw (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text); +EAPI void evas_common_font_draw (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); EAPI int evas_common_font_glyph_search (RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl); EAPI RGBA_Font_Glyph *evas_common_font_int_cache_glyph_get (RGBA_Font_Int *fi, FT_UInt index); @@ -62,12 +63,12 @@ EAPI RGBA_Font_Int *evas_common_font_int_find (const char *name, /* query */ EAPI int evas_common_font_query_kerning (RGBA_Font_Int* fi, FT_UInt prev, FT_UInt index, int* kerning); -EAPI void evas_common_font_query_size (RGBA_Font *fn, const char *text, int *w, int *h); -EAPI int evas_common_font_query_inset (RGBA_Font *fn, const char *text); -EAPI void evas_common_font_query_advance (RGBA_Font *fn, const char *text, int *h_adv, int *v_adv); -EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const char *text, int pos, int *cx, int *cy, int *cw, int *ch); -EAPI int evas_common_font_query_text_at_pos (RGBA_Font *fn, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch); -EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const char *text, int x, int y); +EAPI void evas_common_font_query_size (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h); +EAPI int evas_common_font_query_inset (RGBA_Font *fn, const Eina_Unicode *text); +EAPI void evas_common_font_query_advance (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *h_adv, int *v_adv); +EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); +EAPI int evas_common_font_query_char_at_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); +EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y); void evas_common_font_load_init(void); void evas_common_font_load_shutdown(void); diff --git a/legacy/evas/src/lib/engines/common/evas_font_draw.c b/legacy/evas/src/lib/engines/common/evas_font_draw.c index 078d98d3fb..a00fe81e12 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_draw.c +++ b/legacy/evas/src/lib/engines/common/evas_font_draw.c @@ -6,7 +6,7 @@ #include "evas_private.h" #include "evas_blend_private.h" -#include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */ +#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */ #include "evas_font_private.h" /* for Frame-Queuing support */ #define WORD_CACHE_MAXLEN 50 @@ -20,7 +20,7 @@ struct prword { int size; struct cinfo *cinfo; RGBA_Font *font; - const char *str; + const Eina_Unicode *str; int len; DATA8 *im; int roww; @@ -34,7 +34,6 @@ struct cinfo { FT_UInt index; struct { int x, y; } pos; int posx; - char chr; RGBA_Font_Glyph *fg; struct { int w,h; @@ -46,7 +45,7 @@ struct cinfo { LK(lock_words); // for word cache call static Eina_Inlist *words = NULL; -static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const char *text, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning); +static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *text, Evas_BiDi_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning); EAPI void evas_common_font_draw_init(void) @@ -390,16 +389,22 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl) } - +/* + * BiDi handling: We recieve the shaped string + other props from intl_props, + * we need to reorder it so we'll have the visual string (the way we draw) + * and then for kerning we have to switch the order of the kerning query (as the prev + * is on the right, and not on the left). + */ static void -evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *in_text, - RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w, int ext_h, RGBA_Font_Int *fi, - int im_w, int im_h __UNUSED__, int use_kerning +evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *in_text, + const Evas_BiDi_Props *intl_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w, + int ext_h, RGBA_Font_Int *fi, int im_w, int im_h __UNUSED__, int use_kerning ) { int pen_x, pen_y; + int last_adv; int chr; - const char *text = in_text; + const Eina_Unicode *text = in_text; int len; FT_Face pface = NULL; FT_UInt prev_index; @@ -410,14 +415,11 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font #if defined(METRIC_CACHE) || defined(WORD_CACHE) - /* A fast (portable) strNlen would be nice (there is a wcsnlen strangely) */ - if ((p = memchr(text, 0, WORD_CACHE_MAXLEN))) - len = p - text; - else - len = WORD_CACHE_MAXLEN; + /* A fast strNlen would be nice (there is a wcsnlen strangely) */ + len = evas_common_econding_unicode_strlen(text); if (len > 2 && len < WORD_CACHE_MAXLEN){ - struct prword *word = evas_font_word_prerender(dc, text, len, fn, fi, + struct prword *word = evas_font_word_prerender(dc, text, intl_props, len, fn, fi, use_kerning); if (word){ int j,rowstart,rowend,xstart,xrun; @@ -481,35 +483,39 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font #endif } -} + } #endif -#ifdef INTERNATIONAL_SUPPORT - /*FIXME: should get the direction by parmater */ - EvasIntlParType direction = FRIBIDI_TYPE_ON; - EvasIntlLevel *level_list; +#ifdef BIDI_SUPPORT + Eina_Unicode *visual_text; - /* change the text to visual ordering and update the level list - * for as minimum impact on the code as possible just use text as an - * holder, will change in the future.*/ - char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, NULL, &level_list); - text = (visual_text) ? visual_text : in_text; - + visual_text = eina_unicode_strdup(in_text); + + if (visual_text) + { + evas_bidi_props_reorder_line(visual_text, intl_props, NULL); + text = visual_text; + } + else + { + text = in_text; + } #endif pen_x = x; pen_y = y; + last_adv = 0; prev_index = 0; im = dst->image.data; - for (char_index = 0, c = 0, chr = 0; text[chr]; char_index++) + for (char_index = 0, c = 0; *text; text++, char_index++) { FT_UInt index; RGBA_Font_Glyph *fg; int chr_x, chr_y; int gl, kern; - gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); + gl = *text; if (gl == 0) break; index = evas_common_font_glyph_search(fn, &fi, gl); @@ -521,33 +527,40 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font FTUNLOCK(); fi->src->current_size = fi->size; } + fg = evas_common_font_int_cache_glyph_get(fi, index); + if (!fg) + { + LKU(fi->ft_mutex); + continue; + } /* hmmm kerning means i can't sanely do my own cached metric tables! */ /* grrr - this means font face sharing is kinda... not an option if */ /* you want performance */ if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) { -#ifdef INTERNATIONAL_SUPPORT - /* if it's rtl, the kerning matching should be reversed, i.e prev - * index is now the index and the other way around. */ - if (evas_intl_is_rtl_char(level_list, char_index)) - { - if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) - pen_x += kern; - } +#ifdef BIDI_SUPPORT + /* if it's rtl, the kerning matching should be reversed, i.e prev + * index is now the index and the other way around. + * There is a slight exception when there are compositing chars + * involved.*/ + if (intl_props && + evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) && + fg->glyph->advance.x >> 16 > 0) + { + if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) + pen_x += kern; + } else #endif { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) + if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) pen_x += kern; } } - pface = fi->src->ft.face; - fg = evas_common_font_int_cache_glyph_get(fi, index); LKU(fi->ft_mutex); - if (!fg) continue; if (dc->font_ext.func.gl_new) { @@ -555,7 +568,13 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg); fg->ext_dat_free = dc->font_ext.func.gl_free; } - + /* If the current one is not a compositing char, do the previous advance + * and set the current advance as the next advance to do */ + if (fg->glyph->advance.x >> 16 > 0) + { + pen_x += last_adv; + last_adv = fg->glyph->advance.x >> 16; + } chr_x = (pen_x + (fg->glyph_out->left)); chr_y = (pen_y + (fg->glyph_out->top)); @@ -688,17 +707,18 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font } else break; - pen_x += fg->glyph->advance.x >> 16; + prev_index = index; } -#ifdef INTERNATIONAL_SUPPORT - if (level_list) free(level_list); +#ifdef BIDI_SUPPORT if (visual_text) free(visual_text); #endif } + EAPI void -evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text) +evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, + const Evas_BiDi_Props *intl_props) { int ext_x, ext_y, ext_w, ext_h; int im_w, im_h; @@ -749,7 +769,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int if (!dc->cutout.rects) { - evas_common_font_draw_internal(dst, dc, fn, x, y, text, + evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props, func, ext_x, ext_y, ext_w, ext_h, fi, im_w, im_h, use_kerning ); @@ -766,7 +786,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int { r = rects->rects + i; evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h); - evas_common_font_draw_internal(dst, dc, fn, x, y, text, + evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props, func, r->x, r->y, r->w, r->h, fi, im_w, im_h, use_kerning ); @@ -781,12 +801,12 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int } - +/* FIXME: Where is it freed at? */ struct prword * -evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning){ +evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Evas_BiDi_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning){ int pen_x, pen_y; struct cinfo *metrics; - const char *text; + const Eina_Unicode *text = in_text; int chr; FT_Face pface = NULL; FT_UInt prev_index; @@ -803,7 +823,7 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG LKL(lock_words); EINA_INLIST_FOREACH(words,w){ if (w->len == len && w->font == fn && fi->size == w->size && - (w->str == in_text || memcmp(w->str,in_text,len) == 0)){ + (w->str == in_text || memcmp(w->str, in_text, len * sizeof(Eina_Unicode)) == 0)){ words = eina_inlist_promote(words, EINA_INLIST_GET(w)); LKU(lock_words); return w; @@ -811,30 +831,15 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG } LKU(lock_words); -#ifdef INTERNATIONAL_SUPPORT - /*FIXME: should get the direction by parmater */ - EvasIntlParType direction = FRIBIDI_TYPE_ON; - EvasIntlLevel *level_list; - - /* change the text to visual ordering and update the level list - * for as minimum impact on the code as possible just use text as an - * holder, will change in the future.*/ - char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, NULL, &level_list); - text = (visual_text) ? visual_text : in_text; -#else - text = in_text; -#endif - gl = dc->font_ext.func.gl_new ? 1: 0; pen_x = pen_y = 0; above = 0; below = 0; baseline = 0; height = 0; descent = 0; metrics = malloc(sizeof(struct cinfo) * len); /* First pass: Work out how big */ - for (char_index = 0, c = 0, chr = 0 ; text[chr] ; char_index ++){ + for (char_index = 0, c = 0, chr = 0 ; *text ; text++, char_index ++){ struct cinfo *ci = metrics + char_index; - ci->chr = text[chr]; - ci->gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); + ci->gl = *text; if (ci->gl == 0) break; ci->index = evas_common_font_glyph_search(fn, &fi, ci->gl); LKL(fi->ft_mutex); @@ -845,16 +850,39 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG FTUNLOCK(); fi->src->current_size = fi->size; } - if (use_kerning && char_index && (pface == fi->src->ft.face)) - { - int kern; - if (evas_common_font_query_kerning(fi, prev_index,ci->index,&kern)) - ci->pos.x += kern; - } - pface = fi->src->ft.face; ci->fg = evas_common_font_int_cache_glyph_get(fi, ci->index); LKU(fi->ft_mutex); if (!ci->fg) continue; + + /* hmmm kerning means i can't sanely do my own cached metric tables! */ + /* grrr - this means font face sharing is kinda... not an option if */ + /* you want performance */ + if ((use_kerning) && (prev_index) && (ci->index) && + (pface == fi->src->ft.face)) + { + int kern = 0; +#ifdef BIDI_SUPPORT + /* if it's rtl, the kerning matching should be reversed, i.e prev + * index is now the index and the other way around. + * There is a slight exception when there are compositing chars + * involved.*/ + if (intl_props && + evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) && + ci->fg->glyph->advance.x >> 16 > 0) + { + if (evas_common_font_query_kerning(fi, ci->index, prev_index, &kern)) + ci->pos.x += kern; + } + else +#endif + { + + if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern)) + ci->pos.x += kern; + } + } + + pface = fi->src->ft.face; if (gl){ ci->fg->ext_dat =dc->font_ext.func.gl_new(dc->font_ext.data,ci->fg); ci->fg->ext_dat_free = dc->font_ext.func.gl_free; @@ -897,7 +925,7 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG save = malloc(sizeof(struct prword)); save->cinfo = metrics; - save->str = eina_stringshare_add(in_text); + save->str = eina_ustringshare_add(text); save->font = fn; save->size = fi->size; save->len = len; @@ -914,17 +942,12 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG struct prword *last = (struct prword *)(words->last); if (last->im) free(last->im); if (last->cinfo) free(last->cinfo); - eina_stringshare_del(last->str); + eina_ustringshare_del(last->str); words = eina_inlist_remove(words,EINA_INLIST_GET(last)); free(last); } LKU(lock_words); -#ifdef INTERNATIONAL_SUPPORT - if (level_list) free(level_list); - if (visual_text) free(visual_text); -#endif - return save; } diff --git a/legacy/evas/src/lib/engines/common/evas_font_main.c b/legacy/evas/src/lib/engines/common/evas_font_main.c index d53380d911..05b9d75e85 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_main.c +++ b/legacy/evas/src/lib/engines/common/evas_font_main.c @@ -4,6 +4,8 @@ #include "evas_common.h" #include "evas_private.h" +#include "evas_encoding.h" + #include "evas_font_private.h" FT_Library evas_ft_lib = 0; @@ -207,139 +209,27 @@ evas_common_font_get_line_advance(RGBA_Font *fn) // return ret; } +/*DEPRECATED! Should use evas_common_encoding_* instead */ EAPI int evas_common_font_utf8_get_next(const unsigned char *buf, int *iindex) { - /* Reads UTF8 bytes from @buf, starting at *@index and returns - * the decoded code point at iindex offset, and advances iindex - * to the next code point after this. - * - * Returns 0 to indicate there is no next char - */ - int index = *iindex, len, r; - unsigned char d, d2, d3, d4; - - /* if this char is the null terminator, exit */ - if (!buf[index]) - return 0; - - d = buf[index++]; - - while (buf[index] && ((buf[index] & 0xc0) == 0x80)) - index++; - len = index - *iindex; - - if (len == 1) - r = d; - else if (len == 2) - { - /* 2 bytes */ - d2 = buf[*iindex + 1]; - r = d & 0x1f; /* copy lower 5 */ - r <<= 6; - r |= (d2 & 0x3f); /* copy lower 6 */ - } - else if (len == 3) - { - /* 3 bytes */ - d2 = buf[*iindex + 1]; - d3 = buf[*iindex + 2]; - r = d & 0x0f; /* copy lower 4 */ - r <<= 6; - r |= (d2 & 0x3f); - r <<= 6; - r |= (d3 & 0x3f); - } - else - { - /* 4 bytes */ - d2 = buf[*iindex + 1]; - d3 = buf[*iindex + 2]; - d4 = buf[*iindex + 3]; - r = d & 0x0f; /* copy lower 4 */ - r <<= 6; - r |= (d2 & 0x3f); - r <<= 6; - r |= (d3 & 0x3f); - r <<= 6; - r |= (d4 & 0x3f); - } - - *iindex = index; - return r; + return evas_common_encoding_utf8_get_next(buf, iindex); } EAPI int evas_common_font_utf8_get_prev(const unsigned char *buf, int *iindex) { - /* Reads UTF8 bytes from @buf, starting at *@index and returns - * the decoded code point at iindex offset, and advances iindex - * to the prev code point after this. - * - * Returns 0 to indicate there is no prev char - */ - - int r; - int index = *iindex; - /* although when index == 0 there's no previous char, we still want to get - * the current char */ - if (index < 0) - return 0; - - /* First obtain the codepoint at iindex */ - r = evas_common_font_utf8_get_next(buf, &index); - - /* Next advance iindex to previous codepoint */ - index = *iindex; - index--; - while ((index > 0) && ((buf[index] & 0xc0) == 0x80)) - index--; - - *iindex = index; - return r; + return evas_common_encoding_utf8_get_prev(buf, iindex); } EAPI int evas_common_font_utf8_get_last(const unsigned char *buf, int buflen) { - /* jumps to the nul byte at the buffer end and decodes backwards and - * returns the offset index byte in the buffer where the last character - * in the buffer begins. - * - * Returns -1 to indicate an error - */ - int index; - unsigned char d; - - if (buflen < 1) return 0; - index = buflen - 1; - d = buf[index]; - if (!(d & 0x80)) - return index; - else - { - while (index > 0) - { - index--; - d = buf[index]; - if ((d & 0xc0) != 0x80) - return index; - } - } - return 0; + return evas_common_encoding_utf8_get_last(buf, buflen); } EAPI int evas_common_font_utf8_get_len(const unsigned char *buf) { - /* returns the number of utf8 characters (not bytes) in the string */ - int index = 0, len = 0; - - while (buf[index]) - { - if ((buf[index] & 0xc0) != 0x80) - len++; - index++; - } - return len; + return evas_common_encoding_utf8_get_len(buf); } diff --git a/legacy/evas/src/lib/engines/common/evas_font_query.c b/legacy/evas/src/lib/engines/common/evas_font_query.c index 7ecf1964de..26c4486e57 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_query.c +++ b/legacy/evas/src/lib/engines/common/evas_font_query.c @@ -1,5 +1,5 @@ #include "evas_common.h" -#include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */ +#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */ #include "evas_font_private.h" /* for Frame-Queuing support */ EAPI int @@ -56,9 +56,15 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi, return error; } -/* string extents */ +/* size of the string (width and height) in pixels + * BiDi handling: We recieve the shaped string + other props from intl_props, + * We only care about the size, and the size does not depend on the visual order. + * As long as we follow the logical string and get kerning data like we should, + * we are fine. + */ + EAPI void -evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) +evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h) { int use_kerning; int pen_x, pen_y; @@ -78,14 +84,14 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) // evas_common_font_size_use(fn); use_kerning = FT_HAS_KERNING(fi->src->ft.face); prev_index = 0; - for (chr = 0; text[chr];) + for (chr = 0; *text; text++) { FT_UInt index; RGBA_Font_Glyph *fg; - int chr_x, chr_y, chr_w; + int chr_x, chr_y, advw; int gl, kern; - gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); + gl = *text; if (gl == 0) break; index = evas_common_font_glyph_search(fn, &fi, gl); LKL(fi->ft_mutex); @@ -101,9 +107,9 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) /* you want performance */ kern = 0; if ((use_kerning) && (prev_index) && (index) && - (pface == fi->src->ft.face)) - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; + (pface == fi->src->ft.face) && + evas_common_font_query_kerning(fi, prev_index, index, &kern)) + pen_x += kern; pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); @@ -111,21 +117,28 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) if (!fg) continue; if (kern < 0) kern = 0; - chr_x = ((pen_x - kern) + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); -// chr_w = fg->glyph_out->bitmap.width; - chr_w = fg->glyph_out->bitmap.width + kern; - { - int advw; + + /* We care about advancing the whole string size, and not the actual + * paint size of each string, so we only care about advancing correctly + * and not the actual glyph width */ + advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); + chr_x = pen_x - kern; + chr_y = pen_y; + /* If it's not a compositing char, i.e it advances, we should also add + * the left/top padding of the glyph. As we don't care about the padding + * as the drawing location remains the same. + */ + if (advw > 0) + { + chr_x += fg->glyph_out->left; + chr_y += fg->glyph_out->top; + } - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - if (chr_w < advw) chr_w = advw; - } if ((!prev_index) && (chr_x < 0)) start_x = chr_x; - if ((chr_x + chr_w) > end_x) - end_x = chr_x + chr_w; + if ((chr_x + advw) > end_x) + end_x = chr_x + advw; pen_x += fg->glyph->advance.x >> 16; prev_index = index; @@ -136,7 +149,7 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) /* text x inset */ EAPI int -evas_common_font_query_inset(RGBA_Font *fn, const char *text) +evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text) { FT_UInt index; RGBA_Font_Glyph *fg; @@ -147,8 +160,8 @@ evas_common_font_query_inset(RGBA_Font *fn, const char *text) fi = fn->fonts->data; chr = 0; - if (!text[0]) return 0; - gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); + if (!*text) return 0; + gl = *text; if (gl == 0) return 0; // evas_common_font_size_use(fn); index = evas_common_font_glyph_search(fn, &fi, gl); @@ -180,14 +193,20 @@ evas_common_font_query_inset(RGBA_Font *fn, const char *text) return fg->glyph_out->left; } -/* h & v advance */ +/* h & v advance + * BiDi handling: We recieve the shaped string + other props from intl_props, + * We don't care about the order, as heights will remain the same (we already did + * shaping) and as long as we go through the logical string and match the kerning + * this way, we are safe. + */ + EAPI void -evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int *v_adv) +evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *h_adv, int *v_adv) { int use_kerning; int pen_x, pen_y; int start_x; - int chr; + int char_index; FT_UInt prev_index; RGBA_Font_Int *fi; FT_Face pface = NULL; @@ -202,14 +221,13 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int use_kerning = FT_HAS_KERNING(fi->src->ft.face); FTUNLOCK(); prev_index = 0; - for (chr = 0; text[chr];) + for (char_index = 0 ; *text ; text++, char_index++) { FT_UInt index; RGBA_Font_Glyph *fg; - int chr_x, chr_y, chr_w; int gl, kern; - gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); + gl = *text; if (gl == 0) break; index = evas_common_font_glyph_search(fn, &fi, gl); LKL(fi->ft_mutex); @@ -220,105 +238,12 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int FTUNLOCK(); fi->src->current_size = fi->size; } - /* hmmm kerning means i can't sanely do my own cached metric tables! */ - /* grrr - this means font face sharing is kinda... not an option if */ - /* you want performance */ - if ((use_kerning) && (prev_index) && (index) && - (pface == fi->src->ft.face)) - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - - pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); - LKU(fi->ft_mutex); - if (!fg) continue; - - chr_x = (pen_x + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); - chr_w = fg->glyph_out->bitmap.width; - - pen_x += fg->glyph->advance.x >> 16; - prev_index = index; - } - if (v_adv) *v_adv = evas_common_font_get_line_advance(fn); - if (h_adv) *h_adv = pen_x - start_x; -} - -/* x y w h for char at char pos */ -EAPI int -evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos, int *cx, int *cy, int *cw, int *ch) -{ - int use_kerning; - int pen_x, pen_y; - int prev_chr_end; - int chr; - int asc, desc; - int char_index = 0; /* the index of the current char */ - int position; - const char *text = in_text; - int ret_val = 0; - FT_UInt prev_index; - RGBA_Font_Int *fi; - FT_Face pface = NULL; - -#ifdef INTERNATIONAL_SUPPORT - int len = 0; - EvasIntlParType direction = FRIBIDI_TYPE_ON; - EvasIntlLevel *level_list = NULL; - EvasIntlStrIndex *visual_to_logical = NULL; - char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, &visual_to_logical, NULL, &level_list); - text = (visual_text) ? visual_text : in_text; -#endif - - fi = fn->fonts->data; - - pen_x = 0; - pen_y = 0; -// evas_common_font_size_use(fn); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - prev_index = 0; - prev_chr_end = 0; - asc = evas_common_font_max_ascent_get(fn); - desc = evas_common_font_max_descent_get(fn); - - /* find the actual index, not the byte position */ - for (position = 0 , chr = 0 ; in_text[chr] && chr < pos ; position++) { - evas_common_font_utf8_get_next((unsigned char *)in_text, &chr); - } - /* if we couldn't reach the correct position for some reason, - * return with an error */ - if (chr != pos) { - ret_val = 0; - goto end; - } - -#ifdef INTERNATIONAL_SUPPORT - /* if it's an in string position (not end), get logical position */ - if (position < len) - position = evas_intl_position_visual_to_logical(visual_to_logical, position); -#endif - - - for (char_index = 0, chr = 0; text[chr]; char_index++) - { - int pchr; - FT_UInt index; - RGBA_Font_Glyph *fg; - int chr_x, chr_y, chr_w; - int gl, kern; - - pchr = chr; - gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); - if (gl == 0) break; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); + if (!fg) + { + LKU(fi->ft_mutex); + continue; + } // FIXME: Why no FT_Activate_Size here ? kern = 0; /* hmmm kerning means i can't sanely do my own cached metric tables! */ @@ -327,10 +252,14 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos, if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) { -#ifdef INTERNATIONAL_SUPPORT +#ifdef BIDI_SUPPORT /* if it's rtl, the kerning matching should be reversed, i.e prev - * index is now the index and the other way around. */ - if (evas_intl_is_rtl_char(level_list, char_index)) + * index is now the index and the other way around. + * There is a slight exception when there are compositing chars + * involved.*/ + if (intl_props && + evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) && + fg->glyph->advance.x >> 16 > 0) { if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) pen_x += kern; @@ -345,74 +274,57 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos, } pface = fi->src->ft.face; - fg = evas_common_font_int_cache_glyph_get(fi, index); LKU(fi->ft_mutex); - if (!fg) continue; - if (kern < 0) kern = 0; - chr_x = ((pen_x - kern) + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); - chr_w = fg->glyph_out->bitmap.width + (kern); -/* if (text[chr]) */ - { - int advw; - - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - if (chr_w < advw) chr_w = advw; - } - if (chr_x > prev_chr_end) - { - chr_w += (chr_x - prev_chr_end); - chr_x = prev_chr_end; - } - /* we need to see if the char at the visual position is the char wanted */ - if (char_index == position) - { - if (cx) *cx = chr_x; - if (cy) *cy = -asc; - if (cw) *cw = chr_w; - if (ch) *ch = asc + desc; - ret_val = 1; - goto end; - } - prev_chr_end = chr_x + chr_w; pen_x += fg->glyph->advance.x >> 16; prev_index = index; } -end: - -#ifdef INTERNATIONAL_SUPPORT - if (level_list) free(level_list); - if (visual_to_logical) free(visual_to_logical); - if (visual_text) free(visual_text); -#endif - - return ret_val; + if (v_adv) *v_adv = evas_common_font_get_line_advance(fn); + if (h_adv) *h_adv = pen_x - start_x; } -/* char pos of text at xy pos */ +/* x y w h for char at char pos + * BiDi handling: We recieve the shaped string + other props from intl_props, + * We care about the actual drawing location of the string, this is why we need + * the visual string. We need to know how it's printed. After that we need to calculate + * the reverse kerning in case of rtl parts. "pos" passed to this function is an + * index in bytes, that is the actual byte location of the string, we need to find + * the index in order to find it in the visual string. + */ + EAPI int -evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, int y, int *cx, int *cy, int *cw, int *ch) +evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) { int use_kerning; int pen_x, pen_y; int prev_chr_end; - int chr; int asc, desc; int char_index = 0; /* the index of the current char */ - const char *text = in_text; - int ret_val = -1; + int position = 0; + const Eina_Unicode *text = in_text; + int ret_val = 0; + int last_adv; FT_UInt prev_index; RGBA_Font_Int *fi; FT_Face pface = NULL; -#ifdef INTERNATIONAL_SUPPORT +#ifdef BIDI_SUPPORT int len = 0; - EvasIntlParType direction = FRIBIDI_TYPE_ON; - EvasIntlLevel *level_list = NULL; - EvasIntlStrIndex *visual_to_logical = NULL; - char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, &visual_to_logical, &level_list); - text = (visual_text) ? visual_text : in_text; + EvasBiDiStrIndex *visual_to_logical = NULL; + Eina_Unicode *visual_text; + + visual_text = eina_unicode_strdup(in_text); + + if (visual_text) + { + evas_bidi_props_reorder_line(visual_text, intl_props, &visual_to_logical); + text = visual_text; + } + else + { + text = in_text; + } + len = eina_unicode_strlen(text); #endif fi = fn->fonts->data; @@ -432,20 +344,189 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in prev_chr_end = 0; asc = evas_common_font_max_ascent_get(fn); desc = evas_common_font_max_descent_get(fn); - - for (char_index = 0, chr = 0; text[chr]; char_index++) + +#ifdef BIDI_SUPPORT + /* Get the position in the visual string because those are the coords we care about */ + position = evas_bidi_position_logical_to_visual(visual_to_logical, len, pos); +#else + position = pos; +#endif + + last_adv = 0; + for (char_index = 0; *text ; text++, char_index++) + { + FT_UInt index; + RGBA_Font_Glyph *fg; + int chr_x, chr_y, chr_w; + int gl, kern; + + gl = *text; + if (gl == 0) break; + index = evas_common_font_glyph_search(fn, &fi, gl); + LKL(fi->ft_mutex); + fg = evas_common_font_int_cache_glyph_get(fi, index); + if (!fg) + { + LKU(fi->ft_mutex); + continue; + } + // FIXME: Why no FT_Activate_Size here ? + kern = 0; + /* hmmm kerning means i can't sanely do my own cached metric tables! */ + /* grrr - this means font face sharing is kinda... not an option if */ + /* you want performance */ + if ((use_kerning) && (prev_index) && (index) && + (pface == fi->src->ft.face)) + { +#ifdef BIDI_SUPPORT + /* if it's rtl, the kerning matching should be reversed, i.e prev + * index is now the index and the other way around. + * There is a slight exception when there are compositing chars + * involved.*/ + if (intl_props && + evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) && + fg->glyph->advance.x >> 16 > 0) + { + if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) + pen_x += kern; + } + else +#endif + { + + if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) + pen_x += kern; + } + } + + pface = fi->src->ft.face; + LKU(fi->ft_mutex); + /* If the current one is not a compositing char, do the previous advance + * and set the current advance as the next advance to do */ + if (fg->glyph->advance.x >> 16 > 0) + { + pen_x += last_adv; + last_adv = fg->glyph->advance.x >> 16; + } + if (kern < 0) kern = 0; + chr_x = ((pen_x - kern) + (fg->glyph_out->left)); + chr_y = (pen_y + (fg->glyph_out->top)); + chr_w = fg->glyph_out->bitmap.width + (kern); +/* if (text[chr]) */ + { + int advw; + advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); + if (chr_w < advw) chr_w = advw; + } +#if 0 /* This looks like a hack, we don't want it. - leaving it here in case + * I'm wrong */ + if (chr_x > prev_chr_end) + { + chr_w += (chr_x - prev_chr_end); + chr_x = prev_chr_end; + } +#endif + /* we need to see if the char at the visual position is the char wanted */ + if (char_index == position) + { + if (cx) *cx = chr_x; + if (cy) *cy = -asc; + if (cw) *cw = chr_w; + if (ch) *ch = asc + desc; + ret_val = 1; + goto end; + } + prev_chr_end = chr_x + chr_w; + prev_index = index; + } +end: + +#ifdef BIDI_SUPPORT + if (visual_to_logical) free(visual_to_logical); + if (visual_text) free(visual_text); +#endif + + return ret_val; +} + +/* char pos of text at xy pos + * BiDi handling: Since we are looking for the char at the specific coords, + * we have to get the visual string (to which the coords relate to), do + * reverse kerning query because we are working on the visual string, and then + * we need to get the logical position of the char we found from the visual string. + */ + +EAPI int +evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) +{ + int use_kerning; + int pen_x, pen_y; + int prev_chr_end; + int asc, desc; + int char_index = 0; /* the index of the current char */ + const Eina_Unicode *text = in_text; + int last_adv; + int ret_val = -1; + FT_UInt prev_index; + RGBA_Font_Int *fi; + FT_Face pface = NULL; + +#ifdef BIDI_SUPPORT + int len = 0; + EvasBiDiStrIndex *visual_to_logical = NULL; + Eina_Unicode *visual_text; + + visual_text = eina_unicode_strdup(in_text); + + if (visual_text) + { + evas_bidi_props_reorder_line(visual_text, intl_props, &visual_to_logical); + text = visual_text; + } + else + { + text = in_text; + } + len = eina_unicode_strlen(text); +#endif + + fi = fn->fonts->data; + + pen_x = 0; + pen_y = 0; +// evas_common_font_size_use(fn); + if (fi->src->current_size != fi->size) + { + FTLOCK(); + FT_Activate_Size(fi->ft.size); + FTUNLOCK(); + fi->src->current_size = fi->size; + } + use_kerning = FT_HAS_KERNING(fi->src->ft.face); + last_adv = 0; + prev_index = 0; + prev_chr_end = 0; + asc = evas_common_font_max_ascent_get(fn); + desc = evas_common_font_max_descent_get(fn); + + for (char_index = 0; *text; text++, char_index++) { - int pchr; FT_UInt index; RGBA_Font_Glyph *fg; int chr_x, chr_y, chr_w; int gl, kern; - pchr = chr; - gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); + gl = *text; if (gl == 0) break; index = evas_common_font_glyph_search(fn, &fi, gl); LKL(fi->ft_mutex); + fg = evas_common_font_int_cache_glyph_get(fi, index); + if (!fg) + { + LKU(fi->ft_mutex); + continue; + } + // FIXME: Why not FT_Activate_Size here ? kern = 0; /* hmmm kerning means i can't sanely do my own cached metric tables! */ @@ -454,10 +535,14 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) { -#ifdef INTERNATIONAL_SUPPORT +#ifdef BIDI_SUPPORT /* if it's rtl, the kerning matching should be reversed, i.e prev - * index is now the index and the other way around. */ - if (evas_intl_is_rtl_char(level_list, char_index)) + * index is now the index and the other way around. + * There is a slight exception when there are compositing chars + * involved.*/ + if (intl_props && + evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) && + fg->glyph->advance.x >> 16 > 0) { if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) pen_x += kern; @@ -470,16 +555,21 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in pen_x += kern; } } - pface = fi->src->ft.face; - fg = evas_common_font_int_cache_glyph_get(fi, index); LKU(fi->ft_mutex); - if (!fg) continue; - + /* If the current one is not a compositing char, do the previous advance + * and set the current advance as the next advance to do */ + if (fg->glyph->advance.x >> 16 > 0) + { + pen_x += last_adv; + last_adv = fg->glyph->advance.x >> 16; + } if (kern < 0) kern = 0; + chr_x = ((pen_x - kern) + (fg->glyph_out->left)); chr_y = (pen_y + (fg->glyph_out->top)); chr_w = fg->glyph_out->bitmap.width + kern; + /* if (text[chr]) */ { int advw; @@ -487,43 +577,38 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); if (chr_w < advw) chr_w = advw; } +#if 0 /* This looks like a hack, we don't want it. - leaving it here in case + * I'm wrong */ if (chr_x > prev_chr_end) { chr_w += (chr_x - prev_chr_end); chr_x = prev_chr_end; } +#endif if ((x >= chr_x) && (x <= (chr_x + chr_w)) && (y >= -asc) && (y <= desc)) { + int position = char_index; if (cx) *cx = chr_x; if (cy) *cy = -asc; if (cw) *cw = chr_w; if (ch) *ch = asc + desc; -#ifdef INTERNATIONAL_SUPPORT - { - /* we found the char position of the wanted char in the - * visual string, we now need to translate it to the - * position in the logical string */ - int i; - int position = evas_intl_position_visual_to_logical(visual_to_logical, char_index); - - /* ensure even if the list won't run */ - for (pchr = 0, i = 0; i < position; i++) - evas_common_font_utf8_get_next((unsigned char *)in_text, &pchr); - } +#ifdef BIDI_SUPPORT + /* we found the char position of the wanted char in the + * visual string, we now need to translate it to the + * position in the logical string */ + position = evas_bidi_position_visual_to_logical(visual_to_logical, position); #endif - ret_val = pchr; + ret_val = position; goto end; } prev_chr_end = chr_x + chr_w; - pen_x += fg->glyph->advance.x >> 16; prev_index = index; } end: -#ifdef INTERNATIONAL_SUPPORT - if (level_list) free(level_list); +#ifdef BIDI_SUPPORT if (visual_to_logical) free(visual_to_logical); if (visual_text) free(visual_text); #endif @@ -531,17 +616,23 @@ end: return ret_val; } -/* last char pos of text at xy pos - * Note: no need for special rtl handling - * because the string is in logical order, which is correct */ +/* position of the last char in thext text that will fit in xy. + * BiDi handling: We recieve the shaped string + other props from intl_props, + * All we care about is char sizes + kerning so we only really need to get the + * shaped string to utf8, and then just go through it like in english, as it's + * just the logical string, nothing special about that. + */ + EAPI int -evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, int y) +evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int x, int y) { int use_kerning; int pen_x, pen_y; int prev_chr_end; - int chr; + int char_index; int asc, desc; + int ret=-1; + const Eina_Unicode *text = in_text; FT_UInt prev_index; RGBA_Font_Int *fi; FT_Face pface = NULL; @@ -556,16 +647,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in prev_chr_end = 0; asc = evas_common_font_max_ascent_get(fn); desc = evas_common_font_max_descent_get(fn); - for (chr = 0; text[chr];) + for (char_index = 0; *text; text++, char_index++) { - int pchr; FT_UInt index; RGBA_Font_Glyph *fg; int chr_x, chr_y, chr_w; int gl, kern; - pchr = chr; - gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); + gl = *text; if (gl == 0) break; index = evas_common_font_glyph_search(fn, &fi, gl); LKL(fi->ft_mutex); @@ -582,13 +671,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in /* you want performance */ if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - + { + /* No need for special RTL handling because we are working on the logical string*/ + if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) + pen_x += kern; + } pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); LKU(fi->ft_mutex); - if (!fg) continue; if (kern < 0) kern = 0; chr_x = ((pen_x - kern) + (fg->glyph_out->left)); @@ -609,11 +699,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in if ((x >= chr_x) && (x <= (chr_x + chr_w)) && (y >= -asc) && (y <= desc)) { - return pchr; + ret = char_index; + goto end; } prev_chr_end = chr_x + chr_w; pen_x += fg->glyph->advance.x >> 16; prev_index = index; } - return -1; +end: + + return ret; } diff --git a/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.c b/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.c deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.h b/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/legacy/evas/src/lib/engines/common/evas_intl_utils.c b/legacy/evas/src/lib/engines/common/evas_intl_utils.c deleted file mode 100644 index fa74f52833..0000000000 --- a/legacy/evas/src/lib/engines/common/evas_intl_utils.c +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include - -#include "evas_common.h" -#include "evas_intl_utils.h" - -#include "evas_font_private.h" - -#ifdef INTERNATIONAL_SUPPORT -#include - -#define UTF8_BYTES_PER_CHAR 4 - -/* FIXME: fribidi_utf8_to_unicode should use char len and not byte len!*/ -char * -evas_intl_utf8_to_visual(const char *text, - int *ret_len, - EvasIntlParType *direction, - EvasIntlStrIndex **position_L_to_V_list, - EvasIntlStrIndex **position_V_to_L_list, - EvasIntlLevel **embedding_level_list) -{ - FriBidiChar *unicode_in, *unicode_out; - EvasIntlStrIndex *tmp_L_to_V_list = NULL; - EvasIntlStrIndex *tmp_V_to_L_list = NULL; - EvasIntlLevel *tmp_level_list = NULL; - char *text_out; - size_t len; - size_t byte_len; - - if (!text) - return NULL; - - len = evas_string_char_len_get(text); - - byte_len = strlen(text); /* we need the actual number of bytes, not number of chars */ - - unicode_in = (FriBidiChar *)alloca(sizeof(FriBidiChar) * (len + 1)); - FBDLOCK(); - len = fribidi_utf8_to_unicode(text, byte_len, unicode_in); - FBDUNLOCK(); - unicode_in[len] = 0; - - unicode_out = (FriBidiChar *)alloca(sizeof(FriBidiChar) * (len + 1)); - - if (embedding_level_list) - { - *embedding_level_list = (EvasIntlLevel *)malloc(sizeof(EvasIntlLevel) * len); - if (!*embedding_level_list) - { - len = -1; - goto error1; - } - tmp_level_list = *embedding_level_list; - } - - if (position_L_to_V_list) - { - *position_L_to_V_list = (EvasIntlStrIndex *)malloc(sizeof(EvasIntlStrIndex) * len); - if (!*position_L_to_V_list) - { - len = -1; - goto error2; - } - tmp_L_to_V_list = *position_L_to_V_list; - } - - if (position_V_to_L_list) - { - *position_V_to_L_list = (EvasIntlStrIndex *)malloc(sizeof(EvasIntlStrIndex) * len); - if (!*position_V_to_L_list) - { - len = -1; - goto error2; - } - tmp_V_to_L_list = *position_V_to_L_list; - } - - FBDLOCK(); - if (!fribidi_log2vis(unicode_in, len, direction, - unicode_out, tmp_L_to_V_list, tmp_V_to_L_list, tmp_level_list)) - { - FBDUNLOCK(); - len = -2; - goto error2; - } - FBDUNLOCK(); - - text_out = malloc(UTF8_BYTES_PER_CHAR * len + 1); - if (!text_out) - { - len = -1; - goto error2; - } - - FBDLOCK(); - fribidi_unicode_to_utf8(unicode_out, len, text_out); - FBDUNLOCK(); - - *ret_len = len; - return text_out; - -/* ERROR HANDLING */ -error1: - free(*position_V_to_L_list); - *position_V_to_L_list = NULL; -error2: - free(*position_L_to_V_list); - *position_L_to_V_list = NULL; - free(*embedding_level_list); - *embedding_level_list = NULL; - - *ret_len = len; - return NULL; -} - -int -evas_intl_is_rtl_char(EvasIntlLevel *embedded_level_list, EvasIntlStrIndex i) -{ - if(embedded_level_list || i < 0) - return 0; - return FRIBIDI_IS_RTL(embedded_level_list[i]); -} -#endif diff --git a/legacy/evas/src/lib/engines/common/evas_intl_utils.h b/legacy/evas/src/lib/engines/common/evas_intl_utils.h deleted file mode 100644 index 776182a12d..0000000000 --- a/legacy/evas/src/lib/engines/common/evas_intl_utils.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _EVAS_INTL_UTILS -#define _EVAS_INTL_UTILS - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_FRIBIDI -# define USE_FRIBIDI -# define INTERNATIONAL_SUPPORT -#endif - -#ifdef USE_FRIBIDI -# include - -/* abstract fribidi */ -typedef FriBidiChar EvasIntlChar; -typedef FriBidiCharType EvasIntlParType; -typedef FriBidiStrIndex EvasIntlStrIndex; -typedef FriBidiLevel EvasIntlLevel; - - -# define evas_intl_position_logical_to_visual(list, position) \ - (list) ? list[position] : position; - -# define evas_intl_position_visual_to_logical(list, position) \ - (list) ? list[position] : position; - - -int -evas_intl_is_rtl_char(EvasIntlLevel *embedded_level_list, EvasIntlStrIndex i); - -char * -evas_intl_utf8_to_visual(const char *text, - int *ret_len, - EvasIntlParType *direction, - EvasIntlStrIndex **position_L_to_V_list, - EvasIntlStrIndex **position_V_to_L_list, - EvasIntlLevel **embedding_level_list); -#endif - -#endif diff --git a/legacy/evas/src/lib/engines/common/evas_pipe.c b/legacy/evas/src/lib/engines/common/evas_pipe.c index 1fb2376df4..8cb01efb6a 100644 --- a/legacy/evas/src/lib/engines/common/evas_pipe.c +++ b/legacy/evas/src/lib/engines/common/evas_pipe.c @@ -1399,19 +1399,19 @@ evas_common_pipe_text_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Threa #endif evas_common_font_draw(dst, &(context), op->op.text.font, op->op.text.x, op->op.text.y, - op->op.text.text); + op->op.text.text, op->op.text.intl_props); } else { evas_common_font_draw(dst, &(op->context), op->op.text.font, op->op.text.x, op->op.text.y, - op->op.text.text); + op->op.text.text, op->op.text.intl_props); } } EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, - RGBA_Font *fn, int x, int y, const char *text) + RGBA_Font *fn, int x, int y, const char *text, const Evas_BiDi_Props *intl_props) { RGBA_Pipe_Op *op; @@ -1421,6 +1421,7 @@ evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, op->op.text.x = x; op->op.text.y = y; op->op.text.text = strdup(text); + op->op.text.intl_props = intl_props; #ifdef EVAS_FRAME_QUEUING LKL(fn->ref_fq_add); fn->ref_fq[0]++; diff --git a/legacy/evas/src/lib/engines/common/evas_pipe.h b/legacy/evas/src/lib/engines/common/evas_pipe.h index f6609d5642..74111347d3 100644 --- a/legacy/evas/src/lib/engines/common/evas_pipe.h +++ b/legacy/evas/src/lib/engines/common/evas_pipe.h @@ -1,5 +1,6 @@ #ifndef _EVAS_PIPE_H #define _EVAS_PIPE_H +#include "evas_bidi_utils.h" #ifdef BUILD_PTHREAD typedef struct _Thinfo @@ -88,7 +89,7 @@ EAPI void evas_common_pipe_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int EAPI void evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points, int x, int y); EAPI void evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient *gr); EAPI void evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient2 *gr); -EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text); +EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text, const Evas_BiDi_Props *intl_props); EAPI void evas_common_pipe_image_load(RGBA_Image *im); EAPI void evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int smooth, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h); EAPI void evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst, diff --git a/legacy/evas/src/lib/imaging/evas_imaging.c b/legacy/evas/src/lib/imaging/evas_imaging.c index ee073710f8..836daf00ae 100644 --- a/legacy/evas/src/lib/imaging/evas_imaging.c +++ b/legacy/evas/src/lib/imaging/evas_imaging.c @@ -197,36 +197,86 @@ evas_imaging_font_line_advance_get(const Evas_Imaging_Font *fn) EAPI void evas_imaging_font_string_advance_get(const Evas_Imaging_Font *fn, const char *str, int *x, int *y) { + Evas_BiDi_Props intl_props; + Eina_Unicode *ustr; if (!fn) return; - evas_common_font_query_advance(fn->font, str, x, y); + ustr = evas_common_encoding_utf8_to_unicode(str, NULL); +#ifdef BIDI_SUPPORT + evas_bidi_update_props(ustr, &intl_props); +#endif + evas_common_font_query_advance(fn->font, ustr, &intl_props, x, y); +#ifdef BIDI_SUPPORT + evas_bidi_props_clean(&intl_props); +#endif + if (ustr) free(ustr); } EAPI void evas_imaging_font_string_size_query(const Evas_Imaging_Font *fn, const char *str, int *w, int *h) { + Evas_BiDi_Props intl_props; + Eina_Unicode *ustr; if (!fn) return; - evas_common_font_query_size(fn->font, str, w, h); + ustr = evas_common_encoding_utf8_to_unicode(str, NULL); +#ifdef BIDI_SUPPORT + evas_bidi_update_props(ustr, &intl_props); +#endif + evas_common_font_query_size(fn->font, ustr, &intl_props, w, h); +#ifdef BIDI_SUPPORT + evas_bidi_props_clean(&intl_props); +#endif + if (ustr) free(ustr); } EAPI int evas_imaging_font_string_inset_get(const Evas_Imaging_Font *fn, const char *str) { + Eina_Unicode *ustr; + int ret; + if (!fn) return 0; - return evas_common_font_query_inset(fn->font, str); + ustr = evas_common_encoding_utf8_to_unicode(str, NULL); + ret = evas_common_font_query_inset(fn->font, ustr); + if (ustr) free(ustr); + return ret; } EAPI int evas_imaging_font_string_char_coords_get(const Evas_Imaging_Font *fn, const char *str, int pos, int *cx, int *cy, int *cw, int *ch) { + int ret; + Evas_BiDi_Props intl_props; + Eina_Unicode *ustr; if (!fn) return 0; - return evas_common_font_query_char_coords(fn->font, str, pos, cx, cy, cw, ch); + ustr = evas_common_encoding_utf8_to_unicode(str, NULL); +#ifdef BIDI_SUPPORT + evas_bidi_update_props(ustr, &intl_props); +#endif + ret = evas_common_font_query_char_coords(fn->font, ustr, &intl_props, pos, cx, cy, cw, ch); +#ifdef BIDI_SUPPORT + evas_bidi_props_clean(&intl_props); +#endif + if (ustr) free(ustr); + return ret; } EAPI int evas_imaging_font_string_char_at_coords_get(const Evas_Imaging_Font *fn, const char *str, int x, int y, int *cx, int *cy, int *cw, int *ch) { + int ret; + Evas_BiDi_Props intl_props; + Eina_Unicode *ustr; if (!fn) return -1; - return evas_common_font_query_text_at_pos(fn->font, str, x, y, cx, cy, cw, ch); + ustr = evas_common_encoding_utf8_to_unicode(str, NULL); +#ifdef BIDI_SUPPORT + evas_bidi_update_props(ustr, &intl_props); +#endif + ret = evas_common_font_query_char_at_coords(fn->font, ustr, &intl_props, x, y, cx, cy, cw, ch); +#ifdef BIDI_SUPPORT + evas_bidi_props_clean(&intl_props); +#endif + if (ustr) free(ustr); + return ret; } EAPI void diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index 06c8d2a59c..c2889620b2 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -53,7 +53,9 @@ extern EAPI int _evas_log_dom_global; #endif #define CRIT(...) EINA_LOG_DOM_CRIT(_EVAS_DEFAULT_LOG_DOM, __VA_ARGS__) -/*****************************************************************************/ +/************************ Unicode stuff **************************/ +#include "../engines/common/evas_encoding.h" +/*****************************************************************/ #include "evas_options.h" @@ -670,6 +672,7 @@ struct _RGBA_Draw_Context #ifdef BUILD_PIPE_RENDER #include "../engines/common/evas_map_image.h" +#include "../engines/common/evas_bidi_utils.h" struct _RGBA_Pipe_Op { @@ -698,7 +701,8 @@ struct _RGBA_Pipe_Op struct { RGBA_Font *font; int x, y; - char *text; + Eina_Unicode *text; + Evas_BiDi_Props *intl_props; } text; struct { RGBA_Image *src; @@ -1332,4 +1336,5 @@ void evas_font_dir_cache_free(void); #ifdef __cplusplus } #endif + #endif diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index 2c0185799e..136fa797be 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -15,6 +15,7 @@ #include "../file/evas_module.h" #include "../file/evas_path.h" +#include "../engines/common/evas_bidi_utils.h" #ifdef EVAS_MAGIC_DEBUG /* complain when peole pass in wrong object types etc. */ @@ -703,13 +704,13 @@ struct _Evas_Func int (*font_descent_get) (void *data, void *font); int (*font_max_ascent_get) (void *data, void *font); int (*font_max_descent_get) (void *data, void *font); - void (*font_string_size_get) (void *data, void *font, const char *text, int *w, int *h); - int (*font_inset_get) (void *data, void *font, const char *text); - int (*font_h_advance_get) (void *data, void *font, const char *text); - int (*font_v_advance_get) (void *data, void *font, const char *text); - int (*font_char_coords_get) (void *data, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch); - int (*font_char_at_coords_get) (void *data, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch); - void (*font_draw) (void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text); + void (*font_string_size_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h); + int (*font_inset_get) (void *data, void *font, const Eina_Unicode *text); + int (*font_h_advance_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); + int (*font_v_advance_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); + int (*font_char_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); + int (*font_char_at_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); + void (*font_draw) (void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); void (*font_cache_flush) (void *data); void (*font_cache_set) (void *data, int bytes); @@ -724,7 +725,7 @@ struct _Evas_Func void (*image_scale_hint_set) (void *data, void *image, int hint); int (*image_scale_hint_get) (void *data, void *image); - int (*font_last_up_to_pos) (void *data, void *font, const char *text, int x, int y); + int (*font_last_up_to_pos) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y); void (*image_map4_draw) (void *data, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level); void *(*image_map_surface_new) (void *data, int w, int h, int alpha); diff --git a/legacy/evas/src/modules/engines/direct3d/evas_engine.c b/legacy/evas/src/modules/engines/direct3d/evas_engine.c index 5fcd89d7c3..201a275899 100644 --- a/legacy/evas/src/modules/engines/direct3d/evas_engine.c +++ b/legacy/evas/src/modules/engines/direct3d/evas_engine.c @@ -1,3 +1,4 @@ +#include "evas_common.h" /* Also includes international specific stuff */ #include "evas_engine.h" #include "evas_private.h" #include "Evas_Engine_Direct3D.h" @@ -388,7 +389,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { Render_Engine *re = (Render_Engine *)data; RGBA_Image im; @@ -402,7 +403,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y evas_direct3d_font_texture_new, evas_direct3d_font_texture_free, evas_direct3d_font_texture_draw); - evas_common_font_draw(&im, context, font, x, y, text); + evas_common_font_draw(&im, context, font, x, y, text, intl_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL); } diff --git a/legacy/evas/src/modules/engines/directfb/evas_engine.c b/legacy/evas/src/modules/engines/directfb/evas_engine.c index 1960c228be..ce5c0c428b 100644 --- a/legacy/evas/src/modules/engines/directfb/evas_engine.c +++ b/legacy/evas/src/modules/engines/directfb/evas_engine.c @@ -4,6 +4,7 @@ #include #include #include "evas_engine.h" +#include "evas_common.h" /* Also includes international specific stuff */ /* Uses Evas own image_draw primitive, for comparison purposes only. */ //#define DFB_USE_EVAS_IMAGE_DRAW 1 @@ -1041,7 +1042,7 @@ evas_engine_dfb_output_idle_flush(void *data) * memory. */ static void -evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text) +evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { DirectFB_Engine_Image_Entry *eim = surface; IDirectFBSurface *screen; @@ -1053,7 +1054,7 @@ evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, if (!_dfb_lock_and_sync_image(screen, im, DSLF_READ | DSLF_WRITE)) return; - evas_common_font_draw(im, context, font, x, y, text); + evas_common_font_draw(im, context, font, x, y, text, intl_props); evas_common_cpu_end_opt(); im->image.data = NULL; diff --git a/legacy/evas/src/modules/engines/gl_glew/evas_engine.c b/legacy/evas/src/modules/engines/gl_glew/evas_engine.c index 37b0f435e8..def9a843b1 100644 --- a/legacy/evas/src/modules/engines/gl_glew/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_glew/evas_engine.c @@ -1,3 +1,4 @@ +#include "evas_common.h" /* Also includes international specific stuff */ #include "evas_engine.h" int _evas_engine_GL_glew_log_dom = -1; @@ -986,7 +987,7 @@ eng_image_map_surface_free(void *data __UNUSED__, void *surface) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { Render_Engine *re; @@ -1006,7 +1007,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y evas_gl_font_texture_new, evas_gl_font_texture_free, evas_gl_font_texture_draw); - evas_common_font_draw(im, context, font, x, y, text); + evas_common_font_draw(im, context, font, x, y, text, intl_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, diff --git a/legacy/evas/src/modules/engines/gl_sdl/evas_engine.c b/legacy/evas/src/modules/engines/gl_sdl/evas_engine.c index bfbb12086e..fc0b1fff49 100644 --- a/legacy/evas/src/modules/engines/gl_sdl/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_sdl/evas_engine.c @@ -1,4 +1,4 @@ -#include "evas_common.h" +#include "evas_common.h" /* Also includes international specific stuff */ #include "evas_engine.h" #include /* dlopen,dlclose,etc */ @@ -1172,7 +1172,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { Render_Engine *re; @@ -1192,7 +1192,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y evas_gl_font_texture_new, evas_gl_font_texture_free, evas_gl_font_texture_draw); - evas_common_font_draw(im, context, font, x, y, text); + evas_common_font_draw(im, context, font, x, y, text, intl_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, diff --git a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c index b5680359e5..dcb4d49802 100644 --- a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c @@ -1,3 +1,4 @@ +#include "evas_common.h" /* Also includes international specific stuff */ #include "evas_engine.h" #include /* dlopen,dlclose,etc */ @@ -1949,7 +1950,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { Render_Engine *re; @@ -1970,7 +1971,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y evas_gl_font_texture_new, evas_gl_font_texture_free, evas_gl_font_texture_draw); - evas_common_font_draw(im, context, font, x, y, text); + evas_common_font_draw(im, context, font, x, y, text, intl_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, diff --git a/legacy/evas/src/modules/engines/quartz/evas_engine.c b/legacy/evas/src/modules/engines/quartz/evas_engine.c index c19a6bb92a..a22a30b9df 100644 --- a/legacy/evas/src/modules/engines/quartz/evas_engine.c +++ b/legacy/evas/src/modules/engines/quartz/evas_engine.c @@ -1249,7 +1249,7 @@ eng_font_max_descent_get(void *data, void *font) } static void -eng_font_string_size_get(void *data, void *font, const char *text, int *w, int *h) +eng_font_string_size_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int *w, int *h) { Render_Engine *re = (Render_Engine *)data; Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font; @@ -1279,28 +1279,28 @@ eng_font_inset_get(void *data, void *font, const char *text) } static int -eng_font_h_advance_get(void *data, void *font, const char *text) +eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props) { int w; - eng_font_string_size_get(data, font, text, &w, NULL); + eng_font_string_size_get(data, font, text, intl_props, &w, NULL); return w + 2; // FIXME: shouldn't need a constant here. from where do we get word spacing? // it seems we lose the space between differently-styled text in a text block. Why? } static int -eng_font_v_advance_get(void *data, void *font, const char *text) +eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props) { int h; - eng_font_string_size_get(data, font, text, NULL, &h); + eng_font_string_size_get(data, font, text, intl_props, NULL, &h); return h; } static int -eng_font_char_coords_get(void *data, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch) +eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) { Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font; @@ -1320,7 +1320,7 @@ eng_font_char_coords_get(void *data, void *font, const char *text, int pos, int } static int -eng_font_char_at_coords_get(void *data, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch) +eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { // Return the index of the character at the given point, also lookup it's origin x, y, w, and h. Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font; @@ -1332,8 +1332,8 @@ eng_font_char_at_coords_get(void *data, void *font, const char *text, int x, int int stringIndex = (int) CTLineGetStringIndexForPosition(line, CGPointMake(x, y)); // In order to get the character's size and position, look up the position of this character and the next one - eng_font_char_coords_get(data, font, text, stringIndex, cx, cy, NULL, NULL); - eng_font_char_coords_get(data, font, text, stringIndex + 1, cw, NULL, NULL, NULL); + eng_font_char_coords_get(data, font, text, intl_props, stringIndex, cx, cy, NULL, NULL); + eng_font_char_coords_get(data, font, text, intl_props, stringIndex + 1, cw, NULL, NULL, NULL); if (cw && cx) *cw -= *cx; if (ch) *ch = loaded_font->size; @@ -1359,7 +1359,7 @@ eng_font_hinting_can_hint(void *data, int hinting) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text, const Evas_BiDi_Props *intl_props) { Render_Engine *re = (Render_Engine *)data; Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context; diff --git a/legacy/evas/src/modules/engines/quartz/evas_quartz_private.h b/legacy/evas/src/modules/engines/quartz/evas_quartz_private.h index 67e26fc452..89e5cd6343 100644 --- a/legacy/evas/src/modules/engines/quartz/evas_quartz_private.h +++ b/legacy/evas/src/modules/engines/quartz/evas_quartz_private.h @@ -1,6 +1,7 @@ #ifndef _EVAS_QUARTZ_PRIVATE_H_ #define _EVAS_QUARTZ_PRIVATE_H_ +#include "evas_common.h"/* Also includes international specific stuff */ #include "evas_engine.h" CG_EXTERN void CGContextResetClip (CGContextRef); // undocumented CoreGraphics function to clear clip rect/* @@ -93,7 +94,7 @@ static int eng_font_ascent_get(void *data, void *font); static int eng_font_descent_get(void *data, void *font); static int eng_font_max_ascent_get(void *data, void *font); static int eng_font_max_descent_get(void *data, void *font); -static void eng_font_string_size_get(void *data, void *font, const char *text, int *w, int *h); +static void eng_font_string_size_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int *w, int *h); static int eng_font_inset_get(void *data, void *font, const char *text); static int eng_font_h_advance_get(void *data, void *font, const char *text); static int eng_font_v_advance_get(void *data, void *font, const char *text); diff --git a/legacy/evas/src/modules/engines/software_16/evas_engine.c b/legacy/evas/src/modules/engines/software_16/evas_engine.c index 64c354a007..2e7a7c6ba5 100644 --- a/legacy/evas/src/modules/engines/software_16/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_16/evas_engine.c @@ -1,4 +1,4 @@ -#include "evas_common.h" +#include "evas_common.h"/* Also includes international specific stuff */ #include "evas_common_soft16.h" /* @@ -762,55 +762,55 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font) } static void -eng_font_string_size_get(void *data __UNUSED__, void *font, const char *text, int *w, int *h) +eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h) { - evas_common_font_query_size(font, text, w, h); + evas_common_font_query_size(font, text, intl_props, w, h); } static int -eng_font_inset_get(void *data __UNUSED__, void *font, const char *text) +eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text) { return evas_common_font_query_inset(font, text); } static int -eng_font_h_advance_get(void *data __UNUSED__, void *font, const char *text) +eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { int h, v; - evas_common_font_query_advance(font, text, &h, &v); + evas_common_font_query_advance(font, text, intl_props, &h, &v); return h; } static int -eng_font_v_advance_get(void *data __UNUSED__, void *font, const char *text) +eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { int h, v; - evas_common_font_query_advance(font, text, &h, &v); + evas_common_font_query_advance(font, text, intl_props, &h, &v); return v; } static int -eng_font_char_coords_get(void *data __UNUSED__, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch) +eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) { - return evas_common_font_query_char_coords(font, text, pos, cx, cy, cw, ch); + return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch); } static int -eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch) +eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { - return evas_common_font_query_text_at_pos(font, text, x, y, cx, cy, cw, ch); + return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch); } static int -eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const char *text, int x, int y) +eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y) { - return evas_common_font_query_last_up_to_pos(font, text, x, y); + return evas_common_font_query_last_up_to_pos(font, text, intl_props, x, y); } static void -eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text) +eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { static RGBA_Image *im = NULL; Soft16_Image *dst = surface; @@ -823,7 +823,7 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, i soft16_font_glyph_new, soft16_font_glyph_free, soft16_font_glyph_draw); - evas_common_font_draw(im, context, font, x, y, text); + evas_common_font_draw(im, context, font, x, y, text, intl_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, diff --git a/legacy/evas/src/modules/engines/software_16_sdl/evas_engine.c b/legacy/evas/src/modules/engines/software_16_sdl/evas_engine.c index 049da61bea..e0ce570e97 100644 --- a/legacy/evas/src/modules/engines/software_16_sdl/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_16_sdl/evas_engine.c @@ -5,7 +5,7 @@ #include #include -#include "evas_common.h" +#include "evas_common.h"/* Also includes international specific stuff */ #include "evas_engine.h" int _evas_engine_soft16_sdl_log_dom = -1; @@ -877,7 +877,7 @@ evas_engine_sdl16_image_format_get(void *data __UNUSED__, void *image __UNUSED__ } static void -evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text) +evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { static RGBA_Image *im = NULL; SDL_Engine_Image_Entry *eim = surface; @@ -899,7 +899,7 @@ evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, soft16_font_glyph_new, soft16_font_glyph_free, soft16_font_glyph_draw); - evas_common_font_draw(im, context, font, x, y, text); + evas_common_font_draw(im, context, font, x, y, text, intl_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, diff --git a/legacy/evas/src/modules/engines/software_generic/evas_engine.c b/legacy/evas/src/modules/engines/software_generic/evas_engine.c index e99ce018e3..ed2b34e5da 100644 --- a/legacy/evas/src/modules/engines/software_generic/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_generic/evas_engine.c @@ -1,4 +1,4 @@ -#include "evas_common.h" +#include "evas_common.h" /* Also includes international specific stuff */ #include "evas_private.h" /* @@ -983,55 +983,55 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font) } static void -eng_font_string_size_get(void *data __UNUSED__, void *font, const char *text, int *w, int *h) +eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h) { - evas_common_font_query_size(font, text, w, h); + evas_common_font_query_size(font, text, intl_props, w, h); } static int -eng_font_inset_get(void *data __UNUSED__, void *font, const char *text) +eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text) { return evas_common_font_query_inset(font, text); } static int -eng_font_h_advance_get(void *data __UNUSED__, void *font, const char *text) +eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { int h, v; - evas_common_font_query_advance(font, text, &h, &v); + evas_common_font_query_advance(font, text, intl_props, &h, &v); return h; } static int -eng_font_v_advance_get(void *data __UNUSED__, void *font, const char *text) +eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { int h, v; - evas_common_font_query_advance(font, text, &h, &v); + evas_common_font_query_advance(font, text, intl_props, &h, &v); return v; } static int -eng_font_char_coords_get(void *data __UNUSED__, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch) +eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) { - return evas_common_font_query_char_coords(font, text, pos, cx, cy, cw, ch); + return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch); } static int -eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch) +eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { - return evas_common_font_query_text_at_pos(font, text, x, y, cx, cy, cw, ch); + return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch); } static int -eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const char *text, int x, int y) +eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y) { - return evas_common_font_query_last_up_to_pos(font, text, x, y); + return evas_common_font_query_last_up_to_pos(font, text, intl_props, x, y); } static void -eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text) +eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { #ifdef BUILD_PIPE_RENDER if ((cpunum > 1) @@ -1039,11 +1039,11 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, i && evas_common_frameq_enabled() #endif ) - evas_common_pipe_text_draw(surface, context, font, x, y, text); + evas_common_pipe_text_draw(surface, context, font, x, y, text, intl_props); else #endif { - evas_common_font_draw(surface, context, font, x, y, text); + evas_common_font_draw(surface, context, font, x, y, text, intl_props); evas_common_cpu_end_opt(); } } diff --git a/legacy/evas/src/modules/engines/software_sdl/evas_engine.c b/legacy/evas/src/modules/engines/software_sdl/evas_engine.c index db1e590dc0..bc3577c7a5 100644 --- a/legacy/evas/src/modules/engines/software_sdl/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_sdl/evas_engine.c @@ -5,7 +5,7 @@ #include #include -#include "evas_common.h" +#include "evas_common.h" /* Also includes international specific stuff */ #include "evas_engine.h" int _evas_engine_soft_sdl_log_dom = -1; @@ -739,7 +739,7 @@ evas_engine_sdl_image_format_get(void *data __UNUSED__, void *image __UNUSED__) } static void -evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text) +evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { SDL_Engine_Image_Entry *eim = surface; int mustlock_im = 0; @@ -751,7 +751,7 @@ evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, v _SDL_UPDATE_PIXELS(eim); } - evas_common_font_draw((RGBA_Image *) eim->cache_entry.src, context, font, x, y, text); + evas_common_font_draw((RGBA_Image *) eim->cache_entry.src, context, font, x, y, text, intl_props); evas_common_cpu_end_opt(); if (mustlock_im) diff --git a/legacy/evas/src/modules/engines/xrender_x11/evas_engine.c b/legacy/evas/src/modules/engines/xrender_x11/evas_engine.c index 20880d340d..f5d1067da2 100644 --- a/legacy/evas/src/modules/engines/xrender_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/xrender_x11/evas_engine.c @@ -1,4 +1,4 @@ -#include "evas_common.h" +#include "evas_common.h" /* Also includes international specific stuff */ #include "evas_private.h" #include "Evas_Engine_XRender_X11.h" @@ -1484,7 +1484,7 @@ eng_image_cache_get(void *data) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow __UNUSED__, int oh __UNUSED__, const char *text) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) { Render_Engine *re; RGBA_Image *im; @@ -1503,7 +1503,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y re->font_surface_new, re->font_surface_free, re->font_surface_draw); - evas_common_font_draw(im, context, font, x, y, text); + evas_common_font_draw(im, context, font, x, y, text, intl_props); evas_common_draw_context_font_ext_set(context, NULL, NULL,