From 92866f214cee3a537e855f21a375180b40c9b964 Mon Sep 17 00:00:00 2001 From: antognolli Date: Thu, 31 May 2012 21:34:21 +0000 Subject: [PATCH] evas/cserve2: Add handling of FONT_LOAD. It's not fully functional, some things are still pending: - Free allocated font; - answer with error message if failed. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@71605 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/bin/Makefile.am | 3 + src/bin/evas_cserve2.h | 29 ++++++ src/bin/evas_cserve2_cache.c | 95 +++++++++++++++++- src/bin/evas_cserve2_fonts.c | 211 ++++++++++++++++++++++++++++++++++++++++ src/bin/evas_cserve2_main.c | 4 + src/bin/evas_cserve2_requests.c | 13 ++- 6 files changed, 351 insertions(+), 4 deletions(-) create mode 100644 src/bin/evas_cserve2_fonts.c diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 32108d9..815defc 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -55,6 +55,7 @@ AM_CPPFLAGS = \ -DPACKAGE_BIN_DIR=\"$(bindir)\" \ -DPACKAGE_LIB_DIR=\"$(libdir)\" \ -DPACKAGE_LIBEXEC_DIR=\"$(libexecdir)\" \ +@FREETYPE_CFLAGS@ \ @EINA_CFLAGS@ evas_cserve2_SOURCES = \ @@ -66,9 +67,11 @@ evas_cserve2_messages.c \ evas_cserve2_shm.c \ evas_cserve2_cache.c \ evas_cserve2_requests.c \ +evas_cserve2_fonts.c \ evas_cserve2_main_loop_linux.c evas_cserve2_LDADD = \ +@FREETYPE_LIBS@ \ @EINA_LIBS@ \ @EFL_SHM_OPEN_LIBS@ diff --git a/src/bin/evas_cserve2.h b/src/bin/evas_cserve2.h index b1bee41..ace92b4 100644 --- a/src/bin/evas_cserve2.h +++ b/src/bin/evas_cserve2.h @@ -115,6 +115,25 @@ typedef struct _Slave_Msg_Image_Opened Slave_Msg_Image_Opened; typedef struct _Slave_Msg_Image_Load Slave_Msg_Image_Load; typedef struct _Slave_Msg_Image_Loaded Slave_Msg_Image_Loaded; +struct _Slave_Msg_Font_Load { + void *ftdata1; // Freetype file source info comes here + void *ftdata2; // Freetype font info comes here + unsigned int rend_flags; + unsigned int hint; + unsigned int size; + unsigned int dpi; + const char *name; + const char *file; +}; + +struct _Slave_Msg_Font_Loaded { + void *ftdata1; + void *ftdata2; +}; + +typedef struct _Slave_Msg_Font_Load Slave_Msg_Font_Load; +typedef struct _Slave_Msg_Font_Loaded Slave_Msg_Font_Loaded; + typedef void *(*Font_Request_Msg_Create)(void *data, int *size); typedef void (*Font_Request_Msg_Free)(void *data); typedef void (*Font_Request_Response)(Client *c, void *data, void *resp, unsigned int rid); @@ -131,6 +150,12 @@ typedef struct _Font_Request Font_Request; typedef struct _Font_Request_Funcs Font_Request_Funcs; typedef enum { + FONT_REND_REGULAR = 1, + FONT_REND_SLANT = 1 << 1, + FONT_REND_WEIGHT = 1 << 2 +} Font_Rend_Flags; + +typedef enum { CSERVE2_REQ_FONT_LOAD = 0, CSERVE2_REQ_FONT_GLYPHS_LOAD, CSERVE2_REQ_LAST @@ -212,4 +237,8 @@ void cserve2_requests_shutdown(void); void cserve2_cache_requests_process(void); void cserve2_cache_requests_response(Slave_Command type, void *msg, void *data); +void cserve2_font_init(void); +void cserve2_font_shutdown(void); +void *cserve2_font_slave_cb(Slave_Thread_Data *sd, Slave_Command cmd, const void *cmddata, void *data); + #endif /* _EVAS_CSERVE2_H */ diff --git a/src/bin/evas_cserve2_cache.c b/src/bin/evas_cserve2_cache.c index d0e0fe7..0cc4d87 100644 --- a/src/bin/evas_cserve2_cache.c +++ b/src/bin/evas_cserve2_cache.c @@ -88,15 +88,18 @@ struct _Font_Source { const char *name; const char *file; int references; + void *ft; }; struct _Font_Entry { - Entry *base; + Entry base; + Font_Request *request; unsigned int rend_flags; unsigned int hint; unsigned int size; unsigned int dpi; Font_Source *src; + void *ft; }; struct _Font_Cache { @@ -1068,6 +1071,16 @@ _file_changed_cb(const char *path __UNUSED__, Eina_Bool deleted __UNUSED__, void eina_hash_del_by_key(file_watch, fw->path); } +static Font_Source * +_cserve2_font_source_find(const char *name) +{ + Font_Source *fs; + + fs = eina_hash_find(font_sources, name); + + return fs; +} + static Font_Entry * _cserve2_font_entry_find(const char *name, unsigned int namelen, unsigned int size, unsigned int rend_flags, unsigned int hint, unsigned int dpi) { @@ -1088,6 +1101,59 @@ _cserve2_font_entry_find(const char *name, unsigned int namelen, unsigned int si return fe; } +static void * +_font_load_request_build(void *data, int *size) +{ + Font_Entry *fe = data; + Slave_Msg_Font_Load *msg = calloc(1, sizeof(*msg)); + + msg->ftdata1 = fe->src->ft; + msg->ftdata2 = fe->ft; + msg->rend_flags = fe->rend_flags; + msg->hint = fe->hint; + msg->size = fe->size; + msg->dpi = fe->dpi; + msg->name = fe->src->name; + msg->file = fe->src->file; + + *size = 0; + + return msg; +} + +static void +_font_load_request_free(void *data) +{ + free(data); +} + +static void +_font_load_request_response(Client *client, void *data, void *resp, unsigned int rid) +{ + Slave_Msg_Font_Loaded *msg = resp; + Font_Entry *fe = data; + + if (!fe->src->ft) + fe->src->ft = msg->ftdata1; + + if (!fe->ft) + fe->ft = msg->ftdata2; + + if (fe->request) fe->request = NULL; +} + +static void +_font_load_request_failed(Client *client, void *data, Error_Type error, unsigned int rid) +{ +} + +static Font_Request_Funcs _font_load_funcs = { + .msg_create = (Font_Request_Msg_Create)_font_load_request_build, + .msg_free = (Font_Request_Msg_Free)_font_load_request_free, + .response = (Font_Request_Response)_font_load_request_response, + .error = (Font_Request_Error)_font_load_request_failed +}; + int cserve2_cache_file_open(Client *client, unsigned int client_file_id, const char *path, const char *key, unsigned int rid) { @@ -1382,6 +1448,7 @@ int cserve2_cache_font_load(Client *client, const char *name, unsigned int namelen, unsigned int rend_flags, unsigned int hint, unsigned int size, unsigned int dpi, unsigned int rid) { Reference *ref; + Font_Source *fs; Font_Entry *fe = _cserve2_font_entry_find(name, namelen, size, rend_flags, hint, dpi); @@ -1398,7 +1465,31 @@ cserve2_cache_font_load(Client *client, const char *name, unsigned int namelen, return 0; } - return -1; + fe = calloc(1, sizeof(*fe)); + fe->rend_flags = rend_flags; + fe->hint = hint; + fe->size = size; + fe->dpi = dpi; + fe->base.type = CSERVE2_FONT_ENTRY; + + fs = _cserve2_font_source_find(name); + if (!fs) + { + fs = calloc(1, sizeof(*fs)); + fs->name = eina_stringshare_add_length(name, namelen); + fs->file = eina_stringshare_ref(fs->name); + eina_hash_direct_add(font_sources, fs->name, fs); + } + + + fe->src = fs; + fs->references++; + fe->request = cserve2_request_add(CSERVE2_REQ_FONT_LOAD, rid, + client, &_font_load_funcs, fe); + + eina_hash_direct_add(font_entries, fe, fe); + + return 0; } void diff --git a/src/bin/evas_cserve2_fonts.c b/src/bin/evas_cserve2_fonts.c new file mode 100644 index 0000000..bc3488c --- /dev/null +++ b/src/bin/evas_cserve2_fonts.c @@ -0,0 +1,211 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_SIZES_H +#include FT_MODULE_H + +#include "evas_cserve2.h" + +static FT_Library cserve2_ft_lib = 0; +static int initialised = 0; + +struct _Font_Info +{ + FT_Size size; + int real_size; + int max_h; + unsigned int runtime_rend; +}; + +struct _Font_Source_Info +{ + FT_Face face; + int orig_upem; + int current_size; +}; + +typedef struct _Font_Info Font_Info; +typedef struct _Font_Source_Info Font_Source_Info; + +static Font_Source_Info * +_font_slave_source_load(const char *file) +{ + int error; + Font_Source_Info *fsi = malloc(sizeof(*fsi)); + + error = FT_New_Face(cserve2_ft_lib, file, 0, &(fsi->face)); + if (error) + { + free(fsi); + return NULL; + } + + error = FT_Select_Charmap(fsi->face, ft_encoding_unicode); + if (error) + { + FT_Done_Face(fsi->face); + free(fsi); + return NULL; + } + + fsi->orig_upem = fsi->face->units_per_EM; + fsi->current_size = 0; + + return fsi; +} + +static Font_Info * +_font_slave_int_load(const Slave_Msg_Font_Load *msg, Font_Source_Info *fsi) +{ + int error; + int val, dv; + int ret; + Font_Info *fi = calloc(1, sizeof(*fi)); + + error = FT_New_Size(fsi->face, &(fi->size)); + if (!error) + FT_Activate_Size(fi->size); + + fi->real_size = msg->size * 64; + error = FT_Set_Char_Size(fsi->face, 0, fi->real_size, msg->dpi, msg->dpi); + if (error) + { + fi->real_size = msg->size; + error = FT_Set_Pixel_Sizes(fsi->face, 0, fi->real_size); + } + + if (error) + { + int i; + int chosen_size = 0; + int chosen_width = 0; + + for (i = 0; i < fsi->face->num_fixed_sizes; i++) + { + int s; + int d, cd; + + s = fsi->face->available_sizes[i].height; + cd = chosen_size - msg->size; + if (cd < 0) cd = -cd; + d = s - msg->size; + if (d < 0) d = -d; + if (d < cd) + { + chosen_width = fsi->face->available_sizes[i].width; + chosen_size = s; + } + if (d == 0) break; + } + fi->real_size = chosen_size; + error = FT_Set_Pixel_Sizes(fsi->face, chosen_width, fi->real_size); + + if (error) + ERR("Could not choose the font size."); + } + + fi->max_h = 0; + val = (int)fsi->face->bbox.yMax; + if (fsi->face->units_per_EM != 0) + { + dv = (fsi->orig_upem * 2048) / fsi->face->units_per_EM; + ret = (val * fsi->face->size->metrics.y_scale) / (dv * dv); + } + else ret = val; + fi->max_h += ret; + val = -(int)fsi->face->bbox.yMin; + if (fsi->face->units_per_EM != 0) + { + dv = (fsi->orig_upem * 2048) / fsi->face->units_per_EM; + ret = (val * fsi->face->size->metrics.y_scale) / (dv * dv); + } + else ret = val; + fi->max_h += ret; + + fi->runtime_rend = FONT_REND_REGULAR; + if ((msg->rend_flags & FONT_REND_SLANT) && + !(fsi->face->style_flags & FT_STYLE_FLAG_ITALIC)) + fi->runtime_rend |= FONT_REND_SLANT; + if ((msg->rend_flags & FONT_REND_WEIGHT) && + !(fsi->face->style_flags & FT_STYLE_FLAG_BOLD)) + fi->runtime_rend |= FONT_REND_WEIGHT; + + return fi; +} + +static Slave_Msg_Font_Loaded * +_font_slave_load(const void *cmddata, void *data __UNUSED__) +{ + const Slave_Msg_Font_Load *msg = cmddata; + Slave_Msg_Font_Loaded *response; + Font_Source_Info *fsi; + Font_Info *fi; + + fsi = msg->ftdata1; + + /* Loading Font Source */ + if (!fsi) + fsi = _font_slave_source_load(msg->file); + + // FIXME: Return correct error message + if (!fsi) + return NULL; + + fi = _font_slave_int_load(msg, fsi); + + response = calloc(1, sizeof(*response)); + response->ftdata1 = fsi; + response->ftdata2 = fi; + + return response; +} + +void * +cserve2_font_slave_cb(Slave_Thread_Data *sd __UNUSED__, Slave_Command cmd, const void *cmddata, void *data) +{ + void *response = NULL; + + switch (cmd) + { + case FONT_LOAD: + _font_slave_load(cmddata, data); + break; + case FONT_GLYPHS_LOAD: + // command for FONT_GLYPHS_LOAD + break; + default: + ERR("Invalid command for font slave: %d", cmd); + } + + return response; +} + +void +cserve2_font_init(void) +{ + int error; + + if (initialised++ > 0) return; + + error = FT_Init_FreeType(&cserve2_ft_lib); + if (error) return; +} + +void +cserve2_font_shutdown(void) +{ + initialised--; + if (initialised > 0) return; + if (initialised < 0) + { + ERR("Invalid shutdown of cserve2 font."); + return; + } + + FT_Done_FreeType(cserve2_ft_lib); + cserve2_ft_lib = 0; +} diff --git a/src/bin/evas_cserve2_main.c b/src/bin/evas_cserve2_main.c index 0d8f4df..582fbe0 100644 --- a/src/bin/evas_cserve2_main.c +++ b/src/bin/evas_cserve2_main.c @@ -483,6 +483,8 @@ main(int argc __UNUSED__, const char *argv[] __UNUSED__) cserve2_requests_init(); + cserve2_font_init(); + cserve2_cache_init(); _clients_setup(); @@ -495,6 +497,8 @@ main(int argc __UNUSED__, const char *argv[] __UNUSED__) cserve2_cache_shutdown(); + cserve2_font_shutdown(); + cserve2_requests_shutdown(); _slaves_restart(); diff --git a/src/bin/evas_cserve2_requests.c b/src/bin/evas_cserve2_requests.c index 0f0a7e1..316530c 100644 --- a/src/bin/evas_cserve2_requests.c +++ b/src/bin/evas_cserve2_requests.c @@ -219,6 +219,9 @@ _slave_read_cb(Slave *s __UNUSED__, Slave_Command cmd __UNUSED__, void *msg, voi } req->funcs->msg_free(req->msg); + // FIXME: We shouldn't free this message directly, it must be freed by a + // callback. + free(msg); free(req); sw->data = NULL; @@ -258,9 +261,15 @@ _create_image_slave(void *data) } static Slave * -_create_font_slave(void *data __UNUSED__) +_create_font_slave(void *data) { - return NULL; + Slave *slave; + + slave = cserve2_slave_thread_run(cserve2_font_slave_cb, NULL, + _slave_read_cb, _slave_dead_cb, + data); + + return slave; } static Slave_Worker * -- 2.7.4