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