typedef struct _Evas_Object_Textgrid_Rect Evas_Object_Textgrid_Rect;
typedef struct _Evas_Object_Textgrid_Text Evas_Object_Textgrid_Text;
typedef struct _Evas_Object_Textgrid_Line Evas_Object_Textgrid_Line;
-typedef struct _Evas_Textgrid_Hash_Master Evas_Textgrid_Hash_Master;
-typedef struct _Evas_Textgrid_Hash_Glyphs Evas_Textgrid_Hash_Glyphs;
+typedef struct _Evas_Textgrid_Hash_Master Evas_Textgrid_Hash_Master;
+typedef struct _Evas_Textgrid_Hash_Glyphs Evas_Textgrid_Hash_Glyphs;
struct _Evas_Textgrid_Hash_Master
{
evas_object_textgrid_row_clear(Evas_Object_Textgrid *o, Evas_Object_Textgrid_Row *r)
{
int i;
-
+
if (r->rects)
{
free(r->rects);
if (row->rects_num > row->rects_alloc)
{
Evas_Object_Textgrid_Rect *t;
-
+
row->rects_alloc += 8; // dont expect many rects per line
t = realloc(row->rects, sizeof(Evas_Object_Textgrid_Rect) * row->rects_alloc);
if (!t)
static void
evas_object_textgrid_row_text_append(Evas_Object_Textgrid_Row *row, Evas_Object *eo_obj, Evas_Object_Textgrid *o, int x, Eina_Unicode codepoint, int r, int g, int b, int a)
{
+ unsigned int text_props_index;
+
row->texts_num++;
if (row->texts_num > row->texts_alloc)
{
Evas_Object_Textgrid_Text *t;
-
+
row->texts_alloc += 32; // expect more text per line
t = realloc(row->texts, sizeof(Evas_Object_Textgrid_Text) * row->texts_alloc);
if (!t)
row->texts = t;
}
- row->texts[row->texts_num - 1].text_props = evas_object_textgrid_textprop_ref(eo_obj, o, codepoint);
+ text_props_index = evas_object_textgrid_textprop_ref(eo_obj, o, codepoint);
+
+ row->texts[row->texts_num - 1].text_props = text_props_index;
row->texts[row->texts_num - 1].x = x;
row->texts[row->texts_num - 1].r = r;
row->texts[row->texts_num - 1].g = g;
if (row->lines_num > row->lines_alloc)
{
Evas_Object_Textgrid_Line *t;
-
+
row->lines_alloc += 8; // dont expect many lines per line
t = realloc(row->lines, sizeof(Evas_Object_Textgrid_Line) * row->lines_alloc);
if (!t)
row->lines[row->lines_num - 1].a = a;
}
+static Eina_Bool
+_drop_glyphs_ref(const void *container EINA_UNUSED, void *data, void *fdata)
+{
+ Evas_Font_Array_Data *fad = data;
+ Evas_Public_Data *pd = fdata;
+
+ evas_common_font_glyphs_unref(fad->glyphs);
+ eina_array_pop(&pd->glyph_unref_queue);
+
+ return EINA_TRUE;
+}
+
static void
evas_object_textgrid_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, void *output, void *context, void *surface, int x, int y, Eina_Bool do_async)
{
int xx, yy, xp, yp, w, h, ww, hh;
int rr = 0, rg = 0, rb = 0, ra = 0, rx = 0, rw = 0, run;
- /* render object to surface with context, and offxet by x,y */
+ /* render object to surface with context, and offset by x,y */
Evas_Object_Textgrid *o = eo_data_get(eo_obj, MY_CLASS);
ENFN->context_multiplier_unset(output, context);
ENFN->context_render_op_set(output, context, obj->cur.render_op);
if (!(o->font) || (!o->cur.cells)) return;
-
+
w = o->cur.char_width;
h = o->cur.char_height;
ww = obj->cur.geometry.w;
for (yy = 0, cells = o->cur.cells; yy < o->cur.h; yy++)
{
Evas_Object_Textgrid_Row *row = &(o->cur.rows[yy]);
-
+
if (row->ch1 < 0)
{
cells += o->cur.w;
for (yy = 0, cells = o->cur.cells; yy < o->cur.h; yy++)
{
Evas_Object_Textgrid_Row *row = &(o->cur.rows[yy]);
+ Evas_Font_Array *texts;
xp = obj->cur.geometry.x + x;
for (xx = 0; xx < row->rects_num; xx++)
{
ENFN->context_color_set(output, context,
row->rects[xx].r, row->rects[xx].g,
- row->rects[xx].b, row->rects[xx].a);
+ row->rects[xx].b, row->rects[xx].a);
ENFN->rectangle_draw(output, context, surface,
xp + row->rects[xx].x, yp,
row->rects[xx].w, h,
do_async);
}
- for (xx = 0; xx < row->texts_num; xx++)
+
+ if (row->texts_num)
{
- ENFN->context_color_set(output, context,
- row->texts[xx].r, row->texts[xx].g,
- row->texts[xx].b, row->texts[xx].a);
- evas_font_draw_async_check(obj, output, context, surface, o->font,
- xp + row->texts[xx].x, yp + o->max_ascent,
- ww, hh, ww, hh,
- evas_object_textgrid_textprop_int_to(o, row->texts[xx].text_props),
- do_async);
+ if ((do_async) && (ENFN->multi_font_draw))
+ {
+ Eina_Bool async_unref;
+
+ texts = malloc(sizeof(*texts));
+ texts->array = eina_inarray_new(sizeof(Evas_Font_Array_Data),
+ 32);
+ texts->refcount = 1;
+
+ for (xx = 0; xx < row->texts_num; xx++)
+ {
+ Evas_Text_Props *props;
+ Evas_Font_Array_Data fad;
+
+ props =
+ evas_object_textgrid_textprop_int_to
+ (o, row->texts[xx].text_props);
+
+ evas_common_font_draw_prepare(props);
+
+ evas_common_font_glyphs_ref(props->glyphs);
+ evas_unref_queue_glyph_put(obj->layer->evas,
+ props->glyphs);
+
+ fad.color.r = row->texts[xx].r;
+ fad.color.g = row->texts[xx].g;
+ fad.color.b = row->texts[xx].b;
+ fad.color.a = row->texts[xx].a;
+ fad.x = row->texts[xx].x;
+ fad.glyphs = props->glyphs;
+
+ if (eina_inarray_push(texts->array, &fad) < 0)
+ ERR("Failed to push text onto texts array %p",
+ texts->array);
+ }
+
+ async_unref =
+ ENFN->multi_font_draw(output, context, surface,
+ o->font, xp, yp + o->max_ascent,
+ ww, hh, ww, hh, texts, do_async);
+ if (async_unref)
+ evas_unref_queue_texts_put(obj->layer->evas, texts);
+ else
+ {
+ eina_inarray_foreach(texts->array, _drop_glyphs_ref,
+ obj->layer->evas);
+ eina_inarray_free(texts->array);
+ free(texts);
+ }
+ }
+ else
+ {
+ for (xx = 0; xx < row->texts_num; xx++)
+ {
+ Evas_Text_Props *props;
+ unsigned int r, g, b, a;
+ int tx = xp + row->texts[xx].x;
+ int ty = yp + o->max_ascent;
+
+ props =
+ evas_object_textgrid_textprop_int_to
+ (o, row->texts[xx].text_props);
+
+ r = row->texts[xx].r;
+ g = row->texts[xx].g;
+ b = row->texts[xx].b;
+ a = row->texts[xx].a;
+
+ ENFN->context_color_set(output, context,
+ r, g, b, a);
+ evas_font_draw_async_check(obj, output, context, surface,
+ o->font, tx, ty, ww, hh,
+ ww, hh, props, do_async);
+ }
+ }
}
+
for (xx = 0; xx < row->lines_num; xx++)
{
ENFN->context_color_set(output, context,
row->lines[xx].r, row->lines[xx].g,
- row->lines[xx].b, row->lines[xx].a);
+ row->lines[xx].b, row->lines[xx].a);
ENFN->rectangle_draw(output, context, surface,
xp + row->lines[xx].x, yp + row->lines[xx].y,
row->lines[xx].w, 1,
typedef struct _Evas_Thread_Command_Image Evas_Thread_Command_Image;
typedef struct _Evas_Thread_Command_Font Evas_Thread_Command_Font;
typedef struct _Evas_Thread_Command_Map Evas_Thread_Command_Map;
+typedef struct _Evas_Thread_Command_Multi_Font Evas_Thread_Command_Multi_Font;
struct _Evas_Thread_Command_Rect
{
int smooth, level, offset;
};
+struct _Evas_Thread_Command_Multi_Font
+{
+ RGBA_Draw_Context context;
+ void *surface;
+ int x, y;
+ Evas_Font_Array *texts;
+};
+
Eina_Mempool *_mp_command_rect = NULL;
Eina_Mempool *_mp_command_line = NULL;
Eina_Mempool *_mp_command_polygon = NULL;
Eina_Mempool *_mp_command_image = NULL;
Eina_Mempool *_mp_command_font = NULL;
Eina_Mempool *_mp_command_map = NULL;
+Eina_Mempool *_mp_command_multi_font = NULL;
/*
*****
}
static void
+_draw_thread_multi_font_draw(void *data)
+{
+ Evas_Thread_Command_Multi_Font *mf = data;
+ Evas_Font_Array_Data *itr;
+
+ EINA_INARRAY_FOREACH(mf->texts->array, itr)
+ {
+ unsigned int r, g, b, a;
+ int x = mf->x + itr->x, y = mf->y;
+
+ r = itr->color.r;
+ g = itr->color.g;
+ b = itr->color.b;
+ a = itr->color.a;
+
+ eng_context_color_set(NULL, &mf->context, r, g, b, a);
+ evas_common_font_draw(mf->surface, &mf->context, x, y, itr->glyphs);
+ evas_common_cpu_end_opt();
+ }
+
+ eina_mempool_free(_mp_command_multi_font, mf);
+}
+
+static Eina_Bool
+_multi_font_draw_thread_cmd(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, Evas_Font_Array *texts)
+{
+ Evas_Thread_Command_Multi_Font *mf;
+
+ mf = eina_mempool_malloc(_mp_command_multi_font,
+ sizeof(Evas_Thread_Command_Multi_Font));
+ if (!mf)
+ {
+ ERR("Failed to allocate memory on mempool for multiple text_props "
+ "commands.");
+ return EINA_FALSE;
+ }
+
+ memcpy(&mf->context, dc, sizeof(*dc));
+ mf->surface = dst;
+ mf->x = x;
+ mf->y = y;
+ mf->texts = texts;
+
+ evas_thread_cmd_enqueue(_draw_thread_multi_font_draw, mf);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+eng_multi_font_draw(void *data EINA_UNUSED, void *context, void *surface, Evas_Font_Set *font EINA_UNUSED, int x, int y, int w EINA_UNUSED, int h EINA_UNUSED, int ow EINA_UNUSED, int oh EINA_UNUSED, Evas_Font_Array *texts, Eina_Bool do_async)
+{
+ if (!texts) return EINA_FALSE;
+
+ if (do_async)
+ return _multi_font_draw_thread_cmd(surface, context, x, y, texts);
+
+ return EINA_FALSE;
+}
+
+static void
eng_image_cache_flush(void *data EINA_UNUSED)
{
int tmp_size;
eng_image_animated_loop_count_get,
eng_image_animated_frame_duration_get,
eng_image_animated_frame_set,
- NULL
+ NULL,
+ eng_multi_font_draw,
/* FUTURE software generic calls go here */
};
_mp_command_map = eina_mempool_add("chained_mempool",
"Evas_Thread_Command_Map", NULL,
sizeof (Evas_Thread_Command_Map), 64);
+ _mp_command_multi_font =
+ eina_mempool_add("chained_mempool", "Evas_Thread_Command_Multi_Font",
+ NULL, sizeof(Evas_Thread_Command_Multi_Font), 128);
init_gl();
evas_common_pipe_init();