-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_LIBEXEC_DIR=\"$(libexecdir)\" \
+@FREETYPE_CFLAGS@ \
@EINA_CFLAGS@
evas_cserve2_SOURCES = \
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@
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);
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
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 */
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 {
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)
{
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)
{
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);
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
--- /dev/null
+#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;
+}
cserve2_requests_init();
+ cserve2_font_init();
+
cserve2_cache_init();
_clients_setup();
cserve2_cache_shutdown();
+ cserve2_font_shutdown();
+
cserve2_requests_shutdown();
_slaves_restart();
}
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;
}
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 *