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