Commit | Line | Data |
bfd90409 |
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 | |
2a668066 |
47 | #include "../../src/defines.h" |
48 | #include "../../src/SFont.h" |
bfd90409 |
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') |
24379be6 |
228 | sprintf(text+strlen(text),"%c",ch); |
bfd90409 |
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 |