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