forked from enlightenment/efl
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:
parent
30dcc1c83d
commit
91a1ac65c7
|
@ -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@
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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 *
|
||||
|
|
Loading…
Reference in New Issue