evas/cserve2: Add handling of FONT_LOAD.
authorantognolli <antognolli@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 31 May 2012 21:34:21 +0000 (21:34 +0000)
committerantognolli <antognolli@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 31 May 2012 21:34:21 +0000 (21:34 +0000)
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
src/bin/evas_cserve2.h
src/bin/evas_cserve2_cache.c
src/bin/evas_cserve2_fonts.c [new file with mode: 0644]
src/bin/evas_cserve2_main.c
src/bin/evas_cserve2_requests.c

index 32108d9..815defc 100644 (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@
 
index b1bee41..ace92b4 100644 (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);
@@ -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 */
index d0e0fe7..0cc4d87 100644 (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
diff --git a/src/bin/evas_cserve2_fonts.c b/src/bin/evas_cserve2_fonts.c
new file mode 100644 (file)
index 0000000..bc3488c
--- /dev/null
@@ -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;
+}
index 0d8f4df..582fbe0 100644 (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();
index 0f0a7e1..316530c 100644 (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 *