Evas: Changing the font engine to work with Eina_Unicode instead of utf8.
authortasn <tasn@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 28 Jul 2010 12:00:41 +0000 (12:00 +0000)
committertasn <tasn@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 28 Jul 2010 12:00:41 +0000 (12:00 +0000)
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.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@50595 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

33 files changed:
configure.ac
src/lib/canvas/evas_object_text.c
src/lib/canvas/evas_object_textblock.c
src/lib/engines/common/Makefile.am
src/lib/engines/common/evas_bidi_utils.c [new file with mode: 0644]
src/lib/engines/common/evas_bidi_utils.h [new file with mode: 0644]
src/lib/engines/common/evas_encoding.c [new file with mode: 0644]
src/lib/engines/common/evas_encoding.h [new file with mode: 0644]
src/lib/engines/common/evas_font.h
src/lib/engines/common/evas_font_draw.c
src/lib/engines/common/evas_font_main.c
src/lib/engines/common/evas_font_query.c
src/lib/engines/common/evas_intl/evas_intl_arabic.c [deleted file]
src/lib/engines/common/evas_intl/evas_intl_arabic.h [deleted file]
src/lib/engines/common/evas_intl_utils.c [deleted file]
src/lib/engines/common/evas_intl_utils.h [deleted file]
src/lib/engines/common/evas_pipe.c
src/lib/engines/common/evas_pipe.h
src/lib/imaging/evas_imaging.c
src/lib/include/evas_common.h
src/lib/include/evas_private.h
src/modules/engines/direct3d/evas_engine.c
src/modules/engines/directfb/evas_engine.c
src/modules/engines/gl_glew/evas_engine.c
src/modules/engines/gl_sdl/evas_engine.c
src/modules/engines/gl_x11/evas_engine.c
src/modules/engines/quartz/evas_engine.c
src/modules/engines/quartz/evas_quartz_private.h
src/modules/engines/software_16/evas_engine.c
src/modules/engines/software_16_sdl/evas_engine.c
src/modules/engines/software_generic/evas_engine.c
src/modules/engines/software_sdl/evas_engine.c
src/modules/engines/xrender_x11/evas_engine.c

index ce24f37..31a6a7d 100644 (file)
@@ -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])
index 4905301..de41599 100644 (file)
@@ -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;
index c19a91b..e2095f0 100644 (file)
@@ -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();
index 5ad9142..e1d66bf 100644 (file)
@@ -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/src/lib/engines/common/evas_bidi_utils.c b/src/lib/engines/common/evas_bidi_utils.c
new file mode 100644 (file)
index 0000000..f15f81f
--- /dev/null
@@ -0,0 +1,202 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include "evas_common.h"
+#include "evas_bidi_utils.h"
+#include "evas_encoding.h"
+
+#include "evas_font_private.h"
+
+#ifdef BIDI_SUPPORT
+#include <fribidi/fribidi.h>
+
+#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/src/lib/engines/common/evas_bidi_utils.h b/src/lib/engines/common/evas_bidi_utils.h
new file mode 100644 (file)
index 0000000..3358f20
--- /dev/null
@@ -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 <fribidi/fribidi.h>
+#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/src/lib/engines/common/evas_encoding.c b/src/lib/engines/common/evas_encoding.c
new file mode 100644 (file)
index 0000000..d25c1f8
--- /dev/null
@@ -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/src/lib/engines/common/evas_encoding.h b/src/lib/engines/common/evas_encoding.h
new file mode 100644 (file)
index 0000000..4095b63
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef EVAS_ENCODING_H
+#define EVAS_ENCODING_H
+#include <Eina.h>
+
+/* 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
index e776fe4..5d320a9 100644 (file)
@@ -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);
index 078d98d..a00fe81 100644 (file)
@@ -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;
 }
 
index d53380d..05b9d75 100644 (file)
@@ -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);
 }
index 7ecf196..26c4486 100644 (file)
@@ -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,22 +238,43 @@ 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! */
+       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))
-         if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
-           pen_x += kern;
+            (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;
-       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;
@@ -244,30 +283,48 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int
    if (h_adv) *h_adv = pen_x - start_x;
 }
 
-/* x y w h for char at char 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_char_coords(RGBA_Font *fn, const char *in_text, int pos, 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 */
-   int position;
-   const char *text = in_text;
+   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, &visual_to_logical, NULL, &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;
@@ -288,37 +345,31 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
    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);
+#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
 
-
-   for (char_index = 0, chr = 0; text[chr]; char_index++)
+   last_adv = 0;
+   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;
+   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 no FT_Activate_Size here ?
        kern = 0;
         /* hmmm kerning means i can't sanely do my own cached metric tables! */
@@ -327,10 +378,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;
@@ -343,31 +398,37 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
                      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);
+        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;
@@ -376,13 +437,11 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
             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
@@ -390,29 +449,45 @@ end:
    return ret_val;
 }
 
-/* char pos of text at xy pos */
+/* 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_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_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 chr;
    int asc, desc;
    int char_index = 0; /* the index of the current char */
-   const char *text = in_text;
+   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 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;
@@ -428,24 +503,30 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
         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, chr = 0; text[chr]; char_index++)
+
+   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/src/lib/engines/common/evas_intl/evas_intl_arabic.c b/src/lib/engines/common/evas_intl/evas_intl_arabic.c
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/lib/engines/common/evas_intl/evas_intl_arabic.h b/src/lib/engines/common/evas_intl/evas_intl_arabic.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/lib/engines/common/evas_intl_utils.c b/src/lib/engines/common/evas_intl_utils.c
deleted file mode 100644 (file)
index fa74f52..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-
-#include "evas_common.h"
-#include "evas_intl_utils.h"
-
-#include "evas_font_private.h"
-
-#ifdef INTERNATIONAL_SUPPORT
-#include <fribidi/fribidi.h>
-
-#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/src/lib/engines/common/evas_intl_utils.h b/src/lib/engines/common/evas_intl_utils.h
deleted file mode 100644 (file)
index 776182a..0000000
+++ /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 <fribidi/fribidi.h>
-
-/* 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
index 1fb2376..8cb01ef 100644 (file)
@@ -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]++;
index f6609d5..7411134 100644 (file)
@@ -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,
index ee07371..836daf0 100644 (file)
@@ -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
index 06c8d2a..c288962 100644 (file)
@@ -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
index 2c01857..136fa79 100644 (file)
@@ -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);
index 5fcd89d..201a275 100644 (file)
@@ -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);
 }
 
index 1960c22..ce5c0c4 100644 (file)
@@ -4,6 +4,7 @@
 #include <sys/time.h>
 #include <time.h>
 #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;
index 37b0f43..def9a84 100644 (file)
@@ -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,
index bfbb120..fc0b1ff 100644 (file)
@@ -1,4 +1,4 @@
-#include "evas_common.h"
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_engine.h"
 
 #include <dlfcn.h>      /* 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,
index b568035..dcb4d49 100644 (file)
@@ -1,3 +1,4 @@
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_engine.h"
 
 #include <dlfcn.h>      /* 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,
index c19a6bb..a22a30b 100644 (file)
@@ -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;
index 67e26fc..89e5cd6 100644 (file)
@@ -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);
index 64c354a..2e7a7c6 100644 (file)
@@ -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,
index 049da61..e0ce570 100644 (file)
@@ -5,7 +5,7 @@
 #include <time.h>
 #include <SDL/SDL.h>
 
-#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,
index e99ce01..ed2b34e 100644 (file)
@@ -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();
      }
 }
index db1e590..bc3577c 100644 (file)
@@ -5,7 +5,7 @@
 #include <time.h>
 #include <SDL/SDL.h>
 
-#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)
index 20880d3..f5d1067 100644 (file)
@@ -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,