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])
-#include "evas_common.h"
+#include "evas_common.h" /* Includes evas_bidi_utils stuff. */
#include "evas_private.h"
/* save typing */
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;
{
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);
* @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();
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;
obj->layer->evas->last_timestamp,
NULL);
evas_object_inform_call_resize(obj);
+ if (text) free(text);
}
/**
MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
return NULL;
MAGIC_CHECK_END();
- return o->cur.text;
+ return o->cur.utf8_text;
}
/**
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);
}
/**
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);
}
/**
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;
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);
}
/**
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;
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;
}
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;
}
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);
}
/**
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;
}
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);
}
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)) \
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)
(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)) ||
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;
* 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"
/* 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
{
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;
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
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;
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)
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);
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;
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);
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);
}
}
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
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))
{
}
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))
{
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)
{
{
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;
}
}
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 -
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;
}
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);
}
{
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;
_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)
{
#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;
/* 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);
/* 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;
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));
}
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));
}
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));
}
{
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 */
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) >
{
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))
{
* commented out.
* ch = evas_common_font_utf8_get_next((unsigned char *)str, &twrap);
*/
- str = str + twrap;
+ str += twrap;
}
/* intersects a word */
else
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)
{
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;
{
/* 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;
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;
}
else if (fmt->wrap_char)
{
_layout_item_text_cutoff(c, it, wrap);
- str = str + wrap;
+ str += wrap;
}
new_line = 1;
}
{
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;
if (twrap >= 0)
_layout_item_text_cutoff(c, it, twrap);
if (wrap >= 0)
- str = str + wrap;
+ str += wrap;
else
str = NULL;
}
{
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
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));
}
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;
}
}
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)
{
/* 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);
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;
*/
}
}
+ /* 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:
}
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;
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))
}
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)
{
{
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)
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) |
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)
{
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;
*adv = mc - map_itr;
return escape;
}
- _advance_after_end_of_string(&map_itr);
+ _escaped_advance_after_end_of_string(&map_itr);
}
return NULL;
}
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;
}
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)
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;
{
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);
{
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);
}
}
{
- 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);
}
}
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)
{
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++;
}
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;
p++;
}
}
+ free(base);
}
}
o->markup_text = eina_strbuf_string_steal(txt);
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)
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;
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;
{
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;
}
}
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)
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
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)
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;
* @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)
{
{
if (o->cursor->pos > cur->pos)
{
- o->cursor->pos += strlen(text);
+ o->cursor->pos += eina_unicode_strlen(text);
}
}
}
{
if (data->pos > cur->pos)
{
- data->pos += strlen(text);
+ data->pos += eina_unicode_strlen(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),
}
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;
}
_nodes_adjacent_merge(cur->obj, n);
evas_object_change(cur->obj);
+ free(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;
(o->cursor->node->type == NODE_TEXT) &&
(o->cursor->pos >= cur->pos))
{
- o->cursor->pos += strlen(text);
+ o->cursor->pos += eina_unicode_strlen(text);
}
}
}
(data->node->type == NODE_TEXT) &&
(data->pos >= cur->pos))
{
- data->pos += strlen(text);
+ data->pos += eina_unicode_strlen(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),
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;
}
_nodes_adjacent_merge(cur->obj, n);
evas_object_change(cur->obj);
+ free(text);
}
/**
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));
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;
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));
{
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),
{
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;
{
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)
}
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);
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)
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)
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;
{
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);
}
}
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)
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);
}
}
{
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);
}
}
}
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
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)
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);
}
}
{
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);
}
}
* @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)
{
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;
}
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;
}
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;
}
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++;
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;
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;
}
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)
{
{
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;
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;
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)
free(o);
}
+
static void
evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
{
(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; \
}
ITEM_WALK_END();
+ /* prepare everything for text draw */
+
/* shadows */
ITEM_WALK();
ITEM_WALK_LINE_SKIP_DROP();
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 \
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
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 \
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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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;
+}
+
+
--- /dev/null
+#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
#ifndef _EVAS_FONT_H
#define _EVAS_FONT_H
+#include "evas_bidi_utils.h"
/* main */
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);
/* 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);
#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
int size;
struct cinfo *cinfo;
RGBA_Font *font;
- const char *str;
+ const Eina_Unicode *str;
int len;
DATA8 *im;
int roww;
FT_UInt index;
struct { int x, y; } pos;
int posx;
- char chr;
RGBA_Font_Glyph *fg;
struct {
int w,h;
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)
}
-
+/*
+ * 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;
#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;
#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);
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)
{
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));
}
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;
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
);
{
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
);
}
-
+/* 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;
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;
}
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);
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;
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;
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;
}
#include "evas_common.h"
#include "evas_private.h"
+#include "evas_encoding.h"
+
#include "evas_font_private.h"
FT_Library evas_ft_lib = 0;
// 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);
}
#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
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;
// 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);
/* 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);
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;
/* 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;
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);
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;
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);
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;
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;
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! */
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;
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;
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
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;
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! */
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;
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;
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
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;
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);
/* 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));
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;
}
+++ /dev/null
-#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
+++ /dev/null
-#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
#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;
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]++;
#ifndef _EVAS_PIPE_H
#define _EVAS_PIPE_H
+#include "evas_bidi_utils.h"
#ifdef BUILD_PTHREAD
typedef struct _Thinfo
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,
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
#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"
#ifdef BUILD_PIPE_RENDER
#include "../engines/common/evas_map_image.h"
+#include "../engines/common/evas_bidi_utils.h"
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;
#ifdef __cplusplus
}
#endif
+
#endif
#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. */
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);
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);
+#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
#include "evas_private.h"
#include "Evas_Engine_Direct3D.h"
}
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;
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);
}
#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
* 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;
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;
+#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
int _evas_engine_GL_glew_log_dom = -1;
}
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;
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,
-#include "evas_common.h"
+#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
#include <dlfcn.h> /* dlopen,dlclose,etc */
}
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;
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,
+#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
#include <dlfcn.h> /* dlopen,dlclose,etc */
}
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;
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,
}
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;
}
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;
}
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;
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;
}
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;
#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/*
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);
-#include "evas_common.h"
+#include "evas_common.h"/* Also includes international specific stuff */
#include "evas_common_soft16.h"
/*
}
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;
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,
#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;
}
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;
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,
-#include "evas_common.h"
+#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_private.h"
/*
}
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)
&& 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();
}
}
#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;
}
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;
_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)
-#include "evas_common.h"
+#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_private.h"
#include "Evas_Engine_XRender_X11.h"
}
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;
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,