synced with r22428
[mplayer/greg.git] / libass / ass_cache.c
blob463fdb50af7f012c5a4454550cb0117d738446cf
1 // -*- c-basic-offset: 8; indent-tabs-mode: t -*-
2 // vim:ts=8:sw=8:noet:ai:
3 /*
4 Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
6 This program is free software; you can redistribute it and/or modify
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.
11 This program is distributed in the hope that it will be useful,
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "config.h"
23 #include <inttypes.h>
24 #include <ft2build.h>
25 #include FT_FREETYPE_H
26 #include FT_GLYPH_H
28 #include <assert.h>
30 #include "mputils.h"
31 #include "ass.h"
32 #include "ass_fontconfig.h"
33 #include "ass_font.h"
34 #include "ass_bitmap.h"
35 #include "ass_cache.h"
37 #define MAX_FONT_CACHE_SIZE 100
39 static ass_font_t** font_cache;
40 static int font_cache_size;
42 static int font_compare(ass_font_desc_t* a, ass_font_desc_t* b) {
43 if (strcmp(a->family, b->family) != 0)
44 return 0;
45 if (a->bold != b->bold)
46 return 0;
47 if (a->italic != b->italic)
48 return 0;
49 return 1;
52 /**
53 * \brief Get a face struct from cache.
54 * \param desc required face description
55 * \return font struct
57 ass_font_t* ass_font_cache_find(ass_font_desc_t* desc)
59 int i;
61 for (i=0; i<font_cache_size; ++i)
62 if (font_compare(desc, &(font_cache[i]->desc)))
63 return font_cache[i];
65 return 0;
68 /**
69 * \brief Add a face struct to cache.
70 * \param font font struct
72 void ass_font_cache_add(ass_font_t* font)
74 if (font_cache_size == MAX_FONT_CACHE_SIZE) {
75 mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_TooManyFonts);
76 // FIXME: possible memory leak
77 return;
80 font_cache[font_cache_size] = font;
81 font_cache_size++;
84 void ass_font_cache_init(void)
86 font_cache = calloc(MAX_FONT_CACHE_SIZE, sizeof(ass_font_t*));
87 font_cache_size = 0;
90 void ass_font_cache_done(void)
92 int i;
93 for (i = 0; i < font_cache_size; ++i) {
94 ass_font_t* item = font_cache[i];
95 ass_font_free(item);
97 free(font_cache);
98 font_cache_size = 0;
101 //---------------------------------
102 // glyph cache
104 #define GLYPH_HASH_SIZE (0xFFFF + 13)
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;
112 typedef glyph_hash_item_t* glyph_hash_item_p;
114 static glyph_hash_item_p* glyph_hash_root;
115 static int glyph_hash_size;
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;
124 static unsigned glyph_hash(glyph_hash_key_t* key) {
125 unsigned val = 0;
126 unsigned i;
127 for (i = 0; i < sizeof(key->font); ++i)
128 val += *(unsigned char *)(&(key->font) + i);
129 val <<= 21;
131 if (key->bitmap) val &= 0x80000000;
132 if (key->be) val &= 0x40000000;
133 val += key->ch;
134 val += key->size << 8;
135 val += key->outline << 3;
136 val += key->advance.x << 10;
137 val += key->advance.y << 16;
138 val += key->bold << 1;
139 val += key->italic << 20;
140 val += key->frx;
141 val += key->fry << 1;
142 val += key->frz << 2;
143 return val;
147 * \brief Add a glyph to glyph cache.
148 * \param key hash key
149 * \param val hash val: 2 bitmap glyphs + some additional info
151 void cache_add_glyph(glyph_hash_key_t* key, glyph_hash_val_t* val)
153 unsigned hash = glyph_hash(key);
154 glyph_hash_item_t** next = glyph_hash_root + (hash % GLYPH_HASH_SIZE);
155 while (*next) {
156 if (glyph_compare(key, &((*next)->key)))
157 return;
158 next = &((*next)->next);
159 assert(next);
161 (*next) = malloc(sizeof(glyph_hash_item_t));
162 // (*next)->desc = glyph_key_copy(key, &((*next)->key));
163 memcpy(&((*next)->key), key, sizeof(glyph_hash_key_t));
164 memcpy(&((*next)->val), val, sizeof(glyph_hash_val_t));
165 (*next)->next = 0;
167 glyph_hash_size ++;
168 /* if (glyph_hash_size && (glyph_hash_size % 25 == 0)) {
169 printf("\nGlyph cache: %d entries, %d bytes\n", glyph_hash_size, glyph_hash_size * sizeof(glyph_hash_item_t));
170 } */
174 * \brief Get a glyph from glyph cache.
175 * \param key hash key
176 * \return requested hash val or 0 if not found
178 glyph_hash_val_t* cache_find_glyph(glyph_hash_key_t* key)
180 unsigned hash = glyph_hash(key);
181 glyph_hash_item_t* item = glyph_hash_root[hash % GLYPH_HASH_SIZE];
182 while (item) {
183 if (glyph_compare(key, &(item->key))) {
184 return &(item->val);
186 item = item->next;
188 return 0;
191 void ass_glyph_cache_init(void)
193 glyph_hash_root = calloc(GLYPH_HASH_SIZE, sizeof(glyph_hash_item_p));
194 glyph_hash_size = 0;
197 void ass_glyph_cache_done(void)
199 int i;
200 for (i = 0; i < GLYPH_HASH_SIZE; ++i) {
201 glyph_hash_item_t* item = glyph_hash_root[i];
202 while (item) {
203 glyph_hash_item_t* next = item->next;
204 if (item->val.bm) ass_free_bitmap(item->val.bm);
205 if (item->val.bm_o) ass_free_bitmap(item->val.bm_o);
206 if (item->val.bm_s) ass_free_bitmap(item->val.bm_s);
207 free(item);
208 item = next;
211 free(glyph_hash_root);
212 glyph_hash_size = 0;
215 void ass_glyph_cache_reset(void)
217 ass_glyph_cache_done();
218 ass_glyph_cache_init();