evas/cserve2: Store Glyph_Data in shared mempools

- 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
This commit is contained in:
Jean-Philippe Andre 2013-08-19 12:22:19 +09:00
parent c7515f3300
commit 467b1b1739
7 changed files with 597 additions and 325 deletions

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

View 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,7 +1727,17 @@ _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;
@ -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)
gl = fash_gl_find(fe->glyph_entries, msg->glyphs[j].index);
if (!gl)
{
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++)
{
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;
@ -2117,6 +2232,8 @@ _font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNU
msg->fonts.glyphs_saved_time += fe->gl_saved_time;
msg->fonts.glyphs_request_time += fe->gl_request_time;
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++;
@ -2264,6 +2366,94 @@ _font_entry_debug_size_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EIN
static Eina_Bool
_font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
{
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;
@ -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

View 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);
}

View 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

View 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

View 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;

View 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++)
pos = buf - (const char*) resp;
pos += sizeof(int);
if (pos > size) goto end;
memcpy(&namelen, buf, sizeof(int));
buf += sizeof(int);
pos += namelen + sizeof(int);
if (pos > size) goto end;
name = eina_stringshare_add_length(buf, namelen);
buf += namelen;
memcpy(&nglyphs, buf, sizeof(int));
buf += sizeof(int);
map = eina_hash_find(fe->glyphs_maps, name);
if (!map)
{
int i, nglyphs;
int namelen;
const char *name;
Glyph_Map *map;
int pos = buf - (const char*) resp;
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);
pos += sizeof(int);
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;
memcpy(&namelen, buf, sizeof(int));
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);
pos += namelen + sizeof(int);
if (pos > size) goto end;
name = eina_stringshare_add_length(buf, namelen);
buf += namelen;
memcpy(&nglyphs, buf, sizeof(int));
buf += sizeof(int);
map = eina_hash_find(fe->glyphs_maps, name);
if (!map)
gl = fash_gl_find(fe->fash[grd->hints], idx);
if (gl)
{
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);
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;
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;
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);
}
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