2013-06-20 03:53:29 -07:00
|
|
|
#include "evas_common_private.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 */
|
2011-02-01 04:17:52 -08:00
|
|
|
#include "evas_font_ot.h"
|
2009-09-29 21:23:21 -07:00
|
|
|
|
2011-05-29 02:20:18 -07:00
|
|
|
|
|
|
|
/* FIXME: Check coverage according to the font and not by actually loading */
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Find the end of a run according to font coverage, and return the base script
|
|
|
|
* font and the current wanted font.
|
|
|
|
*
|
|
|
|
* @param[in] fn the font to use.
|
|
|
|
* @param script_fi The base font instance to be used with the script. If NULL, then it's calculated and returned in this variable, if not NULL, it's used and not modified.
|
|
|
|
* @param[out] cur_fi The font instance found for the current run.
|
|
|
|
* @param[in] script the base script
|
|
|
|
* @param[in] text the text to work on.
|
|
|
|
* @param[in] run_let the current run len, i.e "search limit".
|
|
|
|
* @return length of the run found.
|
|
|
|
*/
|
|
|
|
EAPI int
|
|
|
|
evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi, RGBA_Font_Int **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len)
|
|
|
|
{
|
2011-05-30 08:18:53 -07:00
|
|
|
RGBA_Font_Int *fi = NULL;
|
2011-05-29 02:20:18 -07:00
|
|
|
const Eina_Unicode *run_end = text + run_len;
|
|
|
|
const Eina_Unicode *itr;
|
|
|
|
|
|
|
|
/* If there's no current script_fi, find it first */
|
|
|
|
if (!*script_fi)
|
|
|
|
{
|
|
|
|
const Eina_Unicode *base_char = NULL;
|
|
|
|
/* Skip common chars */
|
|
|
|
for (base_char = text ;
|
|
|
|
(base_char < run_end) &&
|
|
|
|
(evas_common_language_char_script_get(*base_char) != script) ;
|
|
|
|
base_char++)
|
|
|
|
;
|
|
|
|
if (base_char == run_end) base_char = text;
|
|
|
|
|
|
|
|
/* Find the first renderable char */
|
|
|
|
while (base_char < run_end)
|
|
|
|
{
|
|
|
|
/* 0x1F is the last ASCII contral char, just a hack in
|
|
|
|
* the meanwhile. */
|
|
|
|
if ((*base_char > 0x1F) &&
|
|
|
|
evas_common_font_glyph_search(fn, &fi, *base_char))
|
|
|
|
break;
|
|
|
|
base_char++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* If everything else fails, at least try to find a font for the
|
|
|
|
* replacement char */
|
|
|
|
if (base_char == run_end)
|
|
|
|
evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
|
|
|
|
|
2011-06-03 13:48:56 -07:00
|
|
|
if (!fi)
|
|
|
|
fi = fn->fonts->data;
|
|
|
|
|
2011-05-29 02:20:18 -07:00
|
|
|
*script_fi = fi;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fi = *script_fi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the longest run of the same font starting from the start position
|
|
|
|
* and update cur_fi accordingly. */
|
|
|
|
itr = text;
|
|
|
|
while (itr < run_end)
|
|
|
|
{
|
|
|
|
RGBA_Font_Int *tmp_fi;
|
|
|
|
/* Itr will end up being the first of the next run */
|
|
|
|
for ( ; itr < run_end ; itr++)
|
|
|
|
{
|
2011-06-02 07:31:15 -07:00
|
|
|
/* 0x1F is the last ASCII contral char, just a hack in
|
|
|
|
* the meanwhile. */
|
|
|
|
if (*itr <= 0x1F)
|
|
|
|
continue;
|
2011-05-29 02:20:18 -07:00
|
|
|
/* Break if either it's not in the font, or if it is in the
|
|
|
|
* script's font. */
|
2013-02-21 06:59:27 -08:00
|
|
|
if (!evas_common_get_char_index(fi, *itr))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (fi != *script_fi)
|
2011-05-29 02:20:18 -07:00
|
|
|
{
|
|
|
|
if (evas_common_get_char_index(*script_fi, *itr))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-20 00:28:57 -07:00
|
|
|
/* Abort if we reached the end */
|
|
|
|
if (itr == run_end)
|
|
|
|
break;
|
|
|
|
|
2011-05-29 02:20:18 -07:00
|
|
|
/* If the script font doesn't fit even one char, find a new font. */
|
|
|
|
if (itr == text)
|
|
|
|
{
|
|
|
|
/* If we can find a font, use it. Otherwise, find the first
|
|
|
|
* char the run of chars that can't be rendered until the first
|
|
|
|
* one that can. */
|
|
|
|
if (evas_common_font_glyph_search(fn, &tmp_fi, *itr))
|
|
|
|
{
|
|
|
|
fi = tmp_fi;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
itr++;
|
|
|
|
/* Go through all the chars that can't be rendered with any
|
|
|
|
* font */
|
|
|
|
for ( ; itr < run_end ; itr++)
|
|
|
|
{
|
2011-05-30 08:18:53 -07:00
|
|
|
tmp_fi = fi;
|
2011-05-29 02:20:18 -07:00
|
|
|
if (evas_common_get_char_index(fi, *itr) ||
|
2011-05-30 06:59:18 -07:00
|
|
|
evas_common_font_glyph_search(fn, &tmp_fi, *itr))
|
|
|
|
{
|
|
|
|
fi = tmp_fi;
|
|
|
|
break;
|
|
|
|
}
|
2011-05-29 02:20:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If we found a renderable character and the found font
|
|
|
|
* can render the replacement char, continue, otherwise
|
|
|
|
* find a font most suitable for the replacement char and
|
|
|
|
* break */
|
|
|
|
if ((itr == run_end) ||
|
|
|
|
!evas_common_get_char_index(fi, REPLACEMENT_CHAR))
|
|
|
|
{
|
|
|
|
evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
itr++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If this char is not renderable by any font, but the replacement
|
|
|
|
* char can be rendered using the currentfont, continue this
|
|
|
|
* run. */
|
|
|
|
if (!evas_common_font_glyph_search(fn, &tmp_fi, *itr) &&
|
|
|
|
evas_common_get_char_index(fi, REPLACEMENT_CHAR))
|
|
|
|
{
|
|
|
|
itr++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Done, we did as much as possible */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-30 01:31:29 -07:00
|
|
|
if (fi)
|
|
|
|
*cur_fi = fi;
|
|
|
|
else
|
|
|
|
*cur_fi = *script_fi;
|
2011-05-29 02:20:18 -07:00
|
|
|
|
|
|
|
return itr - text;
|
|
|
|
}
|
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Calculate the kerning between "left" and "right.
|
|
|
|
*
|
|
|
|
* @param fi the font instance to use
|
|
|
|
* @param left the left glyph index
|
|
|
|
* @param right the right glyph index
|
|
|
|
* @param[out] kerning the kerning calculated.
|
|
|
|
* @return FALSE on error, TRUE on success.
|
|
|
|
*/
|
2009-02-10 07:53:17 -08:00
|
|
|
EAPI int
|
2011-04-28 05:57:35 -07:00
|
|
|
evas_common_font_query_kerning(RGBA_Font_Int *fi, FT_UInt left, FT_UInt right,
|
|
|
|
int *kerning)
|
2009-02-10 07:53:17 -08:00
|
|
|
{
|
|
|
|
int *result;
|
|
|
|
FT_Vector delta;
|
|
|
|
int key[2];
|
2013-09-29 04:14:45 -07:00
|
|
|
int hash;
|
2009-02-10 07:53:17 -08:00
|
|
|
int error = 1;
|
|
|
|
|
2010-08-29 05:44:58 -07:00
|
|
|
key[0] = left;
|
|
|
|
key[1] = right;
|
2013-09-29 04:14:45 -07:00
|
|
|
hash = eina_hash_int32(&left, sizeof (int)) ^ eina_hash_int32(&right, sizeof (int));
|
2009-02-10 07:53:17 -08:00
|
|
|
|
2013-09-29 04:14:45 -07:00
|
|
|
result = eina_hash_find_by_hash(fi->kerning, key, sizeof (int) * 2, hash);
|
2010-02-23 05:31:10 -08:00
|
|
|
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,
|
2013-09-29 04:14:45 -07:00
|
|
|
left, right,
|
2011-05-18 06:47:45 -07:00
|
|
|
FT_KERNING_DEFAULT, &delta) == 0)
|
2009-02-10 07:53:17 -08:00
|
|
|
{
|
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();
|
2011-01-30 02:42:13 -08:00
|
|
|
*kerning = delta.x;
|
2009-02-10 07:53:17 -08:00
|
|
|
|
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
|
|
|
|
2013-09-29 04:14:45 -07:00
|
|
|
push[0] = left;
|
|
|
|
push[1] = right;
|
2010-02-23 05:31:10 -08:00
|
|
|
push[2] = *kerning;
|
2009-02-10 07:53:17 -08:00
|
|
|
|
2013-09-29 04:14:45 -07:00
|
|
|
eina_hash_direct_add_by_hash(fi->kerning, push, sizeof(int) * 2, hash, 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;
|
|
|
|
}
|
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Calculate the inset of the text. Inset is the difference between the pen
|
|
|
|
* position of the first char in the string, and the first pixel drawn.
|
|
|
|
* (can be negative).
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @return the calculated inset.
|
|
|
|
*/
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2012-11-04 03:51:42 -08:00
|
|
|
evas_common_font_query_inset(RGBA_Font *fn EINA_UNUSED, const Evas_Text_Props *text_props)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2011-02-10 01:03:14 -08:00
|
|
|
if (!text_props->len) return 0;
|
|
|
|
return text_props->info->glyph[text_props->start].x_bear;
|
2011-01-30 02:33:24 -08:00
|
|
|
}
|
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Calculate the right inset of the text. This is the difference between the
|
|
|
|
* pen position of the glyph after the last glyph in the text, and the last
|
|
|
|
* pixel drawn in the text (essentially "advance - width" of the last char).
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @return the calculated inset.
|
|
|
|
*
|
|
|
|
* @see evas_common_font_query_inset()
|
|
|
|
*/
|
2011-03-29 06:52:22 -07:00
|
|
|
EAPI int
|
2012-11-04 03:51:42 -08:00
|
|
|
evas_common_font_query_right_inset(RGBA_Font *fn EINA_UNUSED, const Evas_Text_Props *text_props)
|
2011-03-29 06:52:22 -07:00
|
|
|
{
|
|
|
|
const Evas_Font_Glyph_Info *gli;
|
|
|
|
if (!text_props->len) return 0;
|
|
|
|
gli = text_props->info->glyph + text_props->start + text_props->len - 1;
|
|
|
|
|
2011-03-29 06:52:30 -07:00
|
|
|
/* If the last char is a whitespace, we use the advance as the size,
|
|
|
|
* so the right_inset is 0. */
|
|
|
|
if (gli->width == 0)
|
|
|
|
return 0;
|
|
|
|
|
2011-04-20 07:20:51 -07:00
|
|
|
return ((gli > text_props->info->glyph) ?
|
|
|
|
gli->pen_after - (gli - 1)->pen_after : gli->pen_after) -
|
2011-03-29 06:52:22 -07:00
|
|
|
(gli->width + gli->x_bear
|
|
|
|
#ifdef OT_SUPPORT
|
2011-04-20 07:20:51 -07:00
|
|
|
+ EVAS_FONT_ROUND_26_6_TO_INT(EVAS_FONT_OT_X_OFF_GET(
|
|
|
|
text_props->info->ot[text_props->start + text_props->len - 1]))
|
2011-03-29 06:52:22 -07:00
|
|
|
#endif
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-02-28 07:42:35 -08:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Calculate the ascent/descent of a run. This is different from
|
|
|
|
* evas_common_font_[max]_ascent/descent_get because this one returns the
|
|
|
|
* actual sizee (i.e including accents), and not just what the font reports.
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @param[out] ascent the calculated ascent
|
|
|
|
* @param[out] descent the calculated descent
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
evas_common_font_ascent_descent_get(RGBA_Font *fn, const Evas_Text_Props *text_props, int *ascent, int *descent)
|
|
|
|
{
|
|
|
|
int asc = 0, desc = 0;
|
|
|
|
int max_asc, max_desc;
|
|
|
|
|
|
|
|
max_asc = evas_common_font_ascent_get(fn);
|
|
|
|
max_desc = evas_common_font_descent_get(fn);
|
|
|
|
|
|
|
|
/* FIXME: Not supported yet!!! */
|
|
|
|
desc = max_desc;
|
|
|
|
|
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
EVAS_FONT_WALK_TEXT_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_TEXT_WORK();
|
|
|
|
if (!EVAS_FONT_WALK_IS_VISIBLE) continue;
|
|
|
|
|
|
|
|
if ((EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR) > asc)
|
|
|
|
{
|
|
|
|
asc = EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_TEXT_END();
|
|
|
|
|
|
|
|
if (ascent) *ascent = (asc > max_asc) ? asc : max_asc;
|
|
|
|
if (descent) *descent = (desc < max_desc) ? desc : max_desc;
|
|
|
|
}
|
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Calculate the size of the string (width and height).
|
|
|
|
* The width is the disntance between the first pen position and the last pixel
|
|
|
|
* drawn.
|
|
|
|
* The height is the max ascent+descent of the font.
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @param[out] w the calculated width
|
|
|
|
* @param[out] h the calculated height
|
2011-01-30 02:33:24 -08:00
|
|
|
*/
|
|
|
|
EAPI void
|
2011-04-07 09:25:56 -07:00
|
|
|
evas_common_font_query_size(RGBA_Font *fn, const Evas_Text_Props *text_props, int *w, int *h)
|
2011-01-30 02:33:24 -08:00
|
|
|
{
|
2011-04-20 07:20:51 -07:00
|
|
|
Evas_Coord ret_w = 0;
|
2011-01-30 02:33:24 -08:00
|
|
|
|
2011-04-20 07:20:51 -07:00
|
|
|
if (text_props->len > 0)
|
2011-01-30 05:58:06 -08:00
|
|
|
{
|
2011-04-20 07:20:51 -07:00
|
|
|
const Evas_Font_Glyph_Info *glyph = text_props->info->glyph +
|
|
|
|
text_props->start;
|
|
|
|
const Evas_Font_Glyph_Info *last_glyph = glyph;
|
2011-02-01 04:17:52 -08:00
|
|
|
|
2011-04-20 07:20:51 -07:00
|
|
|
if (text_props->len > 1)
|
|
|
|
{
|
|
|
|
last_glyph += text_props->len - 1;
|
|
|
|
ret_w = last_glyph[-1].pen_after;
|
|
|
|
if (text_props->start > 0)
|
|
|
|
ret_w -= glyph[-1].pen_after;
|
|
|
|
}
|
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
ret_w += EVAS_FONT_ROUND_26_6_TO_INT(EVAS_FONT_OT_X_OFF_GET(
|
|
|
|
text_props->info->ot[text_props->start + text_props->len - 1]));
|
|
|
|
#endif
|
|
|
|
ret_w += last_glyph->width + last_glyph->x_bear;
|
2011-03-29 06:52:30 -07:00
|
|
|
}
|
2011-04-20 07:20:51 -07:00
|
|
|
|
|
|
|
if (w) *w = ret_w;
|
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);
|
|
|
|
}
|
2002-11-08 00:02:15 -08:00
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Calculate the advance of the string. Advance is the distance between the
|
|
|
|
* first pen position and the pen position after the string.
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @param[out] h_adv the calculated horizontal advance.
|
|
|
|
* @param[out] v_adv the calculated vertical advance.
|
2010-07-28 05:00:41 -07:00
|
|
|
*/
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI void
|
2011-04-07 09:25:56 -07:00
|
|
|
evas_common_font_query_advance(RGBA_Font *fn, const Evas_Text_Props *text_props, int *h_adv, int *v_adv)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2011-04-20 07:20:51 -07:00
|
|
|
Evas_Coord ret_adv = 0;
|
|
|
|
if (text_props->len > 0)
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
2012-06-25 23:49:28 -07:00
|
|
|
// RGBA_Font_Int *fi = text_props->font_instance;
|
2011-04-20 07:20:51 -07:00
|
|
|
const Evas_Font_Glyph_Info *glyph = text_props->info->glyph +
|
|
|
|
text_props->start;
|
2012-05-29 07:43:17 -07:00
|
|
|
const Evas_Font_Glyph_Info *last_glyph = glyph + text_props->len - 1;
|
|
|
|
ret_adv = last_glyph->pen_after;
|
2011-04-20 07:20:51 -07:00
|
|
|
if (text_props->start > 0)
|
|
|
|
ret_adv -= glyph[-1].pen_after;
|
2012-05-29 07:43:17 -07:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* Runtime slant adjustment. */
|
|
|
|
if (fi->runtime_rend & FONT_REND_SLANT)
|
|
|
|
{
|
|
|
|
RGBA_Font_Glyph *fg =
|
|
|
|
evas_common_font_int_cache_glyph_get(fi, last_glyph->index);
|
|
|
|
if (!fg->glyph_out) evas_common_font_int_cache_glyph_render(fg);
|
|
|
|
ret_adv += fg->glyph_out->bitmap.rows * _EVAS_FONT_SLANT_TAN;
|
|
|
|
}
|
|
|
|
#endif
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2011-01-30 02:33:24 -08:00
|
|
|
|
2011-04-20 07:20:51 -07:00
|
|
|
if (h_adv) *h_adv = ret_adv;
|
2002-11-13 21:38:10 -08:00
|
|
|
if (v_adv) *v_adv = evas_common_font_get_line_advance(fn);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Query the coordinates of the char at position pos. If the position is at the
|
|
|
|
* end of the string (i.e where the finishing null would be) it returns the
|
|
|
|
* coordinates of the position right after the last char. This is either on
|
|
|
|
* the left or on the right of the string, depending on BiDi direction. Returned
|
|
|
|
* width in this case is 0. It returns the x of the leftmost pixel drawn.
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @param pos the position of the char in the string object (not actual position in the string object, but the position of the source character).
|
|
|
|
* @param[out] cx the calculated x - CAN BE NULL
|
|
|
|
* @param[out] cy the calculated y - CAN BE NULL
|
|
|
|
* @param[out] cw the calculated width - CAN BE NULL
|
|
|
|
* @param[out] ch the calculated height - CAN BE NULL
|
|
|
|
* @return TRUE on success, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @see evas_common_font_query_pen_coords()
|
2010-07-28 05:00:41 -07:00
|
|
|
*/
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2011-04-07 09:25:56 -07:00
|
|
|
evas_common_font_query_char_coords(RGBA_Font *fn, const Evas_Text_Props *text_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;
|
2011-02-01 04:17:52 -08:00
|
|
|
size_t position = 0;
|
2009-09-29 21:23:21 -07:00
|
|
|
int ret_val = 0;
|
2011-01-30 02:33:24 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
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. */
|
2011-02-13 04:57:37 -08:00
|
|
|
if (position == text_props->text_len)
|
2010-09-02 04:49:00 -07:00
|
|
|
{
|
|
|
|
/* 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
|
2013-01-12 00:40:46 -08:00
|
|
|
if (text_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-04-07 09:25:56 -07:00
|
|
|
evas_common_font_query_advance(fn, text_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-02-08 07:23:22 -08:00
|
|
|
Evas_Coord cluster_start = 0, last_end = 0;
|
2011-02-01 04:17:52 -08:00
|
|
|
int prev_cluster = -1;
|
|
|
|
int found = 0, items = 1, item_pos = 1;
|
2011-02-08 07:23:22 -08:00
|
|
|
int last_is_visible = 0;
|
2011-04-20 07:20:57 -07:00
|
|
|
EVAS_FONT_WALK_TEXT_START()
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_WORK();
|
2011-01-30 05:58:06 -08:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
if (prev_cluster != (int) EVAS_FONT_WALK_POS)
|
2011-01-30 05:55:04 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
if (found)
|
2011-01-30 02:37:29 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
break;
|
2011-01-30 02:37:29 -08:00
|
|
|
}
|
2011-01-30 05:58:06 -08:00
|
|
|
else
|
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
cluster_start = EVAS_FONT_WALK_PEN_X +
|
|
|
|
EVAS_FONT_WALK_X_OFF +
|
|
|
|
EVAS_FONT_WALK_X_BEAR;
|
2011-01-30 05:58:06 -08:00
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
last_is_visible = EVAS_FONT_WALK_IS_VISIBLE;
|
|
|
|
last_end = EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF +
|
|
|
|
EVAS_FONT_WALK_X_BEAR + EVAS_FONT_WALK_WIDTH;
|
|
|
|
/* we need to see if the char at the visual position is the char wanted */
|
2013-01-12 00:40:46 -08:00
|
|
|
if ((text_props->bidi_dir == EVAS_BIDI_DIRECTION_LTR) &&
|
2011-02-01 04:17:52 -08:00
|
|
|
(EVAS_FONT_WALK_POS <= (size_t) position) &&
|
|
|
|
((((size_t) position) < EVAS_FONT_WALK_POS_NEXT) ||
|
|
|
|
(EVAS_FONT_WALK_IS_LAST)))
|
|
|
|
{
|
|
|
|
found = 1;
|
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
items = evas_common_font_ot_cluster_size_get(text_props,
|
|
|
|
char_index);
|
2011-01-30 05:58:06 -08:00
|
|
|
#endif
|
2011-02-01 04:17:52 -08:00
|
|
|
item_pos = position - EVAS_FONT_WALK_POS + 1;
|
|
|
|
}
|
2013-01-12 00:40:46 -08:00
|
|
|
else if ((text_props->bidi_dir == EVAS_BIDI_DIRECTION_RTL) &&
|
2011-02-01 04:17:52 -08:00
|
|
|
((EVAS_FONT_WALK_POS_PREV > (size_t) position) ||
|
|
|
|
(EVAS_FONT_WALK_IS_FIRST)) &&
|
|
|
|
(((size_t) position) >= EVAS_FONT_WALK_POS))
|
2011-01-30 05:55:04 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
found = 1;
|
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
items = evas_common_font_ot_cluster_size_get(text_props,
|
|
|
|
char_index);
|
|
|
|
#endif
|
|
|
|
item_pos = items - (position - EVAS_FONT_WALK_POS);
|
|
|
|
}
|
2011-01-30 05:58:06 -08:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
prev_cluster = EVAS_FONT_WALK_POS;
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_TEXT_END();
|
|
|
|
if (found)
|
|
|
|
{
|
|
|
|
Evas_Coord cluster_w;
|
|
|
|
cluster_w = last_end - cluster_start;
|
|
|
|
if (cy) *cy = -asc;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
if (last_is_visible)
|
|
|
|
{
|
|
|
|
if (cx) *cx = cluster_start +
|
|
|
|
(cluster_w / items) *
|
|
|
|
(item_pos - 1);
|
|
|
|
if (cw) *cw = (cluster_w / items);
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cx) *cx = cluster_start;
|
|
|
|
if (cw) *cw = 0;
|
|
|
|
}
|
|
|
|
ret_val = 1;
|
|
|
|
goto end;
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
|
|
|
end:
|
2009-09-29 21:23:21 -07:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
return ret_val;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Query the coordinates of the char at position pos. If the position is at the
|
|
|
|
* end of the string (i.e where the finishing null would be) it returns the
|
|
|
|
* coordinates of the position right after the last char. This is either on
|
|
|
|
* the left or on the right of the string, depending on BiDi direction. Returned
|
|
|
|
* advance in this case is 0.
|
|
|
|
*
|
|
|
|
* This is the same as evas_common_font_query_char_coords() except that the
|
|
|
|
* advance of the character is returned instead of the width and the pen
|
|
|
|
* position is returned instead of the actual pixel position.
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @param pos the position of the char in the string object (not actual position in the string object, but the position of the source character).
|
|
|
|
* @param[out] cpenx the calculated x - CAN BE NULL
|
|
|
|
* @param[out] cy the calculated y - CAN BE NULL
|
|
|
|
* @param[out] cadv the calculated advance - CAN BE NULL
|
|
|
|
* @param[out] ch the calculated height - CAN BE NULL
|
|
|
|
* @return TRUE on success, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @see evas_common_font_query_char_coords()
|
2011-01-30 02:34:07 -08:00
|
|
|
*/
|
|
|
|
EAPI int
|
2011-04-07 09:25:56 -07:00
|
|
|
evas_common_font_query_pen_coords(RGBA_Font *fn, const Evas_Text_Props *text_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch)
|
2011-01-30 02:34:07 -08:00
|
|
|
{
|
|
|
|
int asc, desc;
|
2011-02-01 04:17:52 -08:00
|
|
|
size_t position;
|
2011-01-30 02:34:07 -08:00
|
|
|
int ret_val = 0;
|
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
|
|
|
|
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. */
|
2011-02-13 04:57:37 -08:00
|
|
|
if (position == text_props->text_len)
|
2011-01-30 02:34:07 -08:00
|
|
|
{
|
|
|
|
/* if it's rtl then the location is the left of the string,
|
|
|
|
* otherwise, the right. */
|
|
|
|
#ifdef BIDI_SUPPORT
|
2013-01-12 00:40:46 -08:00
|
|
|
if (text_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-04-07 09:25:56 -07:00
|
|
|
evas_common_font_query_advance(fn, text_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-02-08 07:23:22 -08:00
|
|
|
Evas_Coord cluster_start = 0;
|
2011-02-01 04:17:52 -08:00
|
|
|
int prev_cluster = -1;
|
|
|
|
int found = 0, items = 1, item_pos = 1;
|
2011-02-08 07:23:22 -08:00
|
|
|
int last_is_visible = 0;
|
2011-04-20 07:20:57 -07:00
|
|
|
EVAS_FONT_WALK_TEXT_START()
|
2011-01-30 02:34:07 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_WORK();
|
2011-01-30 05:58:06 -08:00
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
if (prev_cluster != (int) EVAS_FONT_WALK_POS)
|
|
|
|
{
|
|
|
|
if (found)
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
break;
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
else
|
2011-01-30 05:58:06 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
cluster_start = EVAS_FONT_WALK_PEN_X;
|
2011-01-30 05:58:06 -08:00
|
|
|
}
|
2011-01-30 02:37:29 -08:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
last_is_visible = EVAS_FONT_WALK_IS_VISIBLE;
|
2011-01-30 02:37:29 -08:00
|
|
|
|
2013-01-12 00:40:46 -08:00
|
|
|
if ((text_props->bidi_dir == EVAS_BIDI_DIRECTION_LTR) &&
|
2011-02-01 04:17:52 -08:00
|
|
|
(EVAS_FONT_WALK_POS <= (size_t) position) &&
|
|
|
|
((((size_t) position) < EVAS_FONT_WALK_POS_NEXT) ||
|
|
|
|
(EVAS_FONT_WALK_IS_LAST)))
|
2011-01-30 02:37:29 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
found = 1;
|
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
items = evas_common_font_ot_cluster_size_get(text_props,
|
|
|
|
char_index);
|
|
|
|
#endif
|
|
|
|
item_pos = position - EVAS_FONT_WALK_POS + 1;
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
2013-01-12 00:40:46 -08:00
|
|
|
else if ((text_props->bidi_dir == EVAS_BIDI_DIRECTION_RTL) &&
|
2011-02-01 04:17:52 -08:00
|
|
|
((EVAS_FONT_WALK_POS_PREV > (size_t) position) ||
|
|
|
|
(EVAS_FONT_WALK_IS_FIRST)) &&
|
|
|
|
(((size_t) position) >= EVAS_FONT_WALK_POS))
|
|
|
|
{
|
|
|
|
found = 1;
|
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
items = evas_common_font_ot_cluster_size_get(text_props,
|
|
|
|
char_index);
|
2011-01-30 05:58:06 -08:00
|
|
|
#endif
|
2011-02-01 04:17:52 -08:00
|
|
|
item_pos = items - (position - EVAS_FONT_WALK_POS);
|
|
|
|
}
|
|
|
|
|
|
|
|
prev_cluster = EVAS_FONT_WALK_POS;
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_TEXT_END();
|
|
|
|
|
|
|
|
if (found)
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
Evas_Coord cluster_adv;
|
|
|
|
cluster_adv = EVAS_FONT_WALK_PEN_X - cluster_start;
|
|
|
|
if (cy) *cy = -asc;
|
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
if (last_is_visible)
|
2011-01-30 05:55:04 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
if (cpen_x) *cpen_x = cluster_start +
|
|
|
|
(cluster_adv / items) *
|
|
|
|
(item_pos - 1);
|
|
|
|
if (cadv) *cadv = (cluster_adv / items);
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (cpen_x) *cpen_x = EVAS_FONT_WALK_PEN_X;
|
|
|
|
if (cadv) *cadv = 0;
|
|
|
|
}
|
|
|
|
ret_val = 1;
|
|
|
|
goto end;
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
|
|
|
end:
|
2011-01-30 02:34:07 -08:00
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* Find the character at a specific x, y coordinates and return it's position
|
|
|
|
* in the text (not in the text object, but in the source text). Also calculate
|
|
|
|
* the char's geometry.
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @param x the x to look at.
|
|
|
|
* @param y the y to look at.
|
|
|
|
* @param[out] cx the calculated x - CAN BE NULL
|
|
|
|
* @param[out] cy the calculated y - CAN BE NULL
|
|
|
|
* @param[out] cw the calculated width - CAN BE NULL
|
|
|
|
* @param[out] ch the calculated height - CAN BE NULL
|
|
|
|
* @return the position found, -1 on failure.
|
2010-07-28 05:00:41 -07:00
|
|
|
*/
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI int
|
2011-04-07 09:25:56 -07:00
|
|
|
evas_common_font_query_char_at_coords(RGBA_Font *fn, const Evas_Text_Props *text_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
|
2009-09-29 21:23:21 -07:00
|
|
|
{
|
|
|
|
int asc, desc;
|
|
|
|
int ret_val = -1;
|
2011-01-30 02:33:24 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
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);
|
2011-02-08 07:23:22 -08:00
|
|
|
Evas_Coord cluster_start = 0;
|
2011-02-01 04:17:52 -08:00
|
|
|
int prev_cluster = -1;
|
|
|
|
int found = 0, items = 1;
|
2011-04-20 07:20:57 -07:00
|
|
|
EVAS_FONT_WALK_TEXT_START()
|
2010-07-28 05:00:41 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_WORK();
|
|
|
|
if (prev_cluster != (int) EVAS_FONT_WALK_POS)
|
2011-01-30 02:35:17 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
if (found)
|
2011-01-30 02:37:29 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
break;
|
2011-01-30 02:37:29 -08:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
else
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
cluster_start = EVAS_FONT_WALK_PEN_X;
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
2011-01-30 05:58:06 -08:00
|
|
|
}
|
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
if (!EVAS_FONT_WALK_IS_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 */
|
2011-04-20 07:20:51 -07:00
|
|
|
if ((x >= EVAS_FONT_WALK_PEN_X) &&
|
|
|
|
(x <= (EVAS_FONT_WALK_PEN_X_AFTER)) && (y >= -asc) && (y <= desc))
|
2011-02-01 04:17:52 -08:00
|
|
|
{
|
|
|
|
#ifdef OT_SUPPORT
|
|
|
|
items = evas_common_font_ot_cluster_size_get(text_props,
|
|
|
|
char_index);
|
|
|
|
#endif
|
|
|
|
found = 1;
|
2011-01-30 02:37:29 -08:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
|
|
|
|
prev_cluster = EVAS_FONT_WALK_POS;
|
2010-07-28 05:00:41 -07:00
|
|
|
}
|
2011-02-01 04:17:52 -08:00
|
|
|
EVAS_FONT_WALK_TEXT_END();
|
|
|
|
if (found)
|
2009-09-29 21:23:21 -07:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
int item_pos;
|
2013-01-05 23:53:17 -08:00
|
|
|
Evas_Coord cx_it, cw_it, cmid;
|
2011-02-01 04:17:52 -08:00
|
|
|
Evas_Coord cluster_adv;
|
|
|
|
cluster_adv = EVAS_FONT_WALK_PEN_X - cluster_start;
|
|
|
|
|
2013-01-12 00:40:46 -08:00
|
|
|
if (text_props->bidi_dir == EVAS_BIDI_DIRECTION_LTR)
|
2011-01-30 05:55:04 -08:00
|
|
|
{
|
2011-02-01 04:17:52 -08:00
|
|
|
double part;
|
|
|
|
part = cluster_adv / items;
|
|
|
|
item_pos = (int) ((x - cluster_start) / part);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double part;
|
|
|
|
part = cluster_adv / items;
|
|
|
|
item_pos = items - ((int) ((x - cluster_start) / part)) - 1;
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
2013-01-05 23:53:17 -08:00
|
|
|
|
|
|
|
cx_it = EVAS_FONT_WALK_PEN_X + ((cluster_adv / items) * (item_pos - 1));
|
|
|
|
cw_it = (cluster_adv / items);
|
|
|
|
|
|
|
|
if (cx) *cx = cx_it;
|
2011-02-01 04:17:52 -08:00
|
|
|
if (cy) *cy = -asc;
|
2013-01-05 23:53:17 -08:00
|
|
|
if (cw) *cw = cw_it;
|
2011-02-01 04:17:52 -08:00
|
|
|
if (ch) *ch = asc + desc;
|
|
|
|
ret_val = prev_cluster + item_pos;
|
2013-01-05 23:53:17 -08:00
|
|
|
|
|
|
|
/* Check, if x coord points to RIGHT half part of LTR char
|
|
|
|
* or to LEFT half char of RTL char. If so, increment found position */
|
|
|
|
cmid = cx_it + (cw_it / 2);
|
|
|
|
if (text_props->bidi_dir == EVAS_BIDI_DIRECTION_LTR)
|
|
|
|
{
|
|
|
|
if (x > cmid)
|
|
|
|
{
|
|
|
|
ret_val++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (x < cmid)
|
|
|
|
{
|
|
|
|
ret_val++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-01 04:17:52 -08:00
|
|
|
goto end;
|
2009-09-29 21:23:21 -07:00
|
|
|
}
|
|
|
|
end:
|
|
|
|
|
2011-01-30 05:57:55 -08:00
|
|
|
return ret_val;
|
2009-09-29 21:23:21 -07:00
|
|
|
}
|
|
|
|
|
2011-04-28 05:57:35 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
2011-05-05 04:05:59 -07:00
|
|
|
* Find one after the last character that fits until the boundaries set by x
|
|
|
|
* and y. I.e find the first char that doesn't fit.
|
2011-04-28 05:57:35 -07:00
|
|
|
* This LOGICALLY walks the string. This is needed for wrapping for example
|
|
|
|
* where we want the first part to be the first logical part.
|
|
|
|
*
|
|
|
|
* @param fn the font set to use.
|
|
|
|
* @param text_props the string object.
|
|
|
|
* @param x the x boundary.
|
|
|
|
* @param y the y boundary.
|
|
|
|
* @return the position found, -1 on failure.
|
2010-07-28 05:00:41 -07:00
|
|
|
*/
|
2009-09-29 21:23:21 -07:00
|
|
|
EAPI int
|
2011-04-07 09:25:56 -07:00
|
|
|
evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Evas_Text_Props *text_props, 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;
|
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
|
|
|
|
2011-04-20 07:20:57 -07:00
|
|
|
#ifdef BIDI_SUPPORT
|
2013-01-12 00:40:46 -08:00
|
|
|
if (text_props->bidi_dir == EVAS_BIDI_DIRECTION_RTL)
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
2011-11-08 23:36:50 -08:00
|
|
|
Evas_Font_Glyph_Info *gli = NULL;
|
2011-04-20 07:20:57 -07:00
|
|
|
Evas_Coord full_adv = 0, pen_x = 0, start_pen = 0;
|
|
|
|
int i;
|
2011-01-30 02:36:39 -08:00
|
|
|
|
2011-11-08 23:36:50 -08:00
|
|
|
if ((text_props->info) && (text_props->len > 0))
|
2011-01-30 02:36:39 -08:00
|
|
|
{
|
2011-11-08 23:36:50 -08:00
|
|
|
gli = text_props->info->glyph + text_props->start;
|
2011-04-20 07:20:57 -07:00
|
|
|
full_adv = gli[text_props->len - 1].pen_after;
|
|
|
|
if (text_props->start > 0)
|
|
|
|
{
|
|
|
|
start_pen = gli[-1].pen_after;
|
|
|
|
full_adv -= start_pen;
|
|
|
|
}
|
2011-11-08 23:36:50 -08:00
|
|
|
|
|
|
|
gli += text_props->len - 1;
|
2011-04-20 07:20:57 -07:00
|
|
|
|
2011-11-10 04:11:17 -08:00
|
|
|
for (i = text_props->len - 1 ; i >= 0 ; i--, gli--)
|
2011-04-20 07:20:57 -07:00
|
|
|
{
|
2011-11-10 04:11:17 -08:00
|
|
|
pen_x = full_adv - (gli->pen_after - start_pen);
|
|
|
|
/* If invisible, skip */
|
|
|
|
if (gli->index == 0) continue;
|
|
|
|
if ((x >= pen_x) &&
|
|
|
|
(((i == 0) && (x <= full_adv)) ||
|
2014-02-27 02:39:52 -08:00
|
|
|
(x < (full_adv - (gli[-1].pen_after - start_pen)) ||
|
2016-03-23 02:53:53 -07:00
|
|
|
(x < (pen_x + gli->x_bear + gli->width)))) &&
|
2011-11-10 04:11:17 -08:00
|
|
|
(y >= -asc) && (y <= desc))
|
|
|
|
{
|
2011-04-20 07:20:57 -07:00
|
|
|
#ifdef OT_SUPPORT
|
2011-11-10 04:11:17 -08:00
|
|
|
ret = EVAS_FONT_OT_POS_GET(
|
|
|
|
text_props->info->ot[text_props->start + i]) -
|
|
|
|
text_props->text_offset;
|
2011-04-20 07:20:57 -07:00
|
|
|
#else
|
2011-11-10 04:11:17 -08:00
|
|
|
ret = text_props->text_len - i - 1;
|
2011-04-20 07:20:57 -07:00
|
|
|
#endif
|
2011-11-10 04:11:17 -08:00
|
|
|
goto end;
|
|
|
|
}
|
2011-04-20 07:20:57 -07:00
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
}
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2011-04-20 07:20:57 -07:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_TEXT_INIT();
|
|
|
|
/* When text is not rtl, visual direction = logical direction */
|
|
|
|
EVAS_FONT_WALK_TEXT_START()
|
|
|
|
{
|
|
|
|
EVAS_FONT_WALK_TEXT_WORK();
|
|
|
|
if (!EVAS_FONT_WALK_IS_VISIBLE) continue;
|
|
|
|
|
|
|
|
if ((x >= EVAS_FONT_WALK_PEN_X) &&
|
2014-02-27 02:39:52 -08:00
|
|
|
((x < (EVAS_FONT_WALK_PEN_X_AFTER)) ||
|
2016-03-23 02:53:53 -07:00
|
|
|
(x < (EVAS_FONT_WALK_PEN_X +
|
|
|
|
_glyph_itr->x_bear + _glyph_itr->width))) &&
|
|
|
|
(y >= -asc) && (y <= desc))
|
2011-04-20 07:20:57 -07:00
|
|
|
{
|
|
|
|
ret = EVAS_FONT_WALK_POS;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EVAS_FONT_WALK_TEXT_END();
|
|
|
|
}
|
2011-01-30 02:33:24 -08:00
|
|
|
|
2010-07-28 05:00:41 -07:00
|
|
|
end:
|
|
|
|
|
2011-01-30 05:57:55 -08:00
|
|
|
return ret;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2011-01-30 02:36:39 -08:00
|
|
|
|