/* */ /* SFont.xs */ /* */ /* Original SFont code Copyright (C) Karl Bartel */ /* Copyright (C) 2005 David J. Goehrig */ /* */ /* ------------------------------------------------------------------------------ */ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Lesser General Public */ /* License as published by the Free Software Foundation; either */ /* version 2.1 of the License, or (at your option) any later version. */ /* */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Lesser General Public License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public */ /* License along with this library; if not, write to the Free Software */ /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* */ /* ------------------------------------------------------------------------------ */ /* */ /* Please feel free to send questions, suggestions or improvements to: */ /* */ /* David J. Goehrig */ /* dgoehrig@cpan.org */ /* */ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #ifndef aTHX_ #define aTHX_ #endif #include #ifdef HAVE_SDL_IMAGE #include #endif #include #include #ifdef USE_THREADS #define HAVE_TLS_CONTEXT #endif #include "SDLx/SFont.h" SFont_FontInfo InternalFont; Uint32 SFont_GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y) { Uint8 *bits; Uint32 Bpp; if (X<0) puts("SFONT ERROR: x too small in SFont_GetPixel. Report this to "); if (X>=Surface->w) puts("SFONT ERROR: x too big in SFont_GetPixel. Report this to "); Bpp = Surface->format->BytesPerPixel; bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp; /* Get the pixel */ switch(Bpp) { case 1: return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X); break; case 2: return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X); break; case 3: { /* Format/endian independent */ Uint8 r, g, b; r = *((bits)+Surface->format->Rshift/8); g = *((bits)+Surface->format->Gshift/8); b = *((bits)+Surface->format->Bshift/8); return SDL_MapRGB(Surface->format, r, g, b); } break; case 4: return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X); break; } return -1; } void SFont_InitFont2(SFont_FontInfo *Font) { int x = 0, i = 0; if ( Font->Surface==NULL ) { printf("The font has not been loaded!\n"); exit(1); } if (SDL_MUSTLOCK(Font->Surface)) SDL_LockSurface(Font->Surface); while ( x < Font->Surface->w ) { if(SFont_GetPixel(Font->Surface,x,0)==SDL_MapRGB(Font->Surface->format,255,0,255)) { Font->CharPos[i++]=x; while (( x < Font->Surface->w-1) && (SFont_GetPixel(Font->Surface,x,0)==SDL_MapRGB(Font->Surface->format,255,0,255))) x++; Font->CharPos[i++]=x; } x++; } if (SDL_MUSTLOCK(Font->Surface)) SDL_UnlockSurface(Font->Surface); Font->h=Font->Surface->h; SDL_SetColorKey(Font->Surface, SDL_SRCCOLORKEY, SFont_GetPixel(Font->Surface, 0, Font->Surface->h-1)); } void SFont_InitFont(SDL_Surface *Font) { InternalFont.Surface=Font; SFont_InitFont2(&InternalFont); } void SFont_PutString2(SDL_Surface *Surface, SFont_FontInfo *Font, int x, int y, char *text) { int ofs; int i=0; SDL_Rect srcrect,dstrect; while (text[i]!='\0') { if (text[i]==' ') { x+=Font->CharPos[2]-Font->CharPos[1]; i++; } else { /* warn("-%c- %c - %u\n",228,text[i],text[i]); */ ofs=(text[i]-33)*2+1; /* warn("printing %c %d\n",text[i],ofs); */ srcrect.w = dstrect.w = (Font->CharPos[ofs+2]+Font->CharPos[ofs+1])/2-(Font->CharPos[ofs]+Font->CharPos[ofs-1])/2; srcrect.h = dstrect.h = Font->Surface->h-1; srcrect.x = (Font->CharPos[ofs]+Font->CharPos[ofs-1])/2; srcrect.y = 1; dstrect.x = x-(float)(Font->CharPos[ofs]-Font->CharPos[ofs-1])/2; dstrect.y = y; SDL_BlitSurface( Font->Surface, &srcrect, Surface, &dstrect); x+=Font->CharPos[ofs+1]-Font->CharPos[ofs]; i++; } } } void SFont_PutString(SDL_Surface *Surface, int x, int y, char *text) { /* warn("putString \n"); */ SFont_PutString2(Surface, &InternalFont, x, y, text); } int SFont_TextWidth2(SFont_FontInfo *Font, char *text) { int ofs=0; int i=0,x=0; while (text[i]!='\0') { if (text[i]==' ') { x+=Font->CharPos[2]-Font->CharPos[1]; i++; } else { ofs=(text[i]-33)*2+1; x+=Font->CharPos[ofs+1]-Font->CharPos[ofs]; i++; } } /* printf ("--%d\n",x); */ return x; } int SFont_TextWidth(char *text) { return SFont_TextWidth2(&InternalFont, text); } void SFont_XCenteredString2(SDL_Surface *Surface, SFont_FontInfo *Font, int y, char *text) { SFont_PutString2(Surface, Font, Surface->w/2-SFont_TextWidth2(Font,text)/2, y, text); } void SFont_XCenteredString(SDL_Surface *Surface, int y, char *text) { SFont_XCenteredString2(Surface, &InternalFont, y, text); } void SFont_InternalInput( SDL_Surface *Dest, SFont_FontInfo *Font, int x, int y, int PixelWidth, char *text) { SDL_Event event; int ch=-1,blink=0; long blinktimer=0; SDL_Surface *Back; SDL_Rect rect; int previous; /* int ofs=(text[0]-33)*2+1; */ /* int leftshift=(Font->CharPos[ofs]-Font->CharPos[ofs-1])/2; */ Back = SDL_AllocSurface(Dest->flags, Dest->w, Font->h, Dest->format->BitsPerPixel, Dest->format->Rmask, Dest->format->Gmask, Dest->format->Bmask, 0); rect.x=0; rect.y=y; rect.w=Dest->w; rect.h=Font->Surface->h; SDL_BlitSurface(Dest, &rect, Back, NULL); SFont_PutString2(Dest,Font,x,y,text); SDL_UpdateRects(Dest, 1, &rect); /* start input */ previous=SDL_EnableUNICODE(1); blinktimer=SDL_GetTicks(); while (ch!=SDLK_RETURN) { if (event.type==SDL_KEYDOWN) { ch=event.key.keysym.unicode; if (((ch>31)||(ch=='\b')) && (ch<128)) { if ((ch=='\b')&&(strlen(text)>0)) text[strlen(text)-1]='\0'; else if (ch!='\b') sprintf(text+strlen(text),"%c",ch); if (SFont_TextWidth2(Font,text)>PixelWidth) text[strlen(text)-1]='\0'; SDL_BlitSurface( Back, NULL, Dest, &rect); SFont_PutString2(Dest, Font, x, y, text); SDL_UpdateRects(Dest, 1, &rect); /* printf("%s ## %d\n",text,strlen(text)); */ SDL_WaitEvent(&event); } } if (SDL_GetTicks()>blinktimer) { blink=1-blink; blinktimer=SDL_GetTicks()+500; if (blink) { SFont_PutString2(Dest, Font, x+SFont_TextWidth2(Font,text), y, "|"); SDL_UpdateRects(Dest, 1, &rect); /* SDL_UpdateRect(Dest, x+SFont_TextWidth2(Font,text), y, SFont_TextWidth2(Font,"|"), Font->Surface->h); */ } else { SDL_BlitSurface( Back, NULL, Dest, &rect); SFont_PutString2(Dest, Font, x, y, text); SDL_UpdateRects(Dest, 1, &rect); /* SDL_UpdateRect(Dest, x-(Font->CharPos[ofs]-Font->CharPos[ofs-1])/2, y, PixelWidth, Font->Surface->h); */ } } SDL_Delay(1); SDL_PollEvent(&event); } text[strlen(text)]='\0'; SDL_FreeSurface(Back); SDL_EnableUNICODE(previous); /*restore the previous state */ } void SFont_Input2( SDL_Surface *Dest, SFont_FontInfo *Font, int x, int y, int PixelWidth, char *text) { SFont_InternalInput( Dest, Font, x, y, PixelWidth, text); } void SFont_Input( SDL_Surface *Dest, int x, int y, int PixelWidth, char *text) { SFont_Input2( Dest, &InternalFont, x, y, PixelWidth, text); } MODULE = SDLx::SFont PACKAGE = SDLx::SFont PREFIX = st_ SDL_Surface * st_new ( CLASS, filename ) char *CLASS char *filename CODE: /* warn( "[xs] new" ); */ #ifdef HAVE_SDL_IMAGE RETVAL = IMG_Load(filename); #else SDL_SetError("SDL_image not available for SFont. Using SDL_loadBMP instead of IMG_loadBMP."); RETVAL = SDL_LoadBMP(filename); #endif SFont_InitFont(RETVAL); OUTPUT: RETVAL void st_use ( surface ) SDL_Surface *surface CODE: /*warn( "[xs] use" ); */ SFont_InitFont(surface); void st_print_string ( surface, x, y, text ) SDL_Surface *surface int x int y char *text CODE: /* warn( "[xs] ps" ); */ SFont_PutString( surface, x, y, text ); int st_TextWidth ( text ) char *text CODE: RETVAL = SFont_TextWidth(text); OUTPUT: RETVAL