From e999c88e8094cf6ae543c9cae51d0a34df6fecd2 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Mon, 18 May 2009 06:08:15 +0000 Subject: [PATCH] tasn's rtl pathes and improvements... continued! SVN revision: 40715 --- legacy/edje/src/lib/edje_text.c | 12 +- legacy/evas/src/lib/Evas.h | 1 + legacy/evas/src/lib/canvas/evas_object_text.c | 34 ++ .../src/lib/canvas/evas_object_textblock.c | 19 +- .../src/lib/engines/common/evas_font_draw.c | 29 +- .../src/lib/engines/common/evas_font_main.c | 5 +- .../src/lib/engines/common/evas_font_query.c | 368 +++++++++++++++++- .../common/evas_intl/evas_intl_arabic.c | 6 +- .../common/evas_intl/evas_intl_arabic.h | 4 +- .../src/lib/engines/common/evas_intl_utils.c | 86 ++-- .../src/lib/engines/common/evas_intl_utils.h | 27 +- legacy/evas/src/lib/include/evas_private.h | 1 + .../modules/engines/cairo_x11/evas_engine.c | 13 +- .../engines/software_generic/evas_engine.c | 11 +- 14 files changed, 526 insertions(+), 90 deletions(-) diff --git a/legacy/edje/src/lib/edje_text.c b/legacy/edje/src/lib/edje_text.c index 2ca19eb6a6..21eedc1a7b 100644 --- a/legacy/edje/src/lib/edje_text.c +++ b/legacy/edje/src/lib/edje_text.c @@ -168,13 +168,13 @@ _edje_text_fit_x(Edje *ed, Edje_Real_Part *ep, if (tw > sw) { if (params->text.elipsis != 0.0) - c1 = evas_object_text_char_coords_get(ep->object, - -p + l, th / 2, - NULL, NULL, NULL, NULL); + /* should be the last in text! not the rightmost */ + c1 = evas_object_text_last_up_to_pos(ep->object, + -p + l, th / 2); if (params->text.elipsis != 1.0) - c2 = evas_object_text_char_coords_get(ep->object, - -p + sw - r, th / 2, - NULL, NULL, NULL, NULL); + /* should be the last in text! not the rightmost */ + c2 = evas_object_text_last_up_to_pos(ep->object, + -p + sw - r, th / 2); if ((c1 < 0) && (c2 < 0)) { c1 = 0; diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index 453acf83c0..65a9b448d7 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -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); diff --git a/legacy/evas/src/lib/canvas/evas_object_text.c b/legacy/evas/src/lib/canvas/evas_object_text.c index 1f6d5cbc7a..0bc5347a48 100644 --- a/legacy/evas/src/lib/canvas/evas_object_text.c +++ b/legacy/evas/src/lib/canvas/evas_object_text.c @@ -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. * diff --git a/legacy/evas/src/lib/canvas/evas_object_textblock.c b/legacy/evas/src/lib/canvas/evas_object_textblock.c index 0427ab953d..8ddf2fab7c 100644 --- a/legacy/evas/src/lib/canvas/evas_object_textblock.c +++ b/legacy/evas/src/lib/canvas/evas_object_textblock.c @@ -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 */ diff --git a/legacy/evas/src/lib/engines/common/evas_font_draw.c b/legacy/evas/src/lib/engines/common/evas_font_draw.c index 485c7fbdff..a31fc03a8b 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_draw.c +++ b/legacy/evas/src/lib/engines/common/evas_font_draw.c @@ -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 } diff --git a/legacy/evas/src/lib/engines/common/evas_font_main.c b/legacy/evas/src/lib/engines/common/evas_font_main.c index c8df596658..289c4cdfe9 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_main.c +++ b/legacy/evas/src/lib/engines/common/evas_font_main.c @@ -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) diff --git a/legacy/evas/src/lib/engines/common/evas_font_query.c b/legacy/evas/src/lib/engines/common/evas_font_query.c index cd269153b6..07b2cd45aa 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_query.c +++ b/legacy/evas/src/lib/engines/common/evas_font_query.c @@ -1,5 +1,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 diff --git a/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.c b/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.c index 9c7c0acbb1..b5d1e9d688 100644 --- a/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.c +++ b/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.c @@ -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 */ diff --git a/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.h b/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.h index 182f4d7989..6e75edcc58 100644 --- a/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.h +++ b/legacy/evas/src/lib/engines/common/evas_intl/evas_intl_arabic.h @@ -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 diff --git a/legacy/evas/src/lib/engines/common/evas_intl_utils.c b/legacy/evas/src/lib/engines/common/evas_intl_utils.c index cced211146..97273d6978 100644 --- a/legacy/evas/src/lib/engines/common/evas_intl_utils.c +++ b/legacy/evas/src/lib/engines/common/evas_intl_utils.c @@ -1,23 +1,27 @@ -/* Authors: - * Tom Hacohen (tom@stsob.com) - */ - #include #include #include "evas_common.h" #include "evas_intl_utils.h" -#ifdef USE_FRIBIDI +#ifdef INTERNATIONAL_SUPPORT #include #define UTF8_BYTES_PER_CHAR 4 /* FIXME: fribidi_utf8_to_unicode should use char len and not byte len!*/ char * -evas_intl_utf8_to_visual(const char *text, int *ret_len, 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; diff --git a/legacy/evas/src/lib/engines/common/evas_intl_utils.h b/legacy/evas/src/lib/engines/common/evas_intl_utils.h index ba859211b2..377d2bafcd 100644 --- a/legacy/evas/src/lib/engines/common/evas_intl_utils.h +++ b/legacy/evas/src/lib/engines/common/evas_intl_utils.h @@ -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 +/* 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 diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index 730496645d..aff6511d15 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -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 diff --git a/legacy/evas/src/modules/engines/cairo_x11/evas_engine.c b/legacy/evas/src/modules/engines/cairo_x11/evas_engine.c index 57c3b9ff42..e2bc976b53 100644 --- a/legacy/evas/src/modules/engines/cairo_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/cairo_x11/evas_engine.c @@ -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" }; + diff --git a/legacy/evas/src/modules/engines/software_generic/evas_engine.c b/legacy/evas/src/modules/engines/software_generic/evas_engine.c index 566dddaba0..5492c6fa8b 100644 --- a/legacy/evas/src/modules/engines/software_generic/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_generic/evas_engine.c @@ -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 */ + }; /*