Mercurial > mplayer.hg
comparison libass/ass_cache.c @ 18937:9e95ac641e77
Initial libass release (without mencoder support).
author | eugeni |
---|---|
date | Fri, 07 Jul 2006 18:26:51 +0000 |
parents | |
children | 64009ae411fb |
comparison
equal
deleted
inserted
replaced
18936:b80b0c115a24 | 18937:9e95ac641e77 |
---|---|
1 #include "config.h" | |
2 | |
3 #include <ft2build.h> | |
4 #include FT_FREETYPE_H | |
5 | |
6 #include <assert.h> | |
7 | |
8 #include "mp_msg.h" | |
9 #include "ass_fontconfig.h" | |
10 #include "ass_cache.h" | |
11 | |
12 | |
13 typedef struct face_cache_item_s { | |
14 face_desc_t desc; | |
15 char* path; | |
16 int index; | |
17 FT_Face face; | |
18 } face_cache_item_t; | |
19 | |
20 #define MAX_FACE_CACHE_SIZE 100 | |
21 | |
22 static face_cache_item_t* face_cache; | |
23 static int face_cache_size; | |
24 | |
25 extern int no_more_font_messages; | |
26 | |
27 static int font_compare(face_desc_t* a, face_desc_t* b) { | |
28 if (strcmp(a->family, b->family) != 0) | |
29 return 0; | |
30 if (a->bold != b->bold) | |
31 return 0; | |
32 if (a->italic != b->italic) | |
33 return 0; | |
34 return 1; | |
35 } | |
36 | |
37 /** | |
38 * \brief Get a face object, either from cache or created through FreeType+FontConfig. | |
39 * \param library FreeType library object | |
40 * \param fontconfig_priv fontconfig private data | |
41 * \param desc required face description | |
42 * \param face out: the face object | |
43 */ | |
44 int ass_new_face(FT_Library library, void* fontconfig_priv, face_desc_t* desc, /*out*/ FT_Face* face) | |
45 { | |
46 FT_Error error; | |
47 int i; | |
48 char* path; | |
49 int index; | |
50 face_cache_item_t* item; | |
51 | |
52 for (i=0; i<face_cache_size; ++i) | |
53 if (font_compare(desc, &(face_cache[i].desc))) { | |
54 *face = face_cache[i].face; | |
55 return 0; | |
56 } | |
57 | |
58 if (face_cache_size == MAX_FACE_CACHE_SIZE) { | |
59 mp_msg(MSGT_GLOBAL, MSGL_FATAL, "Too many fonts\n"); | |
60 return 1; | |
61 } | |
62 | |
63 path = fontconfig_select(fontconfig_priv, desc->family, desc->bold, desc->italic, &index); | |
64 | |
65 error = FT_New_Face(library, path, index, face); | |
66 if (error) { | |
67 if (!no_more_font_messages) | |
68 mp_msg(MSGT_GLOBAL, MSGL_WARN, "Error opening font: %s, %d\n", path, index); | |
69 no_more_font_messages = 1; | |
70 return 1; | |
71 } | |
72 | |
73 item = face_cache + face_cache_size; | |
74 item->path = strdup(path); | |
75 item->index = index; | |
76 item->face = *face; | |
77 memcpy(&(item->desc), desc, sizeof(face_desc_t)); | |
78 face_cache_size++; | |
79 return 0; | |
80 } | |
81 | |
82 void ass_face_cache_init(void) | |
83 { | |
84 face_cache = calloc(MAX_FACE_CACHE_SIZE, sizeof(face_cache_item_t)); | |
85 face_cache_size = 0; | |
86 } | |
87 | |
88 void ass_face_cache_done(void) | |
89 { | |
90 int i; | |
91 for (i = 0; i < face_cache_size; ++i) { | |
92 face_cache_item_t* item = face_cache + i; | |
93 if (item->face) FT_Done_Face(item->face); | |
94 if (item->path) free(item->path); | |
95 // FIXME: free desc ? | |
96 } | |
97 free(face_cache); | |
98 face_cache_size = 0; | |
99 } | |
100 | |
101 //--------------------------------- | |
102 // glyph cache | |
103 | |
104 #define GLYPH_HASH_SIZE (0xFFFF + 13) | |
105 | |
106 typedef struct glyph_hash_item_s { | |
107 glyph_hash_key_t key; | |
108 glyph_hash_val_t val; | |
109 struct glyph_hash_item_s* next; | |
110 } glyph_hash_item_t; | |
111 | |
112 typedef glyph_hash_item_t* glyph_hash_item_p; | |
113 | |
114 static glyph_hash_item_p* glyph_hash_root; | |
115 static int glyph_hash_size; | |
116 | |
117 static int glyph_compare(glyph_hash_key_t* a, glyph_hash_key_t* b) { | |
118 if (memcmp(a, b, sizeof(glyph_hash_key_t)) == 0) | |
119 return 1; | |
120 else | |
121 return 0; | |
122 } | |
123 | |
124 static unsigned glyph_hash(glyph_hash_key_t* key) { | |
125 unsigned val = 0; | |
126 unsigned i; | |
127 for (i = 0; i < sizeof(key->face); ++i) | |
128 val += *(unsigned char *)(&(key->face) + i); | |
129 val <<= 21; | |
130 | |
131 if (key->bitmap) val &= 0x80000000; | |
132 val += key->index; | |
133 val += key->size << 8; | |
134 val += key->outline << 3; | |
135 val += key->advance.x << 10; | |
136 val += key->advance.y << 16; | |
137 val += key->bold << 1; | |
138 val += key->italic << 20; | |
139 return val; | |
140 } | |
141 | |
142 /** | |
143 * \brief Add a glyph to glyph cache. | |
144 * \param key hash key | |
145 * \param val hash val: 2 bitmap glyphs + some additional info | |
146 */ | |
147 void cache_add_glyph(glyph_hash_key_t* key, glyph_hash_val_t* val) | |
148 { | |
149 unsigned hash = glyph_hash(key); | |
150 glyph_hash_item_t** next = glyph_hash_root + (hash % GLYPH_HASH_SIZE); | |
151 while (*next) { | |
152 if (glyph_compare(key, &((*next)->key))) | |
153 return; | |
154 next = &((*next)->next); | |
155 assert(next); | |
156 } | |
157 (*next) = malloc(sizeof(glyph_hash_item_t)); | |
158 // (*next)->desc = glyph_key_copy(key, &((*next)->key)); | |
159 memcpy(&((*next)->key), key, sizeof(glyph_hash_key_t)); | |
160 memcpy(&((*next)->val), val, sizeof(glyph_hash_val_t)); | |
161 (*next)->next = 0; | |
162 | |
163 glyph_hash_size ++; | |
164 /* if (glyph_hash_size && (glyph_hash_size % 25 == 0)) { | |
165 printf("\nGlyph cache: %d entries, %d bytes\n", glyph_hash_size, glyph_hash_size * sizeof(glyph_hash_item_t)); | |
166 } */ | |
167 } | |
168 | |
169 /** | |
170 * \brief Get a glyph from glyph cache. | |
171 * \param key hash key | |
172 * \return requested hash val or 0 if not found | |
173 */ | |
174 glyph_hash_val_t* cache_find_glyph(glyph_hash_key_t* key) | |
175 { | |
176 unsigned hash = glyph_hash(key); | |
177 glyph_hash_item_t* item = glyph_hash_root[hash % GLYPH_HASH_SIZE]; | |
178 while (item) { | |
179 if (glyph_compare(key, &(item->key))) { | |
180 return &(item->val); | |
181 } | |
182 item = item->next; | |
183 } | |
184 return 0; | |
185 } | |
186 | |
187 void ass_glyph_cache_init(void) | |
188 { | |
189 glyph_hash_root = calloc(GLYPH_HASH_SIZE, sizeof(glyph_hash_item_p)); | |
190 glyph_hash_size = 0; | |
191 } | |
192 | |
193 void ass_glyph_cache_done(void) | |
194 { | |
195 int i; | |
196 for (i = 0; i < GLYPH_HASH_SIZE; ++i) { | |
197 glyph_hash_item_t* item = glyph_hash_root[i]; | |
198 while (item) { | |
199 glyph_hash_item_t* next = item->next; | |
200 if (item->val.glyph) FT_Done_Glyph(item->val.glyph); | |
201 if (item->val.outline_glyph) FT_Done_Glyph(item->val.outline_glyph); | |
202 free(item); | |
203 item = next; | |
204 } | |
205 } | |
206 free(glyph_hash_root); | |
207 glyph_hash_size = 0; | |
208 } | |
209 |