1 #include <SDL/SDL.h>
2 #include "SFont.h"
3 #include "string.h"
4 
5 SFont_FontInfo InternalFont;
6 int alpha = 127;
7 int font_height;
8 SDL_Surface *Back = NULL;
9 char tmp[1024];
10 
GetPixel(SDL_Surface * Surface,Sint32 X,Sint32 Y)11 Uint32 GetPixel(SDL_Surface * Surface, Sint32 X, Sint32 Y) {
12 
13   Uint8 *bits;
14   Uint32 Bpp;
15 
16   if(X < 0)
17     puts
18       ("SFONT ERROR: x too small in GetPixel. Report this to <karlb@gmx.net>");
19   if(X >= Surface->w)
20     puts
21       ("SFONT ERROR: x too big in GetPixel. Report this to <karlb@gmx.net>");
22 
23   Bpp = Surface->format->BytesPerPixel;
24 
25   bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch + X * Bpp;
26 
27   // Paint the walls with the fresh blood of your enemies
28 
29   // Get the pixel
30   switch (Bpp) {
31   case 1:
32     return *((Uint8 *) Surface->pixels + Y * Surface->pitch + X);
33     break;
34   case 2:
35     return *((Uint16 *) Surface->pixels + Y * Surface->pitch / 2 + X);
36     break;
37   case 3:{			// Format/endian independent
38       Uint8 r, g, b;
39       r = *((bits) + Surface->format->Rshift / 8);
40       g = *((bits) + Surface->format->Gshift / 8);
41       b = *((bits) + Surface->format->Bshift / 8);
42       return SDL_MapRGB(Surface->format, r, g, b);
43     }
44     break;
45   case 4:
46     return *((Uint32 *) Surface->pixels + Y * Surface->pitch / 4 + X);
47     break;
48   }
49 
50   return -1;
51 }
52 
InitFont2(SFont_FontInfo * Font)53 void InitFont2(SFont_FontInfo * Font) {
54   int x = 0, i = 0;
55 
56   if(Font->Surface == NULL) {
57     printf("The font has not been loaded!\n");
58     exit(1);
59   }
60 
61   while(x < Font->Surface->w) {
62     if(GetPixel(Font->Surface, x, 0) ==
63        SDL_MapRGB(Font->Surface->format, 255, 0, 255)) {
64       Font->CharPos[i++] = x;
65       while((x < Font->Surface->w - 1)
66 	    && (GetPixel(Font->Surface, x, 0) ==
67 		SDL_MapRGB(Font->Surface->format, 255, 0, 255)))
68 	x++;
69       Font->CharPos[i++] = x;
70     }
71     x++;
72   }
73 
74   Font->h = Font->Surface->h;
75   font_height = Font->h;
76   SDL_SetColorKey(Font->Surface, SDL_SRCCOLORKEY,
77 		  GetPixel(Font->Surface, 0, Font->Surface->h - 1));
78 }
79 
InitFont(SDL_Surface * Font)80 void InitFont(SDL_Surface * Font) {
81   InternalFont.Surface = Font;
82   InitFont2(&InternalFont);
83 }
84 
SFont_wide(const char * text)85 int SFont_wide(const char *text) {
86   int i = 0, xwide = 0;
87   int ofs;
88   SFont_FontInfo *Font = &InternalFont;
89 
90   while(text[i]) {
91     if(text[i] == ' ') {
92       xwide += (int) (Font->CharPos[2] - Font->CharPos[1]);
93     } else {
94       ofs = (text[i] - 33) * 2 + 1;
95       xwide += (int) (Font->CharPos[ofs + 1] - Font->CharPos[ofs]);
96     }
97     i++;
98   }
99   return xwide;
100 }
101 
SFont_height()102 int SFont_height() {
103   return InternalFont.Surface->h - 1;
104 }
105 
PutString2(SDL_Surface * Surface,SFont_FontInfo * Font,int x,int y,const char * text)106 void PutString2(SDL_Surface * Surface, SFont_FontInfo * Font, int x, int y,
107 		const char *text) {
108   int ofs;
109   int i = 0;
110   SDL_Rect srcrect, dstrect;
111 
112   while(text[i]) {
113     if(text[i] == ' ') {
114       x += Font->CharPos[2] - Font->CharPos[1];
115     } else {
116 //          printf("-%c- %c - %u\n",228,text[i],text[i]);
117       ofs = (text[i] - 33) * 2 + 1;
118       //printf("printing %c %d\n",text[i],ofs);
119       srcrect.w = dstrect.w =
120 	(Font->CharPos[ofs + 2] + Font->CharPos[ofs + 1]) / 2 -
121 	(Font->CharPos[ofs] + Font->CharPos[ofs - 1]) / 2;
122       srcrect.h = dstrect.h = Font->Surface->h - 1;
123       srcrect.x = (Font->CharPos[ofs] + Font->CharPos[ofs - 1]) / 2;
124       srcrect.y = 1;
125       dstrect.x =
126 	x - (float) (Font->CharPos[ofs] - Font->CharPos[ofs - 1]) / 2;
127       dstrect.y = y;
128 
129       //SDL_SetAlpha ( Font->Surface, SDL_SRCALPHA, 127);
130       SDL_BlitSurface(Font->Surface, &srcrect, Surface, &dstrect);
131 
132       x += Font->CharPos[ofs + 1] - Font->CharPos[ofs];
133     }
134     i++;
135   }
136 }
137 
138 // Return a new surface, with the text on it.
139 // This surface is new, fresh, and must eventually be freed.
140 // Create the new surface with the same colour system as a parent surface.
new_Surface_PutString(SDL_Surface * parent,const char * text)141 SDL_Surface *new_Surface_PutString(SDL_Surface * parent, const char *text) {
142 
143   Uint32 rmask = parent->format->Rmask;
144   Uint32 gmask = parent->format->Gmask;
145   Uint32 bmask = parent->format->Bmask;
146   Uint32 amask = parent->format->Amask;
147   Uint32 bytesperpixel = parent->format->BytesPerPixel;
148 
149   return SDL_CreateRGBSurface(SDL_SWSURFACE,
150 			      SFont_wide(text),
151 			      SFont_height(),
152 			      bytesperpixel, rmask, gmask, bmask, amask);
153 }
154 
PutString(SDL_Surface * Surface,int x,int y,const char * text)155 void PutString(SDL_Surface * Surface, int x, int y, const char *text) {
156   PutString2(Surface, &InternalFont, x, y, text);
157 }
158 
TextWidth2(SFont_FontInfo * Font,char * text)159 int TextWidth2(SFont_FontInfo * Font, char *text) {
160   int x = 0, i = 0;
161   unsigned char ofs = 0;
162   while(text[i] != '\0') {
163     if(text[i] == ' ') {
164       x += Font->CharPos[2] - Font->CharPos[1];
165       i++;
166     } else {
167       ofs = (text[i] - 33) * 2 + 1;
168       x += Font->CharPos[ofs + 1] - Font->CharPos[ofs];
169       i++;
170     }
171   }
172   return x + Font->CharPos[ofs + 2] - Font->CharPos[ofs + 1];
173 }
174 
TextWidth(char * text)175 int TextWidth(char *text) {
176   return TextWidth2(&InternalFont, text);
177 }
178 
TextAlpha(int a)179 void TextAlpha(int a) {
180   alpha = a;
181 }
182 
XCenteredString2(SDL_Surface * Surface,SFont_FontInfo * Font,int y,char * text)183 void XCenteredString2(SDL_Surface * Surface, SFont_FontInfo * Font, int y,
184 		      char *text) {
185   PutString2(Surface, &InternalFont, Surface->w / 2 - TextWidth(text) / 2, y,
186 	     text);
187 }
188 
XCenteredString(SDL_Surface * Surface,int y,char * text)189 void XCenteredString(SDL_Surface * Surface, int y, char *text) {
190   XCenteredString2(Surface, &InternalFont, y, text);
191 }
192 
clearBuffer()193 void clearBuffer() {
194   SDL_Event event;
195 
196   // Delete the event buffer
197   while(SDL_PollEvent(&event));
198   // start input
199   SDL_EnableUNICODE(1);
200 }
201 
SFont_Input2(SDL_Surface * Dest,SFont_FontInfo * Font,int x,int y,int PixelWidth,char * text)202 int SFont_Input2(SDL_Surface * Dest, SFont_FontInfo * Font, int x, int y,
203 		 int PixelWidth, char *text) {
204   SDL_Event event;
205   SDL_Rect rect;
206   int ofs = (text[0] - 33) * 2 + 1;
207   int leftshift;
208   int ch = 0; //Fixes a warning: may be used unintialised.
209   char *sptr;
210 
211   if(ofs < 0) {
212     leftshift = 0;
213   } else {
214     leftshift = (Font->CharPos[ofs] - Font->CharPos[ofs - 1]) / 2;
215   }
216 
217   rect.x = x - leftshift;
218   rect.y = y;
219   rect.w = PixelWidth;
220   rect.h = Font->Surface->h;
221 
222   //SDL_SetAlpha (Dest, SDL_SRCALPHA, 127);
223 
224   SDL_BlitSurface(Dest, &rect, Back, NULL);
225   sprintf(tmp, "%s_", text);
226   PutString2(Dest, Font, x, y, tmp);
227   SDL_UpdateRect(Dest, x - leftshift, y, PixelWidth, Font->h);
228 
229   while(SDL_PollEvent(&event) && event.type == SDL_KEYDOWN) {
230 
231     // Find the character pressed
232     ch = event.key.keysym.unicode;
233 
234     // If the character is illegal, we PASS IT THROUGH TO APPEND TO THE
235     // STRING ANYWAY! Boy are we dumb sometimes.  This character should
236     // first be checked to see if it's in the list of characters supported
237     // by this font.
238     // TODO
239 
240     // If backspace and the length of the text > 0, reduce the string by 1 character
241     if(ch == '\b') {
242       if(strlen(text) > 0) {
243 	text[strlen(text) - 1] = '\0';
244       }
245     } else {
246       for(sptr = text; *sptr; ++sptr) ; //Find end of string.
247       *sptr++ = ch;
248       *sptr++ = '\0';
249     }
250 
251     // If the new character would exceed the allowed width
252     if(TextWidth2(Font, text) > PixelWidth) {
253       text[strlen(text) - 1] = '\0';
254     }
255     //SDL_SetAlpha (Back, SDL_SRCALPHA, 127);
256     SDL_BlitSurface(Back, NULL, Dest, &rect);
257     PutString2(Dest, Font, x, y, text);
258     if(ofs > 0) {
259       SDL_UpdateRect(Dest,
260 		     x - (Font->CharPos[ofs] - Font->CharPos[ofs - 1]) / 2, y,
261 		     PixelWidth, Font->Surface->h);
262     }
263 
264   }
265   if(ch == SDLK_RETURN) {
266     SDL_FreeSurface(Back);
267     Back = NULL;
268     text[strlen(text)-1]='\0'; //Remove the CR character as this produces weird effects.
269     return 1;
270   } else
271     return 0;
272 }
273 
SFont_Input(SDL_Surface * Dest,int x,int y,int PixelWidth,char * text)274 int SFont_Input(SDL_Surface * Dest, int x, int y, int PixelWidth, char *text) {
275   if(Back == NULL) {
276     Back = SDL_AllocSurface(Dest->flags,
277 			    PixelWidth,
278 			    InternalFont.h,
279 			    Dest->format->BitsPerPixel,
280 			    Dest->format->Rmask,
281 			    Dest->format->Gmask, Dest->format->Bmask, 0);
282   }
283   return SFont_Input2(Dest, &InternalFont, x, y, PixelWidth, text);
284   // ph:
285   // Returns 1 when the return key is pressed
286   // Returns 0 when nothing exceptional happened
287 }
288