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