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
This commit is contained in:
Youngbok Shin 2015-03-19 19:02:02 +09:00 committed by Carsten Haitzler (Rasterman)
parent 6616d11619
commit e197f8804f
12 changed files with 242 additions and 31 deletions

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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,

View File

@ -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);