Mercurial > mplayer.hg
annotate libass/ass_cache.c @ 31753:56f42d418bea
Split TV chapter in two.
This avoids a chapter without content apart from the (sub)sections.
author | diego |
---|---|
date | Sun, 25 Jul 2010 13:34:13 +0000 |
parents | 48d020c5ceca |
children | e64df5862cea |
rev | line source |
---|---|
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
1 /* |
26723 | 2 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
3 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
4 * This file is part of libass. |
26723 | 5 * |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
6 * libass is free software; you can redistribute it and/or modify |
26723 | 7 * it under the terms of the GNU General Public License as published by |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
11 * libass is distributed in the hope that it will be useful, |
26723 | 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License along | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
17 * with libass; if not, write to the Free Software Foundation, Inc., |
26723 | 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 */ | |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
20 |
18937 | 21 #include "config.h" |
22 | |
22292 | 23 #include <inttypes.h> |
18937 | 24 #include <ft2build.h> |
25 #include FT_FREETYPE_H | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
26 #include FT_GLYPH_H |
18937 | 27 |
28 #include <assert.h> | |
29 | |
30200 | 30 #include "ass_utils.h" |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21348
diff
changeset
|
31 #include "ass.h" |
18937 | 32 #include "ass_fontconfig.h" |
21322 | 33 #include "ass_font.h" |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
34 #include "ass_bitmap.h" |
18937 | 35 #include "ass_cache.h" |
36 | |
30200 | 37 static unsigned hashmap_hash(void *buf, size_t len) |
38 { | |
39 return fnv_32a_buf(buf, len, FNV1_32A_INIT); | |
40 } | |
23016 | 41 |
30200 | 42 static int hashmap_key_compare(void *a, void *b, size_t size) |
23016 | 43 { |
30200 | 44 return memcmp(a, b, size) == 0; |
23016 | 45 } |
30200 | 46 |
47 static void hashmap_item_dtor(void *key, size_t key_size, void *value, | |
48 size_t value_size) | |
23016 | 49 { |
30200 | 50 free(key); |
51 free(value); | |
23016 | 52 } |
53 | |
30200 | 54 Hashmap *hashmap_init(ASS_Library *library, size_t key_size, |
55 size_t value_size, int nbuckets, | |
56 HashmapItemDtor item_dtor, | |
57 HashmapKeyCompare key_compare, | |
58 HashmapHash hash) | |
23016 | 59 { |
30200 | 60 Hashmap *map = calloc(1, sizeof(Hashmap)); |
61 map->library = library; | |
62 map->nbuckets = nbuckets; | |
63 map->key_size = key_size; | |
64 map->value_size = value_size; | |
65 map->root = calloc(nbuckets, sizeof(hashmap_item_p)); | |
66 map->item_dtor = item_dtor ? item_dtor : hashmap_item_dtor; | |
67 map->key_compare = key_compare ? key_compare : hashmap_key_compare; | |
68 map->hash = hash ? hash : hashmap_hash; | |
69 return map; | |
23016 | 70 } |
18937 | 71 |
30200 | 72 void hashmap_done(Hashmap *map) |
23016 | 73 { |
30200 | 74 int i; |
75 // print stats | |
76 if (map->count > 0 || map->hit_count + map->miss_count > 0) | |
77 ass_msg(map->library, MSGL_V, | |
78 "cache statistics: \n total accesses: %d\n hits: %d\n " | |
79 "misses: %d\n object count: %d", | |
80 map->hit_count + map->miss_count, map->hit_count, | |
81 map->miss_count, map->count); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
82 |
30200 | 83 for (i = 0; i < map->nbuckets; ++i) { |
84 HashmapItem *item = map->root[i]; | |
85 while (item) { | |
86 HashmapItem *next = item->next; | |
87 map->item_dtor(item->key, map->key_size, item->value, | |
88 map->value_size); | |
89 free(item); | |
90 item = next; | |
91 } | |
92 } | |
93 free(map->root); | |
94 free(map); | |
23016 | 95 } |
18937 | 96 |
23016 | 97 // does nothing if key already exists |
30200 | 98 void *hashmap_insert(Hashmap *map, void *key, void *value) |
23016 | 99 { |
30200 | 100 unsigned hash = map->hash(key, map->key_size); |
101 HashmapItem **next = map->root + (hash % map->nbuckets); | |
102 while (*next) { | |
103 if (map->key_compare(key, (*next)->key, map->key_size)) | |
104 return (*next)->value; | |
105 next = &((*next)->next); | |
106 assert(next); | |
107 } | |
108 (*next) = malloc(sizeof(HashmapItem)); | |
109 (*next)->key = malloc(map->key_size); | |
110 (*next)->value = malloc(map->value_size); | |
111 memcpy((*next)->key, key, map->key_size); | |
112 memcpy((*next)->value, value, map->value_size); | |
113 (*next)->next = 0; | |
23016 | 114 |
30200 | 115 map->count++; |
116 return (*next)->value; | |
23016 | 117 } |
118 | |
30200 | 119 void *hashmap_find(Hashmap *map, void *key) |
23016 | 120 { |
30200 | 121 unsigned hash = map->hash(key, map->key_size); |
122 HashmapItem *item = map->root[hash % map->nbuckets]; | |
123 while (item) { | |
124 if (map->key_compare(key, item->key, map->key_size)) { | |
125 map->hit_count++; | |
126 return item->value; | |
127 } | |
128 item = item->next; | |
129 } | |
130 map->miss_count++; | |
131 return 0; | |
23016 | 132 } |
133 | |
134 //--------------------------------- | |
135 // font cache | |
136 | |
30200 | 137 static unsigned font_desc_hash(void *buf, size_t len) |
23016 | 138 { |
30200 | 139 ASS_FontDesc *desc = buf; |
140 unsigned hval; | |
141 hval = fnv_32a_str(desc->family, FNV1_32A_INIT); | |
142 hval = fnv_32a_buf(&desc->bold, sizeof(desc->bold), hval); | |
143 hval = fnv_32a_buf(&desc->italic, sizeof(desc->italic), hval); | |
144 return hval; | |
23016 | 145 } |
146 | |
30200 | 147 static int font_compare(void *key1, void *key2, size_t key_size) |
148 { | |
149 ASS_FontDesc *a = key1; | |
150 ASS_FontDesc *b = key2; | |
151 if (strcmp(a->family, b->family) != 0) | |
152 return 0; | |
153 if (a->bold != b->bold) | |
154 return 0; | |
155 if (a->italic != b->italic) | |
156 return 0; | |
157 if (a->treat_family_as_pattern != b->treat_family_as_pattern) | |
158 return 0; | |
159 return 1; | |
18937 | 160 } |
161 | |
30200 | 162 static void font_hash_dtor(void *key, size_t key_size, void *value, |
163 size_t value_size) | |
23016 | 164 { |
30200 | 165 ass_font_free(value); |
166 free(key); | |
23016 | 167 } |
168 | |
30200 | 169 ASS_Font *ass_font_cache_find(Hashmap *font_cache, |
170 ASS_FontDesc *desc) | |
18937 | 171 { |
30200 | 172 return hashmap_find(font_cache, desc); |
21317 | 173 } |
18937 | 174 |
21317 | 175 /** |
176 * \brief Add a face struct to cache. | |
177 * \param font font struct | |
178 */ | |
30200 | 179 void *ass_font_cache_add(Hashmap *font_cache, ASS_Font *font) |
21317 | 180 { |
30200 | 181 return hashmap_insert(font_cache, &(font->desc), font); |
18937 | 182 } |
183 | |
30200 | 184 Hashmap *ass_font_cache_init(ASS_Library *library) |
18937 | 185 { |
30200 | 186 Hashmap *font_cache; |
187 font_cache = hashmap_init(library, sizeof(ASS_FontDesc), | |
188 sizeof(ASS_Font), | |
189 1000, | |
190 font_hash_dtor, font_compare, font_desc_hash); | |
191 return font_cache; | |
18937 | 192 } |
193 | |
30200 | 194 void ass_font_cache_done(Hashmap *font_cache) |
18937 | 195 { |
30200 | 196 hashmap_done(font_cache); |
18937 | 197 } |
198 | |
30200 | 199 |
200 // Create hash/compare functions for bitmap and glyph | |
201 #define CREATE_HASH_FUNCTIONS | |
202 #include "ass_cache_template.h" | |
203 #define CREATE_COMPARISON_FUNCTIONS | |
204 #include "ass_cache_template.h" | |
205 | |
18937 | 206 //--------------------------------- |
23017 | 207 // bitmap cache |
18937 | 208 |
30200 | 209 static void bitmap_hash_dtor(void *key, size_t key_size, void *value, |
210 size_t value_size) | |
23016 | 211 { |
30200 | 212 BitmapHashValue *v = value; |
213 if (v->bm) | |
214 ass_free_bitmap(v->bm); | |
215 if (v->bm_o) | |
216 ass_free_bitmap(v->bm_o); | |
217 if (v->bm_s) | |
218 ass_free_bitmap(v->bm_s); | |
219 free(key); | |
220 free(value); | |
18937 | 221 } |
222 | |
30200 | 223 void *cache_add_bitmap(Hashmap *bitmap_cache, BitmapHashKey *key, |
224 BitmapHashValue *val) | |
18937 | 225 { |
30200 | 226 // Note: this is only an approximation |
227 if (val->bm_o) | |
228 bitmap_cache->cache_size += val->bm_o->w * val->bm_o->h * 3; | |
229 else if (val->bm) | |
230 bitmap_cache->cache_size += val->bm->w * val->bm->h * 3; | |
231 | |
232 return hashmap_insert(bitmap_cache, key, val); | |
18937 | 233 } |
234 | |
235 /** | |
23017 | 236 * \brief Get a bitmap from bitmap cache. |
18937 | 237 * \param key hash key |
238 * \return requested hash val or 0 if not found | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
239 */ |
30200 | 240 BitmapHashValue *cache_find_bitmap(Hashmap *bitmap_cache, |
241 BitmapHashKey *key) | |
18937 | 242 { |
30200 | 243 return hashmap_find(bitmap_cache, key); |
18937 | 244 } |
245 | |
30200 | 246 Hashmap *ass_bitmap_cache_init(ASS_Library *library) |
18937 | 247 { |
30200 | 248 Hashmap *bitmap_cache; |
249 bitmap_cache = hashmap_init(library, | |
250 sizeof(BitmapHashKey), | |
251 sizeof(BitmapHashValue), | |
252 0xFFFF + 13, | |
253 bitmap_hash_dtor, bitmap_compare, | |
254 bitmap_hash); | |
255 return bitmap_cache; | |
18937 | 256 } |
257 | |
30200 | 258 void ass_bitmap_cache_done(Hashmap *bitmap_cache) |
18937 | 259 { |
30200 | 260 hashmap_done(bitmap_cache); |
18937 | 261 } |
262 | |
30200 | 263 Hashmap *ass_bitmap_cache_reset(Hashmap *bitmap_cache) |
19539 | 264 { |
30200 | 265 ASS_Library *lib = bitmap_cache->library; |
266 | |
267 ass_bitmap_cache_done(bitmap_cache); | |
268 return ass_bitmap_cache_init(lib); | |
19539 | 269 } |
270 | |
23018 | 271 //--------------------------------- |
272 // glyph cache | |
273 | |
30200 | 274 static void glyph_hash_dtor(void *key, size_t key_size, void *value, |
275 size_t value_size) | |
23018 | 276 { |
30200 | 277 GlyphHashValue *v = value; |
278 if (v->glyph) | |
279 FT_Done_Glyph(v->glyph); | |
280 if (v->outline_glyph) | |
281 FT_Done_Glyph(v->outline_glyph); | |
282 free(key); | |
283 free(value); | |
23018 | 284 } |
285 | |
30200 | 286 void *cache_add_glyph(Hashmap *glyph_cache, GlyphHashKey *key, |
287 GlyphHashValue *val) | |
23018 | 288 { |
30200 | 289 return hashmap_insert(glyph_cache, key, val); |
23018 | 290 } |
291 | |
292 /** | |
293 * \brief Get a glyph from glyph cache. | |
294 * \param key hash key | |
295 * \return requested hash val or 0 if not found | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
296 */ |
30200 | 297 GlyphHashValue *cache_find_glyph(Hashmap *glyph_cache, |
298 GlyphHashKey *key) | |
23018 | 299 { |
30200 | 300 return hashmap_find(glyph_cache, key); |
23018 | 301 } |
302 | |
30200 | 303 Hashmap *ass_glyph_cache_init(ASS_Library *library) |
23018 | 304 { |
30200 | 305 Hashmap *glyph_cache; |
306 glyph_cache = hashmap_init(library, sizeof(GlyphHashKey), | |
307 sizeof(GlyphHashValue), | |
308 0xFFFF + 13, | |
309 glyph_hash_dtor, glyph_compare, glyph_hash); | |
310 return glyph_cache; | |
23018 | 311 } |
312 | |
30200 | 313 void ass_glyph_cache_done(Hashmap *glyph_cache) |
23018 | 314 { |
30200 | 315 hashmap_done(glyph_cache); |
23018 | 316 } |
317 | |
30200 | 318 Hashmap *ass_glyph_cache_reset(Hashmap *glyph_cache) |
23018 | 319 { |
30200 | 320 ASS_Library *lib = glyph_cache->library; |
321 | |
322 ass_glyph_cache_done(glyph_cache); | |
323 return ass_glyph_cache_init(lib); | |
23018 | 324 } |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
325 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
326 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
327 //--------------------------------- |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
328 // composite cache |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
329 |
30200 | 330 static void composite_hash_dtor(void *key, size_t key_size, void *value, |
331 size_t value_size) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
332 { |
30200 | 333 CompositeHashValue *v = value; |
334 free(v->a); | |
335 free(v->b); | |
336 free(key); | |
337 free(value); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
338 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
339 |
30200 | 340 void *cache_add_composite(Hashmap *composite_cache, |
341 CompositeHashKey *key, | |
342 CompositeHashValue *val) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
343 { |
30200 | 344 return hashmap_insert(composite_cache, key, val); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
345 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
346 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
347 /** |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
348 * \brief Get a composite bitmap from composite cache. |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
349 * \param key hash key |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
350 * \return requested hash val or 0 if not found |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
351 */ |
30200 | 352 CompositeHashValue *cache_find_composite(Hashmap *composite_cache, |
353 CompositeHashKey *key) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
354 { |
30200 | 355 return hashmap_find(composite_cache, key); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
356 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
357 |
30200 | 358 Hashmap *ass_composite_cache_init(ASS_Library *library) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
359 { |
30200 | 360 Hashmap *composite_cache; |
361 composite_cache = hashmap_init(library, sizeof(CompositeHashKey), | |
362 sizeof(CompositeHashValue), | |
363 0xFFFF + 13, | |
364 composite_hash_dtor, composite_compare, | |
365 composite_hash); | |
366 return composite_cache; | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
367 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
368 |
30200 | 369 void ass_composite_cache_done(Hashmap *composite_cache) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
370 { |
30200 | 371 hashmap_done(composite_cache); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
372 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
373 |
30200 | 374 Hashmap *ass_composite_cache_reset(Hashmap *composite_cache) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
375 { |
30200 | 376 ASS_Library *lib = composite_cache->library; |
377 | |
378 ass_composite_cache_done(composite_cache); | |
379 return ass_composite_cache_init(lib); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
380 } |