1
2 /******************************************************************************
3 * MODIFIED BY JUAN PEDRO BOLIVAR. May not work outside this project *
4 ******************************************************************************/
5
6 /* SFont: a simple font-library that uses special .pngs as fonts
7 Copyright (C) 2003 Karl Bartel
8
9 License: GPL or LGPL (at your choice)
10 WWW: http://www.linux-games.com/sfont/
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26 Karl Bartel
27 Cecilienstr. 14
28 12307 Berlin
29 GERMANY
30 karlb@gmx.net
31 */
32
33 #include <SDL/SDL.h>
34
35 #include <assert.h>
36 #include <stdlib.h>
37
38 #include "SFont.h"
39 #include "surface.h"
40
41 static Uint32
GetPixel(SDL_Surface * Surface,Sint32 X,Sint32 Y)42 GetPixel (SDL_Surface * Surface, Sint32 X, Sint32 Y)
43 {
44 Uint8 *bits;
45 Uint32 Bpp;
46
47 assert (X >= 0);
48 assert (X < Surface->w);
49
50 Bpp = Surface->format->BytesPerPixel;
51 bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch + X * Bpp;
52
53 // Get the pixel
54 switch (Bpp)
55 {
56 case 1:
57 return *((Uint8 *) Surface->pixels + Y * Surface->pitch + X);
58 break;
59 case 2:
60 return *((Uint16 *) Surface->pixels + Y * Surface->pitch / 2 + X);
61 break;
62 case 3:
63 { // Format/endian independent
64 Uint8 r, g, b;
65 r = *((bits) + Surface->format->Rshift / 8);
66 g = *((bits) + Surface->format->Gshift / 8);
67 b = *((bits) + Surface->format->Bshift / 8);
68 return SDL_MapRGB (Surface->format, r, g, b);
69 }
70 break;
71 case 4:
72 return *((Uint32 *) Surface->pixels + Y * Surface->pitch / 4 + X);
73 break;
74 }
75
76 return -1;
77 }
78
79 SFont_Font *
SFont_InitFont(char * file,SDL_Surface * Surface,Uint8 gl,Uint8 alpha)80 SFont_InitFont (char *file, SDL_Surface * Surface, Uint8 gl, Uint8 alpha)
81 {
82 int x = 0, i = 0;
83 Uint32 pixel;
84 SFont_Font *Font;
85 Uint32 pink;
86
87 if (Surface == NULL)
88 return NULL;
89
90 Font = (SFont_Font *) malloc (sizeof (SFont_Font));
91 //Font->Surface = Surface;
92
93 //SDL_LockSurface(Surface);
94
95 pink = SDL_MapRGB (Surface->format, 255, 0, 255);
96 while (x < Surface->w)
97 {
98 if (GetPixel (Surface, x, 0) == pink)
99 {
100 Font->CharPos[i++] = x;
101 while ((x < Surface->w) && (GetPixel (Surface, x, 0) == pink))
102 x++;
103 Font->CharPos[i++] = x;
104 }
105 x++;
106 }
107 Font->MaxPos = x - 1;
108
109 pixel = GetPixel (Surface, 0, Surface->h - 1);
110 //SDL_UnlockSurface(Surface);
111
112 //SDL_SetColorKey(Surface, SDL_SRCCOLORKEY, pixel);
113
114 Font->Surface = JPB_LoadImg (file, gl, alpha, 0, 0);
115
116 return Font;
117 }
118
119 void
SFont_FreeFont(SFont_Font * FontInfo)120 SFont_FreeFont (SFont_Font * FontInfo)
121 {
122 JPB_FreeSurface (FontInfo->Surface);
123 free (FontInfo);
124 }
125
126 void
SFont_Write(SFont_Font * Font,int x,int y,char * text)127 SFont_Write (SFont_Font * Font, int x, int y, char *text)
128 {
129 char *c;
130 int charoffset;
131 SDL_Rect srcrect, dstrect;
132
133 if (text == NULL)
134 return;
135
136 // these values won't change in the loop
137 srcrect.y = 1;
138 dstrect.y = y;
139 srcrect.h = dstrect.h = Font->Surface->h - 1;
140
141 for (c = text; *c != '\0'; c++)
142 {
143 charoffset = ((int) (*c - 33)) * 2 + 1;
144 // skip spaces and nonprintable characters
145 if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos)
146 {
147 x += Font->CharPos[2] - Font->CharPos[1];
148 continue;
149 }
150
151 srcrect.w = dstrect.w =
152 (Font->CharPos[charoffset + 2] + Font->CharPos[charoffset + 1]) / 2 -
153 (Font->CharPos[charoffset] + Font->CharPos[charoffset - 1]) / 2;
154 srcrect.x =
155 (Font->CharPos[charoffset] + Font->CharPos[charoffset - 1]) / 2;
156 dstrect.x =
157 x - (float) (Font->CharPos[charoffset] -
158 Font->CharPos[charoffset - 1]) / 2;
159
160 //JPB_PrintSurface(Font->Surface, &srcrect, &dstrect);
161 JPB_PrintSurface (Font->Surface, &srcrect, &dstrect);
162
163
164 x += Font->CharPos[charoffset + 1] - Font->CharPos[charoffset];
165 }
166 }
167
168 int
SFont_TextWidth(const SFont_Font * Font,const char * text)169 SFont_TextWidth (const SFont_Font * Font, const char *text)
170 {
171 const char *c;
172 int charoffset = 0;
173 int width = 0;
174
175 if (text == NULL)
176 return 0;
177
178 for (c = text; *c != '\0'; c++)
179 {
180 charoffset = ((int) *c - 33) * 2 + 1;
181 // skip spaces and nonprintable characters
182 if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos)
183 {
184 width += Font->CharPos[2] - Font->CharPos[1];
185 continue;
186 }
187
188 width += Font->CharPos[charoffset + 1] - Font->CharPos[charoffset];
189 }
190
191 return width;
192 }
193
194 int
SFont_TextHeight(const SFont_Font * Font)195 SFont_TextHeight (const SFont_Font * Font)
196 {
197 return Font->Surface->h - 1;
198 }
199
200 void
SFont_WriteCenter(SDL_Surface * Surface,SFont_Font * Font,int y,char * text)201 SFont_WriteCenter (SDL_Surface * Surface, SFont_Font * Font,
202 int y, char *text)
203 {
204 SFont_Write (Font, Surface->w / 2 - SFont_TextWidth (Font, text) / 2,
205 y, text);
206 }
207
208 /* Added by Juan Pedro Bolívar Puente */
209 int
charWidth(SFont_Font * Font,char c)210 charWidth (SFont_Font * Font, char c)
211 {
212 int charoffset = ((int) c - 33) * 2 + 1;
213 /* skip spaces and nonprintable characters */
214 if (c == ' ' || charoffset < 0 || charoffset > Font->MaxPos)
215 {
216 return (Font->CharPos[2] - Font->CharPos[1]);
217 }
218 return (Font->CharPos[charoffset + 1] - Font->CharPos[charoffset]);
219 }
220
221 int
findWord(SFont_Font * Font,char * text,int i)222 findWord (SFont_Font * Font, char *text, int i)
223 {
224 char *c;
225 for (c = text + i; *c != ' ' && *c != '/' && *c != '\\' && *c != '\0'; c++)
226 {
227 i++;
228 }
229 return i;
230 }
231
232 int
wordWidth(SFont_Font * Font,char * text,int i,int end)233 wordWidth (SFont_Font * Font, char *text, int i, int end)
234 {
235 int width = 0;
236 for (; i < end; i++)
237 {
238 width += charWidth (Font, text[i]);
239 }
240 return width;
241 }
242
243 void
copyWord(SFont_Font * Font,char * text,char * dest,int start,int end)244 copyWord (SFont_Font * Font, char *text, char *dest, int start, int end)
245 {
246 int i;
247 int len = strlen (dest);
248 for (i = 0; i <= (end - start); i++)
249 {
250 dest[len + i] = text[start + i];
251 }
252 dest[len + i] = '\0';
253 }
254
255 void
SFont_WriteAligned(SFont_Font * Font,int x,int y,int w,int gap,int align,char * text)256 SFont_WriteAligned (SFont_Font * Font, int x, int y, int w,
257 int gap, int align, char *text)
258 {
259 char buf[512] = "";
260 int width = 0;
261 int ww = 0;
262 int len = strlen (text);
263 int i = 0;
264 int nextWord = 0;
265
266 if (text == NULL)
267 return;
268
269 for (i = 0; i < len; i++)
270 {
271 ww = wordWidth (Font, text, i, nextWord + 1);
272 if ((width + ww) >= w)
273 {
274 switch (align)
275 {
276 case ALEFT:
277 SFont_Write (Font, x, y, buf);
278 break;
279 case ARIGHT:
280 SFont_Write (Font, x + w - width, y, buf);
281 break;
282 case ACENTER:
283 SFont_Write (Font, x + (w - width) / 2, y, buf);
284 break;
285 default:
286 break;
287 }
288 width = 0;
289 buf[0] = '\0';
290 y += Font->Surface->h + gap;
291 }
292 width += ww;
293 copyWord (Font, text, buf, i, nextWord);
294 i = nextWord;
295 nextWord = findWord (Font, text, i + 1);
296 }
297
298 switch (align)
299 {
300 case ALEFT:
301 SFont_Write (Font, x, y, buf);
302 break;
303 case ARIGHT:
304 SFont_Write (Font, x + w - width, y, buf);
305 break;
306 case ACENTER:
307 SFont_Write (Font, x + (w - width) / 2, y, buf);
308 break;
309 default:
310 break;
311 }
312 }
313
314 int
SFont_AlignedHeight(SFont_Font * Font,int w,int gap,char * text)315 SFont_AlignedHeight (SFont_Font * Font, int w, int gap, char *text)
316 {
317 char buf[512] = "";
318 int width = 0;
319 int ww = 0;
320 int len = strlen (text);
321 int i = 0;
322 int y = 0;
323 int nextWord = 0;
324
325 if (text == NULL)
326 return 0;
327
328 for (i = 0; i < len; i++)
329 {
330 ww = wordWidth (Font, text, i, nextWord + 1);
331 if ((width + ww) >= w)
332 {
333 width = 0;
334 buf[0] = '\0';
335 y += Font->Surface->h + gap;
336 }
337 width += ww;
338 copyWord (Font, text, buf, i, nextWord);
339 i = nextWord;
340 nextWord = findWord (Font, text, i + 1);
341 }
342 return y += Font->Surface->h;
343 }
344
345 int
SFont_FillWith(SFont_Font * Font,int x,int y,int w,char c)346 SFont_FillWith (SFont_Font * Font, int x, int y, int w, char c)
347 {
348 int charoffset = ((int) c - 33) * 2 + 1;
349 int charw = charWidth (Font, c);
350 int i, j = 0;
351 SDL_Rect srcrect, dstrect;
352
353 srcrect.y = 1;
354 dstrect.y = y;
355 srcrect.h = dstrect.h = Font->Surface->h - 1;
356 for (i = x + (x % charw); i <= x + w - charw; i += charw)
357 {
358 srcrect.w = dstrect.w =
359 (Font->CharPos[charoffset + 2] + Font->CharPos[charoffset + 1]) / 2 -
360 (Font->CharPos[charoffset] + Font->CharPos[charoffset - 1]) / 2;
361 srcrect.x =
362 (Font->CharPos[charoffset] + Font->CharPos[charoffset - 1]) / 2;
363 dstrect.x =
364 i - (float) (Font->CharPos[charoffset] -
365 Font->CharPos[charoffset - 1]) / 2;
366
367 //JPB_PrintSurface(Font->Surface, &srcrect, &dstrect);
368 JPB_PrintSurface (Font->Surface, &srcrect, &dstrect);
369 j++;
370 }
371 return j;
372 }
373
374 void
SFont_WriteMaxWidth(SFont_Font * Font,int x,int y,int w,int align,char * tag,char * text)375 SFont_WriteMaxWidth (SFont_Font * Font, int x, int y, int w, int align,
376 char *tag, char *text)
377 {
378 int tagw = SFont_TextWidth (Font, tag);
379 int width = SFont_TextWidth (Font, text);
380 int i = 0;
381 char *buf = NULL;
382
383 if (width >= w - tagw)
384 {
385 buf = malloc (sizeof (char) * (strlen (text) + 1));
386 width = 0;
387 while (width <= w - tagw)
388 {
389 buf[i] = text[i];
390 buf[i + 1] = '\0';
391 width += charWidth (Font, text[i]);
392 i++;
393 }
394 width -= charWidth (Font, text[i]);
395 buf[--i] = '\0';
396 strcat (buf, tag);
397 width += tagw;
398 }
399 else
400 {
401 buf = text;
402 }
403
404 switch (align)
405 {
406 case ALEFT:
407 SFont_Write (Font, x, y, buf);
408 break;
409 case ARIGHT:
410 SFont_Write (Font, x + w - width, y, buf);
411 break;
412 case ACENTER:
413 SFont_Write (Font, x + (w - width) / 2, y, buf);
414 break;
415 default:
416 break;
417 }
418
419 if (buf != text)
420 free (buf);
421
422 }
423
424 int
SFont_SetAlpha(SFont_Font * font,int alpha)425 SFont_SetAlpha (SFont_Font * font, int alpha)
426 {
427 int r;
428 r = font->Surface->alpha;
429 font->Surface->alpha = alpha;
430 return r;
431 }
432