From 51cb704a9b67fea352725a3a752ef3a47999bf57 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 Change-Id: Ib0a11092c83b9f212783fcbb8db3ae42e7fc2722 Origin: upstream --- 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 | 9 +- .../evas/engines/gl_common/evas_gl_common.h | 3 + src/modules/evas/engines/gl_common/evas_gl_image.c | 26 ++++ src/modules/evas/engines/gl_generic/evas_engine.c | 8 +- .../evas/engines/software_generic/evas_engine.c | 4 + 12 files changed, 238 insertions(+), 31 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_text.c b/src/lib/evas/canvas/evas_object_text.c index 83bb644..08beca4 100644 --- a/src/lib/evas/canvas/evas_object_text.c +++ b/src/lib/evas/canvas/evas_object_text.c @@ -1965,6 +1965,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) { @@ -2040,8 +2041,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 f49eb97..995ae8e 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -11125,8 +11125,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, @@ -11547,6 +11547,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; @@ -11580,6 +11586,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 3f01a75..10cb26f 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 d310fe5..ce37fef 100644 --- a/src/lib/evas/common/evas_draw_main.c +++ b/src/lib/evas/common/evas_draw_main.c @@ -98,15 +98,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 b243667..367b8cd 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 92fdd24..041fe00 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 97961d0..7562d28 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 7d56656..1807313 100644 --- a/src/lib/evas/include/evas_common_private.h +++ b/src/lib/evas/include/evas_common_private.h @@ -716,9 +716,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 9857569..a38b71e 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -804,6 +804,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 0bd990a..cea6d42 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_image.c +++ b/src/modules/evas/engines/gl_common/evas_gl_image.c @@ -1234,3 +1234,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 596565a..e7fd8bc 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -1074,13 +1074,19 @@ 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, NULL); } diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 36e91a8..4685046d 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -360,6 +360,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; @@ -2631,6 +2632,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; @@ -2665,6 +2668,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); -- 2.7.4