Mercurial > mplayer.hg
annotate libass/ass_cache.c @ 34042:89ad6c0928cf
Support act files with -demuxer lavf.
author | cehoyos |
---|---|
date | Sun, 25 Sep 2011 09:55:30 +0000 |
parents | 88eebbbbd6a0 |
children | 6e7f60f6f9d4 |
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 * |
34011 | 6 * Permission to use, copy, modify, and distribute this software for any |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
26723 | 9 * |
34011 | 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
26723 | 17 */ |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
18 |
18937 | 19 #include "config.h" |
20 | |
22292 | 21 #include <inttypes.h> |
18937 | 22 #include <ft2build.h> |
23 #include FT_FREETYPE_H | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
24 #include FT_GLYPH_H |
18937 | 25 |
26 #include <assert.h> | |
27 | |
30200 | 28 #include "ass_utils.h" |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21348
diff
changeset
|
29 #include "ass.h" |
18937 | 30 #include "ass_fontconfig.h" |
21322 | 31 #include "ass_font.h" |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
32 #include "ass_bitmap.h" |
18937 | 33 #include "ass_cache.h" |
34 | |
30200 | 35 static unsigned hashmap_hash(void *buf, size_t len) |
36 { | |
37 return fnv_32a_buf(buf, len, FNV1_32A_INIT); | |
38 } | |
23016 | 39 |
30200 | 40 static int hashmap_key_compare(void *a, void *b, size_t size) |
23016 | 41 { |
30200 | 42 return memcmp(a, b, size) == 0; |
23016 | 43 } |
30200 | 44 |
45 static void hashmap_item_dtor(void *key, size_t key_size, void *value, | |
46 size_t value_size) | |
23016 | 47 { |
30200 | 48 free(key); |
49 free(value); | |
23016 | 50 } |
51 | |
30200 | 52 Hashmap *hashmap_init(ASS_Library *library, size_t key_size, |
53 size_t value_size, int nbuckets, | |
54 HashmapItemDtor item_dtor, | |
55 HashmapKeyCompare key_compare, | |
56 HashmapHash hash) | |
23016 | 57 { |
30200 | 58 Hashmap *map = calloc(1, sizeof(Hashmap)); |
59 map->library = library; | |
60 map->nbuckets = nbuckets; | |
61 map->key_size = key_size; | |
62 map->value_size = value_size; | |
63 map->root = calloc(nbuckets, sizeof(hashmap_item_p)); | |
64 map->item_dtor = item_dtor ? item_dtor : hashmap_item_dtor; | |
65 map->key_compare = key_compare ? key_compare : hashmap_key_compare; | |
66 map->hash = hash ? hash : hashmap_hash; | |
67 return map; | |
23016 | 68 } |
18937 | 69 |
30200 | 70 void hashmap_done(Hashmap *map) |
23016 | 71 { |
30200 | 72 int i; |
73 // print stats | |
74 if (map->count > 0 || map->hit_count + map->miss_count > 0) | |
75 ass_msg(map->library, MSGL_V, | |
76 "cache statistics: \n total accesses: %d\n hits: %d\n " | |
77 "misses: %d\n object count: %d", | |
78 map->hit_count + map->miss_count, map->hit_count, | |
79 map->miss_count, map->count); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
80 |
30200 | 81 for (i = 0; i < map->nbuckets; ++i) { |
82 HashmapItem *item = map->root[i]; | |
83 while (item) { | |
84 HashmapItem *next = item->next; | |
85 map->item_dtor(item->key, map->key_size, item->value, | |
86 map->value_size); | |
87 free(item); | |
88 item = next; | |
89 } | |
90 } | |
91 free(map->root); | |
92 free(map); | |
23016 | 93 } |
18937 | 94 |
23016 | 95 // does nothing if key already exists |
30200 | 96 void *hashmap_insert(Hashmap *map, void *key, void *value) |
23016 | 97 { |
30200 | 98 unsigned hash = map->hash(key, map->key_size); |
99 HashmapItem **next = map->root + (hash % map->nbuckets); | |
100 while (*next) { | |
101 if (map->key_compare(key, (*next)->key, map->key_size)) | |
102 return (*next)->value; | |
103 next = &((*next)->next); | |
104 assert(next); | |
105 } | |
106 (*next) = malloc(sizeof(HashmapItem)); | |
107 (*next)->key = malloc(map->key_size); | |
108 (*next)->value = malloc(map->value_size); | |
109 memcpy((*next)->key, key, map->key_size); | |
110 memcpy((*next)->value, value, map->value_size); | |
111 (*next)->next = 0; | |
23016 | 112 |
30200 | 113 map->count++; |
114 return (*next)->value; | |
23016 | 115 } |
116 | |
30200 | 117 void *hashmap_find(Hashmap *map, void *key) |
23016 | 118 { |
30200 | 119 unsigned hash = map->hash(key, map->key_size); |
120 HashmapItem *item = map->root[hash % map->nbuckets]; | |
121 while (item) { | |
122 if (map->key_compare(key, item->key, map->key_size)) { | |
123 map->hit_count++; | |
124 return item->value; | |
125 } | |
126 item = item->next; | |
127 } | |
128 map->miss_count++; | |
129 return 0; | |
23016 | 130 } |
131 | |
132 //--------------------------------- | |
133 // font cache | |
134 | |
30200 | 135 static unsigned font_desc_hash(void *buf, size_t len) |
23016 | 136 { |
30200 | 137 ASS_FontDesc *desc = buf; |
138 unsigned hval; | |
139 hval = fnv_32a_str(desc->family, FNV1_32A_INIT); | |
140 hval = fnv_32a_buf(&desc->bold, sizeof(desc->bold), hval); | |
141 hval = fnv_32a_buf(&desc->italic, sizeof(desc->italic), hval); | |
142 return hval; | |
23016 | 143 } |
144 | |
30200 | 145 static int font_compare(void *key1, void *key2, size_t key_size) |
146 { | |
147 ASS_FontDesc *a = key1; | |
148 ASS_FontDesc *b = key2; | |
149 if (strcmp(a->family, b->family) != 0) | |
150 return 0; | |
151 if (a->bold != b->bold) | |
152 return 0; | |
153 if (a->italic != b->italic) | |
154 return 0; | |
155 if (a->treat_family_as_pattern != b->treat_family_as_pattern) | |
156 return 0; | |
31853 | 157 if (a->vertical != b->vertical) |
158 return 0; | |
30200 | 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 { |
31853 | 289 if (val->glyph && val->glyph->format == FT_GLYPH_FORMAT_BITMAP) { |
290 FT_Bitmap *bitmap = &((FT_BitmapGlyph) val->glyph)->bitmap; | |
291 glyph_cache->cache_size += bitmap->rows * bitmap->pitch; | |
292 } | |
293 | |
30200 | 294 return hashmap_insert(glyph_cache, key, val); |
23018 | 295 } |
296 | |
297 /** | |
298 * \brief Get a glyph from glyph cache. | |
299 * \param key hash key | |
300 * \return requested hash val or 0 if not found | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
301 */ |
30200 | 302 GlyphHashValue *cache_find_glyph(Hashmap *glyph_cache, |
303 GlyphHashKey *key) | |
23018 | 304 { |
30200 | 305 return hashmap_find(glyph_cache, key); |
23018 | 306 } |
307 | |
30200 | 308 Hashmap *ass_glyph_cache_init(ASS_Library *library) |
23018 | 309 { |
30200 | 310 Hashmap *glyph_cache; |
311 glyph_cache = hashmap_init(library, sizeof(GlyphHashKey), | |
312 sizeof(GlyphHashValue), | |
313 0xFFFF + 13, | |
314 glyph_hash_dtor, glyph_compare, glyph_hash); | |
315 return glyph_cache; | |
23018 | 316 } |
317 | |
30200 | 318 void ass_glyph_cache_done(Hashmap *glyph_cache) |
23018 | 319 { |
30200 | 320 hashmap_done(glyph_cache); |
23018 | 321 } |
322 | |
30200 | 323 Hashmap *ass_glyph_cache_reset(Hashmap *glyph_cache) |
23018 | 324 { |
30200 | 325 ASS_Library *lib = glyph_cache->library; |
326 | |
327 ass_glyph_cache_done(glyph_cache); | |
328 return ass_glyph_cache_init(lib); | |
23018 | 329 } |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
330 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
331 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
332 //--------------------------------- |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
333 // composite cache |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
334 |
30200 | 335 static void composite_hash_dtor(void *key, size_t key_size, void *value, |
336 size_t value_size) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
337 { |
30200 | 338 CompositeHashValue *v = value; |
339 free(v->a); | |
340 free(v->b); | |
341 free(key); | |
342 free(value); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
343 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
344 |
30200 | 345 void *cache_add_composite(Hashmap *composite_cache, |
346 CompositeHashKey *key, | |
347 CompositeHashValue *val) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
348 { |
30200 | 349 return hashmap_insert(composite_cache, key, val); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
350 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
351 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
352 /** |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
353 * \brief Get a composite bitmap from composite cache. |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
354 * \param key hash key |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
355 * \return requested hash val or 0 if not found |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
356 */ |
30200 | 357 CompositeHashValue *cache_find_composite(Hashmap *composite_cache, |
358 CompositeHashKey *key) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
359 { |
30200 | 360 return hashmap_find(composite_cache, key); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
361 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
362 |
30200 | 363 Hashmap *ass_composite_cache_init(ASS_Library *library) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
364 { |
30200 | 365 Hashmap *composite_cache; |
366 composite_cache = hashmap_init(library, sizeof(CompositeHashKey), | |
367 sizeof(CompositeHashValue), | |
368 0xFFFF + 13, | |
369 composite_hash_dtor, composite_compare, | |
370 composite_hash); | |
371 return 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 void ass_composite_cache_done(Hashmap *composite_cache) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
375 { |
30200 | 376 hashmap_done(composite_cache); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
377 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
378 |
30200 | 379 Hashmap *ass_composite_cache_reset(Hashmap *composite_cache) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
380 { |
30200 | 381 ASS_Library *lib = composite_cache->library; |
382 | |
383 ass_composite_cache_done(composite_cache); | |
384 return ass_composite_cache_init(lib); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
385 } |