Fixed XS building
[sdlgit/SDL_perl.git] / src / SFont.xs
1 // SDL::SFont
2 //
3 // SFont bitmap font support
4 //
5 // SFont library code by Karl Bartel <karlb@gmx.net>       
6 //
7 // SFont.xs Copyright (C) 2004 David J. Goehrig
8 //
9
10 #include "EXTERN.h"
11 #include "perl.h"
12 #include "XSUB.h"
13
14 #ifndef aTHX_
15 #define aTHX_
16 #endif
17
18 #include <SDL.h>
19 #include <string.h>
20 #include <stdlib.h>
21
22 #ifdef USE_THREADS
23 #define HAVE_TLS_CONTEXT
24 #endif
25
26 #include "defines.h"
27 #include "SFont.h"
28
29 #ifdef HAVE_SDL_IMAGE
30 #include <SDL_image.h>
31
32 SFont_FontInfo InternalFont;
33 Uint32 SFont_GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
34 {
35
36    Uint8  *bits;
37    Uint32 Bpp;
38    if (X<0) puts("SFONT ERROR: x too small in SFont_GetPixel. Report this to <karlb@gmx.net>");
39    if (X>=Surface->w) puts("SFONT ERROR: x too big in SFont_GetPixel. Report this to <karlb@gmx.net>");
40    
41    Bpp = Surface->format->BytesPerPixel;
42
43    bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp;
44
45    // Get the pixel
46    switch(Bpp) {
47       case 1:
48          return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X);
49          break;
50       case 2:
51          return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X);
52          break;
53       case 3: { // Format/endian independent 
54          Uint8 r, g, b;
55          r = *((bits)+Surface->format->Rshift/8);
56          g = *((bits)+Surface->format->Gshift/8);
57          b = *((bits)+Surface->format->Bshift/8);
58          return SDL_MapRGB(Surface->format, r, g, b);
59          }
60          break;
61       case 4:
62          return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X);
63          break;
64    }
65
66     return -1;
67 }
68
69 void SFont_InitFont2(SFont_FontInfo *Font)
70 {
71     int x = 0, i = 0;
72
73     if ( Font->Surface==NULL ) {
74         printf("The font has not been loaded!\n");
75         exit(1);
76     }
77
78     if (SDL_MUSTLOCK(Font->Surface)) SDL_LockSurface(Font->Surface);
79
80     while ( x < Font->Surface->w ) {
81         if(SFont_GetPixel(Font->Surface,x,0)==SDL_MapRGB(Font->Surface->format,255,0,255)) { 
82             Font->CharPos[i++]=x;
83             while (( x < Font->Surface->w-1) && (SFont_GetPixel(Font->Surface,x,0)==SDL_MapRGB(Font->Surface->format,255,0,255)))
84                 x++;
85             Font->CharPos[i++]=x;
86         }
87         x++;
88     }
89     if (SDL_MUSTLOCK(Font->Surface)) SDL_UnlockSurface(Font->Surface);
90
91     Font->h=Font->Surface->h;
92     SDL_SetColorKey(Font->Surface, SDL_SRCCOLORKEY, SFont_GetPixel(Font->Surface, 0, Font->Surface->h-1));
93 }
94
95 void SFont_InitFont(SDL_Surface *Font)
96 {
97     InternalFont.Surface=Font;
98     SFont_InitFont2(&InternalFont);
99 }
100
101 void SFont_PutString2(SDL_Surface *Surface, SFont_FontInfo *Font, int x, int y, char *text)
102 {
103     int ofs;
104     int i=0;
105     SDL_Rect srcrect,dstrect; 
106
107     while (text[i]!='\0') {
108         if (text[i]==' ') {
109             x+=Font->CharPos[2]-Font->CharPos[1];
110             i++;
111         }
112         else {
113 //          printf("-%c- %c - %u\n",228,text[i],text[i]);
114             ofs=(text[i]-33)*2+1;
115 //          printf("printing %c %d\n",text[i],ofs);
116             srcrect.w = dstrect.w = (Font->CharPos[ofs+2]+Font->CharPos[ofs+1])/2-(Font->CharPos[ofs]+Font->CharPos[ofs-1])/2;
117             srcrect.h = dstrect.h = Font->Surface->h-1;
118             srcrect.x = (Font->CharPos[ofs]+Font->CharPos[ofs-1])/2;
119             srcrect.y = 1;
120             dstrect.x = x-(float)(Font->CharPos[ofs]-Font->CharPos[ofs-1])/2;
121             dstrect.y = y;
122
123             SDL_BlitSurface( Font->Surface, &srcrect, Surface, &dstrect); 
124
125             x+=Font->CharPos[ofs+1]-Font->CharPos[ofs];
126             i++;
127         }
128     }
129 }
130
131 void SFont_PutString(SDL_Surface *Surface, int x, int y, char *text)
132 {
133     SFont_PutString2(Surface, &InternalFont, x, y, text);
134 }
135
136 int SFont_TextWidth2(SFont_FontInfo *Font, char *text)
137 {
138     int ofs=0;
139     int i=0,x=0;
140
141     while (text[i]!='\0') {
142         if (text[i]==' ') {
143             x+=Font->CharPos[2]-Font->CharPos[1];
144             i++;
145         }
146         else {
147             ofs=(text[i]-33)*2+1;
148             x+=Font->CharPos[ofs+1]-Font->CharPos[ofs];
149             i++;
150         }
151     }
152 //    printf ("--%d\n",x);
153     return x;
154 }
155
156 int SFont_TextWidth(char *text)
157 {
158     return SFont_TextWidth2(&InternalFont, text);
159 }
160
161 void SFont_XCenteredString2(SDL_Surface *Surface, SFont_FontInfo *Font, int y, char *text)
162 {
163     SFont_PutString2(Surface, Font, Surface->w/2-SFont_TextWidth2(Font,text)/2, y, text);
164 }
165
166 void SFont_XCenteredString(SDL_Surface *Surface, int y, char *text)
167 {
168     SFont_XCenteredString2(Surface, &InternalFont, y, text);
169 }
170
171 void SFont_InternalInput( SDL_Surface *Dest, SFont_FontInfo *Font, int x, int y, int PixelWidth, char *text)
172 {
173     SDL_Event event;
174     int ch=-1,blink=0;
175     long blinktimer=0;
176     SDL_Surface *Back;
177     SDL_Rect rect;
178     int previous;
179 //    int ofs=(text[0]-33)*2+1;
180 //    int leftshift=(Font->CharPos[ofs]-Font->CharPos[ofs-1])/2;
181     
182     Back = SDL_AllocSurface(Dest->flags,
183                             Dest->w,
184                             Font->h,
185                             Dest->format->BitsPerPixel,
186                             Dest->format->Rmask,
187                             Dest->format->Gmask,
188                             Dest->format->Bmask, 0);
189     rect.x=0;
190     rect.y=y;
191     rect.w=Dest->w;
192     rect.h=Font->Surface->h;
193     SDL_BlitSurface(Dest, &rect, Back, NULL);
194     SFont_PutString2(Dest,Font,x,y,text);
195     SDL_UpdateRects(Dest, 1, &rect);
196         
197     // start input
198     previous=SDL_EnableUNICODE(1);
199     blinktimer=SDL_GetTicks();
200     while (ch!=SDLK_RETURN) {
201         if (event.type==SDL_KEYDOWN) {
202             ch=event.key.keysym.unicode;
203             if (((ch>31)||(ch=='\b')) && (ch<128)) {
204                 if ((ch=='\b')&&(strlen(text)>0))
205                     text[strlen(text)-1]='\0';
206                 else if (ch!='\b')
207                     sprintf(text,"%s%c",text,ch);
208                 if (SFont_TextWidth2(Font,text)>PixelWidth) text[strlen(text)-1]='\0';
209                 SDL_BlitSurface( Back, NULL, Dest, &rect);
210                 SFont_PutString2(Dest, Font, x, y, text);
211                 SDL_UpdateRects(Dest, 1, &rect);
212 //              printf("%s ## %d\n",text,strlen(text));
213                 SDL_WaitEvent(&event);
214             }
215         }
216         if (SDL_GetTicks()>blinktimer) {
217             blink=1-blink;
218             blinktimer=SDL_GetTicks()+500;
219             if (blink) {
220                 SFont_PutString2(Dest, Font, x+SFont_TextWidth2(Font,text), y, "|");
221                 SDL_UpdateRects(Dest, 1, &rect);
222 //              SDL_UpdateRect(Dest, x+SFont_TextWidth2(Font,text), y, SFont_TextWidth2(Font,"|"), Font->Surface->h);
223             } else {
224                 SDL_BlitSurface( Back, NULL, Dest, &rect);
225                 SFont_PutString2(Dest, Font, x, y, text);
226                 SDL_UpdateRects(Dest, 1, &rect);
227 //              SDL_UpdateRect(Dest, x-(Font->CharPos[ofs]-Font->CharPos[ofs-1])/2, y, PixelWidth, Font->Surface->h);
228             }
229         }
230         SDL_Delay(1);
231         SDL_PollEvent(&event);
232     }
233     text[strlen(text)]='\0';
234     SDL_FreeSurface(Back);
235     SDL_EnableUNICODE(previous);  //restore the previous state
236 }
237
238 void SFont_Input2( SDL_Surface *Dest, SFont_FontInfo *Font, int x, int y, int PixelWidth, char *text)
239 {
240     SFont_InternalInput( Dest, Font, x, y, PixelWidth,  text);
241 }
242 void SFont_Input( SDL_Surface *Dest, int x, int y, int PixelWidth, char *text)
243 {
244     SFont_Input2( Dest, &InternalFont, x, y, PixelWidth, text);
245 }
246
247 #endif
248
249 MODULE = SDL::SFont             PACKAGE = SDL::SFont
250 PROTOTYPES : DISABLE
251
252 #ifdef HAVE_SDL_IMAGE
253
254 SDL_Surface *
255 NewFont ( filename )
256         char *filename
257         CODE:
258                 RETVAL = IMG_Load(filename);
259                 SFont_InitFont(RETVAL);
260         OUTPUT:
261                 RETVAL
262
263 void
264 UseFont ( surface )
265         SDL_Surface *surface
266         CODE:
267                 SFont_InitFont(surface);
268
269 void
270 PutString ( surface, x, y, text )
271         SDL_Surface *surface
272         int x
273         int y
274         char *text
275         CODE:
276                 SFont_PutString( surface, x, y, text );
277
278 int
279 TextWidth ( text )
280         char *text
281         CODE:
282                 RETVAL = SFont_TextWidth(text);
283         OUTPUT:
284                 RETVAL
285                 
286
287 #endif