JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
e5d78632bea00014909b9114933bac158e06caaa
[vor.git] / SFont.c
1 #include <SDL/SDL.h>
2 #include <stdlib.h>
3 #include "SFont.h"
4 #include "string.h"
5
6 SFont_FontInfo InternalFont;
7 int alpha=127;
8 int font_height;
9
10 Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
11 {
12
13    Uint8  *bits;
14    Uint32 Bpp;
15
16    if (X<0) puts("SFONT ERROR: x too small in GetPixel. Report this to <karlb@gmx.net>");
17    if (X>=Surface->w) puts("SFONT ERROR: x too big in GetPixel. Report this to <karlb@gmx.net>");
18    
19    Bpp = Surface->format->BytesPerPixel;
20
21    bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp;
22
23    // Paint the walls with the fresh blood of your enemies
24
25    // Get the pixel
26    switch(Bpp) {
27       case 1:
28          return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X);
29          break;
30       case 2:
31          return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X);
32          break;
33       case 3: { // Format/endian independent 
34          Uint8 r, g, b;
35          r = *((bits)+Surface->format->Rshift/8);
36          g = *((bits)+Surface->format->Gshift/8);
37          b = *((bits)+Surface->format->Bshift/8);
38          return SDL_MapRGB(Surface->format, r, g, b);
39          }
40          break;
41       case 4:
42          return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X);
43          break;
44    }
45
46     return -1;
47 }
48
49 void InitFont2(SFont_FontInfo *Font)
50 {
51     int x = 0, i = 0;
52
53     if ( Font->Surface==NULL ) {
54         printf("The font has not been loaded!\n");
55         exit(1);
56     }
57
58     while ( x < Font->Surface->w ) {
59         if(GetPixel(Font->Surface,x,0)==SDL_MapRGB(Font->Surface->format,255,0,255)) { 
60             Font->CharPos[i++]=x;
61             while (( x < Font->Surface->w-1) && (GetPixel(Font->Surface,x,0)==SDL_MapRGB(Font->Surface->format,255,0,255)))
62                 x++;
63             Font->CharPos[i++]=x;
64         }
65         x++;
66     }
67
68     Font->h=Font->Surface->h;
69     font_height = Font->h;
70     SDL_SetColorKey(Font->Surface, SDL_SRCCOLORKEY, GetPixel(Font->Surface, 0, Font->Surface->h-1));
71 }
72
73 void InitFont(SDL_Surface *Font)
74 {
75     InternalFont.Surface=Font;
76     InitFont2(&InternalFont);
77 }
78
79 int SFont_wide(char *text) {
80     int i=0,xwide=0;
81     int ofs;
82     SFont_FontInfo *Font = &InternalFont;
83
84     while (text[i]) {
85         if (text[i]==' ') {
86             xwide += (int)(Font->CharPos[2]-Font->CharPos[1]);
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                 } else {
161                         ofs=(text[i]-33)*2+1;
162                         x+=Font->CharPos[ofs+1]-Font->CharPos[ofs];
163                 }
164                 i++;
165     }
166     return x+Font->CharPos[ofs+2]-Font->CharPos[ofs+1];
167 }
168
169 int TextWidth(char *text)
170 {
171     return TextWidth2(&InternalFont, text);
172 }
173
174 void TextAlpha(int a) {
175     alpha = a;
176 }
177
178 void XCenteredString2(SDL_Surface *Surface, SFont_FontInfo *Font, int y, char *text)
179 {
180     PutString2(Surface, &InternalFont, Surface->w/2-TextWidth(text)/2, y, text);
181 }
182
183 void XCenteredString(SDL_Surface *Surface, int y, char *text)
184 {
185     XCenteredString2(Surface, &InternalFont, y, text);
186 }
187
188 SDL_Surface *Back;
189 char tmp[1024];
190
191 void clearBuffer() {
192     SDL_Event event;
193
194     // Delete the event buffer
195     while (SDL_PollEvent(&event))
196         ;
197     // start input
198     SDL_EnableUNICODE(1);
199 }
200
201 int SFont_Input2( SDL_Surface *Dest, SFont_FontInfo *Font, int x, int y, int PixelWidth, char *text)
202 {
203     SDL_Event event;
204     int ch;
205     SDL_Rect rect;
206     int ofs=(text[0]-33)*2+1;
207     int leftshift;
208
209     if (ofs<0) {
210         leftshift = 0;
211     }
212     else {
213         leftshift = (Font->CharPos[ofs]-Font->CharPos[ofs-1])/2;
214     }
215
216     rect.x=x-leftshift;
217     rect.y=y;
218     rect.w=PixelWidth;
219     rect.h=Font->Surface->h;
220
221     //SDL_SetAlpha (Dest, SDL_SRCALPHA, 127);
222
223     SDL_BlitSurface(Dest, &rect, Back, NULL);
224     sprintf(tmp,"%s_",text);
225     PutString2(Dest,Font,x,y,tmp);
226     SDL_UpdateRect(Dest, x-leftshift, y, PixelWidth, Font->h);
227
228     while (SDL_PollEvent(&event) && event.type==SDL_KEYDOWN) {
229
230         // Find the character pressed
231         ch=event.key.keysym.unicode;
232
233         // If backspace and the length of the text > 0, reduce the string by 1 character
234         if (ch=='\b') {
235             if (strlen(text)>0) {
236                 text[strlen(text)-1]='\0';
237             }
238         }
239         else {
240             sprintf(text,"%s%c",text,ch);
241         }
242
243         // If the new character would exceed the allowed width
244         if (TextWidth2(Font,text)>PixelWidth) {
245             text[strlen(text)-1]='\0';
246         }
247
248         //SDL_SetAlpha (Back, SDL_SRCALPHA, 127);
249         SDL_BlitSurface( Back, NULL, Dest, &rect);
250         PutString2(Dest, Font, x, y, text);
251         if (ofs>0) {
252             SDL_UpdateRect(Dest, x-(Font->CharPos[ofs]-Font->CharPos[ofs-1])/2, y, PixelWidth, Font->Surface->h);
253         }
254
255     }
256     //text[strlen(text)-1]='\0';
257     if (ch==SDLK_RETURN) {
258         SDL_FreeSurface(Back);
259         return 1;
260     }
261     else
262         return 0;
263 }
264
265 int SFont_Input( SDL_Surface *Dest, int x, int y, int PixelWidth, char *text)
266 {
267     
268     Back = SDL_AllocSurface(Dest->flags,
269                             PixelWidth,
270                             InternalFont.h,
271                             Dest->format->BitsPerPixel,
272                             Dest->format->Rmask,
273                             Dest->format->Gmask,
274                             Dest->format->Bmask, 0);
275
276     return SFont_Input2( Dest, &InternalFont, x, y, PixelWidth, text);
277     // ph:
278     // Returns 1 when the return key is pressed
279     // Returns 0 when nothing exceptional happened
280 }