2002-11-08 00:02:15 -08:00
|
|
|
#include "evas_common.h"
|
2011-01-30 02:35:37 -08:00
|
|
|
#include "language/evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
|
2010-05-21 00:10:45 -07:00
|
|
|
#include "evas_font_private.h" /* for Frame-Queuing support */
|
2009-09-29 21:23:21 -07:00
|
|
|
|
2009-02-10 07:53:17 -08:00
|
|
|
EAPI int
|
|
|
|
evas_common_font_query_kerning(RGBA_Font_Int* fi,
|
2010-08-29 05:44:58 -07:00
|
|
|
FT_UInt left, FT_UInt right,
|
2009-02-10 07:53:17 -08:00
|
|
|
int* kerning)
|
|
|
|
{
|
|
|
|
int *result;
|
|
|
|
FT_Vector delta;
|
|
|
|
int key[2];
|
|
|
|
int error = 1;
|
|
|
|
|
2010-02-03 03:18:00 -08:00
|
|
|
// return 0;
|
2010-08-29 05:44:58 -07:00
|
|
|
key[0] = left;
|
|
|
|
key[1] = right;
|
2009-02-10 07:53:17 -08:00
|
|
|
|
2010-02-23 05:31:10 -08:00
|
|
|
result = eina_hash_find(fi->kerning, key);
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
*kerning = result[2];
|
|
|
|
goto on_correct;
|
|
|
|
}
|
2009-02-10 07:53:17 -08:00
|
|
|
|
|
|
|
/* NOTE: ft2 seems to have a bug. and sometimes returns bizarre
|
|
|
|
* values to kern by - given same font, same size and same
|
2010-09-07 20:51:24 -07:00
|
|
|
* prev_index and index. auto/bytecode or none hinting doesn't
|
2009-02-10 07:53:17 -08:00
|
|
|
* matter */
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-05-21 00:10:45 -07:00
|
|
|
FTLOCK();
|
2009-02-10 07:53:17 -08:00
|
|
|
if (FT_Get_Kerning(fi->src->ft.face,
|
|
|
|
key[0], key[1],
|
|
|
|
ft_kerning_default, &delta) == 0)
|
|
|
|
{
|
2010-02-23 05:31:10 -08:00
|
|
|
int *push;
|
2009-02-10 07:53:17 -08:00
|
|
|
|
2010-05-21 00:10:45 -07:00
|
|
|
FTUNLOCK();
|
2009-02-10 07:53:17 -08:00
|
|
|
*kerning = delta.x >> 6;
|
|
|
|
|
2010-02-23 05:31:10 -08:00
|
|
|
push = malloc(sizeof (int) * 3);
|
|
|
|
if (!push) return 1;
|
2009-02-10 07:53:17 -08:00
|
|
|
|
2010-02-23 05:31:10 -08:00
|
|
|
push[0] = key[0];
|
|
|
|
push[1] = key[1];
|
|
|
|
push[2] = *kerning;
|
2009-02-10 07:53:17 -08:00
|
|
|
|
2010-02-23 05:31:10 -08:00
|
|
|
eina_hash_direct_add(fi->kerning, push, push);
|
2009-02-10 07:53:17 -08:00
|
|
|
|
|
|
|
goto on_correct;
|
|
|
|
}
|
|
|
|
|
2010-05-21 00:10:45 -07:00
|
|
|
FTUNLOCK();
|
2009-02-10 07:53:17 -08:00
|
|
|
error = 0;
|
|
|
|
|
|
|
|
on_correct:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2002-11-08 00:02:15 -08:00
|
|
|
/* text x inset */
|
2011-01-30 02:36:39 -08:00
|
|
|
/* FIXME: should use OT info when available. */
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2010-07-28 05:00:41 -07:00
|
|
|
evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
|
|
|
FT_UInt index;
|
|
|
|
RGBA_Font_Glyph *fg;
|
|
|
|
int gl;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-03-20 07:57:55 -08:00
|
|
|
fi = fn->fonts->data;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2010-07-28 05:00:41 -07:00
|
|
|
if (!*text) return 0;
|
|
|
|
gl = *text;
|
2002-11-08 00:02:15 -08:00
|
|
|
if (gl == 0) return 0;
|
2010-02-03 03:18:00 -08:00
|
|
|
// evas_common_font_size_use(fn);
|
2005-03-20 07:57:55 -08:00
|
|
|
index = evas_common_font_glyph_search(fn, &fi, gl);
|
2010-07-20 05:09:46 -07:00
|
|
|
LKL(fi->ft_mutex);
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_reload(fi);
|
2010-02-03 03:18:00 -08:00
|
|
|
if (fi->src->current_size != fi->size)
|
|
|
|
{
|
2010-07-20 05:09:46 -07:00
|
|
|
FTLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
FT_Activate_Size(fi->ft.size);
|
2010-07-20 05:09:46 -07:00
|
|
|
FTUNLOCK();
|
2010-02-03 03:18:00 -08:00
|
|
|
fi->src->current_size = fi->size;
|
|
|
|
}
|
2005-03-20 07:57:55 -08:00
|
|
|
fg = evas_common_font_int_cache_glyph_get(fi, index);
|
2010-07-20 05:09:46 -07:00
|
|
|
LKU(fi->ft_mutex);
|
2002-11-08 00:02:15 -08:00
|
|
|
if (!fg) return 0;
|
2009-04-23 21:35:52 -07:00
|
|
|
/*
|
2010-10-07 16:46:42 -07:00
|
|
|
INF("fg->glyph_out->left = %i, "
|
|
|
|
"fi->src->ft.face->glyph->bitmap_left = %i, "
|
|
|
|
"fi->src->ft.face->glyph->metrics.horiBearingX = %i, "
|
|
|
|
"fi->src->ft.face->glyph->metrics.horiBearingY = %i, "
|
2009-09-21 09:08:51 -07:00
|
|
|
"fi->src->ft.face->glyph->metrics.horiAdvance = %i"
|
2007-08-25 04:54:17 -07:00
|
|
|
,
|
2009-04-23 21:35:52 -07:00
|
|
|
(int)fg->glyph_out->left,
|
2007-08-25 04:54:17 -07:00
|
|
|
(int)fi->src->ft.face->glyph->bitmap_left,
|
|
|
|
(int)fi->src->ft.face->glyph->metrics.horiBearingX >> 6,
|
|
|
|
(int)fi->src->ft.face->glyph->metrics.horiBearingY >> 6,
|
|
|
|
(int)fi->src->ft.face->glyph->metrics.horiAdvance >> 6
|
|
|
|
);
|
|
|
|
*/
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_use_trim();
|
2011-01-30 02:33:24 -08:00
|
|
|
return fg->glyph_out->left;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @def _INIT_FI_AND_KERNINNG()
|
|
|
|
* @internal
|
|
|
|
* This macro inits fi and use_kerning.
|
|
|
|
* Assumes the following variables exist:
|
|
|
|
* fi, fn and use_kerning.
|
|
|
|
*/
|
|
|
|
#define _INIT_FI_AND_KERNING() \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
fi = fn->fonts->data; \
|
|
|
|
/* evas_common_font_size_use(fn); */ \
|
|
|
|
evas_common_font_int_reload(fi); \
|
|
|
|
if (fi->src->current_size != fi->size) \
|
|
|
|
{ \
|
|
|
|
FTLOCK(); \
|
|
|
|
FT_Activate_Size(fi->ft.size); \
|
|
|
|
FTUNLOCK(); \
|
|
|
|
fi->src->current_size = fi->size; \
|
|
|
|
} \
|
|
|
|
FTLOCK(); \
|
|
|
|
use_kerning = FT_HAS_KERNING(fi->src->ft.face); \
|
|
|
|
FTUNLOCK(); \
|
|
|
|
} \
|
|
|
|
while (0)
|
|
|
|
|
|
|
|
/* size of the string (width and height) in pixels
|
|
|
|
* BiDi handling: We receive 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
|
2011-01-30 02:36:39 -08:00
|
|
|
evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props __UNUSED__, int *w, int *h)
|
2011-01-30 02:33:24 -08:00
|
|
|
{
|
2011-01-30 02:33:32 -08:00
|
|
|
int keep_width = 0;
|
2011-01-30 02:34:36 -08:00
|
|
|
int prev_pen_x = 0;
|
2011-01-30 02:33:24 -08:00
|
|
|
int use_kerning;
|
|
|
|
RGBA_Font_Int *fi;
|
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
_INIT_FI_AND_KERNING();
|
|
|
|
|
2011-01-30 02:36:39 -08:00
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
|
2011-01-30 02:33:24 -08:00
|
|
|
{
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_FALSE);
|
|
|
|
if (!visible) continue;
|
|
|
|
/* Keep the width because we'll need it for the last char */
|
|
|
|
keep_width = EVAS_FONT_WALK_OT_WIDTH + EVAS_FONT_WALK_OT_X_OFF +
|
|
|
|
EVAS_FONT_WALK_OT_X_BEAR;
|
|
|
|
/* Keep the previous pen_x, before it's advanced in TEXT_END */
|
|
|
|
prev_pen_x = pen_x;
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_END();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_FALSE);
|
|
|
|
if (!visible) continue;
|
|
|
|
/* Keep the width because we'll need it for the last char */
|
|
|
|
keep_width = EVAS_FONT_WALK_DEFAULT_WIDTH +
|
|
|
|
EVAS_FONT_WALK_DEFAULT_X_OFF +
|
|
|
|
EVAS_FONT_WALK_DEFAULT_X_BEAR;
|
|
|
|
/* Keep the previous pen_x, before it's advanced in TEXT_END */
|
|
|
|
prev_pen_x = pen_x;
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_END();
|
2011-01-30 02:33:24 -08:00
|
|
|
}
|
2011-01-30 02:34:36 -08:00
|
|
|
if (w) *w = prev_pen_x + keep_width;
|
2011-01-30 02:33:24 -08:00
|
|
|
if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn);
|
|
|
|
evas_common_font_int_use_trim();
|
|
|
|
}
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2010-07-28 05:00:41 -07:00
|
|
|
/* h & v advance
|
2010-09-07 20:51:24 -07:00
|
|
|
* BiDi handling: We receive the shaped string + other props from intl_props,
|
2010-07-28 05:00:41 -07:00
|
|
|
* 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.
|
|
|
|
*/
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI void
|
2011-01-30 02:36:39 -08:00
|
|
|
evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int *h_adv, int *v_adv)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
|
|
|
int use_kerning;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2011-01-30 02:33:24 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
_INIT_FI_AND_KERNING();
|
2011-01-30 02:35:10 -08:00
|
|
|
#ifndef BIDI_SUPPORT
|
|
|
|
/* Suppress warnings */
|
|
|
|
(void) intl_props;
|
|
|
|
#endif
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2011-01-30 02:36:39 -08:00
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_FALSE);
|
|
|
|
if (!visible) continue;
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_END();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_FALSE);
|
|
|
|
if (!visible) continue;
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_END();
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2011-01-30 02:33:24 -08:00
|
|
|
|
2002-11-13 21:38:10 -08:00
|
|
|
if (v_adv) *v_adv = evas_common_font_get_line_advance(fn);
|
2011-01-30 02:34:36 -08:00
|
|
|
if (h_adv) *h_adv = pen_x;
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_use_trim();
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2010-09-02 04:57:52 -07:00
|
|
|
/* x y w h for char at char pos for null it returns the position right after
|
|
|
|
* the last char with 0 as width and height.
|
2010-09-07 20:51:24 -07:00
|
|
|
* BiDi handling: We receive the shaped string + other props from intl_props,
|
2010-07-28 05:00:41 -07:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2011-01-30 02:36:39 -08:00
|
|
|
evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2003-06-06 19:32:30 -07:00
|
|
|
int asc, desc;
|
2010-07-28 05:00:41 -07:00
|
|
|
int position = 0;
|
|
|
|
const Eina_Unicode *text = in_text;
|
2009-09-29 21:23:21 -07:00
|
|
|
int ret_val = 0;
|
2011-01-30 02:33:24 -08:00
|
|
|
int use_kerning;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2011-01-30 02:33:24 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
_INIT_FI_AND_KERNING();
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2003-06-06 19:32:30 -07:00
|
|
|
asc = evas_common_font_max_ascent_get(fn);
|
|
|
|
desc = evas_common_font_max_descent_get(fn);
|
2009-09-29 21:23:21 -07:00
|
|
|
|
2010-07-28 05:00:41 -07:00
|
|
|
position = pos;
|
2010-09-02 04:49:00 -07:00
|
|
|
/* If it's the null, choose location according to the direction. */
|
|
|
|
if (!text[position])
|
|
|
|
{
|
|
|
|
/* if it's rtl then the location is the left of the string,
|
|
|
|
* otherwise, the right. */
|
2010-09-02 04:53:40 -07:00
|
|
|
#ifdef BIDI_SUPPORT
|
2011-01-30 02:36:39 -08:00
|
|
|
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
|
2010-09-02 04:49:00 -07:00
|
|
|
{
|
|
|
|
if (cx) *cx = 0;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
}
|
|
|
|
else
|
2010-09-02 04:53:40 -07:00
|
|
|
#endif
|
2010-09-02 04:49:00 -07:00
|
|
|
{
|
2011-01-30 02:35:24 -08:00
|
|
|
evas_common_font_query_advance(fn, in_text, intl_props, cx, ch);
|
2010-09-02 04:49:00 -07:00
|
|
|
}
|
|
|
|
if (cy) *cy = 0;
|
|
|
|
if (cw) *cw = 0;
|
|
|
|
ret_val = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
2009-09-29 21:23:21 -07:00
|
|
|
|
2011-01-30 02:36:39 -08:00
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
|
|
|
|
{
|
|
|
|
int chr_x, chr_w;
|
|
|
|
int found = 0, items = 1, item_pos = 1;
|
|
|
|
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_TRUE);
|
|
|
|
if (visible)
|
|
|
|
{
|
|
|
|
chr_x = (pen_x) + EVAS_FONT_WALK_OT_X_OFF +
|
|
|
|
EVAS_FONT_WALK_OT_X_BEAR;
|
|
|
|
chr_w = EVAS_FONT_WALK_OT_WIDTH;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
chr_x = pen_x;
|
|
|
|
chr_w = 0;
|
|
|
|
}
|
|
|
|
/* we need to see if the char at the visual position is the char wanted */
|
|
|
|
if ((intl_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) &&
|
|
|
|
(EVAS_FONT_WALK_OT_POS <= (size_t) position) &&
|
|
|
|
((((size_t) position) < EVAS_FONT_WALK_OT_POS_NEXT) ||
|
2011-01-30 02:37:12 -08:00
|
|
|
(EVAS_FONT_WALK_OT_IS_LAST)))
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
|
|
|
found = 1;
|
|
|
|
items = EVAS_FONT_WALK_OT_POS_NEXT - EVAS_FONT_WALK_OT_POS;
|
|
|
|
if (EVAS_FONT_WALK_OT_POS == EVAS_FONT_WALK_OT_POS_NEXT)
|
|
|
|
{
|
|
|
|
/* If there was only one char, take the original lens
|
|
|
|
* for the number of items. */
|
|
|
|
items = EVAS_FONT_WALK_ORIG_LEN -
|
|
|
|
EVAS_FONT_WALK_OT_POS;
|
|
|
|
}
|
|
|
|
item_pos = position - EVAS_FONT_WALK_OT_POS + 1;
|
|
|
|
}
|
|
|
|
else if ((intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) &&
|
|
|
|
((EVAS_FONT_WALK_OT_POS_PREV > (size_t) position) ||
|
2011-01-30 02:37:18 -08:00
|
|
|
(EVAS_FONT_WALK_OT_IS_FIRST)) &&
|
2011-01-30 02:36:39 -08:00
|
|
|
(((size_t) position) >= EVAS_FONT_WALK_OT_POS))
|
|
|
|
{
|
|
|
|
found = 1;
|
|
|
|
items = EVAS_FONT_WALK_OT_POS_PREV - EVAS_FONT_WALK_OT_POS;
|
|
|
|
if (EVAS_FONT_WALK_OT_POS == EVAS_FONT_WALK_OT_POS_PREV)
|
|
|
|
{
|
|
|
|
/* If there was only one char, take the original lens
|
|
|
|
* for the number of items. */
|
|
|
|
items = EVAS_FONT_WALK_ORIG_LEN -
|
|
|
|
EVAS_FONT_WALK_OT_POS;
|
|
|
|
}
|
|
|
|
item_pos = items - (position - EVAS_FONT_WALK_OT_POS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
{
|
|
|
|
if (cx) *cx = chr_x +
|
|
|
|
(EVAS_FONT_WALK_OT_WIDTH / items) * (item_pos - 1);
|
|
|
|
if (cy) *cy = -asc;
|
|
|
|
if (cw) *cw = chr_w / items;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
ret_val = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_END();
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
else
|
2009-09-29 21:23:21 -07:00
|
|
|
#endif
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
|
|
|
|
{
|
|
|
|
int chr_x, chr_w;
|
|
|
|
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_TRUE);
|
|
|
|
if (visible)
|
|
|
|
{
|
|
|
|
chr_x = (pen_x) + EVAS_FONT_WALK_DEFAULT_X_OFF +
|
|
|
|
EVAS_FONT_WALK_DEFAULT_X_BEAR;
|
|
|
|
chr_w = EVAS_FONT_WALK_DEFAULT_WIDTH;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
chr_x = pen_x;
|
|
|
|
chr_w = 0;
|
|
|
|
}
|
|
|
|
/* we need to see if the char at the visual position is the char wanted */
|
|
|
|
if (EVAS_FONT_WALK_DEFAULT_POS == (size_t) position)
|
|
|
|
{
|
2011-01-30 02:36:53 -08:00
|
|
|
if (cx) *cx = chr_x;
|
2011-01-30 02:36:39 -08:00
|
|
|
if (cy) *cy = -asc;
|
|
|
|
if (cw) *cw = chr_w;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
ret_val = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_END();
|
|
|
|
}
|
|
|
|
end:
|
2009-09-29 21:23:21 -07:00
|
|
|
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_use_trim();
|
2009-09-29 21:23:21 -07:00
|
|
|
return ret_val;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2011-01-30 02:34:07 -08:00
|
|
|
/* x y w h for pen at char pos for null it returns the position right after
|
|
|
|
* the last char with 0 as width and height. This is the same as char_coords
|
|
|
|
* but it returns the pen_x and adv instead of x and w.
|
|
|
|
* BiDi handling: We receive 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
|
2011-01-30 02:36:39 -08:00
|
|
|
evas_common_font_query_pen_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch)
|
2011-01-30 02:34:07 -08:00
|
|
|
{
|
|
|
|
int asc, desc;
|
|
|
|
int position = 0;
|
|
|
|
const Eina_Unicode *text = in_text;
|
|
|
|
int ret_val = 0;
|
|
|
|
int use_kerning;
|
|
|
|
RGBA_Font_Int *fi;
|
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
_INIT_FI_AND_KERNING();
|
|
|
|
|
|
|
|
asc = evas_common_font_max_ascent_get(fn);
|
|
|
|
desc = evas_common_font_max_descent_get(fn);
|
|
|
|
|
|
|
|
position = pos;
|
|
|
|
/* If it's the null, choose location according to the direction. */
|
|
|
|
if (!text[position])
|
|
|
|
{
|
|
|
|
/* if it's rtl then the location is the left of the string,
|
|
|
|
* otherwise, the right. */
|
|
|
|
#ifdef BIDI_SUPPORT
|
2011-01-30 02:36:39 -08:00
|
|
|
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
|
2011-01-30 02:34:07 -08:00
|
|
|
{
|
|
|
|
if (cpen_x) *cpen_x = 0;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2011-01-30 02:35:24 -08:00
|
|
|
evas_common_font_query_advance(fn, in_text, intl_props, cpen_x, ch);
|
2011-01-30 02:34:07 -08:00
|
|
|
}
|
|
|
|
if (cy) *cy = 0;
|
|
|
|
if (cadv) *cadv = 0;
|
|
|
|
ret_val = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
|
2011-01-30 02:34:07 -08:00
|
|
|
{
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
|
|
|
|
{
|
|
|
|
int found = 0, items = 1, item_pos = 1;
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_TRUE);
|
|
|
|
/* we need to see if the char at the visual position is the char wanted */
|
|
|
|
if ((intl_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) &&
|
|
|
|
(EVAS_FONT_WALK_OT_POS <= (size_t) position) &&
|
|
|
|
((((size_t) position) < EVAS_FONT_WALK_OT_POS_NEXT) ||
|
2011-01-30 02:37:12 -08:00
|
|
|
(EVAS_FONT_WALK_OT_IS_LAST)))
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
|
|
|
found = 1;
|
|
|
|
items = EVAS_FONT_WALK_OT_POS_NEXT - EVAS_FONT_WALK_OT_POS;
|
|
|
|
if (EVAS_FONT_WALK_OT_POS == EVAS_FONT_WALK_OT_POS_NEXT)
|
|
|
|
{
|
|
|
|
/* If there was only one char, take the original lens
|
|
|
|
* for the number of items. */
|
|
|
|
items = EVAS_FONT_WALK_ORIG_LEN -
|
|
|
|
EVAS_FONT_WALK_OT_POS;
|
|
|
|
}
|
|
|
|
item_pos = position - EVAS_FONT_WALK_OT_POS + 1;
|
|
|
|
}
|
|
|
|
else if ((intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) &&
|
|
|
|
((EVAS_FONT_WALK_OT_POS_PREV > (size_t) position) ||
|
2011-01-30 02:37:18 -08:00
|
|
|
(EVAS_FONT_WALK_OT_IS_FIRST)) &&
|
2011-01-30 02:36:39 -08:00
|
|
|
(((size_t) position) >= EVAS_FONT_WALK_OT_POS))
|
|
|
|
{
|
|
|
|
found = 1;
|
|
|
|
items = EVAS_FONT_WALK_OT_POS_PREV - EVAS_FONT_WALK_OT_POS;
|
|
|
|
if (EVAS_FONT_WALK_OT_POS == EVAS_FONT_WALK_OT_POS_PREV)
|
|
|
|
{
|
|
|
|
/* If there was only one char, take the original lens
|
|
|
|
* for the number of items. */
|
|
|
|
items = EVAS_FONT_WALK_ORIG_LEN -
|
|
|
|
EVAS_FONT_WALK_OT_POS;
|
|
|
|
}
|
|
|
|
item_pos = items - (position - EVAS_FONT_WALK_OT_POS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
{
|
|
|
|
if (cy) *cy = -asc;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
/* FIXME: A hack to make combining chars work nice, should
|
|
|
|
* change to take the base char's adv. */
|
|
|
|
if (visible)
|
|
|
|
{
|
|
|
|
if (EVAS_FONT_WALK_OT_X_ADV > 0)
|
|
|
|
{
|
|
|
|
if (cpen_x) *cpen_x = pen_x +
|
|
|
|
(EVAS_FONT_WALK_OT_X_ADV / items) *
|
|
|
|
(item_pos - 1);
|
|
|
|
if (cadv) *cadv = (EVAS_FONT_WALK_OT_X_ADV / items);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cpen_x) *cpen_x = pen_x +
|
|
|
|
EVAS_FONT_WALK_OT_X_OFF +
|
|
|
|
EVAS_FONT_WALK_OT_X_BEAR +
|
|
|
|
(EVAS_FONT_WALK_OT_WIDTH / items) *
|
|
|
|
(item_pos - 1);
|
|
|
|
if (cadv) *cadv = (EVAS_FONT_WALK_OT_WIDTH / items);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cpen_x) *cpen_x = pen_x;
|
|
|
|
if (cadv) *cadv = 0;
|
|
|
|
}
|
|
|
|
ret_val = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_END();
|
2011-01-30 02:34:07 -08:00
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
else
|
2011-01-30 02:34:07 -08:00
|
|
|
#endif
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_TRUE);
|
|
|
|
|
|
|
|
if ((EVAS_FONT_WALK_DEFAULT_POS == (size_t) position))
|
|
|
|
{
|
|
|
|
if (cy) *cy = -asc;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
/* FIXME: A hack to make combining chars work nice, should change
|
|
|
|
* to take the base char's adv. */
|
|
|
|
if (visible)
|
|
|
|
{
|
|
|
|
if (EVAS_FONT_WALK_DEFAULT_X_ADV > 0)
|
|
|
|
{
|
2011-01-30 02:36:53 -08:00
|
|
|
if (cpen_x) *cpen_x = pen_x;
|
2011-01-30 02:36:39 -08:00
|
|
|
if (cadv) *cadv = EVAS_FONT_WALK_DEFAULT_X_ADV;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cpen_x) *cpen_x = pen_x +
|
|
|
|
EVAS_FONT_WALK_DEFAULT_X_OFF +
|
2011-01-30 02:36:53 -08:00
|
|
|
EVAS_FONT_WALK_DEFAULT_X_BEAR;
|
2011-01-30 02:36:39 -08:00
|
|
|
if (cadv) *cadv = EVAS_FONT_WALK_DEFAULT_WIDTH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cpen_x) *cpen_x = pen_x;
|
|
|
|
if (cadv) *cadv = 0;
|
|
|
|
}
|
|
|
|
ret_val = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_END();
|
|
|
|
}
|
|
|
|
end:
|
2011-01-30 02:34:07 -08:00
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
2010-07-28 05:00:41 -07:00
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2011-01-30 02:36:39 -08:00
|
|
|
evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
|
2009-09-29 21:23:21 -07:00
|
|
|
{
|
|
|
|
int asc, desc;
|
2010-07-28 05:00:41 -07:00
|
|
|
const Eina_Unicode *text = in_text;
|
2009-09-29 21:23:21 -07:00
|
|
|
int ret_val = -1;
|
2011-01-30 02:33:24 -08:00
|
|
|
int use_kerning;
|
2009-09-29 21:23:21 -07:00
|
|
|
RGBA_Font_Int *fi;
|
2011-01-30 02:33:24 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
_INIT_FI_AND_KERNING();
|
2011-01-30 02:35:10 -08:00
|
|
|
#ifndef BIDI_SUPPORT
|
|
|
|
/* Suppress warnings */
|
|
|
|
(void) intl_props;
|
|
|
|
#endif
|
2009-09-30 22:18:17 -07:00
|
|
|
|
2011-01-30 02:36:39 -08:00
|
|
|
asc = evas_common_font_max_ascent_get(fn);
|
|
|
|
desc = evas_common_font_max_descent_get(fn);
|
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
|
2010-07-28 05:00:41 -07:00
|
|
|
{
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
|
2011-01-30 02:35:17 -08:00
|
|
|
{
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_TRUE);
|
|
|
|
if (!visible) continue;
|
|
|
|
|
|
|
|
/* we need to see if the char at the visual position is the char,
|
|
|
|
* we check that by checking if it's before the current pen
|
|
|
|
* position and the next */
|
|
|
|
if ((x >= pen_x) && (x <= (pen_x + EVAS_FONT_WALK_OT_X_ADV)) &&
|
|
|
|
(y >= -asc) && (y <= desc))
|
|
|
|
{
|
|
|
|
int items = 1, item_pos = 1;
|
|
|
|
|
|
|
|
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR)
|
|
|
|
{
|
|
|
|
double part;
|
|
|
|
items = EVAS_FONT_WALK_OT_POS_NEXT -
|
|
|
|
EVAS_FONT_WALK_OT_POS;
|
|
|
|
/* If it's the last/first char in a ltr/rtl string */
|
|
|
|
if (items == 0)
|
|
|
|
{
|
|
|
|
items = EVAS_FONT_WALK_ORIG_LEN -
|
|
|
|
EVAS_FONT_WALK_OT_POS;
|
|
|
|
}
|
|
|
|
part = EVAS_FONT_WALK_OT_X_ADV / items;
|
|
|
|
item_pos = (int) ((x - pen_x) / part);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double part;
|
|
|
|
items = EVAS_FONT_WALK_OT_POS_PREV -
|
|
|
|
EVAS_FONT_WALK_OT_POS;
|
|
|
|
/* If it's the last/first char in a ltr/rtl string */
|
|
|
|
if (items == 0)
|
|
|
|
{
|
|
|
|
items = EVAS_FONT_WALK_ORIG_LEN -
|
|
|
|
EVAS_FONT_WALK_OT_POS;
|
|
|
|
}
|
|
|
|
part = EVAS_FONT_WALK_OT_X_ADV / items;
|
|
|
|
item_pos = items - ((int) ((x - pen_x) / part)) - 1;
|
|
|
|
}
|
|
|
|
if (cx) *cx = pen_x + EVAS_FONT_WALK_OT_X_OFF +
|
|
|
|
EVAS_FONT_WALK_OT_X_BEAR +
|
|
|
|
((EVAS_FONT_WALK_OT_X_ADV / items) * (item_pos - 1));
|
|
|
|
if (cy) *cy = -asc;
|
|
|
|
if (cw) *cw = (EVAS_FONT_WALK_OT_X_ADV / items);
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
ret_val = EVAS_FONT_WALK_OT_POS + item_pos;
|
|
|
|
goto end;
|
|
|
|
}
|
2011-01-30 02:35:17 -08:00
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_OT_TEXT_END();
|
2010-07-28 05:00:41 -07:00
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
else
|
2009-09-29 21:23:21 -07:00
|
|
|
#endif
|
|
|
|
{
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_TRUE);
|
|
|
|
if (!visible) continue;
|
|
|
|
|
|
|
|
/* we need to see if the char at the visual position is the char,
|
|
|
|
* we check that by checking if it's before the current pen position
|
|
|
|
* and the next */
|
|
|
|
if ((x >= pen_x) && (x <= (pen_x + EVAS_FONT_WALK_DEFAULT_X_ADV))
|
|
|
|
&& (y >= -asc) && (y <= desc))
|
|
|
|
{
|
|
|
|
if (cx) *cx = pen_x + EVAS_FONT_WALK_DEFAULT_X_OFF +
|
|
|
|
EVAS_FONT_WALK_DEFAULT_X_BEAR +
|
|
|
|
EVAS_FONT_WALK_DEFAULT_X_ADV;
|
|
|
|
if (cy) *cy = -asc;
|
|
|
|
if (cw) *cw = EVAS_FONT_WALK_DEFAULT_X_ADV;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
ret_val = EVAS_FONT_WALK_DEFAULT_POS;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_END();
|
2009-09-29 21:23:21 -07:00
|
|
|
}
|
2011-01-30 02:33:24 -08:00
|
|
|
|
2009-09-29 21:23:21 -07:00
|
|
|
end:
|
|
|
|
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_use_trim();
|
2009-09-29 21:23:21 -07:00
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
2011-01-30 02:34:49 -08:00
|
|
|
/* position of the char after the last char in the text that will fit in xy.
|
2010-09-07 20:51:24 -07:00
|
|
|
* BiDi handling: We receive the shaped string + other props from intl_props,
|
2010-07-28 05:00:41 -07:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2009-09-29 21:23:21 -07:00
|
|
|
EAPI int
|
2011-01-30 02:36:39 -08:00
|
|
|
evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props __UNUSED__, int x, int y)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2003-06-06 19:32:30 -07:00
|
|
|
int asc, desc;
|
2010-07-28 05:00:41 -07:00
|
|
|
int ret=-1;
|
|
|
|
const Eina_Unicode *text = in_text;
|
2011-01-30 02:33:24 -08:00
|
|
|
int use_kerning;
|
2005-03-20 07:57:55 -08:00
|
|
|
RGBA_Font_Int *fi;
|
2011-01-30 02:33:24 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
_INIT_FI_AND_KERNING();
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2003-06-06 19:32:30 -07:00
|
|
|
asc = evas_common_font_max_ascent_get(fn);
|
|
|
|
desc = evas_common_font_max_descent_get(fn);
|
2011-01-30 02:36:39 -08:00
|
|
|
|
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_LOGICAL_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_FALSE);
|
|
|
|
if (!visible) continue;
|
|
|
|
|
|
|
|
if ((x >= pen_x) && (x <= (pen_x + EVAS_FONT_WALK_OT_X_ADV)) &&
|
|
|
|
(y >= -asc) && (y <= desc))
|
|
|
|
{
|
|
|
|
ret = EVAS_FONT_WALK_OT_POS;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_OT_TEXT_END();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2011-01-30 02:36:39 -08:00
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_FALSE);
|
|
|
|
if (!visible) continue;
|
|
|
|
|
|
|
|
if ((x >= pen_x) &&
|
|
|
|
(x <= (pen_x + EVAS_FONT_WALK_DEFAULT_X_ADV)) &&
|
|
|
|
(y >= -asc) && (y <= desc))
|
|
|
|
{
|
|
|
|
ret = char_index;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_DEFAULT_TEXT_END();
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2011-01-30 02:33:24 -08:00
|
|
|
|
2010-07-28 05:00:41 -07:00
|
|
|
end:
|
|
|
|
|
2010-10-29 05:55:42 -07:00
|
|
|
evas_common_font_int_use_trim();
|
2011-01-30 02:33:24 -08:00
|
|
|
return ret;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
|