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