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
31 #include "ass_fontconfig.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)
44 if (a
->bold
!= b
->bold
)
46 if (a
->italic
!= b
->italic
)
52 * \brief Get a face struct from cache.
53 * \param desc required face description
56 ass_font_t
* ass_font_cache_find(ass_font_desc_t
* desc
)
60 for (i
=0; i
<font_cache_size
; ++i
)
61 if (font_compare(desc
, &(font_cache
[i
]->desc
)))
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
79 font_cache
[font_cache_size
] = font
;
83 void ass_font_cache_init(void)
85 font_cache
= calloc(MAX_FONT_CACHE_SIZE
, sizeof(ass_font_t
*));
89 void ass_font_cache_done(void)
92 for (i
= 0; i
< font_cache_size
; ++i
) {
93 ass_font_t
* item
= font_cache
[i
];
100 //---------------------------------
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
;
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)
123 static unsigned glyph_hash(glyph_hash_key_t
* key
) {
126 for (i
= 0; i
< sizeof(key
->font
); ++i
)
127 val
+= *(unsigned char *)(&(key
->font
) + i
);
130 if (key
->bitmap
) val
&= 0x80000000;
131 if (key
->be
) val
&= 0x40000000;
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;
140 val
+= key
->fry
<< 1;
141 val
+= key
->frz
<< 2;
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
);
155 if (glyph_compare(key
, &((*next
)->key
)))
157 next
= &((*next
)->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
));
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));
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
];
182 if (glyph_compare(key
, &(item
->key
))) {
190 void ass_glyph_cache_init(void)
192 glyph_hash_root
= calloc(GLYPH_HASH_SIZE
, sizeof(glyph_hash_item_p
));
196 void ass_glyph_cache_done(void)
199 for (i
= 0; i
< GLYPH_HASH_SIZE
; ++i
) {
200 glyph_hash_item_t
* item
= glyph_hash_root
[i
];
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
);
210 free(glyph_hash_root
);
214 void ass_glyph_cache_reset(void)
216 ass_glyph_cache_done();
217 ass_glyph_cache_init();