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