From 88edaa2e02df6f382646e97b9c4c7a471134424b Mon Sep 17 00:00:00 2001 From: Stafford Mitchell Horne Date: Sat, 22 Apr 2006 11:08:01 +0000 Subject: [PATCH] Add font charmap caching * TODO: store cache on disc, for faster cache loading (this requires EET to support arrays) SVN revision: 22294 --- legacy/evas/src/lib/canvas/evas_font_dir.c | 2 +- legacy/evas/src/lib/data/evas_hash.c | 2 +- .../evas/src/lib/engines/common/Makefile.am | 1 + .../src/lib/engines/common/evas_array_hash.c | 114 ++++++++++++++++++ .../src/lib/engines/common/evas_font_draw.c | 67 ++++++++-- .../src/lib/engines/common/evas_font_load.c | 6 +- legacy/evas/src/lib/include/evas_common.h | 11 +- 7 files changed, 188 insertions(+), 15 deletions(-) create mode 100644 legacy/evas/src/lib/engines/common/evas_array_hash.c diff --git a/legacy/evas/src/lib/canvas/evas_font_dir.c b/legacy/evas/src/lib/canvas/evas_font_dir.c index f50f2bfbf0..3323c8c214 100644 --- a/legacy/evas/src/lib/canvas/evas_font_dir.c +++ b/legacy/evas/src/lib/canvas/evas_font_dir.c @@ -616,7 +616,7 @@ object_text_font_cache_dir_add(char *dir) Evas_Font_Alias *fa; /* skip comments */ - if ((fdef[0] == '!') || (fdef[0] == '#')) continue; + if ((fname[0] == '!') || (fname[0] == '#')) continue; fa = calloc(1, sizeof(Evas_Font_Alias)); if (fa) { diff --git a/legacy/evas/src/lib/data/evas_hash.c b/legacy/evas/src/lib/data/evas_hash.c index 7951747459..84dfbcd8a1 100644 --- a/legacy/evas/src/lib/data/evas_hash.c +++ b/legacy/evas/src/lib/data/evas_hash.c @@ -403,7 +403,7 @@ evas_hash_free(Evas_Hash *hash) * * This function goes through every entry in the hash table @p hash and calls * the function @p func on each member. The function should NOT modify the - * hash table contents if it reeturns 1. IF the hash table contents are + * hash table contents if it returns 1. IF the hash table contents are * modified by this function or the function wishes to stop processing it must * return 0, otherwise return 1 to keep processing. * diff --git a/legacy/evas/src/lib/engines/common/Makefile.am b/legacy/evas/src/lib/engines/common/Makefile.am index 30a00b2529..c460d104d8 100644 --- a/legacy/evas/src/lib/engines/common/Makefile.am +++ b/legacy/evas/src/lib/engines/common/Makefile.am @@ -53,6 +53,7 @@ evas_scale_sample.c \ evas_scale_smooth.c \ evas_tiler.c \ evas_regionbuf.c \ +evas_array_hash.c \ evas_blend_ops.h EXTRA_DIST = \ diff --git a/legacy/evas/src/lib/engines/common/evas_array_hash.c b/legacy/evas/src/lib/engines/common/evas_array_hash.c new file mode 100644 index 0000000000..e594cedf3a --- /dev/null +++ b/legacy/evas/src/lib/engines/common/evas_array_hash.c @@ -0,0 +1,114 @@ +#include "evas_common.h" + +#define EAH_BUCKETS 256 +#define EAH_HASH(key) \ + ( key % EAH_BUCKETS ) + +typedef struct _Evas_Array_Hash_El Evas_Array_Hash_El; + +struct _Evas_Array_Hash +{ + Evas_Array_Hash_El *buckets[EAH_BUCKETS]; +}; + +struct _Evas_Array_Hash_El +{ + int data_max; + int data_count; + int *data; +}; + +/* + These functions provide an interface for a simple hash. The hash + is and array of int array pointers. Right now that hash size is 256. + The hash size is static. The key and data are ints. + + Keys must be added in ascending order because the search function + assumes that the hash buckets are sorted. + */ +Evas_Array_Hash * +evas_common_array_hash_new(void) +{ + Evas_Array_Hash *hash; + + hash = calloc(1, sizeof(Evas_Array_Hash)); + return hash; +} + +void +evas_common_array_hash_free(Evas_Array_Hash *hash) +{ + int i; + + for (i = 0; i < EAH_BUCKETS; i++) + { + if (hash->buckets[i]) + { + free(hash->buckets[i]->data); + free(hash->buckets[i]); + } + } + + free(hash); +} + +void +evas_common_array_hash_add(Evas_Array_Hash *hash, int key, int data) +{ + int hash_val; + Evas_Array_Hash_El *el; + + hash_val = EAH_HASH(key); + el = hash->buckets[hash_val]; + if (!el) + { + el = malloc(sizeof(Evas_Array_Hash_El)); + el->data_max = 1 << 5; + el->data = malloc(sizeof(int) * el->data_max); + el->data_count = 0; + hash->buckets[hash_val] = el; + } + else if (el->data_count == el->data_max) + { + el->data_max = el->data_max << 1; + el->data = realloc(el->data, sizeof(int) * el->data_max); + } + + el->data[el->data_count++] = key; + el->data[el->data_count++] = data; +} + +int +evas_common_array_hash_search(Evas_Array_Hash *hash, int key) +{ + int hash_val; + Evas_Array_Hash_El *el; + int low, high, i, val; + + hash_val = EAH_HASH(key); + + el = hash->buckets[hash_val]; + if (!el) + return 0; + + /* Binary Search the bucket for key */ + low = 0; + high = ( el->data_count / 2 ) - 1; + + while ( high >= low ) + { + i = (high + low) / 2; + + val = el->data[i << 1]; + + if (val == key) + return el->data[(i << 1) + 1]; + else if (val > key) + high = i - 1; + else + low = i + 1; + } + return 0; +} + + diff --git a/legacy/evas/src/lib/engines/common/evas_font_draw.c b/legacy/evas/src/lib/engines/common/evas_font_draw.c index 5043e0eaf7..0624bc5a2a 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_draw.c +++ b/legacy/evas/src/lib/engines/common/evas_font_draw.c @@ -62,20 +62,67 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl) { RGBA_Font_Int *fi; int index; - + fi = l->data; - if (!fi->ft.size) + + if (fi->src->charmap) /* Charmap loaded, FI/FS blank */ { - if (!fi->src->ft.face) - evas_common_font_source_load_complete(fi->src); - evas_common_font_int_load_complete(fi); + index = evas_common_array_hash_search(fi->src->charmap, gl); + if (index != 0) + { + evas_common_font_source_load_complete(fi->src); + evas_common_font_int_load_complete(fi); + + evas_common_array_hash_free(fi->src->charmap); + fi->src->charmap = NULL; + + *fi_ret = fi; + return index; + } } - - index = FT_Get_Char_Index(fi->src->ft.face, gl); - if (index != 0) + else if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */ { - *fi_ret = fi; - return index; + if (evas_common_font_source_load_complete(fi->src)); + return 0; + + index = FT_Get_Char_Index(fi->src->ft.face, gl); + if (index == 0) + { + /* Load Hash */ + FT_ULong charcode; + FT_UInt gindex; + + fi->src->charmap = evas_common_array_hash_new(); + charcode = FT_Get_First_Char(fi->src->ft.face, &gindex ); + while ( gindex != 0 ) + { + evas_common_array_hash_add(fi->src->charmap, charcode, gindex); + charcode = FT_Get_Next_Char(fi->src->ft.face, charcode, &gindex ); + } + + /* Free face */ + FT_Done_Face(fi->src->ft.face); + fi->src->ft.face = NULL; + } + else + { + evas_common_font_int_load_complete(fi); + + *fi_ret = fi; + return index; + } + } + else /* Charmap not loaded, FS loaded */ + { + index = FT_Get_Char_Index(fi->src->ft.face, gl); + if (index != 0) + { + if (!fi->ft.size) + evas_common_font_int_load_complete(fi); + + *fi_ret = fi; + return index; + } } } return 0; diff --git a/legacy/evas/src/lib/engines/common/evas_font_load.c b/legacy/evas/src/lib/engines/common/evas_font_load.c index 62235fc166..b8341d88b4 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_load.c +++ b/legacy/evas/src/lib/engines/common/evas_font_load.c @@ -64,8 +64,8 @@ int evas_common_font_source_load_complete(RGBA_Font_Source *fs) { int error; - - error = FT_New_Face(evas_ft_lib, fs->name, 0, &(fs->ft.face)); + + error = FT_New_Face(evas_ft_lib, fs->file, 0, &(fs->ft.face)); if (error) return error; error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode); @@ -105,6 +105,7 @@ evas_common_font_source_free(RGBA_Font_Source *fs) fonts_src = evas_object_list_remove(fonts_src, fs); FT_Done_Face(fs->ft.face); + if (fs->charmap) evas_common_array_hash_free(fs->charmap); if (fs->name) evas_stringshare_del(fs->name); free(fs); } @@ -546,3 +547,4 @@ evas_common_font_int_find(const char *name, int size) } return NULL; } + diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index b9826dd5eb..c2578ab763 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -109,6 +109,9 @@ typedef struct _Convert_Pal Convert_Pal; typedef struct _Tilebuf Tilebuf; typedef struct _Tilebuf_Tile Tilebuf_Tile; typedef struct _Tilebuf_Rect Tilebuf_Rect; + +typedef struct _Evas_Array_Hash Evas_Array_Hash; + /* typedef struct _Regionbuf Regionbuf; typedef struct _Regionspan Regionspan; @@ -341,7 +344,8 @@ struct _RGBA_Font_Source int data_size; int current_size; - + Evas_Array_Hash *charmap; + struct { int orig_upem; FT_Face face; @@ -965,6 +969,11 @@ Gfx_Func_Blend_Src_Dst evas_common_draw_func_copy_get (int pixe void evas_font_dir_cache_free(void); +Evas_Array_Hash *evas_common_array_hash_new (void); +void evas_common_array_hash_free (Evas_Array_Hash *hash); +void evas_common_array_hash_add (Evas_Array_Hash *hash, int key, int data); +int evas_common_array_hash_search (Evas_Array_Hash *hash, int key); + /*****************************************************************************/ #ifdef __cplusplus