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