1 // -*- c-basic-offset: 8; indent-tabs-mode: t -*-
2 // vim:ts=8:sw=8:noet:ai:
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
24 #include FT_FREETYPE_H
30 #include "ass_fontconfig.h"
31 #include "ass_bitmap.h"
32 #include "ass_cache.h"
35 #define MAX_FONT_CACHE_SIZE 100
37 static ass_font_t* font_cache;
38 static int font_cache_size;
40 static int font_compare(ass_font_desc_t* a, ass_font_desc_t* b) {
41 if (strcmp(a->family, b->family) != 0)
43 if (a->bold != b->bold)
45 if (a->italic != b->italic)
51 * \brief Get a face object, either from cache or created through FreeType+FontConfig.
52 * \param library FreeType library object
53 * \param fontconfig_priv fontconfig private data
54 * \param desc required face description
55 * \return new font struct
57 ass_font_t* ass_new_font(FT_Library library, void* fontconfig_priv, ass_font_desc_t* desc)
63 for (i=0; i<font_cache_size; ++i)
64 if (font_compare(desc, &(font_cache[i].desc)))
65 return font_cache + i;
67 if (font_cache_size == MAX_FONT_CACHE_SIZE) {
68 mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_TooManyFonts);
72 item = font_cache + font_cache_size;
73 error = ass_font_init(library, fontconfig_priv, item, desc);
74 if (error) // FIXME: mp_msg
81 void ass_font_cache_init(void)
83 font_cache = calloc(MAX_FONT_CACHE_SIZE, sizeof(ass_font_t));
87 void ass_font_cache_done(void)
90 for (i = 0; i < font_cache_size; ++i) {
91 ass_font_t* item = font_cache + i;
98 //---------------------------------
101 #define GLYPH_HASH_SIZE (0xFFFF + 13)
103 typedef struct glyph_hash_item_s {
104 glyph_hash_key_t key;
105 glyph_hash_val_t val;
106 struct glyph_hash_item_s* next;
109 typedef glyph_hash_item_t* glyph_hash_item_p;
111 static glyph_hash_item_p* glyph_hash_root;
112 static int glyph_hash_size;
114 static int glyph_compare(glyph_hash_key_t* a, glyph_hash_key_t* b) {
115 if (memcmp(a, b, sizeof(glyph_hash_key_t)) == 0)
121 static unsigned glyph_hash(glyph_hash_key_t* key) {
124 for (i = 0; i < sizeof(key->face); ++i)
125 val += *(unsigned char *)(&(key->face) + i);
128 if (key->bitmap) val &= 0x80000000;
129 if (key->be) val &= 0x40000000;
131 val += key->size << 8;
132 val += key->outline << 3;
133 val += key->advance.x << 10;
134 val += key->advance.y << 16;
135 val += key->bold << 1;
136 val += key->italic << 20;
141 * \brief Add a glyph to glyph cache.
142 * \param key hash key
143 * \param val hash val: 2 bitmap glyphs + some additional info
145 void cache_add_glyph(glyph_hash_key_t* key, glyph_hash_val_t* val)
147 unsigned hash = glyph_hash(key);
148 glyph_hash_item_t** next = glyph_hash_root + (hash % GLYPH_HASH_SIZE);
150 if (glyph_compare(key, &((*next)->key)))
152 next = &((*next)->next);
155 (*next) = malloc(sizeof(glyph_hash_item_t));
156 // (*next)->desc = glyph_key_copy(key, &((*next)->key));
157 memcpy(&((*next)->key), key, sizeof(glyph_hash_key_t));
158 memcpy(&((*next)->val), val, sizeof(glyph_hash_val_t));
162 /* if (glyph_hash_size && (glyph_hash_size % 25 == 0)) {
163 printf("\nGlyph cache: %d entries, %d bytes\n", glyph_hash_size, glyph_hash_size * sizeof(glyph_hash_item_t));
168 * \brief Get a glyph from glyph cache.
169 * \param key hash key
170 * \return requested hash val or 0 if not found
172 glyph_hash_val_t* cache_find_glyph(glyph_hash_key_t* key)
174 unsigned hash = glyph_hash(key);
175 glyph_hash_item_t* item = glyph_hash_root[hash % GLYPH_HASH_SIZE];
177 if (glyph_compare(key, &(item->key))) {
185 void ass_glyph_cache_init(void)
187 glyph_hash_root = calloc(GLYPH_HASH_SIZE, sizeof(glyph_hash_item_p));
191 void ass_glyph_cache_done(void)
194 for (i = 0; i < GLYPH_HASH_SIZE; ++i) {
195 glyph_hash_item_t* item = glyph_hash_root[i];
197 glyph_hash_item_t* next = item->next;
198 if (item->val.bm) ass_free_bitmap(item->val.bm);
199 if (item->val.bm_o) ass_free_bitmap(item->val.bm_o);
200 if (item->val.bm_s) ass_free_bitmap(item->val.bm_s);
205 free(glyph_hash_root);
209 void ass_glyph_cache_reset(void)
211 ass_glyph_cache_done();
212 ass_glyph_cache_init();