tasn's rtl pathes and improvements... continued!
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 18 May 2009 06:08:15 +0000 (06:08 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 18 May 2009 06:08:15 +0000 (06:08 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@40715 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

13 files changed:
src/lib/Evas.h
src/lib/canvas/evas_object_text.c
src/lib/canvas/evas_object_textblock.c
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
src/lib/engines/common/evas_intl/evas_intl_arabic.h
src/lib/engines/common/evas_intl_utils.c
src/lib/engines/common/evas_intl_utils.h
src/lib/include/evas_private.h
src/modules/engines/cairo_x11/evas_engine.c
src/modules/engines/software_generic/evas_engine.c

index 453acf8..65a9b44 100644 (file)
@@ -648,6 +648,7 @@ extern "C" {
    EAPI Evas_Coord        evas_object_text_inset_get        (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
    EAPI int               evas_object_text_char_pos_get     (const Evas_Object *obj, int pos, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) EINA_ARG_NONNULL(1);
    EAPI int               evas_object_text_char_coords_get  (const Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) EINA_ARG_NONNULL(1);
+   EAPI int               evas_object_text_last_up_to_pos(const Evas_Object *obj, Evas_Coord x, Evas_Coord y) EINA_ARG_NONNULL(1);
    EAPI Evas_Text_Style_Type evas_object_text_style_get     (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
    EAPI void              evas_object_text_style_set        (Evas_Object *obj, Evas_Text_Style_Type type) EINA_ARG_NONNULL(1);
    EAPI void              evas_object_text_shadow_color_set (Evas_Object *obj, int r, int g, int b, int a) EINA_ARG_NONNULL(1);
index 1f6d5cb..0bc5347 100644 (file)
@@ -614,6 +614,40 @@ evas_object_text_char_pos_get(const Evas_Object *obj, int pos, Evas_Coord *cx, E
    return ret;
 }
 
+
+/**
+ * Returns the logical position of the last char in the text
+ * up to the pos given. this is NOT the position of the last char
+ * because of the possibilty of RTL in the text.
+ * To be documented.
+ *
+ * FIXME: To be fixed.
+ *
+ */
+EAPI int
+evas_object_text_last_up_to_pos(const Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Evas_Object_Text *o;
+   int inset;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return -1;
+   MAGIC_CHECK_END();
+   o = (Evas_Object_Text *)(obj->object_data);
+   MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
+   return -1;
+   MAGIC_CHECK_END();
+   if (!o->engine_data) return -1;
+   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);      
+}
+
 /**
  * To be documented.
  *
index 0427ab9..8ddf2fa 100644 (file)
@@ -1540,17 +1540,15 @@ _layout_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt, char *st
 static int
 _layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Item *it)
 {
-   int cx, cy, cw, ch;
-
    if (fmt->font.font)
-     return c->ENFN->font_char_at_coords_get(c->ENDT, fmt->font.font, it->text,
+     return c->ENFN->font_last_up_to_pos(c->ENDT, fmt->font.font, it->text,
                                             c->w - 
                                             c->o->style_pad.l - 
                                             c->o->style_pad.r - 
                                             c->marginl - 
                                             c->marginr -
                                             c->x,
-                                            0, &cx, &cy, &cw, &ch);
+                                            0);
    return -1;
 }
 
@@ -1590,7 +1588,6 @@ _layout_word_start(char *str, int start)
        if (_is_white(chr)) break;
        tp = p;
      }
-   p = tp;
    if (p < 0) p = 0;
    if ((p >= 0) && (_is_white(chr)))
      evas_common_font_utf8_get_next((unsigned char *)(str), &p);
@@ -1858,11 +1855,14 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text
              c->marginl - c->marginr)))
          {
             wrap = _layout_text_cutoff_get(c, fmt, it);
-             if (wrap == 0) wrap = 1;
+            /* next line is instead of that awful wrap = 1*/
+             if (wrap == 0)
+               evas_common_font_utf8_get_next((unsigned char *)str, &wrap);
             if (wrap > 0)
               {
+
                  if (fmt->wrap_word)
-                   {
+                   {                  
                       index = wrap;
                       ch = evas_common_font_utf8_get_next((unsigned char *)str, &index);
                       if (!_is_white(ch))
@@ -1876,7 +1876,10 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text
                              {
                                 _layout_item_text_cutoff(c, it, wrap);
                                 twrap = wrap;
-                                ch = evas_common_font_utf8_get_next((unsigned char *)str, &twrap);
+                                /*we don't want to move next, that's why it's
+                                 * commented out.
+                                 * ch = evas_common_font_utf8_get_next((unsigned char *)str, &twrap);
+                                 */
                                 str = str + twrap;
                              }
                            /* intersects a word */
index 485c7fb..a31fc03 100644 (file)
@@ -2,11 +2,6 @@
  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
  */
 
-/* Internationalization (RTL and Arabic contextualizing)
- * was added by Tom Hacohen (tom@stosb.com)
- */
-
-
 #include "evas_common.h"
 #include "evas_blend_private.h"
 
@@ -177,13 +172,14 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
 
 
 static void
-evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text,
+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
                                )
 {
    int pen_x, pen_y;
    int chr;
+   const char *text = in_text;
    FT_Face pface = NULL;
    FT_UInt prev_index;
    DATA32 *im;
@@ -191,18 +187,17 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
    int char_index = 0; /* the index of the current char */
 
 #ifdef INTERNATIONAL_SUPPORT
-   int bidi_err = 0;
+   int len = 0;
    /*FIXME: should get the direction by parmater */
-   FriBidiCharType direction = FRIBIDI_TYPE_ON;
-   FriBidiLevel *level_list;
+   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 *tmp = evas_intl_utf8_to_visual(text, &bidi_err, &direction, &level_list);
-      text = (tmp) ? tmp : text;
-   }
+   char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, NULL, &level_list);
+   text = (visual_text) ? visual_text : in_text;
+   
 #endif
 
    pen_x = x;
@@ -217,6 +212,7 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
        int gl, kern;
 
        gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+
        if (gl == 0) break;
        index = evas_common_font_glyph_search(fn, &fi, gl);
        /* hmmm kerning means i can't sanely do my own cached metric tables! */
@@ -390,11 +386,8 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
          prev_index = index;
      }
 #ifdef INTERNATIONAL_SUPPORT
-   if (bidi_err >= 0)
-     {
-       free(level_list);
-       free(text);
-     }
+   if (level_list) free(level_list);
+   if (visual_text) free(visual_text);
 #endif
 }
 
index c8df596..289c4cd 100644 (file)
@@ -196,12 +196,13 @@ evas_common_font_utf8_get_prev(const unsigned char *buf, int *iindex)
 
    if (index <= 0)
      return 0;
-   d = buf[index--];
+   index--;
 
    while ((index > 0) && ((buf[index] & 0xc0) == 0x80))
      index--;
    len = *iindex - index;
-
+   d = buf[index];
+   
    if (len == 1)
       r = d;
    else if (len == 2)
index cd26915..07b2cd4 100644 (file)
@@ -1,5 +1,7 @@
 #include "evas_common.h"
 
+#include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */
+
 EAPI int
 evas_common_font_query_kerning(RGBA_Font_Int* fi,
                               FT_UInt prev, FT_UInt index,
@@ -57,7 +59,10 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi,
    return error;
 }
 
-/* string extents */
+/* string extents
+ * Note: no need for special rtl handling
+ * we can assume there's not between languages kerning
+ * and that spaces get the same wide anywhere. */
 EAPI void
 evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
 {
@@ -126,6 +131,7 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
    if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn);
 }
 
+
 /* text x inset */
 EAPI int
 evas_common_font_query_inset(RGBA_Font *fn, const char *text)
@@ -163,7 +169,10 @@ evas_common_font_query_inset(RGBA_Font *fn, const char *text)
    return fg->glyph_out->left;
 }
 
-/* h & v advance */
+/* h & v advance
+ * Note: no need for special rtl handling
+ * we can assume there's not between languages kerning
+ * and that spaces get the same wide anywhere. */
 EAPI void
 evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int *v_adv)
 {
@@ -216,19 +225,34 @@ 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 */
 EAPI int
-evas_common_font_query_char_coords(RGBA_Font *fn, const char *text, int pos, int *cx, int *cy, int *cw, int *ch)
+evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos, int *cx, int *cy, int *cw, int *ch)
 {
    int use_kerning;
    int pen_x, pen_y;
    int prev_chr_end;
    int chr;
    int asc, desc;
+   int char_index = 0; /* the index of the current char */
+   int position;
+   const char *text = in_text;
+   int ret_val = 0;
    FT_UInt prev_index;
    RGBA_Font_Int *fi;
    FT_Face pface = NULL;
 
+#ifdef INTERNATIONAL_SUPPORT
+   int len = 0;
+   EvasIntlParType direction = FRIBIDI_TYPE_ON;
+   EvasIntlLevel *level_list;
+   EvasIntlStrIndex *logical_to_visual;
+
+   char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, &logical_to_visual, NULL, &level_list);
+   text = (visual_text) ? visual_text : in_text;
+#endif
+
    fi = fn->fonts->data;
 
    pen_x = 0;
@@ -239,7 +263,27 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *text, int pos, int
    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];)
+
+   /* find the actual index, not the byte position */
+   position = 0;
+   chr = 0;
+   while (in_text[chr] && chr < pos) {
+      evas_common_font_utf8_get_next((unsigned char *)in_text, &chr);
+      position++;
+   }
+   /* if it's a bad position, break */
+   if (chr != pos) goto end;
+   /* if it's the end, the correct position is one after */
+   if (!in_text[chr]) position++;
+   
+#ifdef INTERNATIONAL_SUPPORT 
+   /* if it's an in string position (not end), get logical position */
+   if (position < len)
+      position = evas_intl_position_logical_to_visual(logical_to_visual, position);
+#endif
+
+
+   for (char_index = 0, chr = 0; text[chr]; char_index++)
      {
        int pchr;
        FT_UInt index;
@@ -249,16 +293,33 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *text, int pos, int
 
        pchr = chr;
        gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       
        if (gl == 0) break;
+
        index = evas_common_font_glyph_search(fn, &fi, gl);
        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 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;
+               }
+             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);
@@ -280,24 +341,171 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *text, int pos, int
             chr_w += (chr_x - prev_chr_end);
             chr_x = prev_chr_end;
          }
-       if (pchr == pos)
+       /* we need to see if the char at the visual position is the char wanted */
+       if (char_index == position)
          {
             if (cx) *cx = chr_x;
             if (cy) *cy = -asc;
             if (cw) *cw = chr_w;
             if (ch) *ch = asc + desc;
-            return 1;
+            ret_val = 1;
+            goto end;
          }
        prev_chr_end = chr_x + chr_w;
        pen_x += fg->glyph->advance.x >> 16;
        prev_index = index;
      }
-   return 0;
+end:
+
+#ifdef INTERNATIONAL_SUPPORT
+   if (level_list) free(level_list);
+   if (logical_to_visual) free(logical_to_visual);
+   if (visual_text) free(visual_text);
+#endif
+
+   return ret_val;
 }
 
 /* char pos of text at xy pos */
 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)
+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)
+{
+   int use_kerning;
+   int pen_x, pen_y;
+   int prev_chr_end;
+   int chr;
+   int asc, desc;
+   int char_index = 0; /* the index of the current char */
+   const char *text = in_text;
+   int ret_val = -1;
+   FT_UInt prev_index;
+   RGBA_Font_Int *fi;
+   FT_Face pface = NULL;
+   
+#ifdef INTERNATIONAL_SUPPORT
+   int len = 0;
+   EvasIntlParType direction = FRIBIDI_TYPE_ON;
+   EvasIntlLevel *level_list;
+   EvasIntlStrIndex *visual_to_logical;
+
+   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;
+#endif
+
+   fi = fn->fonts->data;
+
+   pen_x = 0;
+   pen_y = 0;
+   evas_common_font_size_use(fn);
+   use_kerning = FT_HAS_KERNING(fi->src->ft.face);
+   prev_index = 0;
+   prev_chr_end = 0;
+   asc = evas_common_font_max_ascent_get(fn);
+   desc = evas_common_font_max_descent_get(fn);
+
+   for (char_index = 0, chr = 0; text[chr]; char_index++)
+     {
+       int pchr;
+       FT_UInt index;
+       RGBA_Font_Glyph *fg;
+       int chr_x, chr_y, chr_w;
+        int gl, kern;
+
+       
+
+       gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       if (gl == 0) break;
+       index = evas_common_font_glyph_search(fn, &fi, gl);
+       kern = 0;
+        /* hmmm kerning means i can't sanely do my own cached metric tables! */
+       /* grrr - this means font face sharing is kinda... not an option if */
+       /* you want performance */
+       if ((use_kerning) && (prev_index) && (index) &&
+            (pface == fi->src->ft.face))
+          {
+#ifdef 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;
+               }
+             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);
+       if (!fg) continue;
+
+       if (kern < 0) kern = 0;
+        chr_x = ((pen_x - kern) + (fg->glyph_out->left));
+       chr_y = (pen_y + (fg->glyph_out->top));
+       chr_w = fg->glyph_out->bitmap.width + kern;
+/*     if (text[chr]) */
+         {
+            int advw;
+
+            advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
+            if (chr_w < advw) chr_w = advw;
+         }
+       if (chr_x > prev_chr_end)
+         {
+            chr_w += (chr_x - prev_chr_end);
+            chr_x = prev_chr_end;
+         }
+       if ((x >= chr_x) && (x <= (chr_x + chr_w)) &&
+           (y >= -asc) && (y <= desc))
+         {
+            if (cx) *cx = chr_x;
+            if (cy) *cy = -asc;
+            if (cw) *cw = chr_w;
+            if (ch) *ch = asc + desc;
+#ifdef INTERNATIONAL_SUPPORT
+             {
+               int i;
+               int logical_chr;
+               int position = evas_intl_position_visual_to_logical(visual_to_logical, char_index);
+
+                
+               /* ensure even if the list won't run */
+               pchr = 0;                                       
+               for (logical_chr = 0, i = 0; i <= position; i++) {
+                  pchr = logical_chr;
+                  evas_common_font_utf8_get_next((unsigned char *)in_text, &logical_chr);
+                }
+             }
+#endif
+            ret_val = pchr;
+            goto end;
+         }
+       prev_chr_end = chr_x + chr_w;
+       pen_x += fg->glyph->advance.x >> 16;
+       prev_index = index;
+     }
+
+end:
+   
+#ifdef INTERNATIONAL_SUPPORT
+   if (level_list) free(level_list);
+   if (visual_to_logical) free(visual_to_logical);
+   if (visual_text) free(visual_text);
+#endif
+
+   return ret_val;
+}
+
+/* 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 */
+EAPI int
+evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, int y)
 {
    int use_kerning;
    int pen_x, pen_y;
@@ -362,10 +570,6 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *text, int x, int y
        if ((x >= chr_x) && (x <= (chr_x + chr_w)) &&
            (y >= -asc) && (y <= desc))
          {
-            if (cx) *cx = chr_x;
-            if (cy) *cy = -asc;
-            if (cw) *cw = chr_w;
-            if (ch) *ch = asc + desc;
             return pchr;
          }
        prev_chr_end = chr_x + chr_w;
@@ -374,3 +578,137 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *text, int x, int y
      }
    return -1;
 }
+#if 0
+/* last char pos of text at xy pos */
+EAPI int
+evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *in_text, int x, int y)
+{
+   int use_kerning;
+   int pen_x, pen_y;
+   int prev_chr_end;
+   int chr;
+   int asc, desc;
+   int char_index = 0; /* the index of the current char */
+   const char *text = in_text;
+   int ret_val = -1;
+   FT_UInt prev_index;
+   RGBA_Font_Int *fi;
+   FT_Face pface = NULL;
+   
+#ifdef INTERNATIONAL_SUPPORT
+   int len = 0;
+   EvasIntlParType direction = FRIBIDI_TYPE_ON;
+   EvasIntlLevel *level_list;
+   EvasIntlStrIndex *visual_to_logical;
+
+   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;
+#endif
+
+   fi = fn->fonts->data;
+
+   pen_x = 0;
+   pen_y = 0;
+   evas_common_font_size_use(fn);
+   use_kerning = FT_HAS_KERNING(fi->src->ft.face);
+   prev_index = 0;
+   prev_chr_end = 0;
+   asc = evas_common_font_max_ascent_get(fn);
+   desc = evas_common_font_max_descent_get(fn);
+
+   for (char_index = 0, chr = 0; text[chr]; char_index++)
+     {
+       int pchr;
+       FT_UInt index;
+       RGBA_Font_Glyph *fg;
+       int chr_x, chr_y, chr_w;
+        int gl, kern;
+
+       
+
+       gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       if (gl == 0) break;
+       index = evas_common_font_glyph_search(fn, &fi, gl);
+       kern = 0;
+        /* hmmm kerning means i can't sanely do my own cached metric tables! */
+       /* grrr - this means font face sharing is kinda... not an option if */
+       /* you want performance */
+       if ((use_kerning) && (prev_index) && (index) &&
+            (pface == fi->src->ft.face))
+          {
+#ifdef 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;
+               }
+             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);
+       if (!fg) continue;
+
+       if (kern < 0) kern = 0;
+        chr_x = ((pen_x - kern) + (fg->glyph_out->left));
+       chr_y = (pen_y + (fg->glyph_out->top));
+       chr_w = fg->glyph_out->bitmap.width + kern;
+/*     if (text[chr]) */
+         {
+            int advw;
+
+            advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
+            if (chr_w < advw) chr_w = advw;
+         }
+       if (chr_x > prev_chr_end)
+         {
+            chr_w += (chr_x - prev_chr_end);
+            chr_x = prev_chr_end;
+         }
+       if ((x >= chr_x) && (x <= (chr_x + chr_w)) &&
+           (y >= -asc) && (y <= desc))
+         {
+#ifdef INTERNATIONAL_SUPPORT
+             {
+               /* returs the char at the same position as the char found,
+                * though in the logical string which ensures it's the last
+                */
+               int i;
+               int logical_chr;
+                
+               /* ensure even if the list won't run */
+               pchr = 0;                                       
+               for (logical_chr = 0, i = 0; i <= char_index; i++) {
+                  pchr = logical_chr;
+                  evas_common_font_utf8_get_next((unsigned char *)in_text, &logical_chr);
+                }
+             }
+#endif
+            ret_val = pchr;
+            goto end;
+         }
+       prev_chr_end = chr_x + chr_w;
+       pen_x += fg->glyph->advance.x >> 16;
+       prev_index = index;
+     }
+
+end:
+   
+#ifdef INTERNATIONAL_SUPPORT
+   if (level_list) free(level_list);
+   if (visual_to_logical) free(visual_to_logical);
+   if (visual_text) free(visual_text);
+#endif
+
+   return ret_val;
+}
+
+#endif
index 9c7c0ac..b5d1e9d 100644 (file)
@@ -1,7 +1,3 @@
-/* Authors:
- *     Tom Hacohen (tom@stsob.com)
- */
-
 #include "../evas_intl_utils.h"
 
 #ifdef ARABIC_SUPPORT
@@ -118,7 +114,7 @@ evas_intl_arabic_to_context(FriBidiChar *text)
 
    /* check for empty string */
    if (!*text)
-     return;
+     return 0;
 
    len = _evas_intl_arabic_text_to_isolated(text);
    /*FIXME: make it skip vowels */
index 182f4d7..6e75edc 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef _EVAS_INTL_ARABIC
 #define _EVAS_INTL_ARABIC
 
+#include "evas_intl_utils.h"
+
 int
-evas_intl_arabic_to_context(FriBidiChar *text);
+evas_intl_arabic_to_context(EvasIntlChar *text);
 
 #endif
index cced211..97273d6 100644 (file)
@@ -1,23 +1,27 @@
-/* Authors:
- *     Tom Hacohen (tom@stsob.com)
- */
-
 #include <string.h>
 #include <stdlib.h>
 
 #include "evas_common.h"
 #include "evas_intl_utils.h"
 
-#ifdef USE_FRIBIDI
+#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, FriBidiCharType *direction, FriBidiLevel **embedding_level_list)
+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;
@@ -27,15 +31,6 @@ evas_intl_utf8_to_visual(const char *text, int *ret_len, FriBidiCharType *direct
 
    len = evas_string_char_len_get(text);
 
-   /* if there's nothing to do, return text
-    * one char draws are quite common */
-   if (len <= 1)
-     {
-       *ret_len = len;
-       *embedding_level_list = NULL;
-       return strdup(text);
-     }
-
    byte_len = strlen(text); /* we need the actual number of bytes, not number of chars */
 
    unicode_in = (FriBidiChar *)malloc(sizeof(FriBidiChar) * (len + 1));
@@ -50,33 +45,59 @@ evas_intl_utf8_to_visual(const char *text, int *ret_len, FriBidiCharType *direct
    unicode_out = (FriBidiChar *)malloc(sizeof(FriBidiChar) * (len + 1));
    if (!unicode_out)
      {
-       len = -2;
+       len = -1;
        goto error2;
      }
 
-   *embedding_level_list = (FriBidiLevel *)malloc(sizeof(FriBidiLevel) * len);
-   if (!*embedding_level_list)
-     {
-       len = -3;
-       goto error3;
-     }
-
+   if (embedding_level_list)
+      {
+         *embedding_level_list = (EvasIntlLevel *)malloc(sizeof(EvasIntlLevel) * len);
+         if (!*embedding_level_list)
+           {
+             len = -1;
+             goto error3;
+           }
+        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 error4;
+           }
+        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 error5;
+           }
+        tmp_V_to_L_list = *position_V_to_L_list;
+      }
+      
 #ifdef ARABIC_SUPPORT
    /* fix arabic context */
    evas_intl_arabic_to_context(unicode_in);
 #endif
    if (!fribidi_log2vis(unicode_in, len, direction,
-           unicode_out, NULL, NULL, *embedding_level_list))
+           unicode_out, tmp_L_to_V_list, tmp_V_to_L_list, tmp_level_list))
      {
-       len = -4;
-       goto error3;
+       len = -2;
+       goto error5;
      }
 
    text_out = malloc(UTF8_BYTES_PER_CHAR * len + 1);
    if (!text_out)
      {
-       len = -5;
-       goto error4;
+       len = -1;
+       goto error6;
      }
 
    fribidi_unicode_to_utf8(unicode_out, len, text_out);
@@ -88,10 +109,17 @@ evas_intl_utf8_to_visual(const char *text, int *ret_len, FriBidiCharType *direct
    return text_out;
 
    /* ERROR HANDLING */
-error4:
+error6:
    free(unicode_out);
+error5:
+   free(*position_V_to_L_list);
+   *position_V_to_L_list = NULL;
+error4:
+   free(*position_L_to_V_list);
+   *position_L_to_V_list = NULL;
 error3:
    free(*embedding_level_list);
+   *embedding_level_list = NULL;
 error2:
    free(unicode_in);
 error1:
@@ -101,7 +129,7 @@ error1:
 }
 
 int
-evas_intl_is_rtl_char(FriBidiLevel *embedded_level_list, FriBidiStrIndex i)
+evas_intl_is_rtl_char(EvasIntlLevel *embedded_level_list, EvasIntlStrIndex i)
 {
    if(embedded_level_list || i < 0)
      return 0;
index ba85921..377d2ba 100644 (file)
@@ -4,25 +4,44 @@
 #include "config.h"
 
 #ifdef HAVE_FRIBIDI_FRIBIDI_H
-#define USE_FRIBIDI 1
+#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;
+
+
 /* whether should fix arabic specifix issues */
-#define ARABIC_SUPPORT 1
+#define ARABIC_SUPPORT
 
 #ifdef ARABIC_SUPPORT
 #include "evas_intl/evas_intl_arabic.h"
 #endif
 
+#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(FriBidiLevel *embedded_level_list, FriBidiStrIndex i);
+evas_intl_is_rtl_char(EvasIntlLevel *embedded_level_list, EvasIntlStrIndex i);
 
 char *
-evas_intl_utf8_to_visual(const char *text, int *ret_len, FriBidiCharType *direction, FriBidiLevel **embedding_level_list);
+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 7304966..aff6511 100644 (file)
@@ -684,6 +684,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);
 };
 
 struct _Evas_Image_Load_Func
index 57c3b9f..e2bc976 100644 (file)
@@ -121,6 +121,8 @@ static int eng_font_cache_get(void *data);
 static void eng_font_hinting_set(void *data, void *font, int hinting);
 static int eng_font_hinting_can_hint(void *data, int hinting);
 
+static int eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const char *text, int x, int y);
+
 typedef struct _Render_Engine Render_Engine;
 
 struct _Render_Engine
@@ -244,7 +246,9 @@ static Evas_Func eng_func =
      eng_font_hinting_can_hint,
      
      eng_image_scale_hint_set,
-     eng_image_scale_hint_get
+     eng_image_scale_hint_get,
+     /* more font draw functions */
+     eng_font_last_up_to_pos
 };
 
 static void *
@@ -1478,6 +1482,12 @@ eng_font_hinting_can_hint(void *data, int hinting)
    re = (Render_Engine *)data;
 }
 
+static int
+eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const char *text, int x, int y)
+{
+   return evas_common_font_query_last_up_to_pos(font, text, x, y);
+}
+
 EAPI int
 module_open(Evas_Module *em)
 {
@@ -1499,3 +1509,4 @@ EAPI Evas_Module_Api evas_modapi =
      "cairo_x11",
      "none"
 };
+
index 566ddda..5492c6f 100644 (file)
@@ -917,6 +917,12 @@ eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const char *text,
    return evas_common_font_query_text_at_pos(font, text, 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)
+{
+   return evas_common_font_query_last_up_to_pos(font, text, 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)
 {
@@ -1109,8 +1115,11 @@ static Evas_Func func =
      eng_font_hinting_set,
      eng_font_hinting_can_hint,
      eng_image_scale_hint_set,
-     eng_image_scale_hint_get
+     eng_image_scale_hint_get,
+     /* more font draw functions */
+     eng_font_last_up_to_pos
      /* FUTURE software generic calls go here */
+
 };
 
 /*