Mercurial > mplayer.hg
annotate libass/ass_cache.c @ 36730:8bc4d669c5d7
Enable option font_encoding without freetype.
subtitle_font_encoding is now also used when freetype is disabled.
This is corresponding to r36825, although the GUI doesn't support
changing the option through the preferences in this case (but it's
in gui.conf at least).
author | ib |
---|---|
date | Thu, 13 Feb 2014 10:41:33 +0000 |
parents | 6e7f60f6f9d4 |
children |
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> |
34295 | 3 * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx> |
26723 | 4 * |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
5 * This file is part of libass. |
26723 | 6 * |
34011 | 7 * Permission to use, copy, modify, and distribute this software for any |
8 * purpose with or without fee is hereby granted, provided that the above | |
9 * copyright notice and this permission notice appear in all copies. | |
26723 | 10 * |
34011 | 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
26723 | 18 */ |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
19 |
18937 | 20 #include "config.h" |
21 | |
22292 | 22 #include <inttypes.h> |
18937 | 23 #include <ft2build.h> |
34295 | 24 #include FT_OUTLINE_H |
18937 | 25 #include <assert.h> |
26 | |
30200 | 27 #include "ass_utils.h" |
21322 | 28 #include "ass_font.h" |
18937 | 29 #include "ass_cache.h" |
30 | |
34295 | 31 // type-specific functions |
32 // create hash/compare functions for bitmap, outline and composite cache | |
33 #define CREATE_HASH_FUNCTIONS | |
34 #include "ass_cache_template.h" | |
35 #define CREATE_COMPARISON_FUNCTIONS | |
36 #include "ass_cache_template.h" | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
37 |
23016 | 38 // font cache |
34295 | 39 static unsigned font_hash(void *buf, size_t len) |
23016 | 40 { |
30200 | 41 ASS_FontDesc *desc = buf; |
42 unsigned hval; | |
43 hval = fnv_32a_str(desc->family, FNV1_32A_INIT); | |
44 hval = fnv_32a_buf(&desc->bold, sizeof(desc->bold), hval); | |
45 hval = fnv_32a_buf(&desc->italic, sizeof(desc->italic), hval); | |
34295 | 46 hval = fnv_32a_buf(&desc->treat_family_as_pattern, |
47 sizeof(desc->treat_family_as_pattern), hval); | |
48 hval = fnv_32a_buf(&desc->vertical, sizeof(desc->vertical), hval); | |
30200 | 49 return hval; |
23016 | 50 } |
51 | |
34295 | 52 static unsigned font_compare(void *key1, void *key2, size_t key_size) |
30200 | 53 { |
54 ASS_FontDesc *a = key1; | |
55 ASS_FontDesc *b = key2; | |
56 if (strcmp(a->family, b->family) != 0) | |
57 return 0; | |
58 if (a->bold != b->bold) | |
59 return 0; | |
60 if (a->italic != b->italic) | |
61 return 0; | |
62 if (a->treat_family_as_pattern != b->treat_family_as_pattern) | |
63 return 0; | |
31853 | 64 if (a->vertical != b->vertical) |
65 return 0; | |
30200 | 66 return 1; |
18937 | 67 } |
68 | |
34295 | 69 static void font_destruct(void *key, void *value) |
23016 | 70 { |
30200 | 71 ass_font_free(value); |
72 free(key); | |
23016 | 73 } |
74 | |
23017 | 75 // bitmap cache |
34295 | 76 static void bitmap_destruct(void *key, void *value) |
23016 | 77 { |
30200 | 78 BitmapHashValue *v = value; |
34295 | 79 BitmapHashKey *k = key; |
30200 | 80 if (v->bm) |
81 ass_free_bitmap(v->bm); | |
82 if (v->bm_o) | |
83 ass_free_bitmap(v->bm_o); | |
84 if (v->bm_s) | |
85 ass_free_bitmap(v->bm_s); | |
34295 | 86 if (k->type == BITMAP_CLIP) |
87 free(k->u.clip.text); | |
30200 | 88 free(key); |
89 free(value); | |
18937 | 90 } |
91 | |
34295 | 92 static size_t bitmap_size(void *value, size_t value_size) |
18937 | 93 { |
34295 | 94 BitmapHashValue *val = value; |
95 if (val->bm_o) | |
96 return val->bm_o->w * val->bm_o->h * 3; | |
97 else if (val->bm) | |
98 return val->bm->w * val->bm->h * 3; | |
99 return 0; | |
19539 | 100 } |
101 | |
34295 | 102 static unsigned bitmap_hash(void *key, size_t key_size) |
23018 | 103 { |
34295 | 104 BitmapHashKey *k = key; |
105 switch (k->type) { | |
106 case BITMAP_OUTLINE: return outline_bitmap_hash(&k->u, key_size); | |
107 case BITMAP_CLIP: return clip_bitmap_hash(&k->u, key_size); | |
108 default: return 0; | |
109 } | |
23018 | 110 } |
111 | |
34295 | 112 static unsigned bitmap_compare (void *a, void *b, size_t key_size) |
23018 | 113 { |
34295 | 114 BitmapHashKey *ak = a; |
115 BitmapHashKey *bk = b; | |
116 if (ak->type != bk->type) return 0; | |
117 switch (ak->type) { | |
118 case BITMAP_OUTLINE: return outline_bitmap_compare(&ak->u, &bk->u, key_size); | |
119 case BITMAP_CLIP: return clip_bitmap_compare(&ak->u, &bk->u, key_size); | |
120 default: return 0; | |
121 } | |
23018 | 122 } |
123 | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
124 // composite cache |
34295 | 125 static void composite_destruct(void *key, void *value) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
126 { |
30200 | 127 CompositeHashValue *v = value; |
128 free(v->a); | |
129 free(v->b); | |
130 free(key); | |
131 free(value); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
132 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
133 |
34295 | 134 // outline cache |
135 | |
136 static unsigned outline_hash(void *key, size_t key_size) | |
137 { | |
138 OutlineHashKey *k = key; | |
139 switch (k->type) { | |
140 case OUTLINE_GLYPH: return glyph_hash(&k->u, key_size); | |
141 case OUTLINE_DRAWING: return drawing_hash(&k->u, key_size); | |
142 default: return 0; | |
143 } | |
144 } | |
145 | |
146 static unsigned outline_compare(void *a, void *b, size_t key_size) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
147 { |
34295 | 148 OutlineHashKey *ak = a; |
149 OutlineHashKey *bk = b; | |
150 if (ak->type != bk->type) return 0; | |
151 switch (ak->type) { | |
152 case OUTLINE_GLYPH: return glyph_compare(&ak->u, &bk->u, key_size); | |
153 case OUTLINE_DRAWING: return drawing_compare(&ak->u, &bk->u, key_size); | |
154 default: return 0; | |
155 } | |
156 } | |
157 | |
158 static void outline_destruct(void *key, void *value) | |
159 { | |
160 OutlineHashValue *v = value; | |
161 OutlineHashKey *k = key; | |
162 if (v->outline) | |
163 outline_free(v->lib, v->outline); | |
164 if (v->border) | |
165 outline_free(v->lib, v->border); | |
166 if (k->type == OUTLINE_DRAWING) | |
167 free(k->u.drawing.text); | |
168 free(key); | |
169 free(value); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
170 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
171 |
34295 | 172 |
173 | |
174 // Cache data | |
175 typedef struct cache_item { | |
176 void *key; | |
177 void *value; | |
178 struct cache_item *next; | |
179 } CacheItem; | |
180 | |
181 struct cache { | |
182 unsigned buckets; | |
183 CacheItem **map; | |
184 | |
185 HashFunction hash_func; | |
186 ItemSize size_func; | |
187 HashCompare compare_func; | |
188 CacheItemDestructor destruct_func; | |
189 size_t key_size; | |
190 size_t value_size; | |
191 | |
192 size_t cache_size; | |
193 unsigned hits; | |
194 unsigned misses; | |
195 unsigned items; | |
196 }; | |
197 | |
198 // Hash for a simple (single value or array) type | |
199 static unsigned hash_simple(void *key, size_t key_size) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
200 { |
34295 | 201 return fnv_32a_buf(key, key_size, FNV1_32A_INIT); |
202 } | |
203 | |
204 // Comparison of a simple type | |
205 static unsigned compare_simple(void *a, void *b, size_t key_size) | |
206 { | |
207 return memcmp(a, b, key_size) == 0; | |
208 } | |
209 | |
210 // Default destructor | |
211 static void destruct_simple(void *key, void *value) | |
212 { | |
213 free(key); | |
214 free(value); | |
215 } | |
216 | |
217 | |
218 // Create a cache with type-specific hash/compare/destruct/size functions | |
219 Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func, | |
220 CacheItemDestructor destruct_func, ItemSize size_func, | |
221 size_t key_size, size_t value_size) | |
222 { | |
223 Cache *cache = calloc(1, sizeof(*cache)); | |
224 cache->buckets = 0xFFFF; | |
225 cache->hash_func = hash_simple; | |
226 cache->compare_func = compare_simple; | |
227 cache->destruct_func = destruct_simple; | |
228 cache->size_func = size_func; | |
229 if (hash_func) | |
230 cache->hash_func = hash_func; | |
231 if (compare_func) | |
232 cache->compare_func = compare_func; | |
233 if (destruct_func) | |
234 cache->destruct_func = destruct_func; | |
235 cache->key_size = key_size; | |
236 cache->value_size = value_size; | |
237 cache->map = calloc(cache->buckets, sizeof(CacheItem *)); | |
238 | |
239 return cache; | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
240 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
241 |
34295 | 242 void *ass_cache_put(Cache *cache, void *key, void *value) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
243 { |
34295 | 244 unsigned bucket = cache->hash_func(key, cache->key_size) % cache->buckets; |
245 CacheItem **item = &cache->map[bucket]; | |
246 while (*item) | |
247 item = &(*item)->next; | |
248 (*item) = calloc(1, sizeof(CacheItem)); | |
249 (*item)->key = malloc(cache->key_size); | |
250 (*item)->value = malloc(cache->value_size); | |
251 memcpy((*item)->key, key, cache->key_size); | |
252 memcpy((*item)->value, value, cache->value_size); | |
253 | |
254 cache->items++; | |
255 if (cache->size_func) | |
256 cache->cache_size += cache->size_func(value, cache->value_size); | |
257 else | |
258 cache->cache_size++; | |
259 | |
260 return (*item)->value; | |
261 } | |
262 | |
263 void *ass_cache_get(Cache *cache, void *key) | |
264 { | |
265 unsigned bucket = cache->hash_func(key, cache->key_size) % cache->buckets; | |
266 CacheItem *item = cache->map[bucket]; | |
267 while (item) { | |
268 if (cache->compare_func(key, item->key, cache->key_size)) { | |
269 cache->hits++; | |
270 return item->value; | |
271 } | |
272 item = item->next; | |
273 } | |
274 cache->misses++; | |
275 return NULL; | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
276 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
277 |
34295 | 278 int ass_cache_empty(Cache *cache, size_t max_size) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
279 { |
34295 | 280 int i; |
281 | |
282 if (cache->cache_size < max_size) | |
283 return 0; | |
284 | |
285 for (i = 0; i < cache->buckets; i++) { | |
286 CacheItem *item = cache->map[i]; | |
287 while (item) { | |
288 CacheItem *next = item->next; | |
289 cache->destruct_func(item->key, item->value); | |
290 free(item); | |
291 item = next; | |
292 } | |
293 cache->map[i] = NULL; | |
294 } | |
295 | |
296 cache->items = cache->hits = cache->misses = cache->cache_size = 0; | |
297 | |
298 return 1; | |
299 } | |
300 | |
301 void ass_cache_stats(Cache *cache, size_t *size, unsigned *hits, | |
302 unsigned *misses, unsigned *count) | |
303 { | |
304 if (size) | |
305 *size = cache->cache_size; | |
306 if (hits) | |
307 *hits = cache->hits; | |
308 if (misses) | |
309 *misses = cache->misses; | |
310 if (count) | |
311 *count = cache->items; | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
312 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
313 |
34295 | 314 void ass_cache_done(Cache *cache) |
315 { | |
316 ass_cache_empty(cache, 0); | |
317 free(cache->map); | |
318 free(cache); | |
319 } | |
320 | |
321 // Type-specific creation function | |
322 Cache *ass_font_cache_create(void) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
323 { |
34295 | 324 return ass_cache_create(font_hash, font_compare, font_destruct, |
325 (ItemSize)NULL, sizeof(ASS_FontDesc), sizeof(ASS_Font)); | |
326 } | |
327 | |
328 Cache *ass_outline_cache_create(void) | |
329 { | |
330 return ass_cache_create(outline_hash, outline_compare, outline_destruct, | |
331 NULL, sizeof(OutlineHashKey), sizeof(OutlineHashValue)); | |
332 } | |
30200 | 333 |
34295 | 334 Cache *ass_glyph_metrics_cache_create(void) |
335 { | |
336 return ass_cache_create(glyph_metrics_hash, glyph_metrics_compare, NULL, | |
337 (ItemSize) NULL, sizeof(GlyphMetricsHashKey), | |
338 sizeof(GlyphMetricsHashValue)); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
339 } |
34295 | 340 |
341 Cache *ass_bitmap_cache_create(void) | |
342 { | |
343 return ass_cache_create(bitmap_hash, bitmap_compare, bitmap_destruct, | |
344 bitmap_size, sizeof(BitmapHashKey), sizeof(BitmapHashValue)); | |
345 } | |
346 | |
347 Cache *ass_composite_cache_create(void) | |
348 { | |
349 return ass_cache_create(composite_hash, composite_compare, | |
350 composite_destruct, (ItemSize)NULL, sizeof(CompositeHashKey), | |
351 sizeof(CompositeHashValue)); | |
352 } |