From e197f8804f9a2bded1f7a0e5bccf5fb33c415d77 Mon Sep 17 00:00:00 2001 From: Youngbok Shin Date: Thu, 19 Mar 2015 19:02:02 +0900 Subject: [PATCH] evas: Support bitmap embedded color font. Summary: Add the code for getting bitmap buffers from embedded color font, And draw the bitmap buffers as images. For drawing the bitmap buffers as images, evas_common_draw_context_font_ext_set internal API is changed to pass additional gl engine functions. T2139 @feature Test Plan: 1. Set a bitmap embedded color font to textblock. 2. Set a unicode emoticon text. 3. See the result. Please check the sample unicode in the following link. http://www.fileformat.info/info/unicode/char/1f3af/index.htm http://www.fileformat.info/info/unicode/char/1f555/index.htm http://www.fileformat.info/info/unicode/char/2600/index.htm http://www.fileformat.info/info/unicode/char/263a/index.htm Reviewers: tasn, woohyun, jpeg, raster Reviewed By: raster Subscribers: herdsman, cedric Differential Revision: https://phab.enlightenment.org/D2084 --- src/lib/evas/canvas/evas_object_text.c | 8 ++ src/lib/evas/canvas/evas_object_textblock.c | 11 +- src/lib/evas/common/evas_draw.h | 5 +- src/lib/evas/common/evas_draw_main.c | 14 +- src/lib/evas/common/evas_font_draw.c | 135 ++++++++++++++++-- src/lib/evas/common/evas_font_load.c | 9 +- src/lib/evas/common/evas_font_main.c | 37 +++-- src/lib/evas/include/evas_common_private.h | 13 +- .../evas/engines/gl_common/evas_gl_common.h | 3 + .../evas/engines/gl_common/evas_gl_image.c | 26 ++++ .../evas/engines/gl_generic/evas_engine.c | 8 +- .../engines/software_generic/evas_engine.c | 4 + 12 files changed, 242 insertions(+), 31 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_text.c b/src/lib/evas/canvas/evas_object_text.c index f59bbd8669..87c4d5a49b 100644 --- a/src/lib/evas/canvas/evas_object_text.c +++ b/src/lib/evas/canvas/evas_object_text.c @@ -1978,6 +1978,7 @@ normal_render: } EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it) { + ENFN->context_multiplier_set(output, context, 0, 0, 0, 0); /* Shadows */ if (haveshad) { @@ -2053,8 +2054,15 @@ normal_render: } /* normal text */ + ENFN->context_multiplier_unset(output, context); + ENFN->context_multiplier_set(output, context, + obj->cur->clipper->cur->cache.clip.r, + obj->cur->clipper->cur->cache.clip.g, + obj->cur->clipper->cur->cache.clip.b, + obj->cur->clipper->cur->cache.clip.a); COLOR_ONLY_SET(obj, cur->cache, clip); DRAW_TEXT(0, 0); + ENFN->context_multiplier_unset(output, context); } } diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index da4d41ba85..7b836b3548 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -11246,8 +11246,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, }; /* render object to surface with context, and offxet by x,y */ - obj->layer->evas->engine.func->context_multiplier_unset(output, - context); + ENFN->context_multiplier_unset(output, context); + ENFN->context_multiplier_set(output, context, 0, 0, 0, 0); ENFN->context_render_op_set(output, context, obj->cur->render_op); /* FIXME: This clipping is just until we fix inset handling correctly. */ ENFN->context_clip_clip(output, context, @@ -11668,6 +11668,12 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, evas_common_font_instance_underline_thickness_get(NULL); int line_position = evas_common_font_instance_underline_position_get(NULL); + ENFN->context_multiplier_unset(output, context); + ENFN->context_multiplier_set(output, context, + obj->cur->clipper->cur->cache.clip.r, + obj->cur->clipper->cur->cache.clip.g, + obj->cur->clipper->cur->cache.clip.b, + obj->cur->clipper->cur->cache.clip.a); ITEM_WALK() { Evas_Object_Textblock_Text_Item *ti; @@ -11701,6 +11707,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, line_position, line_thickness); } ITEM_WALK_END(); + ENFN->context_multiplier_unset(output, context); } static void diff --git a/src/lib/evas/common/evas_draw.h b/src/lib/evas/common/evas_draw.h index 3f01a750db..10cb26fe73 100644 --- a/src/lib/evas/common/evas_draw.h +++ b/src/lib/evas/common/evas_draw.h @@ -10,7 +10,10 @@ EAPI void evas_common_draw_context_font_ext_set (RGBA_D void *data, void *(*gl_new) (void *data, RGBA_Font_Glyph *fg), void (*gl_free) (void *ext_dat), - void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y)); + void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y), + void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace), + void (*gl_image_free) (void *image), + void (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth)); EAPI void evas_common_draw_context_clip_clip (RGBA_Draw_Context *dc, int x, int y, int w, int h); EAPI void evas_common_draw_context_set_clip (RGBA_Draw_Context *dc, int x, int y, int w, int h); EAPI void evas_common_draw_context_unset_clip (RGBA_Draw_Context *dc); diff --git a/src/lib/evas/common/evas_draw_main.c b/src/lib/evas/common/evas_draw_main.c index 27541bbab3..01ba20c679 100644 --- a/src/lib/evas/common/evas_draw_main.c +++ b/src/lib/evas/common/evas_draw_main.c @@ -108,15 +108,21 @@ evas_common_draw_context_clear_cutouts(RGBA_Draw_Context *dc) EAPI void evas_common_draw_context_font_ext_set(RGBA_Draw_Context *dc, - void *data, - void *(*gl_new) (void *data, RGBA_Font_Glyph *fg), - void (*gl_free) (void *ext_dat), - void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y)) + void *data, + void *(*gl_new) (void *data, RGBA_Font_Glyph *fg), + void (*gl_free) (void *ext_dat), + void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y), + void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace), + void (*gl_image_free) (void *image), + void (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth)) { dc->font_ext.data = data; dc->font_ext.func.gl_new = gl_new; dc->font_ext.func.gl_free = gl_free; dc->font_ext.func.gl_draw = gl_draw; + dc->font_ext.func.gl_image_new_from_data = gl_image_new_from_data; + dc->font_ext.func.gl_image_free = gl_image_free; + dc->font_ext.func.gl_image_draw = gl_image_draw; } EAPI void diff --git a/src/lib/evas/common/evas_font_draw.c b/src/lib/evas/common/evas_font_draw.c index b243667d81..367b8cd168 100644 --- a/src/lib/evas/common/evas_font_draw.c +++ b/src/lib/evas/common/evas_font_draw.c @@ -23,6 +23,72 @@ evas_common_font_draw_init(void) { } +static void * +_software_generic_image_new_from_data(int w, int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace) +{ +#ifdef EVAS_CSERVE2 + if (evas_cserve2_use_get()) + { + Evas_Cache2 *cache = evas_common_image_cache2_get(); + return evas_cache2_image_data(cache, w, h, image_data, alpha, cspace); + } +#endif + return evas_cache_image_data(evas_common_image_cache_get(), w, h, image_data, alpha, cspace); +} + +static void +_software_generic_image_free(void *image) +{ +#ifdef EVAS_CSERVE2 + if (evas_cserve2_use_get() && evas_cache2_image_cached(image)) + { + evas_cache2_image_close(image); + return; + } +#endif + evas_cache_image_drop(image); +} + +static void +_software_generic_image_draw(void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth) +{ + RGBA_Image *im; + + if (!image) return; + im = image; + +#ifdef BUILD_PIPE_RENDER + if ((eina_cpu_count() > 1)) + { +#ifdef EVAS_CSERVE2 + if (evas_cserve2_use_get()) + evas_cache2_image_load_data(&im->cache_entry); +#endif + evas_common_rgba_image_scalecache_prepare((Image_Entry *)(im), + surface, context, smooth, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + + evas_common_pipe_image_draw(im, surface, context, smooth, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + } + else +#endif + { + evas_common_rgba_image_scalecache_prepare + (&im->cache_entry, surface, context, smooth, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + evas_common_rgba_image_scalecache_do + (&im->cache_entry, surface, context, smooth, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + + evas_common_cpu_end_opt(); + } +} + /* * 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) @@ -42,29 +108,80 @@ evas_common_font_rgba_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, EINA_INARRAY_FOREACH(glyphs->array, glyph) { RGBA_Font_Glyph *fg; - int chr_x, chr_y, w; + int chr_x, chr_y, w, h; fg = glyph->fg; + w = fg->glyph_out->bitmap.width; + h = fg->glyph_out->bitmap.rows; + if ((!fg->ext_dat) && (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; } - w = fg->glyph_out->bitmap.width; + + if ((!fg->ext_dat) && FT_HAS_COLOR(fg->fi->src->ft.face)) + { + if (dc->font_ext.func.gl_image_new_from_data) + { + /* extension calls */ + fg->ext_dat = dc->font_ext.func.gl_image_new_from_data(dc->font_ext.data, + (unsigned int)w, (unsigned int)h, + (DATA32 *)fg->glyph_out->bitmap.buffer, + EINA_TRUE, + EVAS_COLORSPACE_ARGB8888); + fg->ext_dat_free = dc->font_ext.func.gl_image_free; + } + else + { + fg->ext_dat = _software_generic_image_new_from_data(w, h, + (DATA32 *)fg->glyph_out->bitmap.buffer, + EINA_TRUE, + EVAS_COLORSPACE_ARGB8888); + fg->ext_dat_free = _software_generic_image_free; + } + } + chr_x = x + glyph->x; chr_y = y + glyph->y; if (chr_x < (ext_x + ext_w)) { if ((w > 0) && ((chr_x + w) > ext_x)) { - if ((fg->ext_dat) && (dc->font_ext.func.gl_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->rle) - evas_common_font_glyph_draw(fg, dc, dst, im_w, - chr_x, y - (chr_y - y), - ext_x, ext_y, ext_w, ext_h); + if (fg->glyph_out->rle) + { + if ((fg->ext_dat) && (dc->font_ext.func.gl_draw)) + { + dc->font_ext.func.gl_draw(dc->font_ext.data, (void *)dst, + dc, fg, chr_x, y - (chr_y - y)); + } + else + { + evas_common_font_glyph_draw(fg, dc, dst, im_w, + chr_x, y - (chr_y - y), + ext_x, ext_y, ext_w, ext_h); + } + } + else if ((fg->ext_dat) && FT_HAS_COLOR(fg->fi->src->ft.face)) + { + if (dc->font_ext.func.gl_image_draw) + { + dc->font_ext.func.gl_image_draw(dc->font_ext.data, + fg->ext_dat, + 0, 0, w, h, + chr_x, y - (chr_y - y), w, h, + EINA_TRUE); + } + else + { + _software_generic_image_draw(dc, dst, + fg->ext_dat, + 0, 0, w, h, + chr_x, y - (chr_y - y), w, h, + EINA_TRUE); + } + } } } else diff --git a/src/lib/evas/common/evas_font_load.c b/src/lib/evas/common/evas_font_load.c index 92fdd243c8..041fe00029 100644 --- a/src/lib/evas/common/evas_font_load.c +++ b/src/lib/evas/common/evas_font_load.c @@ -446,6 +446,7 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi) int i, maxd = 0x7fffffff; int chosen_size = 0; int chosen_size2 = 0; + FT_Int strike_index = 0; for (i = 0; i < fi->src->ft.face->num_fixed_sizes; i++) { @@ -459,12 +460,18 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi) maxd = cd; chosen_size = s; chosen_size2 = fi->src->ft.face->available_sizes[i].y_ppem; + strike_index = (FT_Int)i; if (maxd == 0) break; } } fi->real_size = chosen_size; FTLOCK(); - error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size); + + if (FT_HAS_FIXED_SIZES(fi->src->ft.face)) + error = FT_Select_Size(fi->src->ft.face, strike_index); + else + error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size); + FTUNLOCK(); if (error) { diff --git a/src/lib/evas/common/evas_font_main.c b/src/lib/evas/common/evas_font_main.c index 97961d002c..7562d28a88 100644 --- a/src/lib/evas/common/evas_font_main.c +++ b/src/lib/evas/common/evas_font_main.c @@ -371,6 +371,12 @@ _glyph_free(RGBA_Font_Glyph *fg) if (fg->glyph_out) { + if ((!fg->glyph_out->rle) && (!fg->glyph_out->bitmap.rle_alloc)) + { + FT_BitmapGlyph fbg = (FT_BitmapGlyph)fg->glyph; + FT_Bitmap_Done(evas_ft_lib, &(fbg->bitmap)); + } + if ((fg->glyph_out->rle) && (fg->glyph_out->bitmap.rle_alloc)) free(fg->glyph_out->rle); fg->glyph_out->rle = NULL; @@ -501,8 +507,10 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx) evas_common_font_int_reload(fi); FTLOCK(); error = FT_Load_Glyph(fi->src->ft.face, idx, - FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP | - hintflags[fi->hinting]); + (FT_HAS_COLOR(fi->src->ft.face) ? + (FT_LOAD_COLOR | hintflags[fi->hinting]) : + (FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP | hintflags[fi->hinting]))); + FTUNLOCK(); if (error) { @@ -617,16 +625,25 @@ evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg) fi->usage += size; if (fi->inuse) evas_common_font_int_use_increase(size); - fg->glyph_out->rle = evas_common_font_glyph_compress - (fbg->bitmap.buffer, fbg->bitmap.num_grays, fbg->bitmap.pixel_mode, - fbg->bitmap.pitch, fbg->bitmap.width, fbg->bitmap.rows, - &(fg->glyph_out->rle_size)); + if (!FT_HAS_COLOR(fi->src->ft.face)) + { + fg->glyph_out->rle = evas_common_font_glyph_compress + (fbg->bitmap.buffer, fbg->bitmap.num_grays, fbg->bitmap.pixel_mode, + fbg->bitmap.pitch, fbg->bitmap.width, fbg->bitmap.rows, + &(fg->glyph_out->rle_size)); + fg->glyph_out->bitmap.rle_alloc = EINA_TRUE; - fg->glyph_out->bitmap.buffer = NULL; + fg->glyph_out->bitmap.buffer = NULL; - // this may be technically incorrect as we go and free a bitmap buffer - // behind the ftglyph's back... - FT_Bitmap_Done(evas_ft_lib, &(fbg->bitmap)); + // this may be technically incorrect as we go and free a bitmap buffer + // behind the ftglyph's back... + FT_Bitmap_Done(evas_ft_lib, &(fbg->bitmap)); + } + else + { + fg->glyph_out->rle = NULL; + fg->glyph_out->bitmap.rle_alloc = EINA_FALSE; + } return EINA_TRUE; } diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h index aea5de4811..da53e2ed56 100644 --- a/src/lib/evas/include/evas_common_private.h +++ b/src/lib/evas/include/evas_common_private.h @@ -194,6 +194,10 @@ extern EAPI int _evas_log_dom_global; #include FT_SIZES_H #include FT_MODULE_H +#ifndef FT_HAS_COLOR +# define FT_HAS_COLOR(face) 0 +#endif + #ifdef __GNUC__ # if __GNUC__ >= 4 // BROKEN in gcc 4 on amd64 @@ -708,9 +712,12 @@ struct _RGBA_Draw_Context Cutout_Rects cutout; struct { struct { - void *(*gl_new) (void *data, RGBA_Font_Glyph *fg); - void (*gl_free) (void *ext_dat); - void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y); + void *(*gl_new) (void *data, RGBA_Font_Glyph *fg); + void (*gl_free) (void *ext_dat); + void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y); + void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace); + void (*gl_image_free) (void *image); + void (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth); } func; void *data; } font_ext; diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 5cad385178..112eb442b3 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -827,6 +827,9 @@ void evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_ void *evas_gl_font_texture_new(void *gc, RGBA_Font_Glyph *fg); void evas_gl_font_texture_free(void *); void evas_gl_font_texture_draw(void *gc, void *surface, void *dc, RGBA_Font_Glyph *fg, int x, int y); +void *evas_gl_image_new_from_data(void *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, Evas_Colorspace cspace); +void evas_gl_image_free(void *im); +void evas_gl_image_draw(void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth); Evas_GL_Polygon *evas_gl_common_poly_point_add(Evas_GL_Polygon *poly, int x, int y); Evas_GL_Polygon *evas_gl_common_poly_points_clear(Evas_GL_Polygon *poly); diff --git a/src/modules/evas/engines/gl_common/evas_gl_image.c b/src/modules/evas/engines/gl_common/evas_gl_image.c index ec5eddb8cc..b8076a0e6d 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_image.c +++ b/src/modules/evas/engines/gl_common/evas_gl_image.c @@ -1265,3 +1265,29 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx, /* restore clip info */ gc->dc->clip.use = c; gc->dc->clip.x = cx; gc->dc->clip.y = cy; gc->dc->clip.w = cw; gc->dc->clip.h = ch; } + +void * +evas_gl_image_new_from_data(void *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, Evas_Colorspace cspace) +{ + return (void *)evas_gl_common_image_new_from_data((Evas_Engine_GL_Context *)gc, + w, h, + data, + alpha, + cspace); +} + +void +evas_gl_image_free(void *im) +{ + evas_gl_common_image_free((Evas_GL_Image *)im); +} + +void +evas_gl_image_draw(void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth) +{ + evas_gl_common_image_draw((Evas_Engine_GL_Context *)gc, + (Evas_GL_Image *)im, + sx, sy, sw, sh, + dx, dy, dw, dh, + smooth); +} diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 236a4bc255..2d0bff0e07 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -1165,10 +1165,16 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font EINA gl_context, evas_gl_font_texture_new, evas_gl_font_texture_free, - evas_gl_font_texture_draw); + evas_gl_font_texture_draw, + evas_gl_image_new_from_data, + evas_gl_image_free, + evas_gl_image_draw); evas_common_font_draw_prepare(intl_props); evas_common_font_draw(im, context, x, y, intl_props->glyphs); evas_common_draw_context_font_ext_set(context, + NULL, + NULL, + NULL, NULL, NULL, NULL, diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 3fd180e938..f053acea15 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -352,6 +352,7 @@ struct _Evas_Thread_Command_Font void *gl_draw; void *font_ext_data; DATA32 col; + DATA32 mul_col; Eina_Rectangle clip_rect, ext; int im_w, im_h; void *mask; @@ -2608,6 +2609,8 @@ _draw_thread_font_draw(void *data) dc.font_ext.func.gl_free = font->gl_free; dc.font_ext.func.gl_draw = font->gl_draw; dc.col.col = font->col; + dc.mul.col = font->mul_col; + dc.mul.use = (font->mul_col == 0xffffffff) ? 0 : 1; dc.clip.use = font->clip_use; dc.clip.x = font->clip_rect.x; dc.clip.y = font->clip_rect.y; @@ -2642,6 +2645,7 @@ _font_draw_thread_cmd(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, Evas cf->gl_draw = dc->font_ext.func.gl_draw; cf->font_ext_data = dc->font_ext.data; cf->col = dc->col.col; + cf->mul_col = dc->mul.use ? dc->mul.col : 0xffffffff; cf->clip_use = dc->clip.use; EINA_RECTANGLE_SET(&cf->clip_rect, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);