Evas: Multiple changes that all relate to the Harfbuzz integration:

1. Started feeding Evas_Text_Props to the font engine instead of Evas_BiDi_Props because no we have more general text properties as well - i.e, OpenType stuff.
2. Full Harfbuzz integration which gets compiled in by default (if harfbuzz is present) but only works if the environment variable EVAS_USE_OT is set to 1 (because OT is way slower than regular text rendering).
3. Cleaned the font querying/drawing functions.
4. Added font_shaped function to all of the engines, which by default calls teh harfbuzz stuff (default on linux that is).
5. Moved some source files around a bit to make more sense.

SVN revision: 56455
devs/devilhorns/wayland_egl
Tom Hacohen 12 years ago
parent 836b16f085
commit ff18fa8399
  1. 34
      legacy/evas/src/lib/canvas/evas_object_text.c
  2. 167
      legacy/evas/src/lib/canvas/evas_object_textblock.c
  3. 8
      legacy/evas/src/lib/engines/common/Makefile.am
  4. 16
      legacy/evas/src/lib/engines/common/evas_font.h
  5. 203
      legacy/evas/src/lib/engines/common/evas_font_default_walk.x
  6. 393
      legacy/evas/src/lib/engines/common/evas_font_draw.c
  7. 3
      legacy/evas/src/lib/engines/common/evas_font_main.c
  8. 140
      legacy/evas/src/lib/engines/common/evas_font_ot.c
  9. 70
      legacy/evas/src/lib/engines/common/evas_font_ot.h
  10. 168
      legacy/evas/src/lib/engines/common/evas_font_ot_walk.x
  11. 65
      legacy/evas/src/lib/engines/common/evas_font_private.h
  12. 552
      legacy/evas/src/lib/engines/common/evas_font_query.c
  13. 11
      legacy/evas/src/lib/engines/common/evas_pipe.c
  14. 2
      legacy/evas/src/lib/engines/common/evas_pipe.h
  15. 59
      legacy/evas/src/lib/engines/common/evas_text_utils.c
  16. 32
      legacy/evas/src/lib/engines/common/evas_text_utils.h
  17. 5
      legacy/evas/src/lib/engines/common/language/evas_bidi_utils.h
  18. 146
      legacy/evas/src/lib/engines/common/language/evas_language_utils.c
  19. 128
      legacy/evas/src/lib/engines/common/language/evas_language_utils.h
  20. 42
      legacy/evas/src/lib/engines/common/language/evas_script_utils.c
  21. 11
      legacy/evas/src/lib/engines/common/language/evas_script_utils.h
  22. 4
      legacy/evas/src/lib/include/evas_common.h
  23. 20
      legacy/evas/src/lib/include/evas_private.h
  24. 15
      legacy/evas/src/modules/engines/cairo_x11/evas_engine.c
  25. 2
      legacy/evas/src/modules/engines/direct3d/evas_engine.c
  26. 2
      legacy/evas/src/modules/engines/directfb/evas_engine.c
  27. 2
      legacy/evas/src/modules/engines/gl_glew/evas_engine.c
  28. 2
      legacy/evas/src/modules/engines/gl_sdl/evas_engine.c
  29. 2
      legacy/evas/src/modules/engines/gl_x11/evas_engine.c
  30. 23
      legacy/evas/src/modules/engines/quartz/evas_engine.c
  31. 15
      legacy/evas/src/modules/engines/quartz/evas_quartz_private.h
  32. 38
      legacy/evas/src/modules/engines/software_16/evas_engine.c
  33. 2
      legacy/evas/src/modules/engines/software_16_sdl/evas_engine.c
  34. 38
      legacy/evas/src/modules/engines/software_8/evas_engine.c
  35. 44
      legacy/evas/src/modules/engines/software_generic/evas_engine.c
  36. 2
      legacy/evas/src/modules/engines/software_sdl/evas_engine.c
  37. 2
      legacy/evas/src/modules/engines/xrender_x11/evas_engine.c

@ -45,7 +45,7 @@ struct _Evas_Object_Text_Item
Eina_Unicode *text; /*The shaped text */
size_t text_pos;
size_t visual_pos;
Evas_BiDi_Props bidi_props;
Evas_Text_Props text_props;
Evas_Coord x, w, h, adv;
};
@ -115,7 +115,7 @@ _evas_object_text_char_coords_get(const Evas_Object *obj,
(pos < it->text_pos + eina_unicode_strlen(it->text)))
{
return ENFN->font_char_coords_get(ENDT, o->engine_data, it->text,
&it->bidi_props, pos - it->text_pos, x, y, w, h);
&it->text_props, pos - it->text_pos, x, y, w, h);
}
}
return 0;
@ -125,9 +125,7 @@ _evas_object_text_char_coords_get(const Evas_Object *obj,
static void
_evas_object_text_item_clean(Evas_Object_Text_Item *it)
{
#ifdef BIDI_SUPPORT
evas_bidi_props_clean(&it->bidi_props);
#endif
evas_common_text_props_content_unref(&it->text_props);
if (it->text)
{
free(it->text);
@ -166,7 +164,7 @@ _evas_object_text_last_up_to_pos(const Evas_Object *obj,
{
return ENFN->font_last_up_to_pos(ENDT,
o->engine_data,
it->text, &it->bidi_props,
it->text, &it->text_props,
cx - x,
cy);
}
@ -191,7 +189,7 @@ _evas_object_text_char_at_coords(const Evas_Object *obj,
{
return ENFN->font_char_at_coords_get(ENDT,
o->engine_data,
it->text, &it->bidi_props,
it->text, &it->text_props,
cx,
cy,
rx, ry,
@ -232,7 +230,7 @@ _evas_object_text_vert_advance_get(const Evas_Object *obj,
{
Evas_Coord tmp;
tmp = ENFN->font_v_advance_get(ENDT, o->engine_data, it->text,
&it->bidi_props);
&it->text_props);
if (tmp > adv)
{
adv = tmp;
@ -510,19 +508,17 @@ _evas_object_text_item_new(Evas_Object *obj, Evas_Object_Text *o,
it->text_pos = pos;
it->visual_pos = visual_pos;
eina_unicode_strncpy(it->text, str + pos, len);
#ifdef BIDI_SUPPORT
it->bidi_props.dir = (evas_bidi_is_rtl_char(
o->bidi_par_props,
0,
it->text_pos)) ? EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
evas_bidi_shape_string(it->text, o->bidi_par_props, pos, len);
#endif
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,
o->bidi_par_props, it->text_pos, eina_unicode_strlen(it->text));
ENFN->font_string_size_get(ENDT,
o->engine_data,
it->text, &it->bidi_props,
it->text, &it->text_props,
&it->w, &it->h);
it->adv = ENFN->font_h_advance_get(ENDT, o->engine_data, it->text,
&it->bidi_props);
&it->text_props);
o->items = (Evas_Object_Text_Item *)
eina_inlist_append(EINA_INLIST_GET(o->items), EINA_INLIST_GET(it));
return it;
@ -606,7 +602,7 @@ _evas_object_text_layout(Evas_Object *obj, Evas_Object_Text *o, const Eina_Unico
cutoff = len;
do
{
cutoff = evas_common_script_end_of_run_get(
cutoff = evas_common_language_script_end_of_run_get(
text,
o->bidi_par_props,
pos, cutoff);
@ -1935,7 +1931,7 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur
obj->cur.geometry.h, \
obj->cur.geometry.w, \
obj->cur.geometry.h, \
it->text, &it->bidi_props);
it->text, &it->text_props);
EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
{
/* shadows */

@ -318,7 +318,7 @@ struct _Evas_Object_Textblock_Item
size_t visual_pos;
#endif
Evas_Coord adv, x, w, h;
Evas_BiDi_Props bidi_props;
Evas_Text_Props text_props;
};
struct _Evas_Object_Textblock_Text_Item
@ -630,6 +630,38 @@ _format_unref_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
free(fmt);
}
/**
* @internal
* Free a layout item
* @param obj The evas object, must not be NULL.
* @param ln the layout line on which the item is in, must not be NULL.
* @param it the layout item to be freed
*/
static void
_item_free(const Evas_Object *obj, Evas_Object_Textblock_Line *ln, Evas_Object_Textblock_Item *it)
{
if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
{
Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
if (ti->text) free(ti->text);
_format_unref_free(obj, ti->format);
}
else
{
Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
if (fi->item) eina_stringshare_del(fi->item);
}
evas_common_text_props_content_unref(&it->text_props);
if (ln)
{
ln->items = (Evas_Object_Textblock_Item *) eina_inlist_remove(
EINA_INLIST_GET(ln->items), EINA_INLIST_GET(ln->items));
}
free(it);
}
/**
* @internal
* Free a layout line.
@ -642,22 +674,7 @@ _line_free(const Evas_Object *obj, Evas_Object_Textblock_Line *ln)
while (ln->items)
{
Evas_Object_Textblock_Item *it = ln->items;
if (ln->items->type == EVAS_TEXTBLOCK_ITEM_TEXT)
{
Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
if (ti->text) free(ti->text);
_format_unref_free(obj, ti->format);
}
else
{
Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
if (fi->item) eina_stringshare_del(fi->item);
}
ln->items = (Evas_Object_Textblock_Item *) eina_inlist_remove(
EINA_INLIST_GET(ln->items), EINA_INLIST_GET(ln->items));
free(it);
_item_free(obj, ln, it);
}
if (ln) free(ln);
}
@ -2251,7 +2268,7 @@ _layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_
{
if (fmt->font.font)
return c->ENFN->font_last_up_to_pos(c->ENDT, fmt->font.font, ti->text,
&ti->parent.bidi_props,
&ti->parent.text_props,
c->w -
c->o->style_pad.l -
c->o->style_pad.r -
@ -2279,6 +2296,9 @@ _layout_item_text_cutoff(Ctxt *c __UNUSED__, Evas_Object_Textblock_Text_Item *ti
ts[cut] = 0;
ti->text = eina_unicode_strdup(ts);
free(ts);
c->ENFN->font_shape(c->ENDT, ti->format->font.font, ti->text,
&ti->parent.text_props, ti->parent.text_node->bidi_props,
ti->parent.text_pos, cut);
}
/**
@ -2353,11 +2373,11 @@ _layout_strip_trailing_whitespace(Ctxt *c, Evas_Object_Textblock_Format *fmt __U
adv = 0;
if (ti->format->font.font)
adv = c->ENFN->font_h_advance_get(c->ENDT, ti->format->font.font,
ti->text, &ti->parent.bidi_props);
ti->text, &ti->parent.text_props);
tw = th = 0;
if (ti->format->font.font)
c->ENFN->font_string_size_get(c->ENDT, ti->format->font.font,
ti->text, &ti->parent.bidi_props, &tw, &th);
ti->text, &ti->parent.text_props, &tw, &th);
it->w = tw;
it->h = th;
it->adv = adv;
@ -2379,17 +2399,7 @@ _layout_item_abort(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textb
/*FIXME: handle it in some way? */
if (it->type != EVAS_TEXTBLOCK_ITEM_TEXT)
return 0;
if (ti->text) free(ti->text);
_format_unref_free(c->obj, ti->format);
#ifdef BIDI_SUPPORT
/* FIXME: this also unrefs the paragraph props, we should either
* really count the usage of the paragraph props in the items, or just
* not use clean here. I prefer the latter but that might break if we'll
* start doing fancy stuff in clean in the future. */
/* evas_bidi_props_clean(&it->bidi_props); */
#endif
free(ti);
_item_free(c->obj, NULL, _ITEM(ti));
if (c->ln->items)
{
it = (Evas_Object_Textblock_Item *)(EINA_INLIST_GET(c->ln->items))->last;
@ -2473,6 +2483,7 @@ _layout_text_add_and_split_item(Ctxt *c, Evas_Object_Textblock_Format *fmt,
int cutoff, len;
cutoff = 0;
len = eina_unicode_strlen(ti->text);
do
{
@ -2481,21 +2492,38 @@ _layout_text_add_and_split_item(Ctxt *c, Evas_Object_Textblock_Format *fmt,
* no text nodes, make sure it's the case. */
if (ti->parent.text_node)
{
cutoff = evas_common_script_end_of_run_get(
eina_ustrbuf_string_get(ti->parent.text_node->unicode),
cutoff = evas_common_language_script_end_of_run_get(
ti->text,
ti->parent.text_node->bidi_props,
ti->parent.text_pos, len);
if (cutoff > 0)
{
new_ti = _layout_text_item_new(c, fmt, ti->text + cutoff);
_layout_item_text_cutoff(c, ti, cutoff);
new_ti->parent.text_node = ti->parent.text_node;
new_ti->parent.text_pos = ti->parent.text_pos + cutoff;
evas_common_text_props_bidi_set(&new_ti->parent.text_props,
new_ti->parent.text_node->bidi_props,
new_ti->parent.text_pos);
evas_common_text_props_script_set (&new_ti->parent.text_props,
new_ti->text);
/* FIXME: I possibly can use the alread calculated lengths */
c->ENFN->font_shape(c->ENDT, ti->format->font.font, ti->text,
&ti->parent.text_props,
ti->parent.text_node->bidi_props,
ti->parent.text_pos, cutoff);
c->ENFN->font_shape(c->ENDT, new_ti->format->font.font,
new_ti->text,
&new_ti->parent.text_props,
new_ti->parent.text_node->bidi_props,
new_ti->parent.text_pos, len - cutoff);
}
}
tw = th = 0;
if (fmt->font.font)
c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, ti->text,
&ti->parent.bidi_props, &tw, &th);
&ti->parent.text_props, &tw, &th);
ti->parent.w = tw;
ti->parent.h = th;
inset = 0;
@ -2507,7 +2535,7 @@ _layout_text_add_and_split_item(Ctxt *c, Evas_Object_Textblock_Format *fmt,
adv = 0;
if (fmt->font.font)
adv = c->ENFN->font_h_advance_get(c->ENDT, fmt->font.font,
ti->text, &ti->parent.bidi_props);
ti->text, &ti->parent.text_props);
ti->parent.adv = adv;
c->x += adv;
c->ln->items = (Evas_Object_Textblock_Item *)
@ -2516,16 +2544,6 @@ _layout_text_add_and_split_item(Ctxt *c, Evas_Object_Textblock_Format *fmt,
if (cutoff > 0)
{
new_ti->parent.text_node = ti->parent.text_node;
new_ti->parent.text_pos = ti->parent.text_pos + cutoff;
#ifdef BIDI_SUPPORT
new_ti->parent.bidi_props.dir = (evas_bidi_is_rtl_char(
new_ti->parent.text_node->bidi_props,
new_ti->parent.text_pos,
0)) ? EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
#else
new_ti->parent.bidi_props.dir = EVAS_BIDI_DIRECTION_LTR;
#endif
ti = new_ti;
len -= cutoff;
}
@ -2611,11 +2629,6 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text
alloc_str[off] = 0;
}
str = alloc_str;
/* Shape the string */
# ifdef BIDI_SUPPORT
evas_bidi_shape_string(alloc_str, n->bidi_props, start, off);
# endif
}
}
@ -2636,19 +2649,18 @@ skip:
ti->parent.text_pos = start + str - tbase;
if (ti->parent.text_node)
{
#ifdef BIDI_SUPPORT
ti->parent.bidi_props.dir = (evas_bidi_is_rtl_char(
ti->parent.text_node->bidi_props,
ti->parent.text_pos,
0)) ? EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
#else
ti->parent.bidi_props.dir = EVAS_BIDI_DIRECTION_LTR;
#endif
evas_common_text_props_bidi_set(&ti->parent.text_props,
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->format->font.font, ti->text,
&ti->parent.text_props, ti->parent.text_node->bidi_props,
ti->parent.text_pos, eina_unicode_strlen(ti->text));
}
tw = th = 0;
if (fmt->font.font)
c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, ti->text,
&ti->parent.bidi_props, &tw, &th);
&ti->parent.text_props, &tw, &th);
/* Check if we need to wrap, i.e the text is bigger than the width
* Only calculate wrapping if the width of the object is > 0 */
if ((c->w >= 0) &&
@ -2698,10 +2710,7 @@ skip:
else
{
empty_item = 1;
/* FIXME: use proper cleaning here */
if (ti->text) free(ti->text);
_format_unref_free(c->obj, ti->format);
free(ti);
_item_free(c->obj, NULL, _ITEM(ti));
if (c->ln->items)
{
ti = _ITEM_TEXT((EINA_INLIST_GET(c->ln->items))->last);
@ -2860,14 +2869,8 @@ _layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const cha
fi->parent.text_node = n->text_node;
/* FIXME: make it more efficient */
fi->parent.text_pos = _evas_textblock_node_format_pos_get(n);
#ifdef BIDI_SUPPORT
fi->parent.bidi_props.dir = (evas_bidi_is_rtl_char(
fi->parent.text_node->bidi_props,
fi->parent.text_pos,
0)) ? EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
#else
fi->parent.bidi_props.dir = EVAS_BIDI_DIRECTION_LTR;
#endif
evas_common_text_props_bidi_set(&fi->parent.text_props,
fi->parent.text_node->bidi_props, fi->parent.text_pos);
}
return fi;
}
@ -6821,7 +6824,7 @@ evas_textblock_cursor_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord
* @return line number of the char on success, -1 on error.
*/
static int
_evas_textblock_cursor_char_pen_geometry_common_get(int (*query_func) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch), const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
_evas_textblock_cursor_char_pen_geometry_common_get(int (*query_func) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch), const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
{
Evas_Object_Textblock *o;
Evas_Object_Textblock_Line *ln = NULL;
@ -6876,7 +6879,7 @@ _evas_textblock_cursor_char_pen_geometry_common_get(int (*query_func) (void *dat
{
ret = query_func(cur->ENDT,
ti->format->font.font,
ti->text, &ti->parent.bidi_props,
ti->text, &ti->parent.text_props,
pos,
&x, &y, &w, &h);
}
@ -7058,7 +7061,7 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, E
pos = cur->ENFN->font_char_at_coords_get(
cur->ENDT,
ti->format->font.font,
ti->text, &ti->parent.bidi_props,
ti->text, &ti->parent.text_props,
x - it->x - ln->x, 0,
&cx, &cy, &cw, &ch);
if (pos < 0)
@ -7145,7 +7148,7 @@ _evas_textblock_range_calc_x_w(const Evas_Object_Textblock_Item *it,
if ((start && !switch_items) || (!start && switch_items))
{
#ifdef BIDI_SUPPORT
if (it->bidi_props.dir == EVAS_BIDI_DIRECTION_RTL)
if (it->text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
*w = *x + *w;
*x = 0;
@ -7159,7 +7162,7 @@ _evas_textblock_range_calc_x_w(const Evas_Object_Textblock_Item *it,
else
{
#ifdef BIDI_SUPPORT
if (it->bidi_props.dir == EVAS_BIDI_DIRECTION_RTL)
if (it->text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
*x = *x + *w;
*w = it->adv - *x;
@ -7255,7 +7258,7 @@ _evas_textblock_cursor_range_in_line_geometry_get(
ti = _ITEM_TEXT(it1);
ret = cur->ENFN->font_pen_coords_get(cur->ENDT,
ti->format->font.font,
ti->text, &ti->parent.bidi_props,
ti->text, &ti->parent.text_props,
start,
&x1, &y, &w1, &h);
if (!ret)
@ -7264,7 +7267,7 @@ _evas_textblock_cursor_range_in_line_geometry_get(
}
ret = cur->ENFN->font_pen_coords_get(cur->ENDT,
ti->format->font.font,
ti->text, &ti->parent.bidi_props,
ti->text, &ti->parent.text_props,
end,
&x2, &y, &w2, &h);
if (!ret)
@ -7286,7 +7289,7 @@ _evas_textblock_cursor_range_in_line_geometry_get(
}
#ifdef BIDI_SUPPORT
if (ti->parent.bidi_props.dir == EVAS_BIDI_DIRECTION_RTL)
if (ti->parent.text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL)
{
x = x1 + w1;
w = x2 + w2 - x;
@ -7324,7 +7327,7 @@ _evas_textblock_cursor_range_in_line_geometry_get(
ret = cur->ENFN->font_pen_coords_get(cur->ENDT,
ti->format->font.font,
ti->text, &ti->parent.bidi_props,
ti->text, &ti->parent.text_props,
start,
&x, &y, &w, &h);
if (!ret)
@ -7378,7 +7381,7 @@ _evas_textblock_cursor_range_in_line_geometry_get(
ret = cur->ENFN->font_pen_coords_get(cur->ENDT,
ti->format->font.font,
ti->text, &ti->parent.bidi_props,
ti->text, &ti->parent.text_props,
end,
&x, &y, &w, &h);
if (!ret)
@ -7836,7 +7839,7 @@ evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void
if (ti->format->font.font) ENFN->font_draw(output, context, surface, ti->format->font.font, \
obj->cur.geometry.x + ln->x + ti->parent.x + x + (ox), \
obj->cur.geometry.y + ln->y + yoff + y + (oy), \
ti->parent.w, ti->parent.h, ti->parent.w, ti->parent.h, ti->text, &ti->parent.bidi_props);
ti->parent.w, ti->parent.h, ti->parent.w, ti->parent.h, ti->text, &ti->parent.text_props);
#define ITEM_WALK_LINE_SKIP_DROP() \
if ((ln->y + ln->h) <= 0) continue; \
if (ln->y > obj->cur.geometry.h) break

@ -60,7 +60,9 @@ evas_tiler.c \
evas_regionbuf.c \
evas_pipe.c \
language/evas_bidi_utils.c \
language/evas_script_utils.c \
language/evas_language_utils.c \
evas_text_utils.c \
evas_font_ot.c \
evas_map_image.c \
evas_map_image.h
@ -100,7 +102,9 @@ evas_scale_smooth_scaler_up.c \
evas_scale_span.h \
evas_pipe.h \
language/evas_bidi_utils.h \
language/evas_script_utils.h \
language/evas_language_utils.h \
evas_text_utils.h \
evas_font_ot.h \
evas_map_image_internal.c \
evas_map_image_core.c \
evas_map_image_loop.c

@ -1,6 +1,6 @@
#ifndef _EVAS_FONT_H
#define _EVAS_FONT_H
#include "language/evas_bidi_utils.h"
#include "evas_text_utils.h"
/* main */
@ -17,7 +17,7 @@ EAPI int evas_common_font_get_line_advance (RGBA_Font *fn);
/* draw */
EAPI void evas_common_font_draw (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props);
EAPI 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);
EAPI int evas_common_font_glyph_search (RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl);
EAPI RGBA_Font_Glyph *evas_common_font_int_cache_glyph_get (RGBA_Font_Int *fi, FT_UInt index);
EAPI void evas_common_font_draw_init (void);
@ -56,13 +56,13 @@ EAPI void evas_common_font_all_clear (void);
/* query */
EAPI int evas_common_font_query_kerning (RGBA_Font_Int* fi, FT_UInt left, FT_UInt right, int* kerning);
EAPI void evas_common_font_query_size (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h);
EAPI void evas_common_font_query_size (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int *w, int *h);
EAPI int evas_common_font_query_inset (RGBA_Font *fn, const Eina_Unicode *text);
EAPI void evas_common_font_query_advance (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *h_adv, int *v_adv);
EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch);
EAPI int evas_common_font_query_pen_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch);
EAPI int evas_common_font_query_char_at_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch);
EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y);
EAPI void evas_common_font_query_advance (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int *h_adv, int *v_adv);
EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch);
EAPI int evas_common_font_query_pen_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch);
EAPI int evas_common_font_query_char_at_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch);
EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int x, int y);
#ifdef EVAS_FRAME_QUEUING
EAPI void evas_common_font_draw_finish(void);

@ -0,0 +1,203 @@
#ifndef _EVAS_FONT_DEFAULT_WALK_X
#define _EVAS_FONT_DEFAULT_WALK_X
/* Macros for text walking */
/**
* @def EVAS_FONT_UPDATE_KERN()
* @internal
* This macro updates pen_x and kern according to kerning.
* This macro assumes the following variables exist:
* intl_props, char_index, adv, fi, kern, pen_x
*/
#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
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START
* @internal
* This runs through the variable text while updating char_index,
* which is the current index in the text. This macro exposes (inside
* the loop) the following vars:
* adv - advancement
* gl - the current unicode code point
* bear_x, bear_y, width - info about the bitmap
* pen_x, pen_y - (also available outside of the loop, but updated here)
* fg - the font glyph.
* index, prev_index - font indexes.
* Does not end with a ;
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @see EVAS_FONT_WALK_DEFAULT_TEXT_END
*/
#define EVAS_FONT_WALK_DEFAULT_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;
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START
* @internal
* FIXME: update
* This runs through the variable text while updating char_index,
* which is the current index in the text. This macro exposes (inside
* the loop) the following vars:
* adv - advancement
* gl - the current unicode code point
* bear_x, bear_y, width - info about the bitmap
* pen_x, pen_y - (also available outside of the loop, but updated here)
* fg - the font glyph.
* index, prev_index - font indexes.
* Does not end with a ;
* @see EVAS_FONT_WALK_DEFAULT_TEXT_INIT
* @see EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @see EVAS_FONT_WALK_DEFAULT_TEXT_END
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_LOGICAL_START() \
do \
{ \
int visible; \
prev_index = 0; \
for (char_index = 0 ; *text ; text++, char_index++) \
{ \
FT_UInt index; \
RGBA_Font_Glyph *fg; \
int gl, kern; \
gl = *text; \
if (gl == 0) break;
/*FIXME: doc */
#define EVAS_FONT_WALK_DEFAULT_X_OFF (kern)
#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 >> 16)
#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 \
)
#define EVAS_FONT_WALK_DEFAULT_LEN (EVAS_FONT_WALK_ORIG_LEN)
/**
* @def EVAS_FONT_WALK_DEFAULT_TEXT_WORK
* @internal
* This macro actually updates the values mentioned in EVAS_FONT_WALK_DEFAULT_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
*/
#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); \
/**
* @def EVAS_FONT_WALK_DEFAULT_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
*/
#define EVAS_FONT_WALK_DEFAULT_TEXT_END() \
if (visible) \
{ \
pen_x += EVAS_FONT_WALK_DEFAULT_X_ADV; \
} \
prev_index = index; \
} \
} \
while(0)
#endif

@ -5,6 +5,8 @@
#include "language/evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
#include "evas_font_private.h" /* for Frame-Queuing support */
#include "evas_font_ot.h"
#define WORD_CACHE_MAXLEN 50
/* How many to cache */
#define WORD_CACHE_NWORDS 40
@ -48,7 +50,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, Evas_BiDi_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, Evas_Text_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning);
#endif
EAPI void
@ -395,7 +397,7 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
*/
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_BiDi_Props *intl_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w,
const Evas_Text_Props *intl_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w,
int ext_h, RGBA_Font_Int *fi, int im_w, int im_h __UNUSED__, int use_kerning
)
{
@ -414,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, (Evas_BiDi_Props *)intl_props,
evas_font_word_prerender(dc, text, (Evas_Text_Props *)intl_props,
len, fn, fi, use_kerning);
if (word)
{
@ -493,27 +495,6 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
}
#endif
#ifdef BIDI_SUPPORT
Eina_Unicode *visual_text = NULL;
if (intl_props && (intl_props->dir == EVAS_BIDI_DIRECTION_RTL))
{
visual_text = eina_unicode_strdup(in_text);
if (visual_text)
{
evas_bidi_reverse_string(visual_text);
text = visual_text;
}
}
if (!visual_text)
{
text = in_text;
}
#else
/*Suppress warnings */
(void) intl_props;
#endif
if (fi->src->current_size != fi->size)
{
FTLOCK();
@ -522,144 +503,301 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
fi->src->current_size = fi->size;
}
pen_x = x;
pen_y = y;
im = dst->image.data;
EVAS_FONT_WALK_TEXT_START()
#ifdef OT_SUPPORT
if (evas_common_font_ot_is_enabled() && intl_props->ot_data)
{
int chr_x, chr_y, chr_w;
EVAS_FONT_WALK_OT_TEXT_VISUAL_START()
{
int chr_x, chr_y, chr_w;
if (EVAS_FONT_CHARACTER_IS_INVISIBLE(gl))
continue;
if (EVAS_FONT_CHARACTER_IS_INVISIBLE(gl))
continue;
EVAS_FONT_WALK_TEXT_WORK(EINA_TRUE);
EVAS_FONT_WALK_OT_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;
}
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 = (pen_x) + bear_x;
chr_y = (pen_y) + bear_y;
chr_w = width;
chr_x = (pen_x) + EVAS_FONT_WALK_OT_X_OFF + EVAS_FONT_WALK_OT_X_BEAR;
chr_y = (pen_y) + EVAS_FONT_WALK_OT_Y_OFF + EVAS_FONT_WALK_OT_Y_BEAR;
chr_w = EVAS_FONT_WALK_OT_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 (chr_x < (ext_x + ext_w))
{
if ((j > 0) && (chr_x + w > ext_x))
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 ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
if ((j > 0) && (chr_x + w > ext_x))
{
/* 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->ext_dat) && (dc->font_ext.func.gl_draw))
{
for (i = 0; i < h; i++)
/* 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))
{
int dx, dy;
int in_x, in_w;
for (i = 0; i < h; i++)
{
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++)
{
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
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 + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
tp = tmpbuf;
dp = data + (i * fg->glyph_out->bitmap.pitch);
for (bi = 0; bi < w; bi += 8)
{
in_w += ext_x - dx;
in_x = ext_x - dx;
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++;
}
if (in_w < w)
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
{
func(NULL, data + (i * j) + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_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);
}
}
}
}
}
}
}
}
}
else
break;
}
EVAS_FONT_WALK_OT_TEXT_END();
}
else
#endif
{
EVAS_FONT_WALK_DEFAULT_TEXT_VISUAL_START()
{
int chr_x, chr_y, chr_w;
if (EVAS_FONT_CHARACTER_IS_INVISIBLE(gl))
continue;
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 = (pen_x) + EVAS_FONT_WALK_DEFAULT_X_OFF + EVAS_FONT_WALK_DEFAULT_X_BEAR;
chr_y = (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
{
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
int bi, bj;
const DATA8 bitrepl[2] = {0x0, 0xff};
tmpbuf = alloca(w);
for (i = 0; i < h; i++)
if ((fg->glyph_out->bitmap.num_grays == 256) &&
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
{
int dx, dy;
int in_x, in_w, end;
for (i = 0; i < h; i++)
{
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
{
tp = tmpbuf;
dp = data + (i * fg->glyph_out->bitmap.pitch);
for (bi = 0; bi < w; bi += 8)
{
bits = *dp;
if ((w - bi) < 8) end = w - bi;
else end = 8;
for (bj = 0; bj < end; bj++)
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
{
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
tp++;
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);
}
}
dp++;
}
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
}
}
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 + w > (ext_x + ext_w))
in_w += (dx + w) - (ext_x + ext_w);
if (dx < ext_x)
tp = tmpbuf;
dp = data + (i * fg->glyph_out->bitmap.pitch);
for (bi = 0; bi < w; bi += 8)
{
in_w += ext_x - dx;
in_x = ext_x - dx;
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++;
}
if (in_w < w)
if ((dx < (ext_x + ext_w)) &&
(dy >= (ext_y)) &&
(dy < (ext_y + ext_h)))
{
func(NULL, tmpbuf + in_x, dc->col.col,
im + (dy * im_w) + dx, w - in_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)