evas/cserve2: Store Glyph_Data in shared mempools
authorJean-Philippe Andre <jp.andre@samsung.com>
Mon, 19 Aug 2013 03:22:19 +0000 (12:22 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Mon, 28 Oct 2013 06:47:14 +0000 (15:47 +0900)
- Create one Glyph_Data array per Font_Entry
- Copy Font_Source descriptors in shared array
- Copy font entries in shared index
- Send font index path over socket
- Merge Font_Source and Font_Data in shared memory
- Send font index path on client connect
- Repack font index after free
- Pass font shm name to clients

src/bin/evas/evas_cserve2.h
src/bin/evas/evas_cserve2_cache.c
src/bin/evas/evas_cserve2_fonts.c
src/bin/evas/evas_cserve2_index.c
src/bin/evas/evas_cserve2_main.c
src/lib/evas/cserve2/evas_cs2.h
src/lib/evas/cserve2/evas_cs2_client.c

index 02ee966..88f4370 100644 (file)
@@ -62,6 +62,8 @@ extern Eina_Prefix *_evas_cserve2_pfx;
 typedef struct _Slave Slave;
 typedef struct _Slave_Thread_Data Slave_Thread_Data;
 typedef struct _Shm_Handle Shm_Handle;
+typedef struct _Shared_Array Shared_Array;
+typedef struct _Shared_Mempool Shared_Mempool;
 
 typedef enum {
    FD_READ = 1,
@@ -172,14 +174,13 @@ struct _Slave_Msg_Font_Glyphs_Load {
       unsigned int *glyphs;
    } glyphs;
    struct {
-      Shm_Handle *shm;
-      unsigned int usage;
-      unsigned int nglyphs;
+      Shared_Mempool *mempool;
    } cache;
 };
 
 struct _Slave_Msg_Glyph {
    unsigned int index;
+   unsigned int buffer_id;
    unsigned int offset;
    unsigned int size;
    unsigned int rows;
@@ -191,21 +192,13 @@ struct _Slave_Msg_Glyph {
 
 typedef struct _Slave_Msg_Glyph Slave_Msg_Glyph;
 
-struct _Slave_Msg_Font_Cache {
-   unsigned int nglyphs;
-   Slave_Msg_Glyph *glyphs;
-   Shm_Handle *shm;
-   unsigned int usage;
-};
-
-typedef struct _Slave_Msg_Font_Cache Slave_Msg_Font_Cache;
-
 struct _Slave_Msg_Font_Glyphs_Loaded {
-   unsigned int ncaches;
+   Shared_Mempool *mempool;
    unsigned int gl_load_time;
    unsigned int gl_render_time;
    unsigned int gl_slave_time;
-   Slave_Msg_Font_Cache **caches;
+   Slave_Msg_Glyph *glyphs;
+   unsigned int nglyphs;
 };
 
 typedef struct _Slave_Msg_Font_Load Slave_Msg_Font_Load;
@@ -349,8 +342,6 @@ void cserve2_font_ft_free(void *fontinfo);
 void cserve2_shared_index_init(void);
 void cserve2_shared_index_shutdown(void);
 
-typedef struct _Shared_Array Shared_Array;
-typedef struct _Shared_Mempool Shared_Mempool;
 typedef Eina_Bool (* Shared_Array_Repack_Skip_Cb) (Shared_Array *sa,
                                                    const void *elem,
                                                    void *user_data);
@@ -382,7 +373,9 @@ int cserve2_shared_mempool_buffer_new(Shared_Mempool *sm, int size);
 int cserve2_shared_mempool_buffer_ref(Shared_Mempool *sm, int bufferid);
 void cserve2_shared_mempool_buffer_del(Shared_Mempool *sm, int bufferid);
 void *cserve2_shared_mempool_buffer_get(Shared_Mempool *sm, int bufferid);
-
+int cserve2_shared_mempool_buffer_offset_get(Shared_Mempool *sm, int bufferid);
+size_t cserve2_shared_mempool_size_get(Shared_Mempool *sm);
+const char *cserve2_shared_mempool_name_get(Shared_Mempool *sm);
 
 // Shared strings
 const char *cserve2_shared_strings_table_name_get();
index efe90be..7c7932e 100644 (file)
@@ -26,7 +26,6 @@ typedef struct _File_Watch File_Watch;
 
 typedef struct _Font_Source Font_Source;
 typedef struct _Font_Entry Font_Entry;
-typedef struct _Font_Cache Font_Cache;
 
 typedef enum {
    CSERVE2_IMAGE_FILE,
@@ -62,22 +61,23 @@ struct _Font_Source {
    string_t key;
    string_t name;
    string_t file;
-   int references;
-   void *ft;
+   int refcount;
+   void *ft; // Font_Source_Info
 };
 
 struct _Font_Entry {
-   Entry base;
+   ENTRY;
    unsigned int rend_flags;
    unsigned int size;
    unsigned int dpi;
+   unsigned int font_data_id;
    Font_Source *src;
-   void *ft;
-   Fash_Glyph2 *glyphs;
+   void *ft; // Font_Info
+   Fash_Glyph2 *glyph_entries; // Fast access to the Glyph_Entry objects
+   Shared_Array *glyph_datas; // Contains the Glyph_Data objects
    unsigned int nglyphs;
-   Eina_List *caches;
-   Font_Cache *last_cache;
    Eina_Bool unused : 1;
+   Shared_Mempool *mempool; // Contains the rendered glyphs
 #ifdef DEBUG_LOAD_TIME
    struct timeval rstart; // start of the glyphs load request
    struct timeval rfinish; // finish of the glyphs load request
@@ -89,19 +89,9 @@ struct _Font_Entry {
 #endif
 };
 
-struct _Font_Cache {
-   Font_Entry *fe;
-   Shm_Handle *shm;
-   unsigned int usage;
-   int inuse;
-   Shared_Array *glyphs; // Contains gldata_id only
-   unsigned int nglyphs;
-};
-
 struct _Glyph_Entry {
    unsigned int gldata_id;
    Font_Entry *fe;
-   Font_Cache *fc;
 };
 
 struct _Glyphs_Request {
@@ -119,13 +109,6 @@ struct _Glyphs_Request {
 
 typedef struct _Glyphs_Request Glyphs_Request;
 
-struct _Glyphs_Group {
-   Font_Cache *fc;
-   Eina_List *glyphs;
-};
-
-typedef struct _Glyphs_Group Glyphs_Group;
-
 struct _Reference {
    Client *client;
    Entry *entry;
@@ -140,12 +123,15 @@ struct _File_Watch {
 
 static unsigned int _entry_id = 0;
 static unsigned int _glyph_id = 0;
+static unsigned int _font_data_id = 0;
 static unsigned int _freed_file_entry_count = 0;
 static unsigned int _freed_image_entry_count = 0;
+static unsigned int _freed_font_entry_count = 0;
+static Eina_Bool _shutdown = EINA_FALSE;
 
 static Shared_Array *_file_data_array = NULL;
 static Shared_Array *_image_data_array = NULL;
-static Shared_Array *_glyph_data_array = NULL;
+static Shared_Array *_font_data_array = NULL;
 
 static Eina_Hash *file_ids = NULL; // maps path + key --> file_id
 static Eina_Hash *file_entries = NULL; // maps file_id --> entry
@@ -296,12 +282,28 @@ _image_entry_find(unsigned int entry_id)
    return (Image_Entry *) e;
 }
 
+static Font_Data *
+_font_data_find(unsigned int fs_id)
+{
+   Font_Data *fdata;
+
+   fdata = cserve2_shared_array_item_data_find(_font_data_array,
+                                               &fs_id, _shm_object_id_cmp_cb);
+   if (!fdata)
+     {
+        ERR("Could not find font data %u", fs_id);
+        return NULL;
+     }
+
+   return fdata;
+}
+
 static Glyph_Data *
-_glyph_data_find(unsigned int glyph_id)
+_glyph_data_find(Shared_Array *sa, unsigned int glyph_id)
 {
    Glyph_Data *gldata;
 
-   gldata = cserve2_shared_array_item_data_find(_glyph_data_array, &glyph_id,
+   gldata = cserve2_shared_array_item_data_find(sa, &glyph_id,
                                                 _shm_object_id_cmp_cb);
    if (!gldata)
      {
@@ -327,6 +329,9 @@ _repack()
    int count;
    Eina_Bool updated = EINA_FALSE;
 
+   if (_shutdown)
+     return;
+
    // Repack when we have 10% fragmentation over the whole shm buffer
 
    count = cserve2_shared_array_size_get(_file_data_array);
@@ -341,7 +346,7 @@ _repack()
                                          _shm_object_id_cmp_cb, NULL);
         if (!sa)
           {
-             ERR("Failed to repack array. Keeping previous references!");
+             ERR("Failed to repack files array. Keeping previous references!");
              goto skip_files;
           }
 
@@ -364,7 +369,7 @@ skip_files:
                                          _shm_object_id_cmp_cb, NULL);
         if (!sa)
           {
-             ERR("Failed to repack array. Keeping previous references!");
+             ERR("Failed to repack images array. Keeping previous references!");
              goto skip_images;
           }
 
@@ -375,12 +380,35 @@ skip_files:
      }
 skip_images:
 
+   count = cserve2_shared_array_size_get(_font_data_array);
+   if ((count > 0) && (_freed_font_entry_count > 100 ||
+                       ((_freed_font_entry_count * 100) / count >= 10)))
+     {
+        DBG("Repacking font data array: %s",
+            cserve2_shared_array_name_get(_font_data_array));
+
+        sa = cserve2_shared_array_repack(_font_data_array,
+                                         _repack_skip_cb,
+                                         _shm_object_id_cmp_cb, NULL);
+        if (!sa)
+          {
+             ERR("Failed to repack fonts array. Keeping previous references!");
+             goto skip_fonts;
+          }
+
+        cserve2_shared_array_del(_font_data_array);
+        _freed_font_entry_count = 0;
+        _font_data_array = sa;
+        updated = EINA_TRUE;
+     }
+skip_fonts:
+
    if (updated)
      cserve2_index_list_send(cserve2_shared_strings_index_name_get(),
                              cserve2_shared_strings_table_name_get(),
                              cserve2_shared_array_name_get(_file_data_array),
                              cserve2_shared_array_name_get(_image_data_array),
-                             NULL,
+                             cserve2_shared_array_name_get(_font_data_array),
                              NULL);
 }
 
@@ -1055,15 +1083,32 @@ _font_entry_key_hash(const Font_Entry *key, int key_length EINA_UNUSED)
 static void
 _font_entry_free(Font_Entry *fe)
 {
-   fash_gl_free(fe->glyphs);
-   fe->src->references--;
-   if (fe->ft) cserve2_font_ft_free(fe->ft);
-   if (fe->src->references <= 0)
+   Font_Data *fd;
+
+   if (!fe) return;
+
+   fd = _font_data_find(fe->font_data_id);
+   if (fd)
+     {
+        fd->refcount = 0;
+        cserve2_shared_string_del(fd->glyph_index_shm);
+        cserve2_shared_string_del(fd->file);
+        cserve2_shared_string_del(fd->name);
+     }
+
+   fash_gl_free(fe->glyph_entries);
+   cserve2_shared_array_del(fe->glyph_datas);
+   cserve2_font_ft_free(fe->ft);
+   fe->src->refcount--;
+   if (fe->src->refcount <= 0)
      {
         const char *key = cserve2_shared_string_get(fe->src->key);
         eina_hash_del_by_key(font_sources, key);
      }
    free(fe);
+
+   _freed_font_entry_count++;
+   _repack();
 }
 
 static void
@@ -1072,24 +1117,31 @@ _glyph_free_cb(void *data)
    Glyph_Entry *gl = data;
    Glyph_Data *gldata;
 
-   if (!gl) return;
-   gldata = _glyph_data_find(gl->gldata_id);
-   cserve2_shared_string_del(gldata->shm_id);
-   gldata->refcount--;
+   if (!gl || !gl->fe) return;
+
+   gldata = _glyph_data_find(gl->fe->glyph_datas, gl->gldata_id);
+   if (gldata)
+     {
+        cserve2_shared_string_del(gldata->shm_id);
+        gldata->refcount--;
+     }
    free(gl);
 }
 
 static void
 _font_source_free(Font_Source *fs)
 {
+   if (!fs) return;
+
    cserve2_shared_string_del(fs->key);
    cserve2_shared_string_del(fs->name);
    cserve2_shared_string_del(fs->file);
-   if (fs->ft) cserve2_font_source_ft_free(fs->ft);
+   cserve2_font_source_ft_free(fs->ft);
 
    free(fs);
 }
 
+#if 0
 static void
 _font_shm_promote(Font_Cache *fc)
 {
@@ -1161,6 +1213,7 @@ _font_shm_lru_flush(void)
         l_next = eina_list_next(l);
      }
 }
+#endif
 
 void
 cserve2_cache_init(void)
@@ -1180,16 +1233,13 @@ cserve2_cache_init(void)
 
    _file_data_array = cserve2_shared_array_new(1, sizeof(File_Data), 0);
    _image_data_array = cserve2_shared_array_new(1, sizeof(Image_Data), 0);
-   _glyph_data_array = cserve2_shared_array_new(1, sizeof(Glyph_Data), 0);
+   _font_data_array = cserve2_shared_array_new(1, sizeof(Font_Data), 0);
 }
 
 void
 cserve2_cache_shutdown(void)
 {
-   Font_Cache *fc;
-
-   EINA_LIST_FREE(font_shm_lru, fc)
-     _font_shm_free(fc);
+   _shutdown = EINA_TRUE;
 
    eina_hash_free(image_entries);
    eina_hash_free(image_ids);
@@ -1202,7 +1252,7 @@ cserve2_cache_shutdown(void)
 
    cserve2_shared_array_del(_file_data_array);
    cserve2_shared_array_del(_image_data_array);
-   cserve2_shared_array_del(_glyph_data_array);
+   cserve2_shared_array_del(_font_data_array);
 }
 
 static Reference *
@@ -1304,7 +1354,7 @@ _entry_reference_del(Entry *entry, Reference *ref)
      {
         Font_Entry *fe = (Font_Entry *)entry;
         fe->unused = EINA_TRUE;
-        if (!fe->caches)
+        if (!fe->mempool)
           eina_hash_del_by_key(font_entries, fe);
      }
    else
@@ -1372,7 +1422,7 @@ cserve2_cache_client_new(Client *client)
                            cserve2_shared_strings_table_name_get(),
                            cserve2_shared_array_name_get(_file_data_array),
                            cserve2_shared_array_name_get(_image_data_array),
-                           NULL,
+                           cserve2_shared_array_name_get(_font_data_array),
                            client);
 }
 
@@ -1647,7 +1697,7 @@ _glyphs_request_check(Glyphs_Request *req, Eina_Bool report_load)
    for (i = req->current; i < req->nglyphs; i++)
      {
         Glyph_Entry *ge;
-        ge = fash_gl_find(fe->glyphs, req->glyphs[i]);
+        ge = fash_gl_find(fe->glyph_entries, req->glyphs[i]);
         if (ge)
           {
              req->answer[req->nanswer++] = ge;
@@ -1657,7 +1707,7 @@ _glyphs_request_check(Glyphs_Request *req, Eina_Bool report_load)
                fe->gl_saved_time +=
                   (fe->gl_load_time / fe->nglyphs);
 #endif
-             ge->fc->inuse++;
+             //ge->fc->inuse++;
           }
         else
           break;
@@ -1669,6 +1719,7 @@ _glyphs_request_check(Glyphs_Request *req, Eina_Bool report_load)
    return (req->nanswer == req->nglyphs);
 }
 
+#if 0
 /* organize answer (cache1{gl1, gl2,}, cache2{gl3,gl4,gl5}, cache3{gl6})
  */
 static Eina_List *
@@ -1676,8 +1727,18 @@ _glyphs_group_create(Glyphs_Request *req)
 {
    Eina_List *groups = NULL;
    unsigned int i;
+   Glyphs_Group *gg;
+
+   gg = calloc(1, sizeof(*gg));
+   groups = eina_list_append(groups, gg);
 
    for (i = 0; i < req->nanswer; i++)
+     gg->glyphs = eina_list_append(gg->glyphs, req->answer[i]);
+
+   return groups;
+
+   /*
+   for (i = 0; i < req->nanswer; i++)
      {
         Eina_List *l;
         Glyphs_Group *iter, *gg = NULL;
@@ -1702,6 +1763,7 @@ _glyphs_group_create(Glyphs_Request *req)
      }
 
    return groups;
+   */
 }
 
 static Msg_Font_Glyphs_Loaded *
@@ -1799,6 +1861,76 @@ _glyphs_loaded_msg_create(Glyphs_Request *req, int *resp_size)
 
    return (Msg_Font_Glyphs_Loaded *)resp;
 }
+#endif
+
+static Msg_Font_Glyphs_Loaded *
+_glyphs_loaded_msg_create(Glyphs_Request *req, int *resp_size)
+{
+   Msg_Font_Glyphs_Loaded *msg;
+   unsigned int size;
+   const char *shmname;
+   unsigned int shmname_size;
+   unsigned int k;
+   char *response, *buf;
+
+   shmname = cserve2_shared_mempool_name_get(req->fe->mempool);
+   shmname_size = strlen(shmname) + 1;
+
+   size = sizeof(Msg_Font_Glyphs_Loaded);
+   size += sizeof(int) * 2;
+   size += shmname_size;
+   size += req->nanswer * 9 * sizeof(int);
+
+   response = malloc(size);
+   if (!response) return NULL;
+   msg = (Msg_Font_Glyphs_Loaded *) response;
+   buf = response + sizeof(Msg_Font_Glyphs_Loaded);
+
+   msg->base.type = CSERVE2_FONT_GLYPHS_LOADED;
+   memcpy(buf, &shmname_size, sizeof(int));
+   buf += sizeof(int);
+   memcpy(buf, shmname, shmname_size);
+   buf += shmname_size;
+   memcpy(buf, &req->nanswer, sizeof(int));
+   buf += sizeof(int);
+
+   for (k = 0; k < req->nanswer; k++)
+     {
+        Glyph_Entry *ge;
+        Glyph_Data *gldata;
+
+        ge = req->answer[k];
+        gldata = _glyph_data_find(ge->fe->glyph_datas, ge->gldata_id);
+        if (!gldata)
+          {
+             ERR("Glyph data not found for %d", ge->gldata_id);
+             continue;
+          }
+
+        memcpy(buf, &gldata->index, sizeof(int));
+        buf += sizeof(int);
+        memcpy(buf, &gldata->shm_id, sizeof(string_t));
+        buf += sizeof(string_t);
+        memcpy(buf, &gldata->offset, sizeof(int));
+        buf += sizeof(int);
+        memcpy(buf, &gldata->size, sizeof(int));
+        buf += sizeof(int);
+        memcpy(buf, &gldata->rows, sizeof(int));
+        buf += sizeof(int);
+        memcpy(buf, &gldata->width, sizeof(int));
+        buf += sizeof(int);
+        memcpy(buf, &gldata->pitch, sizeof(int));
+        buf += sizeof(int);
+        memcpy(buf, &gldata->num_grays, sizeof(int));
+        buf += sizeof(int);
+        memcpy(buf, &gldata->pixel_mode, sizeof(int));
+        buf += sizeof(int);
+     }
+
+   *resp_size = size;
+   return msg;
+}
+
 
 static void
 _glyphs_loaded_send(Glyphs_Request *req, unsigned int rid)
@@ -1846,7 +1978,10 @@ _file_path_join(const char *path, const char *end)
 }
 
 static Glyphs_Request *
-_glyphs_request_create(Client *client, const char *source, const char *name, unsigned int hint, unsigned int rend_flags, unsigned int size, unsigned int dpi, unsigned int *glyphs, unsigned int nglyphs)
+_glyphs_request_create(Client *client, const char *source, const char *name,
+                       unsigned int hint, unsigned int rend_flags,
+                       unsigned int size, unsigned int dpi,
+                       unsigned int *glyphs, unsigned int nglyphs)
 {
    char *fullname;
    Glyphs_Request *req = calloc(1, sizeof(*req));
@@ -1909,7 +2044,7 @@ _glyphs_load_request_prepare(Glyphs_Request *req)
    for (i = req->current; i < req->nglyphs; i++)
      {
         Glyph_Entry *ge;
-        ge = fash_gl_find(fe->glyphs, req->glyphs[i]);
+        ge = fash_gl_find(fe->glyph_entries, req->glyphs[i]);
         if (ge)
           {
              req->answer[req->nanswer++] = ge;
@@ -1919,7 +2054,7 @@ _glyphs_load_request_prepare(Glyphs_Request *req)
              fe->gl_saved_time +=
                 (fe->gl_load_time / fe->nglyphs);
 #endif
-             ge->fc->inuse++;
+             //ge->fc->inuse++;
           }
         else
           req->render[req->nrender++] = req->glyphs[i];
@@ -1932,7 +2067,6 @@ _glyphs_load_request_build(void *data, int *size EINA_UNUSED)
    Glyphs_Request *req = data;
    Slave_Msg_Font_Glyphs_Load *msg = NULL;
    Font_Entry *fe = req->fe;
-   Font_Cache *fc;
 
 #ifdef DEBUG_LOAD_TIME
    gettimeofday(&fe->rstart, NULL);
@@ -1947,15 +2081,7 @@ _glyphs_load_request_build(void *data, int *size EINA_UNUSED)
    msg->font.rend_flags = fe->rend_flags;
    msg->glyphs.nglyphs = req->nrender;
    msg->glyphs.glyphs = req->render;
-
-   // Trying to reuse last filled cache.
-   fc = fe->last_cache;
-   if (fc)
-     {
-        msg->cache.shm = fc->shm;
-        msg->cache.usage = fc->usage;
-        msg->cache.nglyphs = fc->nglyphs;
-     }
+   msg->cache.mempool = fe->mempool;
 
    return msg;
 }
@@ -1972,81 +2098,67 @@ _glyphs_load_request_response(Glyphs_Request *req,
                               Slave_Msg_Font_Glyphs_Loaded *msg, int *size)
 {
    Font_Entry *fe = req->fe;
-   Font_Cache *fc = NULL;
-   unsigned int i;
+   Shared_Mempool *mempool = msg->mempool;
+   unsigned int j;
+   string_t shm_id = 0;
 
-   if (fe->last_cache && fe->last_cache->shm == msg->caches[0]->shm)
-     fc = fe->last_cache;
+   if (!msg->nglyphs)
+     return _glyphs_loaded_msg_create(req, size);
 
-   for (i = 0; i < msg->ncaches; i++)
+   if (!mempool)
+     mempool = cserve2_shared_mempool_new(0);
+
+   if (!fe->glyph_datas)
+     fe->glyph_datas = cserve2_shared_array_new(1, sizeof(Glyph_Data), 0);
+
+   shm_id = cserve2_shared_string_add(cserve2_shared_mempool_name_get(mempool));
+   for (j = 0; j < msg->nglyphs; j++)
      {
-        unsigned int j;
-        Slave_Msg_Font_Cache *c = msg->caches[i];
-        string_t shm_id;
+        Glyph_Entry *gl;
 
-        if (!fc)
-          {
-             fc = calloc(1, sizeof(*fc));
-             fe->caches = eina_list_append(fe->caches, fc);
-             fe->last_cache = fc;
-             fc->fe = fe;
-             fc->shm = c->shm;
-             fc->glyphs = cserve2_shared_array_new(1, sizeof(int), 0);
-             fc->nglyphs = 0;
-             fc->inuse = 0;
-             font_shm_lru = eina_list_append(font_shm_lru, fc);
-             font_mem_usage += _font_shm_size_get(fc);
-          }
-        fc->usage = c->usage;
-        shm_id = cserve2_shared_string_add(cserve2_shm_name_get(fc->shm));
-        for (j = 0; j < c->nglyphs; j++)
+        gl = fash_gl_find(fe->glyph_entries, msg->glyphs[j].index);
+        if (!gl)
           {
-             Glyph_Entry *gl;
+             int glyph_id;
+             Glyph_Data *gldata;
 
-             gl = fash_gl_find(fe->glyphs, c->glyphs[j].index);
-             if (!gl)
+             glyph_id = cserve2_shared_array_item_new(fe->glyph_datas);
+             gldata = cserve2_shared_array_item_data_get(fe->glyph_datas,
+                                                         glyph_id);
+             if (!gldata)
                {
-                  int glyph_id, idx, *gldata_id;
-                  Glyph_Data *gldata;
-
-                  gl = calloc(1, sizeof(*gl));
-                  gl->fe = fe;
-                  gl->fc = fc;
-                  gl->gldata_id = ++_glyph_id;
-
-                  glyph_id = cserve2_shared_array_item_new(_glyph_data_array);
-                  gldata = cserve2_shared_array_item_data_get(_glyph_data_array,
-                                                              glyph_id);
-                  gldata->refcount = 1;
-                  gldata->id = gl->gldata_id;
-                  gldata->index = c->glyphs[j].index;
-                  gldata->shm_id = cserve2_shared_string_ref(shm_id);
-                  gldata->offset = c->glyphs[j].offset;
-                  gldata->size = c->glyphs[j].size;
-                  gldata->rows = c->glyphs[j].rows;
-                  gldata->width = c->glyphs[j].width;
-                  gldata->pitch = c->glyphs[j].pitch;
-                  gldata->num_grays = c->glyphs[j].num_grays;
-                  gldata->pixel_mode = c->glyphs[j].pixel_mode;
-                  font_mem_usage += sizeof(*gl) + sizeof(*gldata);
-                  idx = cserve2_shared_array_item_new(fc->glyphs);
-                  gldata_id = cserve2_shared_array_item_data_get(fc->glyphs, idx);
-                  *gldata_id = gldata->id;
-                  fc->nglyphs++;
-                  fe->nglyphs++;
-                  fash_gl_add(fe->glyphs, gldata->index, gl);
+                  ERR("Could not create new Glyph_Data!");
+                  // TODO: Return error?
+                  continue;
                }
-             req->answer[req->nanswer++] = gl;
-             gl->fc->inuse++;
-          }
 
-        cserve2_shared_string_del(shm_id);
-        free(c); // FIXME: We are freeing this here because we only do a
-                 // simple free on the response message. Later we need to
-                 // setup a free callback for the slave response.
-        fc = NULL;
+             gl = calloc(1, sizeof(*gl));
+             gl->fe = fe;
+             gl->gldata_id = ++_glyph_id;
+
+             gldata->refcount = 1;
+             gldata->id = gl->gldata_id;
+             gldata->index = msg->glyphs[j].index;
+             gldata->shm_id = cserve2_shared_string_ref(shm_id);
+             gldata->buffer_id = msg->glyphs[j].buffer_id;
+             gldata->offset = msg->glyphs[j].offset; // TODO: Remove?
+             gldata->size = msg->glyphs[j].size;
+             gldata->rows = msg->glyphs[j].rows;
+             gldata->width = msg->glyphs[j].width;
+             gldata->pitch = msg->glyphs[j].pitch;
+             gldata->num_grays = msg->glyphs[j].num_grays;
+             gldata->pixel_mode = msg->glyphs[j].pixel_mode;
+
+             fe->nglyphs++;
+             fash_gl_add(fe->glyph_entries, gldata->index, gl);
+
+             font_mem_usage += sizeof(*gl) + sizeof(*gldata);
+          }
+        req->answer[req->nanswer++] = gl;
      }
 
+   cserve2_shared_string_del(shm_id);
+
 #ifdef DEBUG_LOAD_TIME
    gettimeofday(&fe->rfinish, NULL);
    fe->gl_request_time += _timeval_sub(&fe->rfinish, &fe->rstart);
@@ -2055,7 +2167,7 @@ _glyphs_load_request_response(Glyphs_Request *req,
    fe->gl_slave_time += msg->gl_slave_time;
 #endif
 
-   _font_shm_lru_flush();
+   fe->mempool = mempool;
 
    return _glyphs_loaded_msg_create(req, size);
 }
@@ -2075,6 +2187,9 @@ static Slave_Request_Funcs _glyphs_load_funcs = {
 static Eina_Bool
 _font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
 {
+   // FIXME TODO Must reimplement this
+
+#if 0
    Font_Entry *fe = data;
    Msg_Stats *msg = fdata;
    Eina_List *iter;
@@ -2119,6 +2234,8 @@ _font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNU
    msg->fonts.glyphs_slave_time += fe->gl_slave_time;
 #endif
 
+#endif
+
    return EINA_TRUE;
 }
 
@@ -2207,8 +2324,6 @@ _font_entry_debug_size_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EIN
    struct _debug_info *di = fdata;
    unsigned int size = di->size;
    Font_Entry *fe = data;
-   Font_Cache *fc;
-   Eina_List *iter;
    const char *str;
 
    // filelen
@@ -2240,20 +2355,7 @@ _font_entry_debug_size_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EIN
    // ncaches
    size += sizeof(int);
 
-   EINA_LIST_FOREACH(fe->caches, iter, fc)
-     {
-        // shmnamelen + shmname
-        size += sizeof(int);
-        size += strlen(cserve2_shm_name_get(fc->shm)) + 1;
-
-        // size + usage
-        size += 2 * sizeof(int);
-
-        // nglyphs
-        size += sizeof(int);
-
-        size += (4 + 3 + 2) * sizeof(int) * fc->nglyphs;
-     }
+   size += cserve2_shared_mempool_size_get(fe->mempool);
 
    di->size = size;
    di->nfonts++;
@@ -2267,6 +2369,94 @@ _font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNU
    char **pos = fdata;
    char *buf = *pos;
    Font_Entry *fe = data;
+   unsigned int len, k, nglyphs;
+   const char *str;
+   char *nglyphs_pos;
+
+   // file
+   str = cserve2_shared_string_get(fe->src->file);
+   len = str ? (strlen(str) + 1) : 0;
+
+   memcpy(buf, &len, sizeof(int));
+   buf += sizeof(int);
+
+   if (len)
+     {
+        memcpy(buf, str, len);
+        buf += len;
+     }
+
+   // name
+   str = cserve2_shared_string_get(fe->src->name);
+   len = str ? (strlen(str) + 1) : 0;
+
+   memcpy(buf, &len, sizeof(int));
+   buf += sizeof(int);
+
+   if (len)
+     {
+        memcpy(buf, str, len);
+        buf += len;
+     }
+
+   // rend_flags, size, dpi, unused
+   memcpy(buf, &fe->rend_flags, sizeof(int));
+   buf += sizeof(int);
+   memcpy(buf, &fe->size, sizeof(int));
+   buf += sizeof(int);
+   memcpy(buf, &fe->dpi, sizeof(int));
+   buf += sizeof(int);
+
+   len = fe->unused;
+   memcpy(buf, &len, sizeof(int));
+   buf += sizeof(int);
+
+   // glyph shared index and mempool
+   if (fe->glyph_datas)
+     eina_strlcpy(buf, cserve2_shared_array_name_get(fe->glyph_datas), 64);
+   else
+     memset(buf, 0, 64);
+   buf += 64;
+
+   if (fe->mempool)
+     eina_strlcpy(buf, cserve2_shared_mempool_name_get(fe->mempool), 64);
+   else
+     memset(buf, 0, 64);
+   buf += 64;
+
+   // skip nglyphs for now...
+   nglyphs_pos = buf;
+   buf += sizeof(int);
+
+   nglyphs = 0;
+   for (k = 0; k < fe->nglyphs; k++)
+     {
+        Glyph_Data *gd = cserve2_shared_array_item_data_get(fe->glyph_datas, k);
+        if (!gd || !gd->id) break;
+
+        nglyphs++;
+        memcpy(buf, gd, sizeof(*gd));
+        buf += sizeof(*gd);
+     }
+
+   // write real value of nglyphs
+   memcpy(nglyphs_pos, &nglyphs, sizeof(int));
+   if (nglyphs != fe->nglyphs)
+     {
+        WRN("Found %u valid glyphs when the font advertised %u entries",
+            nglyphs, fe->nglyphs);
+     }
+
+   *pos = buf;
+   return EINA_TRUE;
+}
+
+   // FIXME TODO Must reimplement this
+#if 0
+
+   char **pos = fdata;
+   char *buf = *pos;
+   Font_Entry *fe = data;
    Font_Cache *fc;
    Eina_List *iter;
    unsigned int len;
@@ -2376,6 +2566,7 @@ _font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNU
 
    *pos = buf;
    return EINA_TRUE;
+#endif
 }
 
 static void *
@@ -2852,12 +3043,16 @@ cserve2_cache_image_unload(Client *client, unsigned int client_image_id)
 }
 
 int
-cserve2_cache_font_load(Client *client, const char *source, const char *name, unsigned int rend_flags, unsigned int size, unsigned int dpi, unsigned int rid)
+cserve2_cache_font_load(Client *client, const char *source, const char *name,
+                        unsigned int rend_flags, unsigned int size,
+                        unsigned int dpi, unsigned int rid)
 {
    Reference *ref;
    Font_Source *fs;
+   Font_Data *fd;
    Font_Entry *fe;
    char *fullname;
+   int fd_index;
 
    if (source && !*source)
      source = NULL;
@@ -2891,10 +3086,9 @@ cserve2_cache_font_load(Client *client, const char *source, const char *name, un
    fe->size = size;
    fe->dpi = dpi;
    fe->base.type = CSERVE2_FONT_ENTRY;
-   fe->glyphs = fash_gl_new(_glyph_free_cb);
+   fe->glyph_entries = fash_gl_new(_glyph_free_cb);
    ref = _entry_reference_add((Entry *)fe, client, 0);
-   client->fonts.referencing = eina_list_append(
-      client->fonts.referencing, ref);
+   client->fonts.referencing = eina_list_append(client->fonts.referencing, ref);
    fe->unused = EINA_FALSE;
 
    fs = _cserve2_font_source_find(fullname);
@@ -2912,14 +3106,28 @@ cserve2_cache_font_load(Client *client, const char *source, const char *name, un
         else
           {
              fs->file = cserve2_shared_string_add(name);
+             fs->name = 0;
              fs->key = cserve2_shared_string_ref(fs->file);
              key = name;
           }
-        eina_hash_direct_add(font_sources, key, fs);
+        eina_hash_add(font_sources, key, fs);
      }
 
+   // Copy descriptor to Shared Array
+   fd_index = cserve2_shared_array_item_new(_font_data_array);
+   fd = cserve2_shared_array_item_data_get(_font_data_array, fd_index);
+   fd->size = fe->size;
+   fd->rend_flags = fe->rend_flags;
+   fd->dpi = fe->dpi;
+   fd->id = ++_font_data_id;
+   fd->refcount = 1;
+   fd->name = cserve2_shared_string_ref(fs->name);
+   fd->file = cserve2_shared_string_ref(fs->file);
+   fd->glyph_index_shm = 0;
+
    fe->src = fs;
-   fs->references++;
+   fe->font_data_id = fd->id;
+   fs->refcount++;
    DBG("adding FONT_LOAD '%s' request.", name);
    fe->base.request = cserve2_request_add(CSERVE2_REQ_FONT_LOAD, rid, client,
                                           NULL, &_font_load_funcs, fe);
@@ -2958,7 +3166,11 @@ cserve2_cache_font_unload(Client *client, const char *source, const char *name,
 }
 
 int
-cserve2_cache_font_glyphs_load(Client *client, const char *source, const char *name, unsigned int hint, unsigned int rend_flags, unsigned int size, unsigned int dpi, unsigned int *glyphs, unsigned int nglyphs, unsigned int rid)
+cserve2_cache_font_glyphs_load(Client *client, const char *source,
+                               const char *name, unsigned int hint,
+                               unsigned int rend_flags, unsigned int size,
+                               unsigned int dpi, unsigned int *glyphs,
+                               unsigned int nglyphs, unsigned int rid)
 {
    Glyphs_Request *req;
 
@@ -2985,8 +3197,17 @@ cserve2_cache_font_glyphs_load(Client *client, const char *source, const char *n
 }
 
 int
-cserve2_cache_font_glyphs_used(Client *client, const char *source, const char *name, unsigned int hint, unsigned int rend_flags, unsigned int size, unsigned int dpi, unsigned int *glyphs, unsigned int nglyphs, unsigned int rid EINA_UNUSED)
-{
+cserve2_cache_font_glyphs_used(Client *client, const char *source,
+                               const char *name, unsigned int hint,
+                               unsigned int rend_flags, unsigned int size,
+                               unsigned int dpi, unsigned int *glyphs,
+                               unsigned int nglyphs,
+                               unsigned int rid EINA_UNUSED)
+{
+   // FIXME TODO: Must reimplement this
+   return 0;
+
+#if 0
    Glyphs_Group *gg;
    Eina_List *groups;
    Glyphs_Request *req;
@@ -3008,13 +3229,14 @@ cserve2_cache_font_glyphs_used(Client *client, const char *source, const char *n
    // glyphs which are not cached anymore, but are in use on the client.
    EINA_LIST_FREE(groups, gg)
      {
-        _font_shm_promote(gg->fc);
+        //_font_shm_promote(gg->fc);
         eina_list_free(gg->glyphs);
         free(gg);
      }
 
    _glyphs_request_free(req);
    return 0;
+#endif
 }
 
 void
index af8139e..8690888 100644 (file)
@@ -47,7 +47,6 @@ struct _Font_Info
    int dpi;
    int max_h;
    unsigned int runtime_rend;
-   int shmsize;
 };
 
 struct _Font_Source_Info
@@ -281,14 +280,6 @@ _font_slave_load(const void *cmddata, void *data EINA_UNUSED)
    return response;
 }
 
-static Shm_Handle *
-_font_slave_memory_alloc(Font_Info *fi)
-{
-   Shm_Handle *shm = cserve2_shm_request("font", fi->shmsize);
-
-   return shm;
-}
-
 /* This function will load the "index" glyph to the glyph slot of the font.
  * In order to use or render it, one should access it from the glyph slot,
  * or get the glyph using FT_Get_Glyph().
@@ -326,39 +317,48 @@ _font_slave_glyph_load(Font_Info *fi, unsigned int idx, unsigned int hint)
  * given Font Cache.
  */
 static Eina_Bool
-_font_slave_glyph_render(Font_Info *fi, Slave_Msg_Font_Cache *c, unsigned int idx)
+_font_slave_glyph_render(Font_Info *fi, Slave_Msg_Font_Glyphs_Loaded *response,
+                         unsigned int idx)
 {
    Font_Source_Info *fsi = fi->fsi;
    unsigned int glyphsize;
-   char *cachedata = cserve2_shm_map(c->shm);
    FT_Glyph glyph;
    FT_BitmapGlyph bglyph;
+   char *data;
+   int buffer_id = 0;
 
    FT_Get_Glyph(fsi->face->glyph, &glyph);
    FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
    bglyph = (FT_BitmapGlyph)glyph;
 
    glyphsize = bglyph->bitmap.pitch * bglyph->bitmap.rows;
-
-   if (c->usage + glyphsize > cserve2_shm_size_get(c->shm))
+   if (!glyphsize)
      {
         FT_Done_Glyph(glyph);
         return EINA_FALSE;
      }
 
-   memcpy(cachedata + c->usage, bglyph->bitmap.buffer, glyphsize);
+   buffer_id = cserve2_shared_mempool_buffer_new(response->mempool, glyphsize);
+   data = cserve2_shared_mempool_buffer_get(response->mempool, buffer_id);
+   if (!data)
+     {
+        FT_Done_Glyph(glyph);
+        return EINA_FALSE;
+     }
+   memcpy(data, bglyph->bitmap.buffer, glyphsize);
 
    // TODO: Check if we have problems with alignment
-   c->glyphs[c->nglyphs].index = idx;
-   c->glyphs[c->nglyphs].offset = c->usage;
-   c->glyphs[c->nglyphs].size = glyphsize;
-   c->glyphs[c->nglyphs].rows = bglyph->bitmap.rows;
-   c->glyphs[c->nglyphs].width = bglyph->bitmap.width;
-   c->glyphs[c->nglyphs].pitch = bglyph->bitmap.pitch;
-   c->glyphs[c->nglyphs].num_grays = bglyph->bitmap.num_grays;
-   c->glyphs[c->nglyphs].pixel_mode = bglyph->bitmap.pixel_mode;
-   c->usage += glyphsize;
-   c->nglyphs++;
+   response->glyphs[response->nglyphs].index = idx;
+   response->glyphs[response->nglyphs].buffer_id = buffer_id;
+   response->glyphs[response->nglyphs].offset =
+         cserve2_shared_mempool_buffer_offset_get(response->mempool, buffer_id);
+   response->glyphs[response->nglyphs].size = glyphsize;
+   response->glyphs[response->nglyphs].rows = bglyph->bitmap.rows;
+   response->glyphs[response->nglyphs].width = bglyph->bitmap.width;
+   response->glyphs[response->nglyphs].pitch = bglyph->bitmap.pitch;
+   response->glyphs[response->nglyphs].num_grays = bglyph->bitmap.num_grays;
+   response->glyphs[response->nglyphs].pixel_mode = bglyph->bitmap.pixel_mode;
+   response->nglyphs++;
 
    FT_Done_Glyph(glyph);
 
@@ -465,15 +465,12 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
    Slave_Msg_Font_Glyphs_Loaded *response;
    Font_Info *fi;
    unsigned int i;
-   unsigned int total_glyphs = 0;
 #ifdef DEBUG_LOAD_TIME
    unsigned int gl_load_time = 0;
    unsigned int gl_render_time = 0;
    struct timeval tv_start, tv_end;
    struct timeval rstart, rfinish;
 #endif
-   Eina_List *caches = NULL;
-   Slave_Msg_Font_Cache *c = NULL;
 
    fi = msg->font.ftdata2;
 
@@ -483,41 +480,22 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
 
    _font_slave_size_use(fi);
 
-   if (msg->cache.shm)
+   response = malloc(sizeof(*response)
+                     + sizeof(Slave_Msg_Glyph) * (msg->glyphs.nglyphs));
+   if (!response) return NULL;
+
+   response->nglyphs = 0;
+   response->glyphs = (void *) (response + 1);
+   response->mempool = msg->cache.mempool;
+   if (!response->mempool)
      {
-        c = malloc(sizeof(*c) + sizeof(Slave_Msg_Glyph) *
-                   (msg->glyphs.nglyphs));
-        c->nglyphs = 0;
-        c->glyphs = (void *)(c + 1);
-        c->shm = msg->cache.shm;
-        c->usage = msg->cache.usage;
-        caches = eina_list_append(caches, c);
-        total_glyphs = msg->cache.nglyphs;
+        unsigned shmsize = _font_slave_int_shm_calculate(fi, msg->font.hint);
+        response->mempool = cserve2_shared_mempool_new(shmsize);
+        if (!response->mempool) return NULL;
      }
 
-   if (!fi->shmsize)
-     fi->shmsize = _font_slave_int_shm_calculate(fi, msg->font.hint);
-
-   i = 0;
-
-   while (i < msg->glyphs.nglyphs)
+   for (i = 0; i < msg->glyphs.nglyphs; i++)
      {
-        Eina_Bool r = EINA_TRUE;
-
-        if (!c)
-          {
-             Shm_Handle *shm;
-             shm = _font_slave_memory_alloc(fi);
-             c = malloc(sizeof(*c) + sizeof(Slave_Msg_Glyph) *
-                        (msg->glyphs.nglyphs - i));
-             c->nglyphs = 0;
-             c->glyphs = (void *)(c + 1);
-             c->shm = shm;
-             c->usage = 0;
-             caches = eina_list_append(caches, c);
-             total_glyphs = 0;
-          }
-
 #ifdef DEBUG_LOAD_TIME
         gettimeofday(&tv_start, NULL);
 #endif
@@ -530,32 +508,14 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
              tv_start.tv_sec = tv_end.tv_sec;
              tv_start.tv_usec = tv_end.tv_usec;
 #endif
-             r = _font_slave_glyph_render(fi, c, msg->glyphs.glyphs[i]);
+             _font_slave_glyph_render(fi, response, msg->glyphs.glyphs[i]);
 #ifdef DEBUG_LOAD_TIME
              gettimeofday(&tv_end, NULL);
              gl_render_time += _timeval_sub(&tv_end, &tv_start);
 #endif
           }
-        if (!r) // SHM is full
-          {
-             fi->shmsize = _font_slave_int_shm_prev_calculate
-                   (c->usage, total_glyphs);
-             c = NULL;
-             continue;
-          }
-        i++;
-        total_glyphs++;
      }
 
-   response = malloc(sizeof(*response) +
-                     sizeof(c) * eina_list_count(caches));
-   response->ncaches = eina_list_count(caches);
-   response->caches = (void *)(response + 1);
-
-   i = 0;
-   EINA_LIST_FREE(caches, c)
-     response->caches[i++] = c;
-
 #ifdef DEBUG_LOAD_TIME
    response->gl_load_time = gl_load_time;
    response->gl_render_time = gl_render_time;
@@ -630,6 +590,8 @@ cserve2_font_source_ft_free(void *fontsource)
 {
    Font_Source_Info *fsi = fontsource;
 
+   if (!fsi) return;
+
    FT_Done_Face(fsi->face);
    free(fsi->data);
    free(fsi);
@@ -640,6 +602,8 @@ cserve2_font_ft_free(void *fontinfo)
 {
    Font_Info *fi = fontinfo;
 
+   if (!fi) return;
+
    FT_Done_Size(fi->size);
    free(fi);
 }
index ccb4903..7c3f176 100644 (file)
@@ -837,6 +837,20 @@ cserve2_shared_mempool_buffer_offset_get(Shared_Mempool *sm, int bufferid)
    return ie->offset;
 }
 
+size_t
+cserve2_shared_mempool_size_get(Shared_Mempool *sm)
+{
+   if (!sm) return 0;
+   return cserve2_shm_map_size_get(sm->ds->shm);
+}
+
+const char *
+cserve2_shared_mempool_name_get(Shared_Mempool *sm)
+{
+   if (!sm) return NULL;
+   return cserve2_shm_name_get(sm->ds->shm);
+}
+
 
 // Shared strings
 
index ae4a80e..00a0fe4 100644 (file)
@@ -47,6 +47,9 @@ cserve2_index_list_send(const char *strings_index_path,
    Msg_Index_List msg;
    const int size = sizeof(msg);
 
+   if (!client_list)
+     return;
+
    INF("New shared index: strings: '%s':'%s' files: '%s' images: '%s', fonts: '%s'",
        strings_index_path, strings_entries_path,
        files_index_path, images_index_path, fonts_index_path);
@@ -339,6 +342,7 @@ static void
 _clients_finish(void)
 {
    eina_hash_free(client_list);
+   client_list = NULL;
 }
 
 int
index 329d0d2..b233be6 100644 (file)
@@ -184,7 +184,6 @@ struct _Msg_Font_Glyphs_Request {
  */
 struct _Msg_Font_Glyphs_Loaded {
    Msg_Base base;
-   unsigned int ncaches;
 };
 
 struct _Msg_Stats {
@@ -287,6 +286,7 @@ typedef struct _Shm_Object Shm_Object;
 typedef struct _Index_Entry Index_Entry;
 typedef struct _File_Data File_Data;
 typedef struct _Image_Data Image_Data;
+typedef struct _Font_Data Font_Data;
 typedef struct _Glyph_Data Glyph_Data;
 typedef struct _Shared_Array_Header Shared_Array_Header;
 typedef int string_t;
@@ -338,10 +338,21 @@ struct _Image_Data {
    Eina_Bool doload : 1;
 };
 
+struct _Font_Data {
+   SHMOBJECT;
+   string_t name;
+   string_t file;
+   string_t glyph_index_shm;
+   uint32_t rend_flags;
+   uint32_t size;
+   uint32_t dpi;
+};
+
 struct _Glyph_Data {
    SHMOBJECT;
    uint32_t index;
    string_t shm_id;
+   uint32_t buffer_id;
    uint32_t offset;
    uint32_t size;
    uint32_t rows;
index 97f4315..47ede9b 100644 (file)
@@ -1085,6 +1085,9 @@ struct _Font_Entry
    unsigned int dpi;
    Font_Rend_Flags wanted_rend;
 
+   char *hkey;
+   int font_data_id;
+
    unsigned int rid; // open
 
    Eina_Hash *glyphs_maps;
@@ -1305,8 +1308,12 @@ _glyph_request_cb(void *data, const void *msg, int size)
    const Msg_Font_Glyphs_Loaded *resp = msg;
    Glyph_Request_Data *grd = data;
    Font_Entry *fe = grd->fe;
-   unsigned int ncaches;
    const char *buf;
+   int i, nglyphs;
+   int namelen;
+   const char *name;
+   Glyph_Map *map;
+   int pos;
 
    if (resp->base.type == CSERVE2_ERROR)
      goto end;
@@ -1317,89 +1324,82 @@ _glyph_request_cb(void *data, const void *msg, int size)
    if (size <= (int) sizeof(*resp)) goto end;
 
    buf = (const char *)resp + sizeof(*resp);
-   for (ncaches = 0; ncaches < resp->ncaches; ncaches++)
-     {
-        int i, nglyphs;
-        int namelen;
-        const char *name;
-        Glyph_Map *map;
-        int pos = buf - (const char*) resp;
+   pos = buf - (const char*) resp;
 
-        pos += sizeof(int);
-        if (pos > size) goto end;
+   pos += sizeof(int);
+   if (pos > size) goto end;
 
-        memcpy(&namelen, buf, sizeof(int));
-        buf += sizeof(int);
+   memcpy(&namelen, buf, sizeof(int));
+   buf += sizeof(int);
 
-        pos += namelen + sizeof(int);
-        if (pos > size) goto end;
+   pos += namelen + sizeof(int);
+   if (pos > size) goto end;
 
-        name = eina_stringshare_add_length(buf, namelen);
-        buf += namelen;
+   name = eina_stringshare_add_length(buf, namelen);
+   buf += namelen;
 
-        memcpy(&nglyphs, buf, sizeof(int));
-        buf += sizeof(int);
+   memcpy(&nglyphs, buf, sizeof(int));
+   buf += sizeof(int);
 
-        map = eina_hash_find(fe->glyphs_maps, name);
-        if (!map)
-          {
-             map = calloc(1, sizeof(*map));
-             map->fe = fe;
-             map->name = name;
-             map->map = eina_file_open(name, EINA_TRUE);
-             map->data = eina_file_map_all(map->map, EINA_FILE_WILLNEED);
-             eina_clist_init(&map->glyphs);
-             eina_hash_direct_add(fe->glyphs_maps, &map->name, map);
-          }
-        else
-          eina_stringshare_del(name);
+   map = eina_hash_find(fe->glyphs_maps, name);
+   if (!map)
+     {
+        map = calloc(1, sizeof(*map));
+        map->fe = fe;
+        map->name = name;
+        map->map = eina_file_open(name, EINA_TRUE);
+        map->data = eina_file_map_all(map->map, EINA_FILE_WILLNEED);
+        eina_clist_init(&map->glyphs);
+        eina_hash_direct_add(fe->glyphs_maps, &map->name, map);
+     }
+   else
+      eina_stringshare_del(name);
+
+   for (i = 0; i < nglyphs; i++)
+     {
+        string_t shm_id;
+        unsigned int idx, offset, glsize;
+        int rows, width, pitch, num_grays, pixel_mode;
+        CS_Glyph_Out *gl;
+
+        pos = buf - (const char*) resp;
+        pos += 8 * sizeof(int);
+        if (pos > size) goto end;
 
-        for (i = 0; i < nglyphs; i++)
+        memcpy(&idx, buf, sizeof(int));
+        buf += sizeof(int);
+        memcpy(&shm_id, buf, sizeof(string_t));
+        buf += sizeof(string_t);
+        memcpy(&offset, buf, sizeof(int));
+        buf += sizeof(int);
+        memcpy(&glsize, buf, sizeof(int));
+        buf += sizeof(int);
+        memcpy(&rows, buf, sizeof(int));
+        buf += sizeof(int);
+        memcpy(&width, buf, sizeof(int));
+        buf += sizeof(int);
+        memcpy(&pitch, buf, sizeof(int));
+        buf += sizeof(int);
+        memcpy(&num_grays, buf, sizeof(int));
+        buf += sizeof(int);
+        memcpy(&pixel_mode, buf, sizeof(int));
+        buf += sizeof(int);
+
+        gl = fash_gl_find(fe->fash[grd->hints], idx);
+        if (gl)
           {
-             string_t shm_id;
-             unsigned int idx, offset, glsize;
-             int rows, width, pitch, num_grays, pixel_mode;
-             CS_Glyph_Out *gl;
-
-             pos = buf - (const char*) resp;
-             pos += 8 * sizeof(int);
-             if (pos > size) goto end;
-
-             memcpy(&idx, buf, sizeof(int));
-             buf += sizeof(int);
-             memcpy(&shm_id, buf, sizeof(string_t));
-             buf += sizeof(string_t);
-             memcpy(&offset, buf, sizeof(int));
-             buf += sizeof(int);
-             memcpy(&glsize, buf, sizeof(int));
-             buf += sizeof(int);
-             memcpy(&rows, buf, sizeof(int));
-             buf += sizeof(int);
-             memcpy(&width, buf, sizeof(int));
-             buf += sizeof(int);
-             memcpy(&pitch, buf, sizeof(int));
-             buf += sizeof(int);
-             memcpy(&num_grays, buf, sizeof(int));
-             buf += sizeof(int);
-             memcpy(&pixel_mode, buf, sizeof(int));
-             buf += sizeof(int);
-
-             gl = fash_gl_find(fe->fash[grd->hints], idx);
-             if (gl)
-               {
-                  gl->map = map;
-                  gl->offset = offset;
-                  gl->size = glsize;
-                  gl->base.bitmap.rows = rows;
-                  gl->base.bitmap.width = width;
-                  gl->base.bitmap.pitch = pitch;
-                  gl->base.bitmap.buffer = map->data + gl->offset;
-                  gl->base.bitmap.num_grays = num_grays;
-                  gl->base.bitmap.pixel_mode = pixel_mode;
-                  gl->rid = 0;
-
-                  eina_clist_add_head(&map->glyphs, &gl->map_entry);
-               }
+             gl->map = map;
+             gl->offset = offset;
+             gl->size = glsize;
+             gl->base.bitmap.rows = rows;
+             gl->base.bitmap.width = width;
+             gl->base.bitmap.pitch = pitch;
+             gl->base.bitmap.buffer = map->data + gl->offset;
+             gl->base.bitmap.num_grays = num_grays;
+             gl->base.bitmap.pixel_mode = pixel_mode;
+             gl->rid = 0;
+
+             eina_clist_add_head(&map->glyphs, &gl->map_entry);
           }
      }
 
@@ -1858,7 +1858,8 @@ _shared_image_entry_file_data_find(Image_Entry *ie)
         file = _shared_string_get(fd->path);
         if (!file)
           {
-             ERR("Could not find filename for file %d", fd->id);
+             ERR("Could not find filename for file %d: path id: %d",
+                 fd->id, fd->path);
              add_to_hash = EINA_FALSE;
              continue;
           }
@@ -2191,5 +2192,68 @@ found:
    return idata;
 }
 
+static const Font_Data *
+_shared_font_entry_data_get_by_id(int id)
+{
+   return (Font_Data *)
+         _shared_index_item_get_by_id(&_index.fonts, sizeof(Font_Data), id);
+}
+
+static const Font_Data *
+_shared_font_entry_data_find(Font_Entry *fe)
+{
+   const Font_Data *fd = NULL;
+   Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
+   char hkey[PATH_MAX];
+   int k;
+
+   if (!_index.strings_entries.data || !_index.strings_index.data)
+     return NULL;
+
+   if (!fe || !fe->hkey)
+     return NULL;
+
+   if (fe->font_data_id)
+     {
+        fd = _shared_font_entry_data_get_by_id(fe->font_data_id);
+        if (fd) return fd;
+        fe->font_data_id = 0;
+     }
+
+   // Find in hash
+   fd = eina_hash_find(_index.fonts.entries_by_hkey, fe->hkey);
+   if (fd) return fd;
+
+   // Find in shared index
+   for (k = _index.fonts.last_entry_in_hash;
+        k < _index.fonts.count && k < _index.fonts.header->emptyidx; k++)
+     {
+        const Font_Data *cur;
+        const char *name, *source;
+
+        cur = &(_index.fonts.entries.fontdata[k]);
+        if (!cur->id) return NULL;
+        if (!cur->refcount) continue;
+
+        name = _shared_string_get(cur->name);
+        source = _shared_string_get(cur->file);
+        snprintf(hkey, PATH_MAX, "%s:%s/%u:%u:%u", source, name,
+                 cur->size, cur->dpi, cur->rend_flags);
+
+        if (add_to_hash)
+          {
+             eina_hash_add(_index.fonts.entries_by_hkey, hkey, cur);
+             _index.fonts.last_entry_in_hash++;
+          }
+
+        if (!strcmp(hkey, fe->hkey))
+          {
+             fe->font_data_id = cur->id;
+             return cur;
+          }
+     }
+
+   return fd;
+}
 
 #endif