typedef struct _Font_Source Font_Source;
typedef struct _Font_Entry Font_Entry;
-typedef struct _Font_Cache Font_Cache;
typedef enum {
CSERVE2_IMAGE_FILE,
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
#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 {
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;
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
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)
{
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);
_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;
}
_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;
}
}
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);
}
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
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)
{
l_next = eina_list_next(l);
}
}
+#endif
void
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);
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 *
{
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
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);
}
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;
fe->gl_saved_time +=
(fe->gl_load_time / fe->nglyphs);
#endif
- ge->fc->inuse++;
+ //ge->fc->inuse++;
}
else
break;
return (req->nanswer == req->nglyphs);
}
+#if 0
/* organize answer (cache1{gl1, gl2,}, cache2{gl3,gl4,gl5}, cache3{gl6})
*/
static Eina_List *
{
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;
}
return groups;
+ */
}
static Msg_Font_Glyphs_Loaded *
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)
}
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));
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;
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];
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);
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;
}
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);
fe->gl_slave_time += msg->gl_slave_time;
#endif
- _font_shm_lru_flush();
+ fe->mempool = mempool;
return _glyphs_loaded_msg_create(req, size);
}
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;
msg->fonts.glyphs_slave_time += fe->gl_slave_time;
#endif
+#endif
+
return EINA_TRUE;
}
struct _debug_info *di = fdata;
unsigned int size = di->size;
Font_Entry *fe = data;
- Font_Cache *fc;
- Eina_List *iter;
const char *str;
// filelen
// 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++;
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;
*pos = buf;
return EINA_TRUE;
+#endif
}
static void *
}
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;
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);
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);
}
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;
}
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;
// 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
int dpi;
int max_h;
unsigned int runtime_rend;
- int shmsize;
};
struct _Font_Source_Info
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().
* 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);
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;
_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
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;
{
Font_Source_Info *fsi = fontsource;
+ if (!fsi) return;
+
FT_Done_Face(fsi->face);
free(fsi->data);
free(fsi);
{
Font_Info *fi = fontinfo;
+ if (!fi) return;
+
FT_Done_Size(fi->size);
free(fi);
}
unsigned int dpi;
Font_Rend_Flags wanted_rend;
+ char *hkey;
+ int font_data_id;
+
unsigned int rid; // open
Eina_Hash *glyphs_maps;
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;
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);
}
}
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;
}
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