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.



SVN revision: 71605
This commit is contained in:
Rafael Antognolli 2012-05-31 21:34:21 +00:00
parent 30dcc1c83d
commit 91a1ac65c7
6 changed files with 351 additions and 4 deletions

View File

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

View File

@ -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);
@ -130,6 +149,12 @@ struct _Font_Request_Funcs {
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,
@ -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 */

View File

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

View File

@ -0,0 +1,211 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ft2build.h>
#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;
}

View File

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

View File

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