Evas font/textblock/text: Started using string objects instead of

strings in most of the font engine (everywhere except draw).
Haven't removed the paramteres yet, but did mark them as UNUSED.
Removing them will be part of a future change.
Removed run-time OT toggling support, OT is now fast, no need for that.
Renamed all of the intl_props->text_props (because it really changed purpose now)
Fixed spliting/merging of text_props to be fast and good, not hacky and
complex like before.
Note to reviewers: Most of the changes are indentation related, sorry
for the mess, but I had to do it all in one commit, splitting was not
trivial (at least not in retrospect). The important parts are
evas_font_default_walk.x and text_utils.c. query and draw were just
adjusted a bit and the rest were only adjusted to conform to renaming or
were renaming on their own.

SVN revision: 56629
devs/devilhorns/wayland_egl
Tom Hacohen 12 years ago
parent 22b440ff2a
commit 94b5a536f0
  1. 3
      legacy/evas/src/lib/canvas/evas_object_text.c
  2. 15
      legacy/evas/src/lib/canvas/evas_object_textblock.c
  3. 279
      legacy/evas/src/lib/engines/common/evas_font_default_walk.x
  4. 487
      legacy/evas/src/lib/engines/common/evas_font_draw.c
  5. 20
      legacy/evas/src/lib/engines/common/evas_font_load.c
  6. 247
      legacy/evas/src/lib/engines/common/evas_font_ot.c
  7. 47
      legacy/evas/src/lib/engines/common/evas_font_ot.h
  8. 177
      legacy/evas/src/lib/engines/common/evas_font_ot_walk.x
  9. 28
      legacy/evas/src/lib/engines/common/evas_font_private.h
  10. 630
      legacy/evas/src/lib/engines/common/evas_font_query.c
  11. 244
      legacy/evas/src/lib/engines/common/evas_text_utils.c
  12. 38
      legacy/evas/src/lib/engines/common/evas_text_utils.h
  13. 67
      legacy/evas/src/lib/engines/common/language/evas_language_utils.c
  14. 2
      legacy/evas/src/lib/include/evas_private.h
  15. 6
      legacy/evas/src/modules/engines/cairo_x11/evas_engine.c
  16. 40
      legacy/evas/src/modules/engines/quartz/evas_engine.c
  17. 2
      legacy/evas/src/modules/engines/quartz/evas_quartz_private.h
  18. 60
      legacy/evas/src/modules/engines/software_16/evas_engine.c
  19. 60
      legacy/evas/src/modules/engines/software_8/evas_engine.c
  20. 56
      legacy/evas/src/modules/engines/software_generic/evas_engine.c

@ -528,7 +528,8 @@ _evas_object_text_item_new(Evas_Object *obj, Evas_Object_Text *o,
evas_common_text_props_bidi_set(&it->text_props, o->bidi_par_props,
it->text_pos);
evas_common_text_props_script_set(&it->text_props, it->text);
ENFN->font_shape(ENDT, o->engine_data, it->text, &it->text_props,
ENFN->font_text_props_info_create(ENDT,
o->engine_data, it->text, &it->text_props,
o->bidi_par_props, it->text_pos, len);
if (o->engine_data)
{

@ -1783,6 +1783,7 @@ struct _Ctxt
};
static void _layout_text_add_logical_item(Ctxt *c, Evas_Object_Textblock_Text_Item *ti, const Evas_Object_Textblock_Item *rel);
static void _text_item_update_sizes(Ctxt *c, Evas_Object_Textblock_Text_Item *ti);
/**
* @internal
* Adjust the ascent/descent of the format and context.
@ -2459,12 +2460,6 @@ _layout_item_text_split_strip_white(Ctxt *c,
_layout_text_add_logical_item(c, new_ti, _ITEM(ti));
}
/* FIXME: Will break with kerning and a bunch of other stuff, should
* maybe adjust the last adv of the prev and the offset of the cur
* There's also another similar fixme below (same case, not marked) */
ti->parent.w -= new_ti->parent.w;
ti->parent.adv -= new_ti->parent.adv;
if (cut2 > cut)
{
white_ti = _layout_text_item_new(c, ti->parent.format, &ts[cut]);
@ -2477,8 +2472,6 @@ _layout_item_text_split_strip_white(Ctxt *c,
evas_common_text_props_split(&ti->parent.text_props,
&white_ti->parent.text_props, cut);
_layout_text_add_logical_item(c, white_ti, _ITEM(ti));
ti->parent.w -= white_ti->parent.w;
ti->parent.adv -= white_ti->parent.adv;
}
if (new_ti || white_ti)
@ -2785,7 +2778,8 @@ skip:
ti->parent.text_node->bidi_props, ti->parent.text_pos);
evas_common_text_props_script_set (&ti->parent.text_props,
ti->text);
c->ENFN->font_shape(c->ENDT, ti->parent.format->font.font,
c->ENFN->font_text_props_info_create(c->ENDT,
ti->parent.format->font.font,
ti->text, &ti->parent.text_props,
ti->parent.text_node->bidi_props,
ti->parent.text_pos, tmp_len);
@ -3201,7 +3195,8 @@ _layout_ellipsis_item_new(Ctxt *c, const Evas_Object_Textblock_Item *cur_it)
ellip_ti->parent.text_node->bidi_props, ellip_ti->parent.text_pos);
evas_common_text_props_script_set (&ellip_ti->parent.text_props,
ellip_ti->text);
c->ENFN->font_shape(c->ENDT, ellip_ti->parent.format->font.font,
c->ENFN->font_text_props_info_create(c->ENDT,
ellip_ti->parent.format->font.font,
ellip_ti->text, &ellip_ti->parent.text_props,
ellip_ti->parent.text_node->bidi_props,
ellip_ti->parent.text_pos, eina_unicode_strlen(_ellip_str));

@ -3,190 +3,169 @@
/* Macros for text walking */
/**
* @def EVAS_FONT_UPDATE_KERN()
* @def EVAS_FONT_WALK_TEXT_INIT
* @internal
* This macro updates kern according to kerning.
* This macro assumes the following variables exist:
* intl_props, char_index, fi, kern, index, prev_index
* This macro defines the variables that will later be used with the following
* macros, and by font handling functions.
* @see EVAS_FONT_WALK_TEXT_START
* @see EVAS_FONT_WALK_TEXT_WORK
* @see EVAS_FONT_WALK_TEXT_END
*/
#ifdef BIDI_SUPPORT
#define EVAS_FONT_UPDATE_KERN(is_visual) \
do \
{ \
/* 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 && (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) && \
visible && !is_visual) \
{ \
if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) \
_pen_x += kern; \
} \
else \
{ \
if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) \
_pen_x += kern; \
} \
} \
while (0)
#else
#define EVAS_FONT_UPDATE_KERN(is_visual) \
do \
{ \
(void) is_visual; \
if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) \
_pen_x += kern; \
} \
while (0)
#endif
# define EVAS_FONT_WALK_TEXT_INIT() \
int _pen_x = 0, _pen_y = 0; \
size_t char_index; \
(void) _pen_y; /* Sometimes it won't be used */
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* @def EVAS_FONT_WALK_TEXT_VISUAL_START
* @internal
* This runs through the text in visual order while updating char_index,
* which is the current index in the text.
* Does not end with a ;
* Take a look at EVAS_FONT_WALK_DEFAULT_X_OFF and the like.
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @see EVAS_FONT_WALK_DEFAULT_TEXT_END
* @see EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START
* Take a look at EVAS_FONT_WALK_X_OFF and the like.
* @see EVAS_FONT_WALK_TEXT_INIT
* @see EVAS_FONT_WALK_TEXT_WORK
* @see EVAS_FONT_WALK_TEXT_END
* @see EVAS_FONT_WALK_TEXT_LOGICAL_START
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START() \
#define EVAS_FONT_WALK_TEXT_VISUAL_START() \
do \
{ \
const Eina_Unicode *_base_text; \
int _char_index_d, _i; \
int visible; \
prev_index = 0; \
_base_text = text; \
for ( ; *text ; text++); \
_i = text - _base_text; \
if (intl_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) \
{ \
char_index = text - _base_text - 1; \
text--; \
_char_index_d = -1; \
} \
else \
{ \
char_index = 0; \
text = _base_text; \
_char_index_d = 1; \
} \
for ( ; _i > 0 ; char_index += _char_index_d, text += _char_index_d, _i--) \
{ \
FT_UInt index; \
RGBA_Font_Glyph *fg; \
int _gl, kern; \
_gl = *text; \
if (_gl == 0) break;
for (char_index = text_props->start ; char_index < text_props->start + text_props->len ; char_index++) \
{
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START
* @def EVAS_FONT_WALK_TEXT_LOGICAL_START
* @internal
* This runs through the text in logical order while updating char_index,
* which is the current index in the text.
* Does not end with a ;
* Take a look at EVAS_FONT_WALK_DEFAULT_X_OFF and the like.
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @see EVAS_FONT_WALK_DEFAULT_TEXT_END
* @see EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* Take a look at EVAS_FONT_WALK_X_OFF and the like.
* @see EVAS_FONT_WALK_TEXT_INIT
* @see EVAS_FONT_WALK_TEXT_WORK
* @see EVAS_FONT_WALK_TEXT_END
* @see EVAS_FONT_WALK_TEXT_VISUAL_START
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START() \
#ifdef BIDI_SUPPORT
#define EVAS_FONT_WALK_TEXT_LOGICAL_START() \
do \
{ \
int visible; \
prev_index = 0; \
for (char_index = 0 ; *text ; text++, char_index++) \
int _char_index_d; \
size_t _i; \
_i = text_props->len; \
if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) \
{ \
FT_UInt index; \
RGBA_Font_Glyph *fg; \
int _gl, kern; \
_gl = *text; \
if (_gl == 0) break;
char_index = text_props->len - 1; \
_char_index_d = -1; \
} \
else \
{ \
char_index = 0; \
_char_index_d = 1; \
} \
char_index += text_props->start; \
_i += text_props->start; \
for ( ; _i > text_props->start ; char_index += _char_index_d, _i--) \
{
#else
#define EVAS_FONT_WALK_TEXT_LOGICAL_START() EVAS_FONT_WALK_TEXT_VISUAL_START()
#endif
#define EVAS_FONT_WALK_ORIG_LEN (_len)
/*FIXME: doc */
#define EVAS_FONT_WALK_DEFAULT_X_OFF (0)
#define EVAS_FONT_WALK_DEFAULT_Y_OFF (0)
#define EVAS_FONT_WALK_DEFAULT_X_BEAR (fg->glyph_out->left)
#define EVAS_FONT_WALK_DEFAULT_Y_BEAR (fg->glyph_out->top)
#define _EVAS_FONT_WALK_DEFAULT_X_ADV (fg->glyph->advance.x >> 10)
#define EVAS_FONT_WALK_DEFAULT_X_ADV \
(EVAS_FONT_ROUND_26_6_TO_INT(_EVAS_FONT_WALK_DEFAULT_X_ADV))
#define EVAS_FONT_WALK_DEFAULT_Y_ADV (0)
#define EVAS_FONT_WALK_DEFAULT_WIDTH (fg->glyph_out->bitmap.width)
#define EVAS_FONT_WALK_DEFAULT_POS (char_index)
#define EVAS_FONT_WALK_DEFAULT_IS_LAST \
(!text[char_index])
#define EVAS_FONT_WALK_DEFAULT_IS_FIRST \
(!char_index)
#define EVAS_FONT_WALK_DEFAULT_POS_NEXT \
((!EVAS_FONT_WALK_DEFAULT_IS_LAST) ? \
(char_index + 1) : \
(char_index) \
)
#define EVAS_FONT_WALK_DEFAULT_POS_PREV \
((!EVAS_FONT_WALK_DEFAULT_IS_FIRST) ? \
(char_index - 1) : \
EVAS_FONT_WALK_DEFAULT_POS \
#ifdef OT_SUPPORT
# define EVAS_FONT_WALK_X_OFF \
(EVAS_FONT_ROUND_26_6_TO_INT( \
EVAS_FONT_OT_X_OFF_GET( \
text_props->info->ot[char_index])))
# define EVAS_FONT_WALK_Y_OFF \
(EVAS_FONT_ROUND_26_6_TO_INT( \
EVAS_FONT_OT_Y_OFF_GET( \
text_props->info->ot[char_index])))
# define EVAS_FONT_WALK_POS \
(EVAS_FONT_OT_POS_GET( \
text_props->info->ot[char_index]) - text_props->text_offset)
# define EVAS_FONT_WALK_POS_NEXT \
((!EVAS_FONT_WALK_IS_LAST) ? \
EVAS_FONT_OT_POS_GET( \
text_props->info->ot[char_index + 1]) - \
text_props->text_offset : \
EVAS_FONT_WALK_POS \
)
# define EVAS_FONT_WALK_POS_PREV \
((char_index > 0) ? \
EVAS_FONT_OT_POS_GET( \
text_props->info->ot[char_index - 1]) - \
text_props->text_offset : \
EVAS_FONT_WALK_POS \
)
#define EVAS_FONT_WALK_DEFAULT_LEN (EVAS_FONT_WALK_ORIG_LEN)
#else
# define EVAS_FONT_WALK_X_OFF 0
# define EVAS_FONT_WALK_Y_OFF 0
# define EVAS_FONT_WALK_POS \
((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ? \
(text_props->len - (char_index - text_props->start) - 1) : \
(char_index - text_props->start))
# define EVAS_FONT_WALK_POS_NEXT \
((!EVAS_FONT_WALK_IS_LAST) ? \
((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ? \
text_props->len - ((char_index + 1) - text_props->start) \
: (char_index + 1) - text_props->start) : \
EVAS_FONT_WALK_POS)
# define EVAS_FONT_WALK_POS_PREV \
((char_index > text_props->start) ? \
((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ? \
text_props->len - ((char_index - 1) - text_props->start) \
: (char_index - 1) - text_props->start) : \
EVAS_FONT_WALK_POS)
#endif
#define EVAS_FONT_WALK_IS_VISIBLE \
(text_props->info->glyph[char_index].index != 0)
#define EVAS_FONT_WALK_X_BEAR (text_props->info->glyph[char_index].x_bear)
#define EVAS_FONT_WALK_Y_BEAR (fg->glyph_out->top)
#define _EVAS_FONT_WALK_X_ADV \
(text_props->info->glyph[char_index].advance)
#define EVAS_FONT_WALK_WIDTH (text_props->info->glyph[char_index].width)
#define EVAS_FONT_WALK_X_ADV \
(EVAS_FONT_ROUND_26_6_TO_INT(_EVAS_FONT_WALK_X_ADV))
#define EVAS_FONT_WALK_PEN_X (EVAS_FONT_ROUND_26_6_TO_INT(_pen_x))
#define EVAS_FONT_WALK_PEN_Y (EVAS_FONT_ROUND_26_6_TO_INT(_pen_y))
#define EVAS_FONT_WALK_Y_ADV (0)
#define EVAS_FONT_WALK_IS_LAST \
(char_index + 1 == text_props->start + text_props->len)
#define EVAS_FONT_WALK_IS_FIRST \
(!char_index)
#define EVAS_FONT_WALK_LEN (text_props->len)
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @def EVAS_FONT_WALK_TEXT_WORK
* @internal
* This macro actually updates the values mentioned in EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* This macro actually updates the values mentioned in EVAS_FONT_WALK_TEXT_VISUAL_START
* according to the current positing in the walk.
* @see EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_END
* @see EVAS_FONT_WALK_TEXT_VISUAL_START
* @see EVAS_FONT_WALK_TEXT_INIT
* @see EVAS_FONT_WALK_TEXT_END
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_WORK(is_visual) \
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; \
} \
kern = 0; \
if (EVAS_FONT_CHARACTER_IS_INVISIBLE(_gl)) \
{ \
visible = 0; \
} \
else \
{ \
visible = 1; \
} \
/* 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)) \
{ \
EVAS_FONT_UPDATE_KERN(is_visual); \
} \
\
pface = fi->src->ft.face; \
LKU(fi->ft_mutex); \
#define EVAS_FONT_WALK_TEXT_WORK() do {} while(0)
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_END
* @def EVAS_FONT_WALK_TEXT_END
* @internal
* Closes EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START, needs to end with a ;
* @see EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* Closes EVAS_FONT_WALK_TEXT_VISUAL_START, needs to end with a ;
* @see EVAS_FONT_WALK_TEXT_VISUAL_START
* @see EVAS_FONT_WALK_TEXT_INIT
* @see EVAS_FONT_WALK_TEXT_WORK
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_END() \
if (visible) \
#define EVAS_FONT_WALK_TEXT_END() \
if (EVAS_FONT_WALK_IS_VISIBLE) \
{ \
_pen_x += _EVAS_FONT_WALK_DEFAULT_X_ADV; \
_pen_x += _EVAS_FONT_WALK_X_ADV; \
} \
prev_index = index; \
} \
} \
while(0)

@ -49,7 +49,7 @@ struct cinfo
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
LK(lock_words); // for word cache call
static Eina_Inlist *words = NULL;
static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *text, const Evas_Text_Props *intl_props, 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, const Evas_Text_Props *text_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning);
#endif
EAPI void
@ -389,19 +389,20 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
}
/*
* BiDi handling: We receive the shaped string + other props from intl_props,
* BiDi handling: We receive the shaped string + other props from text_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 Eina_Unicode *in_text,
const Evas_Text_Props *intl_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w,
const Evas_Text_Props *text_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
)
{
const Eina_Unicode *text = in_text;
DATA32 *im;
FT_Face pface = NULL;
EVAS_FONT_WALK_TEXT_INIT();
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
@ -415,7 +416,7 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
struct prword *word;
word =
evas_font_word_prerender(dc, text, intl_props,
evas_font_word_prerender(dc, text, text_props,
len, fn, fi, use_kerning);
if (word)
{
@ -492,6 +493,8 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
# endif
}
}
#else
(void) use_kerning;
#endif
if (fi->src->current_size != fi->size)
@ -504,291 +507,172 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
im = dst->image.data;
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
/* Load the glyph according to the first letter of the script, preety
* bad, but will have to do */
{
/* Skip common chars */
const Eina_Unicode *tmp;
for (tmp = text ;
*tmp &&
evas_common_language_char_script_get(*tmp) ==
EVAS_SCRIPT_COMMON ;
tmp++)
;
if (!*tmp && (tmp > text)) tmp--;
evas_common_font_glyph_search(fn, &fi, *tmp);
}
EVAS_FONT_WALK_TEXT_VISUAL_START()
{
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
FT_UInt index;
RGBA_Font_Glyph *fg;
int chr_x, chr_y, chr_w;
if (!EVAS_FONT_WALK_IS_VISIBLE) continue;
#ifdef OT_SUPPORT
index = text_props->info->glyph[char_index].index;
#else
/* FIXME: Should be removed once we split according to script without
* the use of harfbuzz */
index =
evas_common_font_glyph_search(fn, &fi, text[EVAS_FONT_WALK_POS]);
#endif
LKL(fi->ft_mutex);
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg)
{
int chr_x, chr_y, chr_w;
LKU(fi->ft_mutex);
continue;
}
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_TRUE);
pface = fi->src->ft.face;
LKU(fi->ft_mutex);
if (dc->font_ext.func.gl_new)
{
/* extension calls */
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 (dc->font_ext.func.gl_new)
{
/* extension calls */
fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
fg->ext_dat_free = dc->font_ext.func.gl_free;
}
chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_OT_X_OFF + EVAS_FONT_WALK_OT_X_BEAR;
chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_OT_Y_OFF + EVAS_FONT_WALK_OT_Y_BEAR;
chr_w = EVAS_FONT_WALK_OT_WIDTH;
chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR;
chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR;
chr_w = EVAS_FONT_WALK_WIDTH;
if (chr_x < (ext_x + ext_w))
if (chr_x < (ext_x + ext_w))
{
DATA8 *data;
int i, j, w, h;
data = fg->glyph_out->bitmap.buffer;
j = fg->glyph_out->bitmap.pitch;
w = fg->glyph_out->bitmap.width;
if (j < w) j = w;
h = fg->glyph_out->bitmap.rows;
/*
if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
&& (fg->glyph_out->bitmap.num_grays == 256)
)
*/
{
DATA8 *data;
int i, j, w, h;
data = fg->glyph_out->bitmap.buffer;
j = fg->glyph_out->bitmap.pitch;
w = fg->glyph_out->bitmap.width;
if (j < w) j = w;
h = fg->glyph_out->bitmap.rows;
/*
if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
&& (fg->glyph_out->bitmap.num_grays == 256)
)
*/
if ((j > 0) && (chr_x + w > ext_x))
{
if ((j > 0) && (chr_x + w > ext_x))
if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
{
if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
{
/* ext glyph draw */
dc->font_ext.func.gl_draw(dc->font_ext.data,
(void *)dst,
dc, fg, chr_x,
y - (chr_y - y));
}
else
/* ext glyph draw */
dc->font_ext.func.gl_draw(dc->font_ext.data,
(void *)dst,
dc, fg, chr_x,
y - (chr_y - y));
}
else
{
if ((fg->glyph_out->bitmap.num_grays == 256) &&
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
{
if ((fg->glyph_out->bitmap.num_grays == 256) &&
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
for (i = 0; i < h; i++)
{
for (i = 0; i < h; i++)
{
int dx, dy;
int in_x, in_w;
int dx, dy;
int in_x, in_w;
in_x = 0;
in_w = 0;
dx = chr_x;
dy = y - (chr_y - i - y);
in_x = 0;
in_w = 0;
dx = chr_x;
dy = y - (chr_y - i - y);
#ifdef EVAS_SLI
if (((dy) % dc->sli.h) == dc->sli.y)
if (((dy) % dc->sli.h) == dc->sli.y)
#endif
{
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
{
if (dx + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
{
in_w += ext_x - dx;
in_x = ext_x - dx;
dx = ext_x;
}
if (in_w < w)
{
func(NULL, data + (i * j) + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_w);
}
}
}
}
}
else
{
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
int bi, bj;
const DATA8 bitrepl[2] = {0x0, 0xff};
tmpbuf = alloca(w);
for (i = 0; i < h; i++)
{
int dx, dy;
int in_x, in_w, end;
in_x = 0;
in_w = 0;
dx = chr_x;
dy = y - (chr_y - i - y);
#ifdef EVAS_SLI
if (((dy) % dc->sli.h) == dc->sli.y)
#endif
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
{
tp = tmpbuf;
dp = data + (i * fg->glyph_out->bitmap.pitch);
for (bi = 0; bi < w; bi += 8)
if (dx + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
{
bits = *dp;
if ((w - bi) < 8) end = w - bi;
else end = 8;
for (bj = 0; bj < end; bj++)
{
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
tp++;
}
dp++;
in_w += ext_x - dx;
in_x = ext_x - dx;
dx = ext_x;
}
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
if (in_w < w)
{
if (dx + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
{
in_w += ext_x - dx;
in_x = ext_x - dx;
dx = ext_x;
}
if (in_w < w)
{
func(NULL, tmpbuf + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_w);
}
func(NULL, data + (i * j) + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_w);
}
}
}
}
}
}
}
}
else
break;
}
EVAS_FONT_WALK_OT_TEXT_END();
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
{
int chr_x, chr_y, chr_w;
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_TRUE);
if (dc->font_ext.func.gl_new)
{
/* extension calls */
fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
fg->ext_dat_free = dc->font_ext.func.gl_free;
}
chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_DEFAULT_X_OFF + EVAS_FONT_WALK_DEFAULT_X_BEAR;
chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_DEFAULT_Y_OFF + EVAS_FONT_WALK_DEFAULT_Y_BEAR;
chr_w = EVAS_FONT_WALK_DEFAULT_WIDTH;
if (chr_x < (ext_x + ext_w))
{
DATA8 *data;
int i, j, w, h;
data = fg->glyph_out->bitmap.buffer;
j = fg->glyph_out->bitmap.pitch;
w = fg->glyph_out->bitmap.width;
if (j < w) j = w;
h = fg->glyph_out->bitmap.rows;
/*
if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
&& (fg->glyph_out->bitmap.num_grays == 256)
)
*/
{
if ((j > 0) && (chr_x + w > ext_x))
{
if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
{
/* ext glyph draw */
dc->font_ext.func.gl_draw(dc->font_ext.data,
(void *)dst,
dc, fg, chr_x,
y - (chr_y - y));
}
else
{
if ((fg->glyph_out->bitmap.num_grays == 256) &&
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
int bi, bj;
const DATA8 bitrepl[2] = {0x0, 0xff};
tmpbuf = alloca(w);
for (i = 0; i < h; i++)
{
for (i = 0; i < h; i++)
{
int dx, dy;
int in_x, in_w;
int dx, dy;
int in_x, in_w, end;
in_x = 0;
in_w = 0;
dx = chr_x;
dy = y - (chr_y - i - y);
in_x = 0;
in_w = 0;
dx = chr_x;
dy = y - (chr_y - i - y);
#ifdef EVAS_SLI
if (((dy) % dc->sli.h) == dc->sli.y)
if (((dy) % dc->sli.h) == dc->sli.y)
#endif
{
tp = tmpbuf;
dp = data + (i * fg->glyph_out->bitmap.pitch);
for (bi = 0; bi < w; bi += 8)
{
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
bits = *dp;
if ((w - bi) < 8) end = w - bi;
else end = 8;
for (bj = 0; bj < end; bj++)
{
if (dx + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
{
in_w += ext_x - dx;
in_x = ext_x - dx;
dx = ext_x;
}
if (in_w < w)
{
func(NULL, data + (i * j) + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_w);
}
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
tp++;
}
dp++;
}
}
}
else
{
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
int bi, bj;
const DATA8 bitrepl[2] = {0x0, 0xff};
tmpbuf = alloca(w);
for (i = 0; i < h; i++)
{
int dx, dy;
int in_x, in_w, end;
in_x = 0;
in_w = 0;
dx = chr_x;
dy = y - (chr_y - i - y);
#ifdef EVAS_SLI
if (((dy) % dc->sli.h) == dc->sli.y)
#endif
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
{
tp = tmpbuf;
dp = data + (i * fg->glyph_out->bitmap.pitch);
for (bi = 0; bi < w; bi += 8)
if (dx + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
{
bits = *dp;
if ((w - bi) < 8) end = w - bi;
else end = 8;
for (bj = 0; bj < end; bj++)
{
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
tp++;
}
dp++;
in_w += ext_x - dx;
in_x = ext_x - dx;
dx = ext_x;
}
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
if (in_w < w)
{
if (dx + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
{
in_w += ext_x - dx;
in_x = ext_x - dx;
dx = ext_x;
}
if (in_w < w)
{
func(NULL, tmpbuf + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_w);
}
func(NULL, tmpbuf + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_w);
}
}
}
@ -797,17 +681,17 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
}
}
}
else
break;
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
else
break;
}
EVAS_FONT_WALK_TEXT_END();
evas_common_font_int_use_trim();
}
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_Text_Props *intl_props)
const Evas_Text_Props *text_props)
{
int ext_x, ext_y, ext_w, ext_h;
int im_w, im_h;
@ -859,7 +743,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, intl_props,
evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props,
func, ext_x, ext_y, ext_w, ext_h, fi,
im_w, im_h, use_kerning);
}
@ -875,7 +759,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, intl_props,
evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props,
func, r->x, r->y, r->w, r->h, fi,
im_w, im_h, use_kerning);
}
@ -892,7 +776,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
/* Only used if cache is on */
#if defined(METRIC_CACHE) || defined(WORD_CACHE)
struct prword *
evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, const Evas_Text_Props *intl_props, 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, const Evas_Text_Props *text_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning)
{
struct cinfo *metrics;
const Eina_Unicode *text = in_text;
@ -929,73 +813,36 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, con
/* First pass: Work out how big and populate */
/* It's a bit hackish to use index and fg here as they are internal,
* but that'll have to be good enough ATM */
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
len = text_props->len;
metrics = malloc(sizeof(struct cinfo) * len);
EVAS_FONT_WALK_TEXT_VISUAL_START()
{
len = intl_props->ot_data->len;
metrics = malloc(sizeof(struct cinfo) * len);
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
{
struct cinfo *ci = metrics + char_index;
EVAS_FONT_WALK_OT_TEXT_WORK(EINA_FALSE);
/* Currently broken with invisible chars if (!visible) continue; */
ci->index = index;
ci->fg = fg;
struct cinfo *ci = metrics + char_index;
EVAS_FONT_WALK_TEXT_WORK(EINA_FALSE);
/* Currently broken with invisible chars if (!EVAS_FONT_WALK_IS_VISIBLE) continue; */
ci->index = index;
ci->fg = fg;
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;
}
ci->bm.data = ci->fg->glyph_out->bitmap.buffer;
ci->bm.w = MAX(ci->fg->glyph_out->bitmap.pitch,
ci->fg->glyph_out->bitmap.width);
ci->bm.rows = ci->fg->glyph_out->bitmap.rows;
ci->bm.h = ci->fg->glyph_out->top;
above = ci->bm.rows - (ci->bm.rows - ci->bm.h);
below = ci->bm.rows - ci->bm.h;
if (below > descent) descent = below;
if (above > baseline) baseline = above;
ci->pos.x = EVAS_FONT_WALK_PEN_X + ci->fg->glyph_out->left;
ci->pos.y = EVAS_FONT_WALK_PEN_Y + ci->fg->glyph_out->top;
last_delta = EVAS_FONT_WALK_OT_X_ADV -
(ci->bm.w + ci->fg->glyph_out->left);
}
EVAS_FONT_WALK_OT_TEXT_END();
}
else
#endif
{
metrics = malloc(sizeof(struct cinfo) * len);
EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START()
if (gl)
{
struct cinfo *ci = metrics + char_index;
EVAS_FONT_WALK_DEFAULT_TEXT_WORK(EINA_FALSE);
/* Currently broken with invisible chars if (!visible) continue; */
ci->index = index;
ci->fg = fg;
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;
}
ci->bm.data = ci->fg->glyph_out->bitmap.buffer;
ci->bm.w = MAX(ci->fg->glyph_out->bitmap.pitch,
ci->fg->glyph_out->bitmap.width);
ci->bm.rows = ci->fg->glyph_out->bitmap.rows;
ci->bm.h = ci->fg->glyph_out->top;
above = ci->bm.rows - (ci->bm.rows - ci->bm.h);
below = ci->bm.rows - ci->bm.h;
if (below > descent) descent = below;
if (above > baseline) baseline = above;
ci->pos.x = EVAS_FONT_WALK_PEN_X + ci->fg->glyph_out->left;
ci->pos.y = EVAS_FONT_WALK_PEN_Y + ci->fg->glyph_out->top;
last_delta = EVAS_FONT_WALK_DEFAULT_X_ADV -
(ci->bm.w + ci->fg->glyph_out->left);
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;
}
EVAS_FONT_WALK_DEFAULT_TEXT_END();
ci->bm.data = ci->fg->glyph_out->bitmap.buffer;
ci->bm.w = MAX(ci->fg->glyph_out->bitmap.pitch,
ci->fg->glyph_out->bitmap.width);
ci->bm.rows = ci->fg->glyph_out->bitmap.rows;
ci->bm.h = ci->fg->glyph_out->top;
above = ci->bm.rows - (ci->bm.rows - ci->bm.h);
below = ci->bm.rows - ci->bm.h;
if (below > descent) descent = below;
if (above > baseline) baseline = above;
ci->pos.x = EVAS_FONT_WALK_PEN_X + ci->fg->glyph_out->left;
ci->pos.y = EVAS_FONT_WALK_PEN_Y + ci->fg->glyph_out->top;
last_delta = EVAS_FONT_WALK_X_ADV -
(ci->bm.w + ci->fg->glyph_out->left);
}
EVAS_FONT_WALK_TEXT_END();
/* First loop done */
width = EVAS_FONT_WALK_PEN_X;

@ -46,10 +46,7 @@ _evas_common_font_source_free(RGBA_Font_Source *fs)
FT_Done_Face(fs->ft.face);
FTUNLOCK();
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
evas_common_font_ot_unload_face(fs);
}
evas_common_font_ot_unload_face(fs);
#endif
if (fs->name) eina_stringshare_del(fs->name);
free(fs);
@ -139,10 +136,7 @@ evas_common_font_source_memory_load(const char *name, const void *data, int data
return NULL;
}
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
evas_common_font_ot_load_face(fs);
}
evas_common_font_ot_load_face(fs);
#endif
FTUNLOCK();
fs->ft.orig_upem = fs->ft.face->units_per_EM;
@ -178,10 +172,7 @@ evas_common_font_source_unload(RGBA_Font_Source *fs)
FT_Done_Face(fs->ft.face);
fs->ft.face = NULL;
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
evas_common_font_ot_unload_face(fs);
}
evas_common_font_ot_unload_face(fs);
#endif
FTUNLOCK();
}
@ -233,10 +224,7 @@ evas_common_font_source_load_complete(RGBA_Font_Source *fs)
return error;
}
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled())
{
evas_common_font_ot_load_face(fs);
}
evas_common_font_ot_load_face(fs);
#endif
FTUNLOCK();
fs->ft.orig_upem = fs->ft.face->units_per_EM;

@ -10,48 +10,32 @@
#include <Eina.h>
#include "evas_font_private.h"
EAPI Eina_Bool
evas_common_font_ot_is_enabled(void)
{
#ifdef OT_SUPPORT
static int ret = -1;
const char *env;
if (ret != -1)
{
return ret;
}
env = getenv("EVAS_USE_OT");
if (env && atoi(env))
{
ret = EINA_TRUE;
return ret;
}
#endif
return EINA_FALSE;
}
#ifdef OT_SUPPORT
/* FIXME: doc. returns #items */
EAPI int
evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index, int orig_len)
evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index)
{
int i;
int items;
int left_bound, right_bound;
size_t base_cluster = EVAS_FONT_OT_POS_GET(props->ot_data->items[char_index]);
size_t base_cluster = EVAS_FONT_OT_POS_GET(props->info->ot[char_index]);
for (i = (int) char_index ;
(i >= 0) &&
(EVAS_FONT_OT_POS_GET(props->ot_data->items[i]) == base_cluster) ;
(i >= (int) props->start) &&
(EVAS_FONT_OT_POS_GET(props->info->ot[i]) == base_cluster) ;
i--)
;
left_bound = i;
for (i = (int) char_index + 1;
(i < (int) props->ot_data->len) &&
(EVAS_FONT_OT_POS_GET(props->ot_data->items[i]) == base_cluster) ;
(i < (int) (props->start + props->len)) &&
(EVAS_FONT_OT_POS_GET(props->info->ot[i]) == base_cluster) ;
i++)
;
right_bound = i;
if (left_bound < 0)
left_bound = 0;
if (right_bound >= (int) (props->start + props->len))
right_bound = props->start + props->len - 1;
if (right_bound == left_bound)
{
items = 1;
@ -60,26 +44,26 @@ evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_i
{
if (left_bound < 0)
{
items = orig_len -
props->ot_data->items[left_bound + 1].source_cluster;
items = props->start + props->len -
props->info->ot[left_bound + 1].source_cluster;
}
else
{
items = props->ot_data->items[left_bound].source_cluster -
props->ot_data->items[left_bound + 1].source_cluster;
items = props->info->ot[left_bound].source_cluster -
props->info->ot[left_bound + 1].source_cluster;
}
}
else
{
if (right_bound == (int) props->ot_data->len)
if (right_bound == (int) (props->start + props->len))
{
items = orig_len -
props->ot_data->items[right_bound - 1].source_cluster;
items = props->start + props->len -
props->info->ot[right_bound - 1].source_cluster;
}
else
{
items = props->ot_data->items[right_bound].source_cluster -
props->ot_data->items[right_bound - 1].source_cluster;
items = props->info->ot[right_bound].source_cluster -
props->info->ot[right_bound - 1].source_cluster;
}
}
return (items > 0) ? items : 1;
@ -114,152 +98,6 @@ _evas_common_font_ot_shape(hb_buffer_t *buffer, RGBA_Font_Source *src)
hb_font_destroy(hb_font);
}
/* Won't work in the middle of ligatures */
EAPI void
evas_common_font_ot_cutoff_text_props(Evas_Text_Props *props, int cutoff)
{
Evas_Font_OT_Data *new_data;
if ((cutoff <= 0) || (!props->ot_data) ||
(((size_t) cutoff) >= props->ot_data->len))
return;
new_data = malloc(sizeof(Evas_Font_OT_Data));
memcpy(new_data, props->ot_data, sizeof(Evas_Font_OT_Data));
new_data->refcount = 1;
new_data->len = cutoff;
new_data->items = malloc(cutoff * sizeof(Evas_Font_OT_Data_Item));
if (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
memcpy(new_data->items,
props->ot_data->items + (props->ot_data->len - cutoff),
cutoff * sizeof(Evas_Font_OT_Data_Item));
}
else
{
memcpy(new_data->items,
props->ot_data->items,
cutoff * sizeof(Evas_Font_OT_Data_Item));
}
evas_common_font_ot_props_unref(props->ot_data);
props->ot_data = new_data;
}
/* Won't work in the middle of ligatures
* aissumes ext doesn't have an already init ot_data
* we assume there's at least one char in each part */
EAPI void
evas_common_font_ot_split_text_props(Evas_Text_Props *base,
Evas_Text_Props *ext, int cutoff)
{
Evas_Font_OT_Data *new_data;
int i;
if ((cutoff <= 0) || (!base->ot_data) ||
(((size_t) cutoff) >= base->ot_data->len))
return;
ext->ot_data = calloc(1, sizeof(Evas_Font_OT_Data));
ext->ot_data->refcount = 1;
ext->ot_data->len = base->ot_data->len - cutoff;
ext->ot_data->items = calloc(ext->ot_data->len,
sizeof(Evas_Font_OT_Data_Item));
new_data = malloc(sizeof(Evas_Font_OT_Data));
memcpy(new_data, base->ot_data, sizeof(Evas_Font_OT_Data));
new_data->refcount = 1;
new_data->items = malloc(cutoff * sizeof(Evas_Font_OT_Data_Item));
new_data->len = cutoff;
if (base->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
memcpy(ext->ot_data->items, base->ot_data->items,
ext->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
memcpy(new_data->items,
base->ot_data->items + ext->ot_data->len,
cutoff * sizeof(Evas_Font_OT_Data_Item));
}
else
{
memcpy(ext->ot_data->items, base->ot_data->items + cutoff,
ext->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
memcpy(new_data->items, base->ot_data->items,
cutoff * sizeof(Evas_Font_OT_Data_Item));
}
evas_common_font_ot_props_unref(base->ot_data);
base->ot_data = new_data;
/* Adjust the offset of the clusters */
{
size_t min;
min = ext->ot_data->items[0].source_cluster;
for (i = 1 ; i < (int) ext->ot_data->len ; i++)
{
if (ext->ot_data->items[i].source_cluster < min)
{
min = ext->ot_data->items[i].source_cluster;
}
}
for (i = 0 ; i < (int) ext->ot_data->len ; i++)
{
ext->ot_data->items[i].source_cluster -= min;
}
ext->ot_data->offset = base->ot_data->offset + min;
}
}
/* Won't work in the middle of ligatures
* assumes both are init correctly and that both are from the
* same origin item, i.e both have the same script + direction.
* assume item1 is logically first */
EAPI void
evas_common_font_ot_merge_text_props(Evas_Text_Props *item1,
const Evas_Text_Props *item2)
{
Evas_Font_OT_Data *new_data;
Evas_Font_OT_Data_Item *itr; /* Itr will be used for adding back
the offsets */
size_t len;
if (!item1->ot_data || !item2->ot_data)
return;
len = item1->ot_data->len + item2->ot_data->len;
new_data = malloc(sizeof(Evas_Font_OT_Data));
memcpy(new_data, item1->ot_data, sizeof(Evas_Font_OT_Data));
new_data->refcount = 1;
new_data->items = malloc(len * sizeof(Evas_Font_OT_Data_Item));
new_data->len = len;
if (item1->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
memcpy(new_data->items, item2->ot_data->items,
item2->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
memcpy(new_data->items + item2->ot_data->len, item1->ot_data->items,
item1->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
itr = new_data->items;
}
else
{
memcpy(new_data->items, item1->ot_data->items,
item1->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
memcpy(new_data->items + item1->ot_data->len, item2->ot_data->items,
item2->ot_data->len * sizeof(Evas_Font_OT_Data_Item));
itr = new_data->items + item1->ot_data->len;
}
evas_common_font_ot_props_unref(item1->ot_data);
item1->ot_data = new_data;
/* Add back the offset of item2 to the newly created */
if (item2->ot_data->offset > 0)