Evas: Changing the font engine to work with Eina_Unicode instead of utf8.

Changing textblock and text objects to work with Eina_Unicode instead of utf8 (internally, API remains intact).
Started relying on new fribidi 0.19.2 instead of the old fribidi.
A lot of fixes to the font engine.
Renaming of evas_common_font_utf8_* to evas_common_encoding_utf8_*
This relies on new Eina changes and types: Eina_Unicode, Eina_UStrbuf and Eina_UStringshare.

SVN revision: 50595
This commit is contained in:
Tom Hacohen 2010-07-28 12:00:41 +00:00
parent 1a0f8b1c51
commit a6d428334f
33 changed files with 1637 additions and 975 deletions

View File

@ -280,7 +280,7 @@ AC_ARG_ENABLE([fribidi],
if test "x${want_fribidi}" = "xyes" -o "x${want_fribidi}" = "xauto" ; then
PKG_CHECK_MODULES([FRIBIDI],
[fribidi],
[fribidi >= 0.19.2],
[
have_fribidi="yes"
AC_DEFINE(HAVE_FRIBIDI, 1, [have fribidi support])

View File

@ -1,4 +1,4 @@
#include "evas_common.h"
#include "evas_common.h" /* Includes evas_bidi_utils stuff. */
#include "evas_private.h"
/* save typing */
@ -16,15 +16,17 @@ struct _Evas_Object_Text
DATA32 magic;
struct {
const char *text;
const char *font;
const char *source;
Evas_Font_Size size;
const Eina_Unicode *text; /*The shaped text */
const char *utf8_text; /* The text exposed to the API */
const char *font;
const char *source;
Evas_Font_Size size;
struct {
unsigned char r, g, b, a;
} outline, shadow, glow, glow2;
unsigned char style;
Evas_BiDi_Props intl_props;
} cur, prev;
float ascent, descent;
@ -227,8 +229,11 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
{
int w, h;
ENFN->font_string_size_get(ENDT, o->engine_data, o->cur.text, &w, &h);
o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data);
o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data);
ENFN->font_string_size_get(ENDT,
o->engine_data,
o->cur.text, &o->cur.intl_props,
&w, &h); o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data);
o->descent = ENFN->font_descent_get(ENDT, o->engine_data);
o->max_ascent = ENFN->font_max_ascent_get(ENDT, o->engine_data);
o->max_descent = ENFN->font_max_descent_get(ENDT, o->engine_data);
@ -316,12 +321,12 @@ evas_object_text_font_get(const Evas_Object *obj, const char **font, Evas_Font_S
* @param text Text to display.
*/
EAPI void
evas_object_text_text_set(Evas_Object *obj, const char *text)
evas_object_text_text_set(Evas_Object *obj, const char *_text)
{
Evas_Object_Text *o;
int is, was;
if (!text) text = "";
Eina_Unicode *text;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
@ -329,24 +334,48 @@ evas_object_text_text_set(Evas_Object *obj, const char *text)
MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
return;
MAGIC_CHECK_END();
if ((o->cur.text) && (text) && (!strcmp(o->cur.text, text))) return;
text = evas_common_encoding_utf8_to_unicode(_text, NULL);
if (!text) text = eina_unicode_strdup(EINA_UNICODE_EMPTY_STRING);
if ((o->cur.text) && (text) && (!eina_unicode_strcmp(o->cur.text, text)))
{
free(text);
return;
}
was = evas_object_is_in_output_rect(obj,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y, 1, 1);
/* DO II */
/*
if (o->cur.text) eina_stringshare_del(o->cur.text);
if ((text) && (*text)) o->cur.text = eina_stringshare_add(text);
else o->cur.text = NULL;
*/
eina_stringshare_replace(&o->cur.text, text);
/*Update intl_props*/
#ifdef BIDI_SUPPORT
evas_bidi_update_props(text, &o->cur.intl_props);
#endif
if (o->cur.text) eina_ustringshare_del(o->cur.text);
if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
if ((text) && (*text))
{
o->cur.text = eina_ustringshare_add(text);
o->cur.utf8_text = eina_stringshare_add(_text);
}
else
{
o->cur.text = NULL;
o->cur.utf8_text = NULL;
}
o->prev.text = NULL;
if ((o->engine_data) && (o->cur.text))
{
int w, h;
int l = 0, r = 0, t = 0, b = 0;
ENFN->font_string_size_get(ENDT, o->engine_data, o->cur.text, &w, &h);
ENFN->font_string_size_get(ENDT,
o->engine_data,
o->cur.text, &o->cur.intl_props,
&w, &h);
evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
obj->cur.geometry.w = w + l + r;
obj->cur.geometry.h = h + t + b;
@ -375,6 +404,7 @@ evas_object_text_text_set(Evas_Object *obj, const char *text)
obj->layer->evas->last_timestamp,
NULL);
evas_object_inform_call_resize(obj);
if (text) free(text);
}
/**
@ -394,7 +424,7 @@ evas_object_text_text_get(const Evas_Object *obj)
MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
return NULL;
MAGIC_CHECK_END();
return o->cur.text;
return o->cur.utf8_text;
}
/**
@ -524,7 +554,7 @@ evas_object_text_horiz_advance_get(const Evas_Object *obj)
MAGIC_CHECK_END();
if (!o->engine_data) return 0;
if (!o->cur.text) return 0;
return ENFN->font_h_advance_get(ENDT, o->engine_data, o->cur.text);
return ENFN->font_h_advance_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props);
}
/**
@ -547,7 +577,7 @@ evas_object_text_vert_advance_get(const Evas_Object *obj)
MAGIC_CHECK_END();
if (!o->engine_data) return 0;
if (!o->cur.text) return o->ascent + o->descent;
return ENFN->font_v_advance_get(ENDT, o->engine_data, o->cur.text);
return ENFN->font_v_advance_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props);
}
/**
@ -587,7 +617,7 @@ evas_object_text_char_pos_get(const Evas_Object *obj, int pos, Evas_Coord *cx, E
if (!o->cur.text) return EINA_FALSE;
inset =
ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
ret = ENFN->font_char_coords_get(ENDT, o->engine_data, o->cur.text,
ret = ENFN->font_char_coords_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props,
pos, &x, &y, &w, &h);
evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
y += o->max_ascent - t;
@ -640,8 +670,11 @@ evas_object_text_last_up_to_pos(const Evas_Object *obj, Evas_Coord x, Evas_Coord
if (!o->cur.text) return -1;
inset =
ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
return ENFN->font_last_up_to_pos(ENDT, o->engine_data, o->cur.text,
x + inset, y - o->max_ascent);
return ENFN->font_last_up_to_pos(ENDT,
o->engine_data,
o->cur.text, &o->cur.intl_props,
x + inset,
y - o->max_ascent);
}
/**
@ -669,9 +702,13 @@ evas_object_text_char_coords_get(const Evas_Object *obj, Evas_Coord x, Evas_Coor
if (!o->cur.text) return -1;
inset =
ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
ret = ENFN->font_char_at_coords_get(ENDT, o->engine_data, o->cur.text,
x + inset, y - o->max_ascent,
&rx, &ry, &rw, &rh);
ret = ENFN->font_char_at_coords_get(ENDT,
o->engine_data,
o->cur.text, &o->cur.intl_props,
x + inset,
y - o->max_ascent,
&rx, &ry,
&rw, &rh);
evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
ry += o->max_ascent - t;
rx -= inset + l;
@ -1258,7 +1295,7 @@ evas_string_char_next_get(const char *str, int pos, int *decoded)
if (decoded) *decoded = 0;
if ((!str) || (pos < 0)) return 0;
p = pos;
d = evas_common_font_utf8_get_next((unsigned char *)str, &p);
d = evas_common_encoding_utf8_get_next((unsigned char *)str, &p);
if (decoded) *decoded = d;
return p;
}
@ -1278,7 +1315,7 @@ evas_string_char_prev_get(const char *str, int pos, int *decoded)
if (decoded) *decoded = 0;
if ((!str) || (pos < 1)) return 0;
p = pos;
d = evas_common_font_utf8_get_prev((unsigned char *)str, &p);
d = evas_common_encoding_utf8_get_prev((unsigned char *)str, &p);
if (decoded) *decoded = d;
return p;
}
@ -1293,7 +1330,7 @@ EAPI int
evas_string_char_len_get(const char *str)
{
if (!str) return 0;
return evas_common_font_utf8_get_len((const unsigned char *) str);
return evas_common_encoding_utf8_get_len((const unsigned char *) str);
}
/**
@ -1417,6 +1454,9 @@ evas_object_text_new(void)
o = calloc(1, sizeof(Evas_Object_Text));
o->magic = MAGIC_OBJ_TEXT;
o->prev = o->cur;
#ifdef BIDI_SUPPORT
o->cur.intl_props.direction = FRIBIDI_PAR_ON;
#endif
return o;
}
@ -1431,10 +1471,13 @@ evas_object_text_free(Evas_Object *obj)
return;
MAGIC_CHECK_END();
/* free obj */
if (o->cur.text) eina_stringshare_del(o->cur.text);
if (o->cur.text) eina_ustringshare_del(o->cur.text);
if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
if (o->cur.font) eina_stringshare_del(o->cur.font);
if (o->cur.source) eina_stringshare_del(o->cur.source);
if (o->engine_data) evas_font_free(obj->layer->evas, o->engine_data);
if (o->cur.intl_props.embedding_levels) free(o->cur.intl_props.embedding_levels);
if (o->cur.intl_props.char_types) free(o->cur.intl_props.char_types);
o->magic = 0;
free(o);
}
@ -1520,7 +1563,7 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur
obj->cur.geometry.h, \
obj->cur.geometry.w, \
obj->cur.geometry.h, \
o->cur.text);
o->cur.text, &o->cur.intl_props);
#if 0
#define DRAW_TEXT(ox, oy) \
if ((o->engine_data) && (o->cur.text)) \
@ -1537,7 +1580,7 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur
obj->cur.cache.geometry.h, \
obj->cur.geometry.w, \
obj->cur.geometry.h, \
o->cur.text);
o->cur.text, &o->cur.intl_props);
#endif
/* shadows */
if (o->cur.style == EVAS_TEXT_STYLE_SHADOW)
@ -1724,8 +1767,8 @@ evas_object_text_render_pre(Evas_Object *obj)
(strcmp(o->cur.font, o->prev.font))) ||
((o->cur.font) && (!o->prev.font)) ||
((!o->cur.font) && (o->prev.font)) ||
((o->cur.text) && (o->prev.text) &&
(strcmp(o->cur.text, o->prev.text))) ||
((o->cur.text) && (o->prev.text) &&
(eina_unicode_strcmp(o->cur.text, o->prev.text))) ||
((o->cur.text) && (!o->prev.text)) ||
((!o->cur.text) && (o->prev.text)) ||
((o->cur.style != o->prev.style)) ||
@ -1860,7 +1903,10 @@ _evas_object_text_rehint(Evas_Object *obj)
int w, h;
int l = 0, r = 0, t = 0, b = 0;
ENFN->font_string_size_get(ENDT, o->engine_data, o->cur.text, &w, &h);
ENFN->font_string_size_get(ENDT,
o->engine_data,
o->cur.text, &o->cur.intl_props,
&w, &h);
evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
obj->cur.geometry.w = w + l + r;
obj->cur.geometry.h = h + t + b;

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,7 @@ evas_convert_grypal_6.c \
evas_convert_yuv.c \
evas_cpu.c \
evas_draw_main.c \
evas_encoding.c \
evas_font_draw.c \
evas_font_load.c \
evas_font_main.c \
@ -67,7 +68,7 @@ evas_scale_span.c \
evas_tiler.c \
evas_regionbuf.c \
evas_pipe.c \
evas_intl_utils.c \
evas_bidi_utils.c \
evas_map_image.c \
evas_map_image.h
@ -87,6 +88,7 @@ evas_convert_rgb_32.h \
evas_convert_rgb_8.h \
evas_convert_yuv.h \
evas_draw.h \
evas_encoding.h \
evas_font.h \
evas_font_private.h \
evas_gradient.h \
@ -107,7 +109,7 @@ evas_scale_smooth_scaler_noscale.c \
evas_scale_smooth_scaler_up.c \
evas_scale_span.h \
evas_pipe.h \
evas_intl_utils.h \
evas_bidi_utils.h \
evas_map_image_internal.c \
evas_map_image_core.c \
evas_map_image_loop.c

View File

@ -0,0 +1,202 @@
#include <string.h>
#include <stdlib.h>
#include "evas_common.h"
#include "evas_bidi_utils.h"
#include "evas_encoding.h"
#include "evas_font_private.h"
#ifdef BIDI_SUPPORT
#include <fribidi/fribidi.h>
#define _SAFE_FREE(x) \
do { \
if (x) \
{ \
free(x); \
x = NULL; \
} \
} while(0)
Eina_Bool
evas_bidi_is_rtl_str(const Eina_Unicode *str)
{
int i = 0;
int ch;
EvasBiDiCharType type;
if (!str)
return EINA_FALSE;
for ( ; *str ; str++)
{
type = fribidi_get_bidi_type(*str);
if (FRIBIDI_IS_LETTER(type) && FRIBIDI_IS_RTL(type))
{
return EINA_TRUE;
}
}
return EINA_FALSE;
}
int
evas_bidi_update_props(Eina_Unicode *ustr, Evas_BiDi_Props *intl_props)
{
EvasBiDiCharType *char_types = NULL;
EvasBiDiLevel *embedding_levels = NULL;
EvasBiDiJoiningType *join_types = NULL;
size_t len;
if (!ustr)
return -2;
if (!evas_bidi_is_rtl_str(ustr)) /* No need to handle bidi */
{
len = -1;
goto cleanup;
}
len = eina_unicode_strlen(ustr);
/* Prep work for reordering */
char_types = (EvasBiDiCharType *) malloc(sizeof(EvasBiDiCharType) * len);
if (!char_types)
{
len = -2;
goto cleanup;
}
fribidi_get_bidi_types(ustr, len, char_types);
embedding_levels = (EvasBiDiLevel *)malloc(sizeof(EvasBiDiLevel) * len);
if (!embedding_levels)
{
len = -2;
goto cleanup;
}
if (!fribidi_get_par_embedding_levels(char_types, len, &intl_props->direction, embedding_levels))
{
len = -2;
goto cleanup;
}
join_types = (EvasBiDiJoiningType *) malloc(sizeof(EvasBiDiJoiningType) * len);
if (!join_types)
{
len = -2;
goto cleanup;
}
fribidi_get_joining_types(ustr, len, join_types);
fribidi_join_arabic(char_types, len, embedding_levels, join_types);
/* Actually modify the string */
fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC, embedding_levels, len, join_types,
ustr);
/* clean up */
if (intl_props->embedding_levels)
{
free(intl_props->embedding_levels);
}
intl_props->embedding_levels = embedding_levels;
/* clean up */
if (intl_props->char_types)
{
free(intl_props->char_types);
}
intl_props->char_types = char_types;
if (join_types) free(join_types);
return len;
/* Cleanup */
cleanup:
if (join_types) free(join_types);
if (char_types) free(char_types);
if (embedding_levels) free(embedding_levels);
evas_bidi_props_clean(intl_props); /*Mark that we don't need bidi handling */
return len;
}
int
evas_bidi_props_reorder_line(Eina_Unicode *ustr, const Evas_BiDi_Props *intl_props, EvasBiDiStrIndex **_v_to_l)
{
EvasBiDiStrIndex *v_to_l = NULL;
size_t len;
if (!EVAS_BIDI_IS_BIDI_PROP(intl_props))
return 0;
len = eina_unicode_strlen(ustr);
if (_v_to_l) {
int i;
v_to_l = *_v_to_l = calloc(len, sizeof(EvasBiDiStrIndex));
if (!v_to_l)
{
goto error;
}
/* init the array for fribidi */
for (i = 0 ; i < len ; i++)
{
v_to_l[i] = i;
}
}
/* Shaping must be done *BEFORE* breaking to lines so there's no choice but
doing it in textblock. */
if (!fribidi_reorder_line (FRIBIDI_FLAGS_DEFAULT, intl_props->char_types,
len, 0, intl_props->direction,
intl_props->embedding_levels, ustr, v_to_l))
{
goto error;
}
return 0;
/* ERROR HANDLING */
error:
_SAFE_FREE(v_to_l);
return 1;
}
EvasBiDiStrIndex
evas_bidi_position_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDiStrIndex position)
{
int i;
EvasBiDiStrIndex *ind;
if (position >= len || !v_to_l)
return position;
for (i = 0, ind = v_to_l ; i < len ; i++, ind++)
{
if (*ind == position)
{
return i;
}
}
return position;
}
Eina_Bool
evas_bidi_is_rtl_char(EvasBiDiLevel *embedded_level_list, EvasBiDiStrIndex index)
{
if(!embedded_level_list || index < 0)
return EINA_FALSE;
return (FRIBIDI_IS_RTL(embedded_level_list[index])) ? EINA_TRUE : EINA_FALSE;
}
void
evas_bidi_props_clean(Evas_BiDi_Props *intl_props)
{
_SAFE_FREE(intl_props->embedding_levels);
_SAFE_FREE(intl_props->char_types);
}
#endif

View File

@ -0,0 +1,105 @@
#ifndef _EVAS_BIDI_UTILS
#define _EVAS_BIDI_UTILS
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_FRIBIDI
# define USE_FRIBIDI
# define BIDI_SUPPORT
#endif
#include "evas_common.h"
#ifdef USE_FRIBIDI
# include <fribidi/fribidi.h>
#endif
/* abstract fribidi - we statically define sizes here because otherwise we would
* have to ifdef everywhere (because function decorations may change with/without
* bidi support)
* These types should only be passed as pointers! i.e do not directely use any of
* these types in function declarations. Defining as void should help ensuring that.
*/
#ifdef USE_FRIBIDI
# define _EVAS_BIDI_TYPEDEF(type) \
typedef FriBidi ## type EvasBiDi ## type
#else
# define _EVAS_BIDI_TYPEDEF(type) \
typedef void EvasBiDi ## type
#endif
#if 0 /* We are using Eina_Unicode instead */
_EVAS_BIDI_TYPEDEF(Char);
#endif
_EVAS_BIDI_TYPEDEF(CharType);
_EVAS_BIDI_TYPEDEF(ParType);
_EVAS_BIDI_TYPEDEF(StrIndex);
_EVAS_BIDI_TYPEDEF(Level);
_EVAS_BIDI_TYPEDEF(JoiningType);
/* This structure defines a set of properties of a BiDi string. In case of a
* non-bidi string, all values should be NULL.
* To check if a structure describes a bidi string or not, use the macro
* EVAS_BIDI_IS_BIDI_PROP. RTL-only strings are also treated as bidi ATM.
*/
struct _Evas_BiDi_Props {
EvasBiDiCharType *char_types; /* BiDi char types */
EvasBiDiLevel *embedding_levels; /* BiDi embedding levels */
#ifdef USE_FRIBIDI
EvasBiDiParType direction; /* The paragraph direction, FIXME-tom: should be a
pointer to the paragraph structure */
#endif
};
typedef struct _Evas_BiDi_Props Evas_BiDi_Props;
#ifdef USE_FRIBIDI
# define EVAS_BIDI_IS_BIDI_PROP(intl_props) ((intl_props) && (intl_props)->char_types)
# define evas_bidi_position_visual_to_logical(list, position) \
(list) ? list[position] : position;
/* Gets a v_to_l list, it's len and a logical character index, and returns the
* the visual index of that character.
*/
EvasBiDiStrIndex
evas_bidi_position_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDiStrIndex position);
/* Returns true if the string has rtl characters, false otherwise */
Eina_Bool
evas_bidi_is_rtl_str(const Eina_Unicode *str);
/* Returns true if the embedding level of the index is rtl, false otherwise */
Eina_Bool
evas_bidi_is_rtl_char(EvasBiDiLevel *embedded_level_list, EvasBiDiStrIndex index);
/* Overallocates a bit, if anyone cares, he should realloc, though usually,
* the string get freed very fast so there's really no need to care about it
* (rellaoc-ing is slower than not)
*/
int
evas_bidi_props_reorder_line(Eina_Unicode *text, const Evas_BiDi_Props *intl_props, EvasBiDiStrIndex **_v_to_l);
/* Updates the international properties according to the text. First checks to see
* if the text in question has rtl chars, if not, it cleans intl_props and returns.
* Otherwise, it essentially frees the old fields, allocates new fields, and
* populates them.
* On error, intl_props gets cleaned.
* Return value: the length of the string.
*/
int
evas_bidi_update_props(Eina_Unicode *text, Evas_BiDi_Props *intl_props) EINA_ARG_NONNULL(1, 2);
/* Cleans and frees the international properties. - Just the content, not the
* poitner itself.
*/
void
evas_bidi_props_clean(Evas_BiDi_Props *intl_props) EINA_ARG_NONNULL(1);
#endif
#endif

View File

@ -0,0 +1,211 @@
#include "evas_common.h"
#include "evas_encoding.h"
EAPI int
evas_common_encoding_utf8_get_next(const unsigned char *buf, int *iindex)
{
/* Reads UTF8 bytes from @buf, starting at *@index and returns
* the decoded code point at iindex offset, and advances iindex
* to the next code point after this.
*
* Returns 0 to indicate there is no next char
*/
int index = *iindex, len, r;
unsigned char d, d2, d3, d4;
/* if this char is the null terminator, exit */
if (!buf[index])
return 0;
d = buf[index++];
while (buf[index] && ((buf[index] & 0xc0) == 0x80))
index++;
len = index - *iindex;
if (len == 1)
r = d;
else if (len == 2)
{
/* 2 bytes */
d2 = buf[*iindex + 1];
r = d & 0x1f; /* copy lower 5 */
r <<= 6;
r |= (d2 & 0x3f); /* copy lower 6 */
}
else if (len == 3)
{
/* 3 bytes */
d2 = buf[*iindex + 1];
d3 = buf[*iindex + 2];
r = d & 0x0f; /* copy lower 4 */
r <<= 6;
r |= (d2 & 0x3f);
r <<= 6;
r |= (d3 & 0x3f);
}
else
{
/* 4 bytes */
d2 = buf[*iindex + 1];
d3 = buf[*iindex + 2];
d4 = buf[*iindex + 3];
r = d & 0x0f; /* copy lower 4 */
r <<= 6;
r |= (d2 & 0x3f);
r <<= 6;
r |= (d3 & 0x3f);
r <<= 6;
r |= (d4 & 0x3f);
}
*iindex = index;
return r;
}
EAPI int
evas_common_encoding_utf8_get_prev(const unsigned char *buf, int *iindex)
{
/* Reads UTF8 bytes from @buf, starting at *@index and returns
* the decoded code point at iindex offset, and advances iindex
* to the prev code point after this.
*
* Returns 0 to indicate there is no prev char
*/
int r;
int index = *iindex;
/* although when index == 0 there's no previous char, we still want to get
* the current char */
if (index < 0)
return 0;
/* First obtain the codepoint at iindex */
r = evas_common_encoding_utf8_get_next(buf, &index);
/* Next advance iindex to previous codepoint */
index = *iindex;
index--;
while ((index > 0) && ((buf[index] & 0xc0) == 0x80))
index--;
*iindex = index;
return r;
}
EAPI int
evas_common_encoding_utf8_get_last(const unsigned char *buf, int buflen)
{
/* jumps to the nul byte at the buffer end and decodes backwards and
* returns the offset index byte in the buffer where the last character
* in the buffer begins.
*
* Returns -1 to indicate an error
*/
int index;
unsigned char d;
if (buflen < 1) return 0;
index = buflen - 1;
d = buf[index];
if (!(d & 0x80))
return index;
else
{
while (index > 0)
{
index--;
d = buf[index];
if ((d & 0xc0) != 0x80)
return index;
}
}
return 0;
}
EAPI int
evas_common_encoding_utf8_get_len(const unsigned char *buf)
{
/* returns the number of utf8 characters (not bytes) in the string */
int index = 0, len = 0;
while (buf[index])
{
if ((buf[index] & 0xc0) != 0x80)
len++;
index++;
}
return len;
}
/* FIXME: Should optimize! */
EAPI Eina_Unicode *
evas_common_encoding_utf8_to_unicode(const unsigned char *utf, int *_len)
{
int len, i;
int index;
Eina_Unicode *buf, *ind;
len = evas_common_encoding_utf8_get_len(utf);
if (_len)
*_len = len;
buf = (Eina_Unicode *) calloc(sizeof(Eina_Unicode), (len + 1));
if (!buf) return buf;
for (i = 0, index = 0, ind = buf ; i < len ; i++, ind++)
{
*ind = evas_common_encoding_utf8_get_next(utf, &index);
}
return buf;
}
EAPI char *
evas_common_encoding_unicode_to_utf8(const Eina_Unicode *uni, int *_len)
{
char *buf;
const Eina_Unicode *uind;
char *ind;
int ulen, len;
ulen = eina_unicode_strlen(uni);
buf = (char *) calloc(ulen + 1, EVAS_ENCODING_UTF8_BYTES_PER_CHAR);
len = 0;
for (uind = uni, ind = buf ; *uind ; uind++)
{
if (*uind <= 0x7F) /* 1 byte char */
{
*ind++ = *uind;
len += 1;
}
else if (*uind <= 0x7FF) /* 2 byte char */
{
*ind++ = 0xC0 | (unsigned char) (*uind >> 6);
*ind++ = 0x80 | (unsigned char) (*uind & 0x3F);
len += 2;
}
else if (*uind <= 0xFFFF) /* 3 byte char */
{
*ind++ = 0xE0 | (unsigned char) (*uind >> 12);
*ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F);
*ind++ = 0x80 | (unsigned char) (*uind & 0x3F);
len += 3;
}
else /* 4 byte char */
{
*ind++ = 0xF0 | (unsigned char) ((*uind >> 18) & 0x07);
*ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F);
*ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F);
*ind++ = 0x80 | (unsigned char) (*uind & 0x3F);
len += 4;
}
}
buf = realloc(buf, len + 1);
buf[len] = '\0';
if (_len)
*_len = len;
return buf;
}

View File

@ -0,0 +1,26 @@
#ifndef EVAS_ENCODING_H
#define EVAS_ENCODING_H
#include <Eina.h>
/* FIXME: An assumption that will probably break in the future */
#define EVAS_ENCODING_UTF8_BYTES_PER_CHAR 4
EAPI int
evas_common_encoding_utf8_get_next(const unsigned char *buf, int *iindex);
EAPI int
evas_common_encoding_utf8_get_prev(const unsigned char *buf, int *iindex);
EAPI int
evas_common_encoding_utf8_get_last(const unsigned char *buf, int buflen);
EAPI int
evas_common_encoding_utf8_get_len(const unsigned char *buf);
EAPI Eina_Unicode *
evas_common_encoding_utf8_to_unicode(const unsigned char *utf, int *_len) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
EAPI char *
evas_common_encoding_unicode_to_utf8(const Eina_Unicode *uni, int *_len) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
#endif

View File

@ -4,6 +4,7 @@
#ifndef _EVAS_FONT_H
#define _EVAS_FONT_H
#include "evas_bidi_utils.h"
/* main */
@ -18,14 +19,14 @@ EAPI int evas_common_font_max_ascent_get (RGBA_Font *fn);
EAPI int evas_common_font_max_descent_get (RGBA_Font *fn);
EAPI int evas_common_font_get_line_advance (RGBA_Font *fn);
EAPI int evas_common_font_utf8_get_next (const unsigned char *buf, int *iindex);
EAPI int evas_common_font_utf8_get_prev (const unsigned char *buf, int *iindex);
EAPI int evas_common_font_utf8_get_last (const unsigned char *buf, int buflen);
EAPI int evas_common_font_utf8_get_len (const unsigned char *buf);
EINA_DEPRECATED EAPI int evas_common_font_utf8_get_next (const unsigned char *buf, int *iindex);
EINA_DEPRECATED EAPI int evas_common_font_utf8_get_prev (const unsigned char *buf, int *iindex);
EINA_DEPRECATED EAPI int evas_common_font_utf8_get_last (const unsigned char *buf, int buflen);
EINA_DEPRECATED EAPI int evas_common_font_utf8_get_len (const unsigned char *buf);
/* draw */
EAPI void evas_common_font_draw (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text);
EAPI void evas_common_font_draw (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props);
EAPI int evas_common_font_glyph_search (RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl);
EAPI RGBA_Font_Glyph *evas_common_font_int_cache_glyph_get (RGBA_Font_Int *fi, FT_UInt index);
@ -62,12 +63,12 @@ EAPI RGBA_Font_Int *evas_common_font_int_find (const char *name,
/* query */
EAPI int evas_common_font_query_kerning (RGBA_Font_Int* fi, FT_UInt prev, FT_UInt index, int* kerning);
EAPI void evas_common_font_query_size (RGBA_Font *fn, const char *text, int *w, int *h);
EAPI int evas_common_font_query_inset (RGBA_Font *fn, const char *text);
EAPI void evas_common_font_query_advance (RGBA_Font *fn, const char *text, int *h_adv, int *v_adv);
EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const char *text, int pos, int *cx, int *cy, int *cw, int *ch);
EAPI int evas_common_font_query_text_at_pos (RGBA_Font *fn, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch);
EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const char *text, int x, int y);
EAPI void evas_common_font_query_size (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h);
EAPI int evas_common_font_query_inset (RGBA_Font *fn, const Eina_Unicode *text);
EAPI void evas_common_font_query_advance (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *h_adv, int *v_adv);
EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch);
EAPI int evas_common_font_query_char_at_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch);
EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y);
void evas_common_font_load_init(void);
void evas_common_font_load_shutdown(void);

View File

@ -6,7 +6,7 @@
#include "evas_private.h"
#include "evas_blend_private.h"
#include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */
#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
#include "evas_font_private.h" /* for Frame-Queuing support */
#define WORD_CACHE_MAXLEN 50
@ -20,7 +20,7 @@ struct prword {
int size;
struct cinfo *cinfo;
RGBA_Font *font;
const char *str;
const Eina_Unicode *str;
int len;
DATA8 *im;
int roww;
@ -34,7 +34,6 @@ struct cinfo {
FT_UInt index;
struct { int x, y; } pos;
int posx;
char chr;
RGBA_Font_Glyph *fg;
struct {
int w,h;
@ -46,7 +45,7 @@ struct cinfo {
LK(lock_words); // for word cache call
static Eina_Inlist *words = NULL;
static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const char *text, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning);
static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *text, Evas_BiDi_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning);
EAPI void
evas_common_font_draw_init(void)
@ -390,16 +389,22 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
}
/*
* BiDi handling: We recieve the shaped string + other props from intl_props,
* we need to reorder it so we'll have the visual string (the way we draw)
* and then for kerning we have to switch the order of the kerning query (as the prev
* is on the right, and not on the left).
*/
static void
evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *in_text,
RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w, int ext_h, RGBA_Font_Int *fi,
int im_w, int im_h __UNUSED__, int use_kerning
evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *in_text,
const Evas_BiDi_Props *intl_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w,
int ext_h, RGBA_Font_Int *fi, int im_w, int im_h __UNUSED__, int use_kerning
)
{
int pen_x, pen_y;
int last_adv;
int chr;
const char *text = in_text;
const Eina_Unicode *text = in_text;
int len;
FT_Face pface = NULL;
FT_UInt prev_index;
@ -410,14 +415,11 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
/* A fast (portable) strNlen would be nice (there is a wcsnlen strangely) */
if ((p = memchr(text, 0, WORD_CACHE_MAXLEN)))
len = p - text;
else
len = WORD_CACHE_MAXLEN;
/* A fast strNlen would be nice (there is a wcsnlen strangely) */
len = evas_common_econding_unicode_strlen(text);
if (len > 2 && len < WORD_CACHE_MAXLEN){
struct prword *word = evas_font_word_prerender(dc, text, len, fn, fi,
struct prword *word = evas_font_word_prerender(dc, text, intl_props, len, fn, fi,
use_kerning);
if (word){
int j,rowstart,rowend,xstart,xrun;
@ -481,35 +483,39 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
#endif
}
}
}
#endif
#ifdef INTERNATIONAL_SUPPORT
/*FIXME: should get the direction by parmater */
EvasIntlParType direction = FRIBIDI_TYPE_ON;
EvasIntlLevel *level_list;
#ifdef BIDI_SUPPORT
Eina_Unicode *visual_text;
/* change the text to visual ordering and update the level list
* for as minimum impact on the code as possible just use text as an
* holder, will change in the future.*/
char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, NULL, &level_list);
text = (visual_text) ? visual_text : in_text;
visual_text = eina_unicode_strdup(in_text);
if (visual_text)
{
evas_bidi_props_reorder_line(visual_text, intl_props, NULL);
text = visual_text;
}
else
{
text = in_text;
}
#endif
pen_x = x;
pen_y = y;
last_adv = 0;
prev_index = 0;
im = dst->image.data;
for (char_index = 0, c = 0, chr = 0; text[chr]; char_index++)
for (char_index = 0, c = 0; *text; text++, char_index++)
{
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y;
int gl, kern;
gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
gl = *text;
if (gl == 0) break;
index = evas_common_font_glyph_search(fn, &fi, gl);
@ -521,33 +527,40 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
FTUNLOCK();
fi->src->current_size = fi->size;
}
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg)
{
LKU(fi->ft_mutex);
continue;
}
/* hmmm kerning means i can't sanely do my own cached metric tables! */
/* grrr - this means font face sharing is kinda... not an option if */
/* you want performance */
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
{
#ifdef INTERNATIONAL_SUPPORT
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around. */
if (evas_intl_is_rtl_char(level_list, char_index))
{
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
pen_x += kern;
}
#ifdef BIDI_SUPPORT
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props &&
evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) &&
fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
pen_x += kern;
}
else
#endif
{
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
pen_x += kern;
}
}
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
LKU(fi->ft_mutex);
if (!fg) continue;
if (dc->font_ext.func.gl_new)
{
@ -555,7 +568,13 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
fg->ext_dat_free = dc->font_ext.func.gl_free;
}
/* If the current one is not a compositing char, do the previous advance
* and set the current advance as the next advance to do */
if (fg->glyph->advance.x >> 16 > 0)
{
pen_x += last_adv;
last_adv = fg->glyph->advance.x >> 16;
}
chr_x = (pen_x + (fg->glyph_out->left));
chr_y = (pen_y + (fg->glyph_out->top));
@ -688,17 +707,18 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
}
else
break;
pen_x += fg->glyph->advance.x >> 16;
prev_index = index;
}
#ifdef INTERNATIONAL_SUPPORT
if (level_list) free(level_list);
#ifdef BIDI_SUPPORT
if (visual_text) free(visual_text);
#endif
}
EAPI void
evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text)
evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text,
const Evas_BiDi_Props *intl_props)
{
int ext_x, ext_y, ext_w, ext_h;
int im_w, im_h;
@ -749,7 +769,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
if (!dc->cutout.rects)
{
evas_common_font_draw_internal(dst, dc, fn, x, y, text,
evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
func, ext_x, ext_y, ext_w, ext_h, fi,
im_w, im_h, use_kerning
);
@ -766,7 +786,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
{
r = rects->rects + i;
evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
evas_common_font_draw_internal(dst, dc, fn, x, y, text,
evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
func, r->x, r->y, r->w, r->h, fi,
im_w, im_h, use_kerning
);
@ -781,12 +801,12 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
}
/* FIXME: Where is it freed at? */
struct prword *
evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning){
evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Evas_BiDi_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning){
int pen_x, pen_y;
struct cinfo *metrics;
const char *text;
const Eina_Unicode *text = in_text;
int chr;
FT_Face pface = NULL;
FT_UInt prev_index;
@ -803,7 +823,7 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG
LKL(lock_words);
EINA_INLIST_FOREACH(words,w){
if (w->len == len && w->font == fn && fi->size == w->size &&
(w->str == in_text || memcmp(w->str,in_text,len) == 0)){
(w->str == in_text || memcmp(w->str, in_text, len * sizeof(Eina_Unicode)) == 0)){
words = eina_inlist_promote(words, EINA_INLIST_GET(w));
LKU(lock_words);
return w;
@ -811,30 +831,15 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG
}
LKU(lock_words);
#ifdef INTERNATIONAL_SUPPORT
/*FIXME: should get the direction by parmater */
EvasIntlParType direction = FRIBIDI_TYPE_ON;
EvasIntlLevel *level_list;
/* change the text to visual ordering and update the level list
* for as minimum impact on the code as possible just use text as an
* holder, will change in the future.*/
char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, NULL, &level_list);
text = (visual_text) ? visual_text : in_text;
#else
text = in_text;
#endif
gl = dc->font_ext.func.gl_new ? 1: 0;
pen_x = pen_y = 0;
above = 0; below = 0; baseline = 0; height = 0; descent = 0;
metrics = malloc(sizeof(struct cinfo) * len);
/* First pass: Work out how big */
for (char_index = 0, c = 0, chr = 0 ; text[chr] ; char_index ++){
for (char_index = 0, c = 0, chr = 0 ; *text ; text++, char_index ++){
struct cinfo *ci = metrics + char_index;
ci->chr = text[chr];
ci->gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
ci->gl = *text;
if (ci->gl == 0) break;
ci->index = evas_common_font_glyph_search(fn, &fi, ci->gl);
LKL(fi->ft_mutex);
@ -845,16 +850,39 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG
FTUNLOCK();
fi->src->current_size = fi->size;
}
if (use_kerning && char_index && (pface == fi->src->ft.face))
{
int kern;
if (evas_common_font_query_kerning(fi, prev_index,ci->index,&kern))
ci->pos.x += kern;
}
pface = fi->src->ft.face;
ci->fg = evas_common_font_int_cache_glyph_get(fi, ci->index);
LKU(fi->ft_mutex);
if (!ci->fg) continue;
/* hmmm kerning means i can't sanely do my own cached metric tables! */
/* grrr - this means font face sharing is kinda... not an option if */
/* you want performance */
if ((use_kerning) && (prev_index) && (ci->index) &&
(pface == fi->src->ft.face))
{
int kern = 0;
#ifdef BIDI_SUPPORT
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props &&
evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) &&
ci->fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, ci->index, prev_index, &kern))
ci->pos.x += kern;
}
else
#endif
{
if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern))
ci->pos.x += kern;
}
}
pface = fi->src->ft.face;
if (gl){
ci->fg->ext_dat =dc->font_ext.func.gl_new(dc->font_ext.data,ci->fg);
ci->fg->ext_dat_free = dc->font_ext.func.gl_free;
@ -897,7 +925,7 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG
save = malloc(sizeof(struct prword));
save->cinfo = metrics;
save->str = eina_stringshare_add(in_text);
save->str = eina_ustringshare_add(text);
save->font = fn;
save->size = fi->size;
save->len = len;
@ -914,17 +942,12 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const char *in_text, int len, RG
struct prword *last = (struct prword *)(words->last);
if (last->im) free(last->im);
if (last->cinfo) free(last->cinfo);
eina_stringshare_del(last->str);
eina_ustringshare_del(last->str);
words = eina_inlist_remove(words,EINA_INLIST_GET(last));
free(last);
}
LKU(lock_words);
#ifdef INTERNATIONAL_SUPPORT
if (level_list) free(level_list);
if (visual_text) free(visual_text);
#endif
return save;
}

View File

@ -4,6 +4,8 @@
#include "evas_common.h"
#include "evas_private.h"
#include "evas_encoding.h"
#include "evas_font_private.h"
FT_Library evas_ft_lib = 0;
@ -207,139 +209,27 @@ evas_common_font_get_line_advance(RGBA_Font *fn)
// return ret;
}
/*DEPRECATED! Should use evas_common_encoding_* instead */
EAPI int
evas_common_font_utf8_get_next(const unsigned char *buf, int *iindex)
{
/* Reads UTF8 bytes from @buf, starting at *@index and returns
* the decoded code point at iindex offset, and advances iindex
* to the next code point after this.
*
* Returns 0 to indicate there is no next char
*/
int index = *iindex, len, r;
unsigned char d, d2, d3, d4;
/* if this char is the null terminator, exit */
if (!buf[index])
return 0;
d = buf[index++];
while (buf[index] && ((buf[index] & 0xc0) == 0x80))
index++;
len = index - *iindex;
if (len == 1)
r = d;
else if (len == 2)
{
/* 2 bytes */
d2 = buf[*iindex + 1];
r = d & 0x1f; /* copy lower 5 */
r <<= 6;
r |= (d2 & 0x3f); /* copy lower 6 */
}
else if (len == 3)
{
/* 3 bytes */
d2 = buf[*iindex + 1];
d3 = buf[*iindex + 2];
r = d & 0x0f; /* copy lower 4 */
r <<= 6;
r |= (d2 & 0x3f);
r <<= 6;
r |= (d3 & 0x3f);
}
else
{
/* 4 bytes */
d2 = buf[*iindex + 1];
d3 = buf[*iindex + 2];
d4 = buf[*iindex + 3];
r = d & 0x0f; /* copy lower 4 */
r <<= 6;
r |= (d2 & 0x3f);
r <<= 6;
r |= (d3 & 0x3f);
r <<= 6;
r |= (d4 & 0x3f);
}
*iindex = index;
return r;
return evas_common_encoding_utf8_get_next(buf, iindex);
}
EAPI int
evas_common_font_utf8_get_prev(const unsigned char *buf, int *iindex)
{
/* Reads UTF8 bytes from @buf, starting at *@index and returns
* the decoded code point at iindex offset, and advances iindex
* to the prev code point after this.
*
* Returns 0 to indicate there is no prev char
*/
int r;
int index = *iindex;
/* although when index == 0 there's no previous char, we still want to get
* the current char */
if (index < 0)
return 0;
/* First obtain the codepoint at iindex */
r = evas_common_font_utf8_get_next(buf, &index);
/* Next advance iindex to previous codepoint */
index = *iindex;
index--;
while ((index > 0) && ((buf[index] & 0xc0) == 0x80))
index--;
*iindex = index;
return r;
return evas_common_encoding_utf8_get_prev(buf, iindex);
}
EAPI int
evas_common_font_utf8_get_last(const unsigned char *buf, int buflen)
{
/* jumps to the nul byte at the buffer end and decodes backwards and
* returns the offset index byte in the buffer where the last character
* in the buffer begins.
*
* Returns -1 to indicate an error
*/
int index;
unsigned char d;
if (buflen < 1) return 0;
index = buflen - 1;
d = buf[index];
if (!(d & 0x80))
return index;
else
{
while (index > 0)
{
index--;
d = buf[index];
if ((d & 0xc0) != 0x80)
return index;
}
}
return 0;
return evas_common_encoding_utf8_get_last(buf, buflen);
}
EAPI int
evas_common_font_utf8_get_len(const unsigned char *buf)
{
/* returns the number of utf8 characters (not bytes) in the string */
int index = 0, len = 0;
while (buf[index])
{
if ((buf[index] & 0xc0) != 0x80)
len++;
index++;
}
return len;
return evas_common_encoding_utf8_get_len(buf);
}

View File

@ -1,5 +1,5 @@
#include "evas_common.h"
#include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */
#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
#include "evas_font_private.h" /* for Frame-Queuing support */
EAPI int
@ -56,9 +56,15 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi,
return error;
}
/* string extents */
/* size of the string (width and height) in pixels
* BiDi handling: We recieve the shaped string + other props from intl_props,
* We only care about the size, and the size does not depend on the visual order.
* As long as we follow the logical string and get kerning data like we should,
* we are fine.
*/
EAPI void
evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h)
{
int use_kerning;
int pen_x, pen_y;
@ -78,14 +84,14 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
// evas_common_font_size_use(fn);
use_kerning = FT_HAS_KERNING(fi->src->ft.face);
prev_index = 0;
for (chr = 0; text[chr];)
for (chr = 0; *text; text++)
{
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y, chr_w;
int chr_x, chr_y, advw;
int gl, kern;
gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
gl = *text;
if (gl == 0) break;
index = evas_common_font_glyph_search(fn, &fi, gl);
LKL(fi->ft_mutex);
@ -101,9 +107,9 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
/* you want performance */
kern = 0;
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
(pface == fi->src->ft.face) &&
evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
@ -111,21 +117,28 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
if (!fg) continue;
if (kern < 0) kern = 0;
chr_x = ((pen_x - kern) + (fg->glyph_out->left));
chr_y = (pen_y + (fg->glyph_out->top));
// chr_w = fg->glyph_out->bitmap.width;
chr_w = fg->glyph_out->bitmap.width + kern;
{
int advw;
/* We care about advancing the whole string size, and not the actual
* paint size of each string, so we only care about advancing correctly
* and not the actual glyph width */
advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
chr_x = pen_x - kern;
chr_y = pen_y;
/* If it's not a compositing char, i.e it advances, we should also add
* the left/top padding of the glyph. As we don't care about the padding
* as the drawing location remains the same.
*/
if (advw > 0)
{
chr_x += fg->glyph_out->left;
chr_y += fg->glyph_out->top;
}
advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
if (chr_w < advw) chr_w = advw;
}
if ((!prev_index) && (chr_x < 0))
start_x = chr_x;
if ((chr_x + chr_w) > end_x)
end_x = chr_x + chr_w;
if ((chr_x + advw) > end_x)
end_x = chr_x + advw;
pen_x += fg->glyph->advance.x >> 16;
prev_index = index;
@ -136,7 +149,7 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
/* text x inset */
EAPI int
evas_common_font_query_inset(RGBA_Font *fn, const char *text)
evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text)
{
FT_UInt index;
RGBA_Font_Glyph *fg;
@ -147,8 +160,8 @@ evas_common_font_query_inset(RGBA_Font *fn, const char *text)
fi = fn->fonts->data;
chr = 0;
if (!text[0]) return 0;
gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
if (!*text) return 0;
gl = *text;
if (gl == 0) return 0;
// evas_common_font_size_use(fn);
index = evas_common_font_glyph_search(fn, &fi, gl);
@ -180,14 +193,20 @@ evas_common_font_query_inset(RGBA_Font *fn, const char *text)
return fg->glyph_out->left;
}
/* h & v advance */
/* h & v advance
* BiDi handling: We recieve the shaped string + other props from intl_props,
* We don't care about the order, as heights will remain the same (we already did
* shaping) and as long as we go through the logical string and match the kerning
* this way, we are safe.
*/
EAPI void
evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int *v_adv)
evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *h_adv, int *v_adv)
{
int use_kerning;
int pen_x, pen_y;
int start_x;
int chr;
int char_index;
FT_UInt prev_index;
RGBA_Font_Int *fi;
FT_Face pface = NULL;
@ -202,14 +221,13 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int
use_kerning = FT_HAS_KERNING(fi->src->ft.face);
FTUNLOCK();
prev_index = 0;
for (chr = 0; text[chr];)
for (char_index = 0 ; *text ; text++, char_index++)
{
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y, chr_w;
int gl, kern;
gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
gl = *text;
if (gl == 0) break;
index = evas_common_font_glyph_search(fn, &fi, gl);
LKL(fi->ft_mutex);
@ -220,105 +238,12 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int
FTUNLOCK();
fi->src->current_size = fi->size;
}
/* hmmm kerning means i can't sanely do my own cached metric tables! */
/* grrr - this means font face sharing is kinda... not an option if */
/* you want performance */
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
LKU(fi->ft_mutex);
if (!fg) continue;
chr_x = (pen_x + (fg->glyph_out->left));
chr_y = (pen_y + (fg->glyph_out->top));
chr_w = fg->glyph_out->bitmap.width;
pen_x += fg->glyph->advance.x >> 16;
prev_index = index;
}
if (v_adv) *v_adv = evas_common_font_get_line_advance(fn);
if (h_adv) *h_adv = pen_x - start_x;
}
/* x y w h for char at char pos */
EAPI int
evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos, int *cx, int *cy, int *cw, int *ch)
{
int use_kerning;
int pen_x, pen_y;
int prev_chr_end;
int chr;
int asc, desc;
int char_index = 0; /* the index of the current char */
int position;
const char *text = in_text;
int ret_val = 0;
FT_UInt prev_index;
RGBA_Font_Int *fi;
FT_Face pface = NULL;
#ifdef INTERNATIONAL_SUPPORT
int len = 0;
EvasIntlParType direction = FRIBIDI_TYPE_ON;
EvasIntlLevel *level_list = NULL;
EvasIntlStrIndex *visual_to_logical = NULL;
char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, &visual_to_logical, NULL, &level_list);
text = (visual_text) ? visual_text : in_text;
#endif
fi = fn->fonts->data;
pen_x = 0;
pen_y = 0;
// evas_common_font_size_use(fn);
if (fi->src->current_size != fi->size)
{
FTLOCK();
FT_Activate_Size(fi->ft.size);
FTUNLOCK();
fi->src->current_size = fi->size;
}
use_kerning = FT_HAS_KERNING(fi->src->ft.face);
prev_index = 0;
prev_chr_end = 0;
asc = evas_common_font_max_ascent_get(fn);
desc = evas_common_font_max_descent_get(fn);
/* find the actual index, not the byte position */
for (position = 0 , chr = 0 ; in_text[chr] && chr < pos ; position++) {
evas_common_font_utf8_get_next((unsigned char *)in_text, &chr);
}
/* if we couldn't reach the correct position for some reason,
* return with an error */
if (chr != pos) {
ret_val = 0;
goto end;
}
#ifdef INTERNATIONAL_SUPPORT
/* if it's an in string position (not end), get logical position */
if (position < len)
position = evas_intl_position_visual_to_logical(visual_to_logical, position);
#endif
for (char_index = 0, chr = 0; text[chr]; char_index++)
{
int pchr;
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y, chr_w;
int gl, kern;
pchr = chr;
gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
if (gl == 0) break;
index = evas_common_font_glyph_search(fn, &fi, gl);
LKL(fi->ft_mutex);
if (!fg)
{
LKU(fi->ft_mutex);
continue;
}
// FIXME: Why no FT_Activate_Size here ?
kern = 0;
/* hmmm kerning means i can't sanely do my own cached metric tables! */
@ -327,10 +252,14 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
{
#ifdef INTERNATIONAL_SUPPORT
#ifdef BIDI_SUPPORT
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around. */
if (evas_intl_is_rtl_char(level_list, char_index))
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props &&
evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) &&
fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
pen_x += kern;
@ -345,74 +274,57 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
}
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
LKU(fi->ft_mutex);
if (!fg) continue;
if (kern < 0) kern = 0;
chr_x = ((pen_x - kern) + (fg->glyph_out->left));
chr_y = (pen_y + (fg->glyph_out->top));
chr_w = fg->glyph_out->bitmap.width + (kern);
/* if (text[chr]) */
{
int advw;
advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
if (chr_w < advw) chr_w = advw;
}
if (chr_x > prev_chr_end)
{
chr_w += (chr_x - prev_chr_end);
chr_x = prev_chr_end;
}
/* we need to see if the char at the visual position is the char wanted */
if (char_index == position)
{
if (cx) *cx = chr_x;
if (cy) *cy = -asc;
if (cw) *cw = chr_w;
if (ch) *ch = asc + desc;
ret_val = 1;
goto end;
}
prev_chr_end = chr_x + chr_w;
pen_x += fg->glyph->advance.x >> 16;
prev_index = index;
}
end:
#ifdef INTERNATIONAL_SUPPORT
if (level_list) free(level_list);
if (visual_to_logical) free(visual_to_logical);
if (visual_text) free(visual_text);
#endif
return ret_val;
if (v_adv) *v_adv = evas_common_font_get_line_advance(fn);
if (h_adv) *h_adv = pen_x - start_x;
}
/* char pos of text at xy pos */
/* x y w h for char at char pos
* BiDi handling: We recieve the shaped string + other props from intl_props,
* We care about the actual drawing location of the string, this is why we need
* the visual string. We need to know how it's printed. After that we need to calculate
* the reverse kerning in case of rtl parts. "pos" passed to this function is an
* index in bytes, that is the actual byte location of the string, we need to find
* the index in order to find it in the visual string.
*/
EAPI int
evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, int y, int *cx, int *cy, int *cw, int *ch)
evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch)
{
int use_kerning;
int pen_x, pen_y;
int prev_chr_end;
int chr;
int asc, desc;
int char_index = 0; /* the index of the current char */
const char *text = in_text;
int ret_val = -1;
int position = 0;
const Eina_Unicode *text = in_text;
int ret_val = 0;
int last_adv;
FT_UInt prev_index;
RGBA_Font_Int *fi;
FT_Face pface = NULL;
#ifdef INTERNATIONAL_SUPPORT
#ifdef BIDI_SUPPORT
int len = 0;
EvasIntlParType direction = FRIBIDI_TYPE_ON;
EvasIntlLevel *level_list = NULL;
EvasIntlStrIndex *visual_to_logical = NULL;
char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, &visual_to_logical, &level_list);
text = (visual_text) ? visual_text : in_text;
EvasBiDiStrIndex *visual_to_logical = NULL;
Eina_Unicode *visual_text;
visual_text = eina_unicode_strdup(in_text);
if (visual_text)
{
evas_bidi_props_reorder_line(visual_text, intl_props, &visual_to_logical);
text = visual_text;
}
else
{
text = in_text;
}
len = eina_unicode_strlen(text);
#endif
fi = fn->fonts->data;
@ -432,20 +344,189 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
prev_chr_end = 0;
asc = evas_common_font_max_ascent_get(fn);
desc = evas_common_font_max_descent_get(fn);
for (char_index = 0, chr = 0; text[chr]; char_index++)
#ifdef BIDI_SUPPORT
/* Get the position in the visual string because those are the coords we care about */
position = evas_bidi_position_logical_to_visual(visual_to_logical, len, pos);
#else
position = pos;
#endif
last_adv = 0;
for (char_index = 0; *text ; text++, char_index++)
{
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y, chr_w;
int gl, kern;
gl = *text;
if (gl == 0) break;
index = evas_common_font_glyph_search(fn, &fi, gl);
LKL(fi->ft_mutex);
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg)
{
LKU(fi->ft_mutex);
continue;
}
// FIXME: Why no FT_Activate_Size here ?
kern = 0;
/* hmmm kerning means i can't sanely do my own cached metric tables! */
/* grrr - this means font face sharing is kinda... not an option if */
/* you want performance */
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
{
#ifdef BIDI_SUPPORT
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props &&
evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) &&
fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
pen_x += kern;
}
else
#endif
{
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
}
}
pface = fi->src->ft.face;
LKU(fi->ft_mutex);
/* If the current one is not a compositing char, do the previous advance
* and set the current advance as the next advance to do */
if (fg->glyph->advance.x >> 16 > 0)
{
pen_x += last_adv;
last_adv = fg->glyph->advance.x >> 16;
}
if (kern < 0) kern = 0;
chr_x = ((pen_x - kern) + (fg->glyph_out->left));
chr_y = (pen_y + (fg->glyph_out->top));
chr_w = fg->glyph_out->bitmap.width + (kern);
/* if (text[chr]) */
{
int advw;
advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
if (chr_w < advw) chr_w = advw;
}
#if 0 /* This looks like a hack, we don't want it. - leaving it here in case
* I'm wrong */
if (chr_x > prev_chr_end)
{
chr_w += (chr_x - prev_chr_end);
chr_x = prev_chr_end;
}
#endif
/* we need to see if the char at the visual position is the char wanted */
if (char_index == position)
{
if (cx) *cx = chr_x;
if (cy) *cy = -asc;
if (cw) *cw = chr_w;
if (ch) *ch = asc + desc;
ret_val = 1;
goto end;
}
prev_chr_end = chr_x + chr_w;
prev_index = index;
}
end:
#ifdef BIDI_SUPPORT
if (visual_to_logical) free(visual_to_logical);
if (visual_text) free(visual_text);
#endif
return ret_val;
}
/* char pos of text at xy pos
* BiDi handling: Since we are looking for the char at the specific coords,
* we have to get the visual string (to which the coords relate to), do
* reverse kerning query because we are working on the visual string, and then
* we need to get the logical position of the char we found from the visual string.
*/
EAPI int
evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
{
int use_kerning;
int pen_x, pen_y;
int prev_chr_end;
int asc, desc;
int char_index = 0; /* the index of the current char */
const Eina_Unicode *text = in_text;
int last_adv;
int ret_val = -1;
FT_UInt prev_index;
RGBA_Font_Int *fi;
FT_Face pface = NULL;
#ifdef BIDI_SUPPORT
int len = 0;
EvasBiDiStrIndex *visual_to_logical = NULL;
Eina_Unicode *visual_text;
visual_text = eina_unicode_strdup(in_text);
if (visual_text)
{
evas_bidi_props_reorder_line(visual_text, intl_props, &visual_to_logical);
text = visual_text;
}
else
{
text = in_text;
}
len = eina_unicode_strlen(text);
#endif
fi = fn->fonts->data;
pen_x = 0;
pen_y = 0;
// evas_common_font_size_use(fn);
if (fi->src->current_size != fi->size)
{
FTLOCK();
FT_Activate_Size(fi->ft.size);
FTUNLOCK();
fi->src->current_size = fi->size;
}
use_kerning = FT_HAS_KERNING(fi->src->ft.face);
last_adv = 0;
prev_index = 0;
prev_chr_end = 0;
asc = evas_common_font_max_ascent_get(fn);
desc = evas_common_font_max_descent_get(fn);
for (char_index = 0; *text; text++, char_index++)
{
int pchr;
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y, chr_w;
int gl, kern;
pchr = chr;
gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
gl = *text;
if (gl == 0) break;
index = evas_common_font_glyph_search(fn, &fi, gl);
LKL(fi->ft_mutex);
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg)
{
LKU(fi->ft_mutex);
continue;
}
// FIXME: Why not FT_Activate_Size here ?
kern = 0;
/* hmmm kerning means i can't sanely do my own cached metric tables! */
@ -454,10 +535,14 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
{
#ifdef INTERNATIONAL_SUPPORT
#ifdef BIDI_SUPPORT
/* if it's rtl, the kerning matching should be reversed, i.e prev
* index is now the index and the other way around. */
if (evas_intl_is_rtl_char(level_list, char_index))
* index is now the index and the other way around.
* There is a slight exception when there are compositing chars
* involved.*/
if (intl_props &&
evas_bidi_is_rtl_char(intl_props->embedding_levels, char_index) &&
fg->glyph->advance.x >> 16 > 0)
{
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
pen_x += kern;
@ -470,16 +555,21 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
pen_x += kern;
}
}
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
LKU(fi->ft_mutex);
if (!fg) continue;
/* If the current one is not a compositing char, do the previous advance
* and set the current advance as the next advance to do */
if (fg->glyph->advance.x >> 16 > 0)
{
pen_x += last_adv;
last_adv = fg->glyph->advance.x >> 16;
}
if (kern < 0) kern = 0;
chr_x = ((pen_x - kern) + (fg->glyph_out->left));
chr_y = (pen_y + (fg->glyph_out->top));
chr_w = fg->glyph_out->bitmap.width + kern;
/* if (text[chr]) */
{
int advw;
@ -487,43 +577,38 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
if (chr_w < advw) chr_w = advw;
}
#if 0 /* This looks like a hack, we don't want it. - leaving it here in case
* I'm wrong */
if (chr_x > prev_chr_end)
{
chr_w += (chr_x - prev_chr_end);
chr_x = prev_chr_end;
}
#endif
if ((x >= chr_x) && (x <= (chr_x + chr_w)) &&
(y >= -asc) && (y <= desc))
{
int position = char_index;
if (cx) *cx = chr_x;
if (cy) *cy = -asc;
if (cw) *cw = chr_w;
if (ch) *ch = asc + desc;
#ifdef INTERNATIONAL_SUPPORT
{
/* we found the char position of the wanted char in the
* visual string, we now need to translate it to the
* position in the logical string */
int i;
int position = evas_intl_position_visual_to_logical(visual_to_logical, char_index);
/* ensure even if the list won't run */
for (pchr = 0, i = 0; i < position; i++)
evas_common_font_utf8_get_next((unsigned char *)in_text, &pchr);
}
#ifdef BIDI_SUPPORT
/* we found the char position of the wanted char in the
* visual string, we now need to translate it to the
* position in the logical string */
position = evas_bidi_position_visual_to_logical(visual_to_logical, position);
#endif
ret_val = pchr;
ret_val = position;
goto end;
}
prev_chr_end = chr_x + chr_w;
pen_x += fg->glyph->advance.x >> 16;
prev_index = index;
}
end:
#ifdef INTERNATIONAL_SUPPORT
if (level_list) free(level_list);
#ifdef BIDI_SUPPORT
if (visual_to_logical) free(visual_to_logical);
if (visual_text) free(visual_text);
#endif
@ -531,17 +616,23 @@ end:
return ret_val;
}
/* last char pos of text at xy pos
* Note: no need for special rtl handling
* because the string is in logical order, which is correct */
/* position of the last char in thext text that will fit in xy.
* BiDi handling: We recieve the shaped string + other props from intl_props,
* All we care about is char sizes + kerning so we only really need to get the
* shaped string to utf8, and then just go through it like in english, as it's
* just the logical string, nothing special about that.
*/
EAPI int
evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, int y)
evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int x, int y)
{
int use_kerning;
int pen_x, pen_y;
int prev_chr_end;
int chr;
int char_index;
int asc, desc;
int ret=-1;
const Eina_Unicode *text = in_text;
FT_UInt prev_index;
RGBA_Font_Int *fi;
FT_Face pface = NULL;
@ -556,16 +647,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in
prev_chr_end = 0;
asc = evas_common_font_max_ascent_get(fn);
desc = evas_common_font_max_descent_get(fn);
for (chr = 0; text[chr];)
for (char_index = 0; *text; text++, char_index++)
{
int pchr;
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y, chr_w;
int gl, kern;
pchr = chr;
gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
gl = *text;
if (gl == 0) break;
index = evas_common_font_glyph_search(fn, &fi, gl);
LKL(fi->ft_mutex);
@ -582,13 +671,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in
/* you want performance */
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
pen_x += kern;
{
/* No need for special RTL handling because we are working on the logical string*/
if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
pen_x += kern;
}
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
LKU(fi->ft_mutex);
if (!fg) continue;
if (kern < 0) kern = 0;
chr_x = ((pen_x - kern) + (fg->glyph_out->left));
@ -609,11 +699,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in
if ((x >= chr_x) && (x <= (chr_x + chr_w)) &&
(y >= -asc) && (y <= desc))
{
return pchr;
ret = char_index;
goto end;
}
prev_chr_end = chr_x + chr_w;
pen_x += fg->glyph->advance.x >> 16;
prev_index = index;
}
return -1;
end:
return ret;
}

View File

@ -1,124 +0,0 @@
#include <string.h>
#include <stdlib.h>
#include "evas_common.h"
#include "evas_intl_utils.h"
#include "evas_font_private.h"
#ifdef INTERNATIONAL_SUPPORT
#include <fribidi/fribidi.h>
#define UTF8_BYTES_PER_CHAR 4
/* FIXME: fribidi_utf8_to_unicode should use char len and not byte len!*/
char *
evas_intl_utf8_to_visual(const char *text,
int *ret_len,
EvasIntlParType *direction,
EvasIntlStrIndex **position_L_to_V_list,
EvasIntlStrIndex **position_V_to_L_list,
EvasIntlLevel **embedding_level_list)
{
FriBidiChar *unicode_in, *unicode_out;
EvasIntlStrIndex *tmp_L_to_V_list = NULL;
EvasIntlStrIndex *tmp_V_to_L_list = NULL;
EvasIntlLevel *tmp_level_list = NULL;
char *text_out;
size_t len;
size_t byte_len;
if (!text)
return NULL;
len = evas_string_char_len_get(text);
byte_len = strlen(text); /* we need the actual number of bytes, not number of chars */
unicode_in = (FriBidiChar *)alloca(sizeof(FriBidiChar) * (len + 1));
FBDLOCK();
len = fribidi_utf8_to_unicode(text, byte_len, unicode_in);
FBDUNLOCK();
unicode_in[len] = 0;
unicode_out = (FriBidiChar *)alloca(sizeof(FriBidiChar) * (len + 1));
if (embedding_level_list)
{
*embedding_level_list = (EvasIntlLevel *)malloc(sizeof(EvasIntlLevel) * len);
if (!*embedding_level_list)
{
len = -1;
goto error1;
}
tmp_level_list = *embedding_level_list;
}
if (position_L_to_V_list)
{
*position_L_to_V_list = (EvasIntlStrIndex *)malloc(sizeof(EvasIntlStrIndex) * len);
if (!*position_L_to_V_list)
{
len = -1;
goto error2;
}
tmp_L_to_V_list = *position_L_to_V_list;
}
if (position_V_to_L_list)
{
*position_V_to_L_list = (EvasIntlStrIndex *)malloc(sizeof(EvasIntlStrIndex) * len);
if (!*position_V_to_L_list)
{
len = -1;
goto error2;
}
tmp_V_to_L_list = *position_V_to_L_list;
}
FBDLOCK();
if (!fribidi_log2vis(unicode_in, len, direction,
unicode_out, tmp_L_to_V_list, tmp_V_to_L_list, tmp_level_list))
{
FBDUNLOCK();
len = -2;
goto error2;
}
FBDUNLOCK();
text_out = malloc(UTF8_BYTES_PER_CHAR * len + 1);
if (!text_out)
{
len = -1;
goto error2;
}
FBDLOCK();
fribidi_unicode_to_utf8(unicode_out, len, text_out);
FBDUNLOCK();
*ret_len = len;
return text_out;
/* ERROR HANDLING */
error1:
free(*position_V_to_L_list);
*position_V_to_L_list = NULL;
error2:
free(*position_L_to_V_list);
*position_L_to_V_list = NULL;
free(*embedding_level_list);
*embedding_level_list = NULL;
*ret_len = len;
return NULL;
}
int
evas_intl_is_rtl_char(EvasIntlLevel *embedded_level_list, EvasIntlStrIndex i)
{
if(embedded_level_list || i < 0)
return 0;
return FRIBIDI_IS_RTL(embedded_level_list[i]);
}
#endif

View File

@ -1,42 +0,0 @@
#ifndef _EVAS_INTL_UTILS
#define _EVAS_INTL_UTILS
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_FRIBIDI
# define USE_FRIBIDI
# define INTERNATIONAL_SUPPORT
#endif
#ifdef USE_FRIBIDI
# include <fribidi/fribidi.h>
/* abstract fribidi */
typedef FriBidiChar EvasIntlChar;
typedef FriBidiCharType EvasIntlParType;
typedef FriBidiStrIndex EvasIntlStrIndex;
typedef FriBidiLevel EvasIntlLevel;
# define evas_intl_position_logical_to_visual(list, position) \
(list) ? list[position] : position;
# define evas_intl_position_visual_to_logical(list, position) \
(list) ? list[position] : position;
int
evas_intl_is_rtl_char(EvasIntlLevel *embedded_level_list, EvasIntlStrIndex i);
char *
evas_intl_utf8_to_visual(const char *text,
int *ret_len,
EvasIntlParType *direction,
EvasIntlStrIndex **position_L_to_V_list,
EvasIntlStrIndex **position_V_to_L_list,
EvasIntlLevel **embedding_level_list);
#endif
#endif

View File

@ -1399,19 +1399,19 @@ evas_common_pipe_text_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Threa
#endif
evas_common_font_draw(dst, &(context),
op->op.text.font, op->op.text.x, op->op.text.y,
op->op.text.text);
op->op.text.text, op->op.text.intl_props);
}
else
{
evas_common_font_draw(dst, &(op->context),
op->op.text.font, op->op.text.x, op->op.text.y,
op->op.text.text);
op->op.text.text, op->op.text.intl_props);
}
}
EAPI void
evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
RGBA_Font *fn, int x, int y, const char *text)
RGBA_Font *fn, int x, int y, const char *text, const Evas_BiDi_Props *intl_props)
{
RGBA_Pipe_Op *op;
@ -1421,6 +1421,7 @@ evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
op->op.text.x = x;
op->op.text.y = y;
op->op.text.text = strdup(text);
op->op.text.intl_props = intl_props;
#ifdef EVAS_FRAME_QUEUING
LKL(fn->ref_fq_add);
fn->ref_fq[0]++;

View File

@ -1,5 +1,6 @@
#ifndef _EVAS_PIPE_H
#define _EVAS_PIPE_H
#include "evas_bidi_utils.h"
#ifdef BUILD_PTHREAD
typedef struct _Thinfo
@ -88,7 +89,7 @@ EAPI void evas_common_pipe_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int
EAPI void evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points, int x, int y);
EAPI void evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient *gr);
EAPI void evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient2 *gr);
EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text);
EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text, const Evas_BiDi_Props *intl_props);
EAPI void evas_common_pipe_image_load(RGBA_Image *im);
EAPI void evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int smooth, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h);
EAPI void evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst,

View File

@ -197,36 +197,86 @@ evas_imaging_font_line_advance_get(const Evas_Imaging_Font *fn)
EAPI void
evas_imaging_font_string_advance_get(const Evas_Imaging_Font *fn, const char *str, int *x, int *y)
{
Evas_BiDi_Props intl_props;
Eina_Unicode *ustr;
if (!fn) return;
evas_common_font_query_advance(fn->font, str, x, y);
ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
#ifdef BIDI_SUPPORT
evas_bidi_update_props(ustr, &intl_props);
#endif
evas_common_font_query_advance(fn->font, ustr, &intl_props, x, y);
#ifdef BIDI_SUPPORT
evas_bidi_props_clean(&intl_props);
#endif
if (ustr) free(ustr);
}
EAPI void
evas_imaging_font_string_size_query(const Evas_Imaging_Font *fn, const char *str, int *w, int *h)
{
Evas_BiDi_Props intl_props;
Eina_Unicode *ustr;
if (!fn) return;
evas_common_font_query_size(fn->font, str, w, h);
ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
#ifdef BIDI_SUPPORT
evas_bidi_update_props(ustr, &intl_props);
#endif
evas_common_font_query_size(fn->font, ustr, &intl_props, w, h);
#ifdef BIDI_SUPPORT
evas_bidi_props_clean(&intl_props);
#endif
if (ustr) free(ustr);
}
EAPI int
evas_imaging_font_string_inset_get(const Evas_Imaging_Font *fn, const char *str)
{
Eina_Unicode *ustr;
int ret;
if (!fn) return 0;
return evas_common_font_query_inset(fn->font, str);
ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
ret = evas_common_font_query_inset(fn->font, ustr);
if (ustr) free(ustr);
return ret;
}
EAPI int
evas_imaging_font_string_char_coords_get(const Evas_Imaging_Font *fn, const char *str, int pos, int *cx, int *cy, int *cw, int *ch)
{
int ret;
Evas_BiDi_Props intl_props;
Eina_Unicode *ustr;
if (!fn) return 0;
return evas_common_font_query_char_coords(fn->font, str, pos, cx, cy, cw, ch);
ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
#ifdef BIDI_SUPPORT
evas_bidi_update_props(ustr, &intl_props);
#endif
ret = evas_common_font_query_char_coords(fn->font, ustr, &intl_props, pos, cx, cy, cw, ch);
#ifdef BIDI_SUPPORT
evas_bidi_props_clean(&intl_props);
#endif
if (ustr) free(ustr);
return ret;
}
EAPI int
evas_imaging_font_string_char_at_coords_get(const Evas_Imaging_Font *fn, const char *str, int x, int y, int *cx, int *cy, int *cw, int *ch)
{
int ret;
Evas_BiDi_Props intl_props;
Eina_Unicode *ustr;
if (!fn) return -1;
return evas_common_font_query_text_at_pos(fn->font, str, x, y, cx, cy, cw, ch);
ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
#ifdef BIDI_SUPPORT
evas_bidi_update_props(ustr, &intl_props);
#endif
ret = evas_common_font_query_char_at_coords(fn->font, ustr, &intl_props, x, y, cx, cy, cw, ch);
#ifdef BIDI_SUPPORT
evas_bidi_props_clean(&intl_props);
#endif
if (ustr) free(ustr);
return ret;
}
EAPI void

View File

@ -53,7 +53,9 @@ extern EAPI int _evas_log_dom_global;
#endif
#define CRIT(...) EINA_LOG_DOM_CRIT(_EVAS_DEFAULT_LOG_DOM, __VA_ARGS__)
/*****************************************************************************/
/************************ Unicode stuff **************************/
#include "../engines/common/evas_encoding.h"
/*****************************************************************/
#include "evas_options.h"
@ -670,6 +672,7 @@ struct _RGBA_Draw_Context
#ifdef BUILD_PIPE_RENDER
#include "../engines/common/evas_map_image.h"
#include "../engines/common/evas_bidi_utils.h"
struct _RGBA_Pipe_Op
{
@ -698,7 +701,8 @@ struct _RGBA_Pipe_Op
struct {
RGBA_Font *font;
int x, y;
char *text;
Eina_Unicode *text;
Evas_BiDi_Props *intl_props;
} text;
struct {
RGBA_Image *src;
@ -1332,4 +1336,5 @@ void evas_font_dir_cache_free(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -15,6 +15,7 @@
#include "../file/evas_module.h"
#include "../file/evas_path.h"
#include "../engines/common/evas_bidi_utils.h"
#ifdef EVAS_MAGIC_DEBUG
/* complain when peole pass in wrong object types etc. */
@ -703,13 +704,13 @@ struct _Evas_Func
int (*font_descent_get) (void *data, void *font);
int (*font_max_ascent_get) (void *data, void *font);
int (*font_max_descent_get) (void *data, void *font);
void (*font_string_size_get) (void *data, void *font, const char *text, int *w, int *h);
int (*font_inset_get) (void *data, void *font, const char *text);
int (*font_h_advance_get) (void *data, void *font, const char *text);
int (*font_v_advance_get) (void *data, void *font, const char *text);
int (*font_char_coords_get) (void *data, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch);
int (*font_char_at_coords_get) (void *data, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch);
void (*font_draw) (void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text);
void (*font_string_size_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h);
int (*font_inset_get) (void *data, void *font, const Eina_Unicode *text);
int (*font_h_advance_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props);
int (*font_v_advance_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props);
int (*font_char_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch);
int (*font_char_at_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch);
void (*font_draw) (void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props);
void (*font_cache_flush) (void *data);
void (*font_cache_set) (void *data, int bytes);
@ -724,7 +725,7 @@ struct _Evas_Func
void (*image_scale_hint_set) (void *data, void *image, int hint);
int (*image_scale_hint_get) (void *data, void *image);
int (*font_last_up_to_pos) (void *data, void *font, const char *text, int x, int y);
int (*font_last_up_to_pos) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y);
void (*image_map4_draw) (void *data, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level);
void *(*image_map_surface_new) (void *data, int w, int h, int alpha);

View File

@ -1,3 +1,4 @@
#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
#include "evas_private.h"
#include "Evas_Engine_Direct3D.h"
@ -388,7 +389,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image)
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text)
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
Render_Engine *re = (Render_Engine *)data;
RGBA_Image im;
@ -402,7 +403,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
evas_direct3d_font_texture_new,
evas_direct3d_font_texture_free,
evas_direct3d_font_texture_draw);
evas_common_font_draw(&im, context, font, x, y, text);
evas_common_font_draw(&im, context, font, x, y, text, intl_props);
evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL);
}

View File

@ -4,6 +4,7 @@
#include <sys/time.h>
#include <time.h>
#include "evas_engine.h"
#include "evas_common.h" /* Also includes international specific stuff */
/* Uses Evas own image_draw primitive, for comparison purposes only. */
//#define DFB_USE_EVAS_IMAGE_DRAW 1
@ -1041,7 +1042,7 @@ evas_engine_dfb_output_idle_flush(void *data)
* memory.
*/
static void
evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
DirectFB_Engine_Image_Entry *eim = surface;
IDirectFBSurface *screen;
@ -1053,7 +1054,7 @@ evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font,
if (!_dfb_lock_and_sync_image(screen, im, DSLF_READ | DSLF_WRITE))
return;
evas_common_font_draw(im, context, font, x, y, text);
evas_common_font_draw(im, context, font, x, y, text, intl_props);
evas_common_cpu_end_opt();
im->image.data = NULL;

View File

@ -1,3 +1,4 @@
#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
int _evas_engine_GL_glew_log_dom = -1;
@ -986,7 +987,7 @@ eng_image_map_surface_free(void *data __UNUSED__, void *surface)
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text)
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
Render_Engine *re;
@ -1006,7 +1007,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
evas_gl_font_texture_new,
evas_gl_font_texture_free,
evas_gl_font_texture_draw);
evas_common_font_draw(im, context, font, x, y, text);
evas_common_font_draw(im, context, font, x, y, text, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,
NULL,

View File

@ -1,4 +1,4 @@
#include "evas_common.h"
#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
#include <dlfcn.h> /* dlopen,dlclose,etc */
@ -1172,7 +1172,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image)
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
Render_Engine *re;
@ -1192,7 +1192,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
evas_gl_font_texture_new,
evas_gl_font_texture_free,
evas_gl_font_texture_draw);
evas_common_font_draw(im, context, font, x, y, text);
evas_common_font_draw(im, context, font, x, y, text, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,
NULL,

View File

@ -1,3 +1,4 @@
#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
#include <dlfcn.h> /* dlopen,dlclose,etc */
@ -1949,7 +1950,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image)
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
Render_Engine *re;
@ -1970,7 +1971,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
evas_gl_font_texture_new,
evas_gl_font_texture_free,
evas_gl_font_texture_draw);
evas_common_font_draw(im, context, font, x, y, text);
evas_common_font_draw(im, context, font, x, y, text, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,
NULL,

View File

@ -1249,7 +1249,7 @@ eng_font_max_descent_get(void *data, void *font)
}
static void
eng_font_string_size_get(void *data, void *font, const char *text, int *w, int *h)
eng_font_string_size_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int *w, int *h)
{
Render_Engine *re = (Render_Engine *)data;
Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
@ -1279,28 +1279,28 @@ eng_font_inset_get(void *data, void *font, const char *text)
}
static int
eng_font_h_advance_get(void *data, void *font, const char *text)
eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props)
{
int w;
eng_font_string_size_get(data, font, text, &w, NULL);
eng_font_string_size_get(data, font, text, intl_props, &w, NULL);
return w + 2; // FIXME: shouldn't need a constant here. from where do we get word spacing?
// it seems we lose the space between differently-styled text in a text block. Why?
}
static int
eng_font_v_advance_get(void *data, void *font, const char *text)
eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props)
{
int h;
eng_font_string_size_get(data, font, text, NULL, &h);
eng_font_string_size_get(data, font, text, intl_props, NULL, &h);
return h;
}
static int
eng_font_char_coords_get(void *data, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch)
eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch)
{
Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
@ -1320,7 +1320,7 @@ eng_font_char_coords_get(void *data, void *font, const char *text, int pos, int
}
static int
eng_font_char_at_coords_get(void *data, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch)
eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
{
// Return the index of the character at the given point, also lookup it's origin x, y, w, and h.
Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
@ -1332,8 +1332,8 @@ eng_font_char_at_coords_get(void *data, void *font, const char *text, int x, int
int stringIndex = (int) CTLineGetStringIndexForPosition(line, CGPointMake(x, y));
// In order to get the character's size and position, look up the position of this character and the next one
eng_font_char_coords_get(data, font, text, stringIndex, cx, cy, NULL, NULL);
eng_font_char_coords_get(data, font, text, stringIndex + 1, cw, NULL, NULL, NULL);
eng_font_char_coords_get(data, font, text, intl_props, stringIndex, cx, cy, NULL, NULL);
eng_font_char_coords_get(data, font, text, intl_props, stringIndex + 1, cw, NULL, NULL, NULL);
if (cw && cx) *cw -= *cx;
if (ch) *ch = loaded_font->size;
@ -1359,7 +1359,7 @@ eng_font_hinting_can_hint(void *data, int hinting)
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text)
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text, const Evas_BiDi_Props *intl_props)
{
Render_Engine *re = (Render_Engine *)data;
Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;

View File

@ -1,6 +1,7 @@
#ifndef _EVAS_QUARTZ_PRIVATE_H_
#define _EVAS_QUARTZ_PRIVATE_H_
#include "evas_common.h"/* Also includes international specific stuff */
#include "evas_engine.h"
CG_EXTERN void CGContextResetClip (CGContextRef); // undocumented CoreGraphics function to clear clip rect/*
@ -93,7 +94,7 @@ static int eng_font_ascent_get(void *data, void *font);
static int eng_font_descent_get(void *data, void *font);
static int eng_font_max_ascent_get(void *data, void *font);
static int eng_font_max_descent_get(void *data, void *font);
static void eng_font_string_size_get(void *data, void *font, const char *text, int *w, int *h);
static void eng_font_string_size_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int *w, int *h);
static int eng_font_inset_get(void *data, void *font, const char *text);
static int eng_font_h_advance_get(void *data, void *font, const char *text);
static int eng_font_v_advance_get(void *data, void *font, const char *text);

View File

@ -1,4 +1,4 @@
#include "evas_common.h"
#include "evas_common.h"/* Also includes international specific stuff */
#include "evas_common_soft16.h"
/*
@ -762,55 +762,55 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font)
}
static void
eng_font_string_size_get(void *data __UNUSED__, void *font, const char *text, int *w, int *h)
eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h)
{
evas_common_font_query_size(font, text, w, h);
evas_common_font_query_size(font, text, intl_props, w, h);
}
static int
eng_font_inset_get(void *data __UNUSED__, void *font, const char *text)
eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text)
{
return evas_common_font_query_inset(font, text);
}
static int
eng_font_h_advance_get(void *data __UNUSED__, void *font, const char *text)
eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
int h, v;
evas_common_font_query_advance(font, text, &h, &v);
evas_common_font_query_advance(font, text, intl_props, &h, &v);
return h;
}
static int
eng_font_v_advance_get(void *data __UNUSED__, void *font, const char *text)
eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
int h, v;
evas_common_font_query_advance(font, text, &h, &v);
evas_common_font_query_advance(font, text, intl_props, &h, &v);
return v;
}
static int
eng_font_char_coords_get(void *data __UNUSED__, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch)
eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch)
{
return evas_common_font_query_char_coords(font, text, pos, cx, cy, cw, ch);
return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch);
}
static int
eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch)
eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
{
return evas_common_font_query_text_at_pos(font, text, x, y, cx, cy, cw, ch);
return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch);
}
static int
eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const char *text, int x, int y)
eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y)
{
return evas_common_font_query_last_up_to_pos(font, text, x, y);
return evas_common_font_query_last_up_to_pos(font, text, intl_props, x, y);
}
static void
eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
static RGBA_Image *im = NULL;
Soft16_Image *dst = surface;
@ -823,7 +823,7 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, i
soft16_font_glyph_new,
soft16_font_glyph_free,
soft16_font_glyph_draw);
evas_common_font_draw(im, context, font, x, y, text);
evas_common_font_draw(im, context, font, x, y, text, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,
NULL,

View File

@ -5,7 +5,7 @@
#include <time.h>
#include <SDL/SDL.h>
#include "evas_common.h"
#include "evas_common.h"/* Also includes international specific stuff */
#include "evas_engine.h"
int _evas_engine_soft16_sdl_log_dom = -1;
@ -877,7 +877,7 @@ evas_engine_sdl16_image_format_get(void *data __UNUSED__, void *image __UNUSED__
}
static void
evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
static RGBA_Image *im = NULL;
SDL_Engine_Image_Entry *eim = surface;
@ -899,7 +899,7 @@ evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface,
soft16_font_glyph_new,
soft16_font_glyph_free,
soft16_font_glyph_draw);
evas_common_font_draw(im, context, font, x, y, text);
evas_common_font_draw(im, context, font, x, y, text, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,
NULL,

View File

@ -1,4 +1,4 @@
#include "evas_common.h"
#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_private.h"
/*
@ -983,55 +983,55 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font)
}
static void
eng_font_string_size_get(void *data __UNUSED__, void *font, const char *text, int *w, int *h)
eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h)
{
evas_common_font_query_size(font, text, w, h);
evas_common_font_query_size(font, text, intl_props, w, h);
}
static int
eng_font_inset_get(void *data __UNUSED__, void *font, const char *text)
eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text)
{
return evas_common_font_query_inset(font, text);
}
static int
eng_font_h_advance_get(void *data __UNUSED__, void *font, const char *text)
eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
int h, v;
evas_common_font_query_advance(font, text, &h, &v);
evas_common_font_query_advance(font, text, intl_props, &h, &v);
return h;
}
static int
eng_font_v_advance_get(void *data __UNUSED__, void *font, const char *text)
eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
int h, v;
evas_common_font_query_advance(font, text, &h, &v);
evas_common_font_query_advance(font, text, intl_props, &h, &v);
return v;
}
static int
eng_font_char_coords_get(void *data __UNUSED__, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch)
eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch)
{
return evas_common_font_query_char_coords(font, text, pos, cx, cy, cw, ch);
return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch);
}
static int
eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch)
eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
{
return evas_common_font_query_text_at_pos(font, text, x, y, cx, cy, cw, ch);
return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch);
}
static int
eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const char *text, int x, int y)
eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y)
{
return evas_common_font_query_last_up_to_pos(font, text, x, y);
return evas_common_font_query_last_up_to_pos(font, text, intl_props, x, y);
}
static void
eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
#ifdef BUILD_PIPE_RENDER
if ((cpunum > 1)
@ -1039,11 +1039,11 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, i
&& evas_common_frameq_enabled()
#endif
)
evas_common_pipe_text_draw(surface, context, font, x, y, text);
evas_common_pipe_text_draw(surface, context, font, x, y, text, intl_props);
else
#endif
{
evas_common_font_draw(surface, context, font, x, y, text);
evas_common_font_draw(surface, context, font, x, y, text, intl_props);
evas_common_cpu_end_opt();
}
}

View File

@ -5,7 +5,7 @@
#include <time.h>
#include <SDL/SDL.h>
#include "evas_common.h"
#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_engine.h"
int _evas_engine_soft_sdl_log_dom = -1;
@ -739,7 +739,7 @@ evas_engine_sdl_image_format_get(void *data __UNUSED__, void *image __UNUSED__)
}
static void
evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
SDL_Engine_Image_Entry *eim = surface;
int mustlock_im = 0;
@ -751,7 +751,7 @@ evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, v
_SDL_UPDATE_PIXELS(eim);
}
evas_common_font_draw((RGBA_Image *) eim->cache_entry.src, context, font, x, y, text);
evas_common_font_draw((RGBA_Image *) eim->cache_entry.src, context, font, x, y, text, intl_props);
evas_common_cpu_end_opt();
if (mustlock_im)

View File

@ -1,4 +1,4 @@
#include "evas_common.h"
#include "evas_common.h" /* Also includes international specific stuff */
#include "evas_private.h"
#include "Evas_Engine_XRender_X11.h"
@ -1484,7 +1484,7 @@ eng_image_cache_get(void *data)
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow __UNUSED__, int oh __UNUSED__, const char *text)
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
{
Render_Engine *re;
RGBA_Image *im;
@ -1503,7 +1503,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
re->font_surface_new,
re->font_surface_free,
re->font_surface_draw);
evas_common_font_draw(im, context, font, x, y, text);
evas_common_font_draw(im, context, font, x, y, text, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,
NULL,