10l: comparison of char* ptrs with string literals
[mplayer.git] / libass / ass_cache.c
blob144ac5ac548d35e2224935ed3f86b3742210925e
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 <ft2build.h>
24 #include FT_FREETYPE_H
25 #include FT_GLYPH_H
27 #include <assert.h>
29 #include "mputils.h"
30 #include "ass.h"
31 #include "ass_fontconfig.h"
32 #include "ass_font.h"
33 #include "ass_bitmap.h"
34 #include "ass_cache.h"
36 #define MAX_FONT_CACHE_SIZE 100
38 static ass_font_t** font_cache;
39 static int font_cache_size;
41 static int font_compare(ass_font_desc_t* a, ass_font_desc_t* b) {
42 if (strcmp(a->family, b->family) != 0)
43 return 0;
44 if (a->bold != b->bold)
45 return 0;
46 if (a->italic != b->italic)
47 return 0;
48 return 1;
51 /**
52 * \brief Get a face struct from cache.
53 * \param desc required face description
54 * \return font struct
56 ass_font_t* ass_font_cache_find(ass_font_desc_t* desc)
58 int i;
60 for (i=0; i<font_cache_size; ++i)
61 if (font_compare(desc, &(font_cache[i]->desc)))
62 return font_cache[i];
64 return 0;
67 /**
68 * \brief Add a face struct to cache.
69 * \param font font struct
71 void ass_font_cache_add(ass_font_t* font)
73 if (font_cache_size == MAX_FONT_CACHE_SIZE) {
74 mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_TooManyFonts);
75 // FIXME: possible memory leak
76 return;
79 font_cache[font_cache_size] = font;
80 font_cache_size++;
83 void ass_font_cache_init(void)
85 font_cache = calloc(MAX_FONT_CACHE_SIZE, sizeof(ass_font_t*));
86 font_cache_size = 0;
89 void ass_font_cache_done(void)
91 int i;
92 for (i = 0; i < font_cache_size; ++i) {
93 ass_font_t* item = font_cache[i];
94 ass_font_free(item);
96 free(font_cache);
97 font_cache_size = 0;
100 //---------------------------------
101 // glyph cache
103 #define GLYPH_HASH_SIZE (0xFFFF + 13)
105 typedef struct glyph_hash_item_s {
106 glyph_hash_key_t key;
107 glyph_hash_val_t val;
108 struct glyph_hash_item_s* next;
109 } glyph_hash_item_t;
111 typedef glyph_hash_item_t* glyph_hash_item_p;
113 static glyph_hash_item_p* glyph_hash_root;
114 static int glyph_hash_size;
116 static int glyph_compare(glyph_hash_key_t* a, glyph_hash_key_t* b) {
117 if (memcmp(a, b, sizeof(glyph_hash_key_t)) == 0)
118 return 1;
119 else
120 return 0;
123 static unsigned glyph_hash(glyph_hash_key_t* key) {
124 unsigned val = 0;
125 unsigned i;
126 for (i = 0; i < sizeof(key->font); ++i)
127 val += *(unsigned char *)(&(key->font) + i);
128 val <<= 21;
130 if (key->bitmap) val &= 0x80000000;
131 if (key->be) val &= 0x40000000;
132 val += key->ch;
133 val += key->size << 8;
134 val += key->outline << 3;
135 val += key->advance.x << 10;
136 val += key->advance.y << 16;
137 val += key->bold << 1;
138 val += key->italic << 20;
139 val += key->frx;
140 val += key->fry << 1;
141 val += key->frz << 2;
142 return val;
146 * \brief Add a glyph to glyph cache.
147 * \param key hash key
148 * \param val hash val: 2 bitmap glyphs + some additional info
150 void cache_add_glyph(glyph_hash_key_t* key, glyph_hash_val_t* val)
152 unsigned hash = glyph_hash(key);
153 glyph_hash_item_t** next = glyph_hash_root + (hash % GLYPH_HASH_SIZE);
154 while (*next) {
155 if (glyph_compare(key, &((*next)->key)))
156 return;
157 next = &((*next)->next);
158 assert(next);
160 (*next) = malloc(sizeof(glyph_hash_item_t));
161 // (*next)->desc = glyph_key_copy(key, &((*next)->key));
162 memcpy(&((*next)->key), key, sizeof(glyph_hash_key_t));
163 memcpy(&((*next)->val), val, sizeof(glyph_hash_val_t));
164 (*next)->next = 0;
166 glyph_hash_size ++;
167 /* if (glyph_hash_size && (glyph_hash_size % 25 == 0)) {
168 printf("\nGlyph cache: %d entries, %d bytes\n", glyph_hash_size, glyph_hash_size * sizeof(glyph_hash_item_t));
169 } */
173 * \brief Get a glyph from glyph cache.
174 * \param key hash key
175 * \return requested hash val or 0 if not found
177 glyph_hash_val_t* cache_find_glyph(glyph_hash_key_t* key)
179 unsigned hash = glyph_hash(key);
180 glyph_hash_item_t* item = glyph_hash_root[hash % GLYPH_HASH_SIZE];
181 while (item) {
182 if (glyph_compare(key, &(item->key))) {
183 return &(item->val);
185 item = item->next;
187 return 0;
190 void ass_glyph_cache_init(void)
192 glyph_hash_root = calloc(GLYPH_HASH_SIZE, sizeof(glyph_hash_item_p));
193 glyph_hash_size = 0;
196 void ass_glyph_cache_done(void)
198 int i;
199 for (i = 0; i < GLYPH_HASH_SIZE; ++i) {
200 glyph_hash_item_t* item = glyph_hash_root[i];
201 while (item) {
202 glyph_hash_item_t* next = item->next;
203 if (item->val.bm) ass_free_bitmap(item->val.bm);
204 if (item->val.bm_o) ass_free_bitmap(item->val.bm_o);
205 if (item->val.bm_s) ass_free_bitmap(item->val.bm_s);
206 free(item);
207 item = next;
210 free(glyph_hash_root);
211 glyph_hash_size = 0;
214 void ass_glyph_cache_reset(void)
216 ass_glyph_cache_done();
217 ass_glyph_cache_init();