1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Top level font reading routines.
12 *
13 * By Evert Glebbeek.
14 *
15 * See readme.txt for copyright information.
16 */
17
18
19 #include <string.h>
20
21 #include "allegro.h"
22 #include "allegro/internal/aintern.h"
23
24
25
26 typedef struct FONT_TYPE_INFO
27 {
28 char *ext;
29 FONT *(*load)(AL_CONST char *filename, RGB *pal, void *param);
30 struct FONT_TYPE_INFO *next;
31 } FONT_TYPE_INFO;
32
33 static FONT_TYPE_INFO *font_type_list = NULL;
34
35
36
37 /* register_font_file_type:
38 * Informs Allegro of a new font file type, telling it how to load files of
39 * this format.
40 */
register_font_file_type(AL_CONST char * ext,FONT * (* load)(AL_CONST char * filename,RGB * pal,void * param))41 void register_font_file_type(AL_CONST char *ext, FONT *(*load)(AL_CONST char *filename, RGB *pal, void *param))
42 {
43 char tmp[32], *aext;
44 FONT_TYPE_INFO *iter = font_type_list;
45
46 aext = uconvert_toascii(ext, tmp);
47 if (strlen(aext) == 0) return;
48
49 if (!iter)
50 iter = font_type_list = _AL_MALLOC(sizeof(struct FONT_TYPE_INFO));
51 else {
52 for (iter = font_type_list; iter->next; iter = iter->next);
53 iter = iter->next = _AL_MALLOC(sizeof(struct FONT_TYPE_INFO));
54 }
55
56 if (iter) {
57 iter->load = load;
58 iter->ext = _al_strdup(aext);
59 iter->next = NULL;
60 }
61 }
62
63
64
65 /* load_font:
66 * Loads a font from disk. Will try to load a font from a bitmap if all else
67 * fails.
68 */
load_font(AL_CONST char * filename,RGB * pal,void * param)69 FONT *load_font(AL_CONST char *filename, RGB *pal, void *param)
70 {
71 char tmp[32], *aext;
72 FONT_TYPE_INFO *iter;
73 ASSERT(filename);
74
75 aext = uconvert_toascii(get_extension(filename), tmp);
76
77 for (iter = font_type_list; iter; iter = iter->next) {
78 if (stricmp(iter->ext, aext) == 0) {
79 if (iter->load)
80 return iter->load(filename, pal, param);
81 return NULL;
82 }
83 }
84
85 /* Try to load the file as a bitmap image and grab the font from there */
86 return load_bitmap_font(filename, pal, param);
87 }
88
89
90
91 /* register_font_file_type_exit:
92 * Free list of registered bitmap file types.
93 */
register_font_file_type_exit(void)94 static void register_font_file_type_exit(void)
95 {
96 FONT_TYPE_INFO *iter = font_type_list, *next;
97
98 while (iter) {
99 next = iter->next;
100 _AL_FREE(iter->ext);
101 _AL_FREE(iter);
102 iter = next;
103 }
104
105 font_type_list = NULL;
106
107 /* If we are using a destructor, then we only want to prune the list
108 * down to valid modules. So we clean up as usual, but then reinstall
109 * the internal modules.
110 */
111 #ifdef ALLEGRO_USE_CONSTRUCTOR
112 _register_font_file_type_init();
113 #endif
114
115 _remove_exit_func(register_font_file_type_exit);
116 }
117
118
119
120 /* _register_font_file_type_init:
121 * Register built-in font file types.
122 */
_register_font_file_type_init(void)123 void _register_font_file_type_init(void)
124 {
125 char buf[32];
126
127 _add_exit_func(register_font_file_type_exit,
128 "register_font_file_type_exit");
129
130 register_font_file_type(uconvert_ascii("dat", buf), load_dat_font);
131 register_font_file_type(uconvert_ascii("fnt", buf), load_grx_or_bios_font);
132 register_font_file_type(uconvert_ascii("txt", buf), load_txt_font);
133 }
134
135
136
137 #ifdef ALLEGRO_USE_CONSTRUCTOR
138 CONSTRUCTOR_FUNCTION(static void font_filetype_constructor(void));
139 DESTRUCTOR_FUNCTION(static void font_filetype_destructor(void));
140
141 /* font_filetype_constructor:
142 * Register font filetype functions if this object file is linked
143 * in. This isn't called if the load_font() function isn't used
144 * in a program, thus saving a little space in statically linked
145 * programs.
146 */
font_filetype_constructor(void)147 void font_filetype_constructor(void)
148 {
149 _register_font_file_type_init();
150 }
151
152 /* font_filetype_destructor:
153 * Since we only want to destroy the whole list when we *actually*
154 * quit, not just when allegro_exit() is called, we need to use a
155 * destructor to accomplish this.
156 */
font_filetype_destructor(void)157 static void font_filetype_destructor(void)
158 {
159 FONT_TYPE_INFO *iter = font_type_list, *next;
160
161 while (iter) {
162 next = iter->next;
163 _AL_FREE(iter->ext);
164 _AL_FREE(iter);
165 iter = next;
166 }
167
168 font_type_list = NULL;
169
170 _remove_exit_func(register_font_file_type_exit);
171 }
172 #endif
173