Commit | Line | Data |
8fde61e3 |
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 | |
e00a4871 |
26 | #include "defines.h" |
27 | #include "SFont.h" |
8fde61e3 |
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 |