Mercurial > mplayer.hg
annotate libass/ass_cache.c @ 21265:4e7a7dea3e1f
Rename:
face_desc_t -> ass_font_desc_t
face_cache_item_t -> ass_font_t
*face* -> *font*
| author | eugeni |
|---|---|
| date | Sun, 26 Nov 2006 20:34:54 +0000 |
| parents | 6196ba31e97e |
| children | cda1a5ebc150 |
| rev | line source |
|---|---|
|
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
1 // -*- c-basic-offset: 8; indent-tabs-mode: t -*- |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
2 // vim:ts=8:sw=8:noet:ai: |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
3 /* |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
4 Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
5 |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
6 This program is free software; you can redistribute it and/or modify |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
7 it under the terms of the GNU General Public License as published by |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
8 the Free Software Foundation; either version 2 of the License, or |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
9 (at your option) any later version. |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
10 |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
11 This program is distributed in the hope that it will be useful, |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
14 GNU General Public License for more details. |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
15 |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
16 You should have received a copy of the GNU General Public License |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
17 along with this program; if not, write to the Free Software |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
19 */ |
|
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 | |
| 23 #include <ft2build.h> | |
| 24 #include FT_FREETYPE_H | |
|
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
25 #include FT_GLYPH_H |
| 18937 | 26 |
| 27 #include <assert.h> | |
| 28 | |
|
21026
d138463e820b
Collect all includes of mplayer headers in libass in a single file (mputils.h).
eugeni
parents:
20637
diff
changeset
|
29 #include "mputils.h" |
| 18937 | 30 #include "ass_fontconfig.h" |
|
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
31 #include "ass_bitmap.h" |
| 18937 | 32 #include "ass_cache.h" |
| 33 | |
| 34 | |
| 21265 | 35 typedef struct ass_font_s { |
| 36 ass_font_desc_t desc; | |
| 18937 | 37 char* path; |
| 38 int index; | |
| 39 FT_Face face; | |
| 21265 | 40 } ass_font_t; |
| 18937 | 41 |
| 21265 | 42 #define MAX_FONT_CACHE_SIZE 100 |
| 18937 | 43 |
| 21265 | 44 static ass_font_t* font_cache; |
| 45 static int font_cache_size; | |
| 18937 | 46 |
| 47 extern int no_more_font_messages; | |
| 48 | |
| 21265 | 49 static int font_compare(ass_font_desc_t* a, ass_font_desc_t* b) { |
| 18937 | 50 if (strcmp(a->family, b->family) != 0) |
| 51 return 0; | |
| 52 if (a->bold != b->bold) | |
| 53 return 0; | |
| 54 if (a->italic != b->italic) | |
| 55 return 0; | |
| 56 return 1; | |
| 57 } | |
| 58 | |
| 59 /** | |
| 20637 | 60 * Select Microfost Unicode CharMap, if the font has one. |
| 61 * Otherwise, let FreeType decide. | |
| 62 */ | |
| 63 static void charmap_magic(FT_Face face) | |
| 64 { | |
| 65 int i; | |
| 66 for (i = 0; i < face->num_charmaps; ++i) { | |
| 67 FT_CharMap cmap = face->charmaps[i]; | |
| 68 unsigned pid = cmap->platform_id; | |
| 69 unsigned eid = cmap->encoding_id; | |
| 70 if (pid == 3 /*microsoft*/ && (eid == 1 /*unicode bmp*/ || eid == 10 /*full unicode*/)) { | |
| 71 FT_Set_Charmap(face, cmap); | |
| 72 break; | |
| 73 } | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 /** | |
| 18937 | 78 * \brief Get a face object, either from cache or created through FreeType+FontConfig. |
| 79 * \param library FreeType library object | |
| 80 * \param fontconfig_priv fontconfig private data | |
| 81 * \param desc required face description | |
| 82 * \param face out: the face object | |
| 83 */ | |
| 21265 | 84 int ass_new_font(FT_Library library, void* fontconfig_priv, ass_font_desc_t* desc, /*out*/ FT_Face* face) |
| 18937 | 85 { |
| 86 FT_Error error; | |
| 87 int i; | |
| 88 char* path; | |
| 89 int index; | |
| 21265 | 90 ass_font_t* item; |
| 18937 | 91 |
| 21265 | 92 for (i=0; i<font_cache_size; ++i) |
| 93 if (font_compare(desc, &(font_cache[i].desc))) { | |
| 94 *face = font_cache[i].face; | |
| 18937 | 95 return 0; |
| 96 } | |
| 97 | |
| 21265 | 98 if (font_cache_size == MAX_FONT_CACHE_SIZE) { |
| 21066 | 99 mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_TooManyFonts); |
| 18937 | 100 return 1; |
| 101 } | |
| 102 | |
| 103 path = fontconfig_select(fontconfig_priv, desc->family, desc->bold, desc->italic, &index); | |
| 104 | |
| 105 error = FT_New_Face(library, path, index, face); | |
| 106 if (error) { | |
| 107 if (!no_more_font_messages) | |
| 21066 | 108 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningFont, path, index); |
| 18937 | 109 no_more_font_messages = 1; |
| 110 return 1; | |
| 111 } | |
| 20637 | 112 |
| 113 charmap_magic(*face); | |
| 18937 | 114 |
| 21265 | 115 item = font_cache + font_cache_size; |
| 18937 | 116 item->path = strdup(path); |
| 117 item->index = index; | |
| 118 item->face = *face; | |
| 21265 | 119 memcpy(&(item->desc), desc, sizeof(font_desc_t)); |
| 120 font_cache_size++; | |
| 18937 | 121 return 0; |
| 122 } | |
| 123 | |
| 21265 | 124 void ass_font_cache_init(void) |
| 18937 | 125 { |
| 21265 | 126 font_cache = calloc(MAX_FONT_CACHE_SIZE, sizeof(ass_font_t)); |
| 127 font_cache_size = 0; | |
| 18937 | 128 } |
| 129 | |
| 21265 | 130 void ass_font_cache_done(void) |
| 18937 | 131 { |
| 132 int i; | |
| 21265 | 133 for (i = 0; i < font_cache_size; ++i) { |
| 134 ass_font_t* item = font_cache + i; | |
| 18937 | 135 if (item->face) FT_Done_Face(item->face); |
| 136 if (item->path) free(item->path); | |
| 137 // FIXME: free desc ? | |
| 138 } | |
| 21265 | 139 free(font_cache); |
| 140 font_cache_size = 0; | |
| 18937 | 141 } |
| 142 | |
| 143 //--------------------------------- | |
| 144 // glyph cache | |
| 145 | |
| 146 #define GLYPH_HASH_SIZE (0xFFFF + 13) | |
| 147 | |
| 148 typedef struct glyph_hash_item_s { | |
| 149 glyph_hash_key_t key; | |
| 150 glyph_hash_val_t val; | |
| 151 struct glyph_hash_item_s* next; | |
| 152 } glyph_hash_item_t; | |
| 153 | |
| 154 typedef glyph_hash_item_t* glyph_hash_item_p; | |
| 155 | |
| 156 static glyph_hash_item_p* glyph_hash_root; | |
| 157 static int glyph_hash_size; | |
| 158 | |
| 159 static int glyph_compare(glyph_hash_key_t* a, glyph_hash_key_t* b) { | |
| 160 if (memcmp(a, b, sizeof(glyph_hash_key_t)) == 0) | |
| 161 return 1; | |
| 162 else | |
| 163 return 0; | |
| 164 } | |
| 165 | |
| 166 static unsigned glyph_hash(glyph_hash_key_t* key) { | |
| 167 unsigned val = 0; | |
| 168 unsigned i; | |
| 169 for (i = 0; i < sizeof(key->face); ++i) | |
| 170 val += *(unsigned char *)(&(key->face) + i); | |
| 171 val <<= 21; | |
| 172 | |
| 173 if (key->bitmap) val &= 0x80000000; | |
| 19848 | 174 if (key->be) val &= 0x40000000; |
| 18937 | 175 val += key->index; |
| 176 val += key->size << 8; | |
| 177 val += key->outline << 3; | |
| 178 val += key->advance.x << 10; | |
| 179 val += key->advance.y << 16; | |
| 180 val += key->bold << 1; | |
| 181 val += key->italic << 20; | |
| 182 return val; | |
| 183 } | |
| 184 | |
| 185 /** | |
| 186 * \brief Add a glyph to glyph cache. | |
| 187 * \param key hash key | |
| 188 * \param val hash val: 2 bitmap glyphs + some additional info | |
| 189 */ | |
| 190 void cache_add_glyph(glyph_hash_key_t* key, glyph_hash_val_t* val) | |
| 191 { | |
| 192 unsigned hash = glyph_hash(key); | |
| 193 glyph_hash_item_t** next = glyph_hash_root + (hash % GLYPH_HASH_SIZE); | |
| 194 while (*next) { | |
| 195 if (glyph_compare(key, &((*next)->key))) | |
| 196 return; | |
| 197 next = &((*next)->next); | |
| 198 assert(next); | |
| 199 } | |
| 200 (*next) = malloc(sizeof(glyph_hash_item_t)); | |
| 201 // (*next)->desc = glyph_key_copy(key, &((*next)->key)); | |
| 202 memcpy(&((*next)->key), key, sizeof(glyph_hash_key_t)); | |
| 203 memcpy(&((*next)->val), val, sizeof(glyph_hash_val_t)); | |
| 204 (*next)->next = 0; | |
| 205 | |
| 206 glyph_hash_size ++; | |
| 207 /* if (glyph_hash_size && (glyph_hash_size % 25 == 0)) { | |
| 208 printf("\nGlyph cache: %d entries, %d bytes\n", glyph_hash_size, glyph_hash_size * sizeof(glyph_hash_item_t)); | |
| 209 } */ | |
| 210 } | |
| 211 | |
| 212 /** | |
| 213 * \brief Get a glyph from glyph cache. | |
| 214 * \param key hash key | |
| 215 * \return requested hash val or 0 if not found | |
| 216 */ | |
| 217 glyph_hash_val_t* cache_find_glyph(glyph_hash_key_t* key) | |
| 218 { | |
| 219 unsigned hash = glyph_hash(key); | |
| 220 glyph_hash_item_t* item = glyph_hash_root[hash % GLYPH_HASH_SIZE]; | |
| 221 while (item) { | |
| 222 if (glyph_compare(key, &(item->key))) { | |
| 223 return &(item->val); | |
| 224 } | |
| 225 item = item->next; | |
| 226 } | |
| 227 return 0; | |
| 228 } | |
| 229 | |
| 230 void ass_glyph_cache_init(void) | |
| 231 { | |
| 232 glyph_hash_root = calloc(GLYPH_HASH_SIZE, sizeof(glyph_hash_item_p)); | |
| 233 glyph_hash_size = 0; | |
| 234 } | |
| 235 | |
| 19545 | 236 void ass_glyph_cache_done(void) |
| 18937 | 237 { |
| 238 int i; | |
| 239 for (i = 0; i < GLYPH_HASH_SIZE; ++i) { | |
| 240 glyph_hash_item_t* item = glyph_hash_root[i]; | |
| 241 while (item) { | |
| 242 glyph_hash_item_t* next = item->next; | |
|
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
243 if (item->val.bm) ass_free_bitmap(item->val.bm); |
|
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
244 if (item->val.bm_o) ass_free_bitmap(item->val.bm_o); |
| 19965 | 245 if (item->val.bm_s) ass_free_bitmap(item->val.bm_s); |
| 18937 | 246 free(item); |
| 247 item = next; | |
| 248 } | |
| 249 } | |
| 19545 | 250 free(glyph_hash_root); |
| 18937 | 251 glyph_hash_size = 0; |
| 252 } | |
| 253 | |
| 19545 | 254 void ass_glyph_cache_reset(void) |
| 19539 | 255 { |
| 19545 | 256 ass_glyph_cache_done(); |
| 257 ass_glyph_cache_init(); | |
| 19539 | 258 } |
| 259 |
