1 /*
2  * Luola - 2D multiplayer cave-flying game
3  * Copyright (C) 2003-2006 Calle Laakkonen
4  *
5  * File        : font.c
6  * Description : Font library abstraction
7  * Author(s)   : Calle Laakkonen
8  *
9  * Luola is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Luola is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */
23 
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "console.h"
28 #include "fs.h"
29 #include "font.h"
30 #include "startup.h"
31 #include "parser.h"
32 
33 #include "SFont.h"
34 
35 #ifdef HAVE_LIBSDL_TTF
36 #include "SDL_ttf.h"
37 #else
38 typedef void TTF_Font;
39 #endif
40 
41 /* Internally used type definitions */
42 typedef union {
43     SFont_Font *sfont;
44     TTF_Font *tfont;
45 } FontInfo;
46 
47 /* Internally used globals */
48 static SFont_Font *sfont_big, *sfont_small;
49 static char use_sfont;
50 #ifdef HAVE_LIBSDL_TTF
51 static TTF_Font *tfont_big, *tfont_small;
52 static struct {
53     char *bigfont;
54     char *smallfont;
55     int bigsize;
56     int smallsize;
57 } TruetypeFonts;
58 
59 #endif
60 
61 /* Exported globals */
62 SDL_Color font_color_white, font_color_gray;
63 SDL_Color font_color_red;
64 SDL_Color font_color_green;
65 SDL_Color font_color_blue;
66 SDL_Color font_color_cyan;
67 int MENU_SPACING;
68 
69 /* Pointers to functions to use */
70 int (*ttf_sizetext) (TTF_Font * font, const char *text, int *w, int *h);
71 SDL_Surface *(*ttf_rendertext_blended) (TTF_Font * font, const char *text,
72                                         SDL_Color fg);
73 
set_proper_font(FontInfo * fi,FontSize size)74 static inline void set_proper_font (FontInfo * fi, FontSize size)
75 {
76     if (use_sfont) {
77         if (size == Smallfont)
78             fi->sfont = sfont_small;
79         else
80             fi->sfont = sfont_big;
81     }
82 #ifdef HAVE_LIBSDL_TTF
83     else {
84         if (size == Smallfont)
85             fi->tfont = tfont_small;
86         else
87             fi->tfont = tfont_big;
88     }
89 #endif
90 }
91 
92 #ifdef HAVE_LIBSDL_TTF
93 /* Load the font configuration file */
load_font_cfg(const char * filename)94 static int load_font_cfg (const char *filename) {
95     struct dllist *fontcfg;
96     struct ConfigBlock *block;
97     struct Translate tr[] = {
98         {"bigfont", CFG_STRING, &TruetypeFonts.bigfont},
99         {"smallfont", CFG_STRING, &TruetypeFonts.smallfont},
100         {"smallsize", CFG_INT, &TruetypeFonts.smallsize},
101         {"bigsize", CFG_INT, &TruetypeFonts.bigsize},
102         {0,0,0}
103     };
104 
105     fontcfg = read_config_file(filename,1);
106     if(!fontcfg) return 1;
107 
108     block=fontcfg->data;
109 
110     translate_config(block->values,tr,0);
111 
112     dllist_free(fontcfg,free_config_file);
113 
114     if(TruetypeFonts.bigfont==NULL) {
115         printf("Error: bigfont not specified\n");
116         return 1;
117     }
118     if(TruetypeFonts.smallfont==NULL) {
119         printf("Error: smallfont not specified\n");
120         return 1;
121     }
122     return 0;
123 }
124 #endif
125 
126 /* Initialize the font library			*/
127 /* If SDL_ttf is compiled in, it is used unless */
128 /* the fonts are unavailable. In that case,	*/
129 /* Luola falls back to the built-in SFont	*/
init_font(void)130 int init_font (void) {
131     use_sfont = 1;
132 #ifdef HAVE_LIBSDL_TTF
133     /* Initialize SDL_ttf */
134     if (luola_options.sfont || TTF_Init () < 0) {
135         if (luola_options.sfont == 0) {
136             printf ("Couldn't initialize SDL_ttf: %s\n", SDL_GetError ());
137             printf ("Reverting to built-in SFont.\n");
138         }
139     } else {
140         /* Load the font configuration file. First check the home directory,
141            if there isn't one there, check the font directory. */
142         const char *fcfg;
143         const char *filename;
144         fcfg = getfullpath (HOME_DIRECTORY, "fonts.cfg");
145         if (load_font_cfg (fcfg)) {
146             fcfg = getfullpath (FONT_DIRECTORY, "fonts.cfg");
147             if (load_font_cfg (fcfg)) {
148                 fprintf(stderr,
149                     "Error: Couldn't load font configuration file\n");
150                 return 1;
151             }
152         }
153         if (strchr (TruetypeFonts.bigfont, '/'))
154             filename = TruetypeFonts.bigfont;
155         else
156             filename = getfullpath (FONT_DIRECTORY, TruetypeFonts.bigfont);
157         tfont_big = TTF_OpenFont (filename, TruetypeFonts.bigsize);
158         if (tfont_big == NULL) {
159             printf ("Could not open font \"%s\" with point size %d\n",
160                     filename, TruetypeFonts.bigsize);
161             printf ("SDL reports: %s\n", SDL_GetError ());
162             printf ("Reverting to built-in SFont.\n");
163         } else {
164             if (strchr (TruetypeFonts.smallfont, '/'))
165                 filename = TruetypeFonts.smallfont;
166             else
167                 filename =
168                     getfullpath (FONT_DIRECTORY, TruetypeFonts.smallfont);
169             tfont_small = TTF_OpenFont (filename, TruetypeFonts.smallsize);
170             if (tfont_small == NULL) {
171                 printf ("Could not open font \"%s\" with point size %d\n",
172                         filename,TruetypeFonts.smallsize);
173                 printf ("SDL reports: %s\n", SDL_GetError ());
174                 printf ("Reverting to built-in SFont.\n");
175             } else
176                 use_sfont = 0;
177             /* Set functions pointers */
178             ttf_sizetext = TTF_SizeText;
179             ttf_rendertext_blended = TTF_RenderText_Blended;
180             MENU_SPACING = TTF_FontHeight (tfont_big);
181         }
182     }
183 #endif
184     /* Initialize SFont */
185     if (use_sfont) {
186         sfont_big=SFont_InitFont(load_image(
187                     getfullpath(FONT_DIRECTORY,"font1.png"), 0,T_ALPHA));
188         sfont_small=SFont_InitFont(load_image(
189                     getfullpath(FONT_DIRECTORY,"font2.png"), 0,T_ALPHA));
190         MENU_SPACING = sfont_big->Surface->h;
191     }
192     /* Initialize font colors */
193     font_color_white.r = 255;
194     font_color_white.g = 255;
195     font_color_white.b = 255;
196     font_color_gray.r = 128;
197     font_color_gray.g = 128;
198     font_color_gray.b = 128;
199     font_color_red.r = 255;
200     font_color_red.g = 0;
201     font_color_red.b = 0;
202     font_color_green.r = 0;
203     font_color_green.g = 255;
204     font_color_green.b = 0;
205     font_color_blue.r = 0;
206     font_color_blue.g = 0;
207     font_color_blue.b = 255;
208     font_color_cyan.r = 0;
209     font_color_cyan.g = 128;
210     font_color_cyan.b = 255;
211     return 0;
212 }
213 
214 /* Write a string directly to the surface.		*/
215 /* This is slow if you use SDL_ttf because 		*/
216 /* an extra surface needs to be created and freed 	*/
217 /* Or, if you are using SFont, this is slow if color is */
218 /* something else than white				*/
putstring_direct(SDL_Surface * surface,FontSize size,int x,int y,const char * text,SDL_Color color)219 void putstring_direct (SDL_Surface * surface, FontSize size, int x, int y,
220                        const char *text, SDL_Color color)
221 {
222     SDL_Surface *fontsurface;
223     SDL_Rect rect;
224     FontInfo font;
225     rect.x = x;
226     rect.y = y;
227     set_proper_font (&font, size);
228     if (use_sfont) {            /* SFont version */
229         if (color.r == 255 && color.g == 255 && color.b == 255) {
230             SFont_Write (surface, font.sfont, x, y, text,0);
231         } else {
232             fontsurface = make_surface(font.sfont->Surface,
233                      SFont_TextWidth(font.sfont, text), font.sfont->Surface->h);
234             SFont_Write (fontsurface, font.sfont, 0, 0, text,1);
235             recolor (fontsurface, color.r / 255.0, color.g / 255.0,
236                      color.b / 255.0, 1.0);
237             SDL_SetColorKey (fontsurface, SDL_SRCCOLORKEY, 0);
238             SDL_BlitSurface (fontsurface, NULL, surface, &rect);
239             SDL_FreeSurface (fontsurface);
240         }
241     } else {                    /* SDL_ttf version */
242         fontsurface = ttf_rendertext_blended (font.tfont, text, color);
243         SDL_BlitSurface (fontsurface, NULL, surface, &rect);
244         SDL_FreeSurface (fontsurface);
245     }
246 }
247 
248 /* A convenience wrapper for putstring_direct */
249 /* Centers the string horizontaly */
centered_string(SDL_Surface * surface,FontSize size,int y,const char * text,SDL_Color color)250 void centered_string (SDL_Surface * surface, FontSize size, int y,
251                       const char *text, SDL_Color color)
252 {
253     FontInfo font;
254     int x, w, h;
255     set_proper_font (&font, size);
256     x = surface->w / 2;
257     if (use_sfont)
258         w = SFont_TextWidth(font.sfont, text);
259     else
260         ttf_sizetext (font.tfont, text, &w, &h);
261     x -= w / 2;
262     putstring_direct (surface, size, x, y, text, color);
263 }
264 
265 /* Return a surface containing the text              */
266 /* This is slow with SFont when the you use a color	 */
267 /* other than white. The returned surface will be in */
268 /* the same format as the display                    */
renderstring(FontSize size,const char * text,SDL_Color color)269 SDL_Surface *renderstring (FontSize size, const char *text, SDL_Color color)
270 {
271     SDL_Surface *fontsurface;
272     FontInfo font;
273     set_proper_font (&font, size);
274     if (use_sfont) {            /* SFont version */
275         fontsurface = make_surface(font.sfont->Surface,
276                      SFont_TextWidth(font.sfont, text), font.sfont->Surface->h);
277         SFont_Write(fontsurface, font.sfont, 0, 0, text,1);
278         if (color.r != 255 || color.g != 255 || color.b != 255) {
279             recolor (fontsurface, color.r / 255.0, color.g / 255.0,
280                      color.b / 255.0, 1.0);
281         }
282         return fontsurface;
283     } else {                    /* SDL_ttf version */
284         return ttf_rendertext_blended (font.tfont, text, color);
285     }
286 }
287 
288 /* Get the height of the font */
font_height(FontSize size)289 int font_height (FontSize size)
290 {
291     FontInfo font;
292     set_proper_font (&font, size);
293     if (use_sfont) {
294         return font.sfont->Surface->h;
295     }
296 #ifdef HAVE_LIBSDL_TTF
297     else {
298         return TTF_FontHeight (font.tfont);
299     }
300 #endif
301     return 0;
302 }
303 
304