/***********************************************************/
/* */
/* BFONT.c v. 1.0.3 - Billi Font Library by Diego Billi */
/* */
/***********************************************************/
^M
#include "stdio.h"^M
#include "string.h"
#include "stdlib.h"
#include "stdarg.h"
#include "SDL_image.h"
#include "BFont.h"
/* Current font */
BFont_Info *CurrentFont;
^M
/* utility functions */
Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y);
void PutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel);
void InitFont(BFont_Info *Font)
{
int x = 0, i = 0;
Uint32 sentry;
i= '!';
sentry = GetPixel(Font->Surface,0,0);
/* sentry = SDL_MapRGB(Font->Surface->format, 255, 0, 255); */
if ( Font->Surface==NULL ) {
fprintf(stderr,"BFont: The font has not been loaded!\n");
exit(1);
}
if (SDL_MUSTLOCK(Font->Surface)) SDL_LockSurface(Font->Surface);
x=0;
while ( x < (Font->Surface->w-1) ) {
if(GetPixel(Font->Surface,x,0) != sentry) {
Font->Chars[i].x = x;
Font->Chars[i].y = 1;
Font->Chars[i].h = Font->Surface->h;
for (; GetPixel(Font->Surface, x, 0) != sentry && x < (Font->Surface->w); ++x) ;
Font->Chars[i].w = (x - Font->Chars[i].x);
i++;
}
else {
x++;
}
}
Font->Chars[' '].x = 0;
Font->Chars[' '].y = 0;
Font->Chars[' '].h = Font->Surface->h;
Font->Chars[' '].w = Font->Chars['!'].w;
if (SDL_MUSTLOCK(Font->Surface)) SDL_UnlockSurface(Font->Surface);
Font->h = Font->Surface->h;
SDL_SetColorKey(Font->Surface, SDL_SRCCOLORKEY, GetPixel(Font->Surface, 0, Font->Surface->h-1));
}
/* Load the font and stores it in the BFont_Info structure */
BFont_Info * LoadFont (char *filename)
{^M
SDL_Surface *surface = NULL;
int x;
BFont_Info *Font=NULL;^M
^M
if (filename != NULL) {^M
Font = (BFont_Info *) malloc(sizeof(BFont_Info));^M
if (Font != NULL) {
surface = (SDL_Surface *) IMG_Load(filename);
if (surface != NULL) {^M
Font->Surface = surface;
for (x=0; x<256; x++) {
Font->Chars[x].x = 0;
Font->Chars[x].y = 0;
Font->Chars[x].h = 0;
Font->Chars[x].w = 0;
}
/* Init the font */
InitFont(Font);
/* Set the font as the current font */
SetCurrentFont(Font);
}^M
else {^M
/* free memory allocated for the BFont_Info structure */^M
free(Font);^M
Font = NULL;^M
}
}^M
}^M
return Font;
}
void FreeFont(BFont_Info *Font)
{
SDL_FreeSurface(Font->Surface);^M
free(Font);
}
BFont_Info * SetFontColor(BFont_Info *Font,Uint8 r, Uint8 g, Uint8 b)
{
int x,y;
BFont_Info *newfont;
SDL_Surface *surface = NULL;
Uint32 pixel;
Uint8 old_r, old_g, old_b;
Uint8 new_r, new_g, new_b;
Uint32 color_key;
^M
newfont = (BFont_Info *) malloc(sizeof(BFont_Info));^M
if (newfont != NULL) {^M
newfont->h = Font->h;
for (x=0; x<256; x++) {
newfont->Chars[x].x = Font->Chars[x].x;
newfont->Chars[x].y = Font->Chars[x].y;
newfont->Chars[x].h = Font->Chars[x].h;
newfont->Chars[x].w = Font->Chars[x].w;
}
surface = SDL_ConvertSurface(Font->Surface, Font->Surface->format, Font->Surface->flags);
if (surface != NULL) {
if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
if (SDL_MUSTLOCK(Font->Surface)) SDL_LockSurface(Font->Surface);
color_key = GetPixel(surface, 0, surface->h-1);
printf("looking...\n");
for( x=0; x < Font->Surface->w; x++) {
for( y=0; y < Font->Surface->h; y++) {
old_r = old_g = old_b = 0;
pixel = GetPixel(Font->Surface,x,y);
if (pixel != color_key) {
SDL_GetRGB(pixel, surface->format, &old_r,&old_g,&old_b);
new_r = (Uint8) ((old_r * r) / 255);
new_g = (Uint8) ((old_g * g) / 255);
new_b = (Uint8) ((old_b * b) / 255);
pixel = SDL_MapRGB(surface->format,new_r,new_g,new_b);
PutPixel(surface,x,y,pixel);
}
}
}
printf("unlooking...\n");
if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
if (SDL_MUSTLOCK(Font->Surface)) SDL_UnlockSurface(Font->Surface);
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, color_key);
}
newfont->Surface = surface;
}
return newfont;
}
/* Set the current font */
void SetCurrentFont(BFont_Info *Font)
{
CurrentFont = Font;
}
/* Returns the pointer to the current font strucure in use */
BFont_Info * GetCurrentFont(void)
{
return CurrentFont;
}
/* Return the font height */
int FontHeight (BFont_Info *Font)
{
return (Font->h);
}
void SetFontHeight(BFont_Info *Font, int height)
{
Font->h = height;
}
/* Return the width of the "c" character */
int CharWidth(BFont_Info *Font,int c)
{
return Font->Chars[c].w;
}
/* Puts a single char on the surface */
int PutChar(SDL_Surface *Surface, int x, int y, int c)
{^M
return PutCharFont(Surface, CurrentFont, x,y,c);
}
/* Puts a single char on the surface with the specified font */
int PutCharFont(SDL_Surface *Surface, BFont_Info *Font,int x, int y, int c)
{^M
int r=0;
SDL_Rect dest;
dest.w = CharWidth(Font,' ');
dest.h = FontHeight(Font);
dest.x = x;
dest.y = y;
if (c != ' ') {
SDL_BlitSurface( Font->Surface, &Font->Chars[c], Surface, &dest);
}
r = dest.w;
return r;
}
void PutString(SDL_Surface *Surface, int x, int y, char *text)
{
PutStringFont(Surface, CurrentFont, x, y, text);
}
void PutStringFont(SDL_Surface *Surface, BFont_Info *Font, int x, int y, char *text)
{
int i=0;
while (text[i]!='\0') {
x += PutCharFont(Surface,Font,x,y,text[i]);
i++;
}
}
int TextWidth(char *text)
{
return TextWidthFont( CurrentFont, text);
}
int TextWidthFont(BFont_Info *Font, char *text)
{
int i=0,x=0;
while (text[i]!='\0') {
x += CharWidth(Font,text[i]);
i++;
}
return x;
}
/* counts the spaces of the strings */
int count (char *text)
{
char *p = NULL;
int pos = -1;
int i = 0;
/* Calculate the space occupied by the text without spaces */
while ((p=strchr(&text[pos+1],' ')) != NULL) {
i++;
pos = p - text;
}
return i;
}
void JustifiedPutString(SDL_Surface *Surface, int y, char *text)
{
JustifiedPutStringFont( Surface, CurrentFont, y,text);
}
void JustifiedPutStringFont(SDL_Surface *Surface, BFont_Info *Font, int y, char *text)
{
int spaces = 0;
int gap;
int single_gap;
int dif;
char *strtmp;
char *p;
int pos = -1;
int xpos = 0;
if (strchr(text,' ') == NULL) {
PutStringFont(Surface, Font, 0, y, text);
}
else {
gap = (Surface->w-1) - TextWidthFont(Font,text);
if (gap <= 0) {
PutStringFont(Surface, Font,0,y,text);
} else {
spaces = count(text);
dif = gap % spaces;
single_gap = (gap - dif) / spaces;
xpos=0;
pos = -1;
while ( spaces > 0 ) {
p = strstr(&text[pos+1]," ");
strtmp = NULL;
strtmp = (char *) calloc ( (p - &text[pos+1]) + 1,sizeof(char));
if (strtmp != NULL) {
strncpy (strtmp, &text[pos+1], (p - &text[pos+1]));
PutStringFont(Surface, Font, xpos, y, strtmp);
xpos = xpos + TextWidthFont(Font, strtmp) + single_gap + CharWidth(Font,' ');
if (dif >= 0) {
xpos ++;
dif--;
}
pos = p - text;
spaces--;
free(strtmp);
}
}
strtmp = NULL;
strtmp = (char *) calloc ( strlen( &text[pos+1]) + 1,sizeof(char));
if (strtmp != NULL) {
strncpy (strtmp, &text[pos+1], strlen( &text[pos+1]));
PutStringFont(Surface, Font,xpos, y, strtmp);
free(strtmp);
}
}
}
}
void CenteredPutString(SDL_Surface *Surface, int y, char *text)
{
CenteredPutStringFont(Surface, CurrentFont, y, text);
}
void CenteredPutStringFont(SDL_Surface *Surface, BFont_Info *Font, int y, char *text)
{
PutStringFont(Surface, Font, Surface->w/2-TextWidthFont(Font,text)/2, y, text);
}
void RightPutString(SDL_Surface *Surface, int y, char *text)
{
RightPutStringFont(Surface, CurrentFont, y, text);
}
void RightPutStringFont(SDL_Surface *Surface, BFont_Info *Font, int y, char *text)
{
PutStringFont(Surface, Font, Surface->w - TextWidthFont(Font,text) - 1, y, text);
}
void LeftPutString(SDL_Surface *Surface, int y, char *text)
{
LeftPutStringFont(Surface, CurrentFont, y, text);
}
void LeftPutStringFont(SDL_Surface *Surface, BFont_Info *Font, int y, char *text)
{
PutStringFont(Surface, Font, 0, y, text);
}
/******/
void PrintString (SDL_Surface *Surface, int x, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
PutStringFont(Surface, CurrentFont, x, y, temp);
free (temp);
}
va_end(args);
}
void PrintStringFont(SDL_Surface *Surface, BFont_Info *Font, int x, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
PutStringFont(Surface, Font, x, y, temp);
free (temp);
}
va_end(args);
}
void CenteredPrintString(SDL_Surface *Surface, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
CenteredPutString(Surface, y, temp);
free (temp);
}
va_end(args);
}
void CenteredPrintStringFont(SDL_Surface *Surface, BFont_Info *Font, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
CenteredPutStringFont(Surface, Font, y, temp);
free (temp);
}
va_end(args);
}
void RightPrintString(SDL_Surface *Surface, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
RightPutString(Surface, y, temp);
free (temp);
}
va_end(args);
}
void RightPrintStringFont(SDL_Surface *Surface, BFont_Info *Font, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
RightPutStringFont(Surface, Font, y, temp);
free (temp);
}
va_end(args);
}
void LeftPrintString(SDL_Surface *Surface, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
LeftPutString(Surface, y, temp);
free (temp);
}
va_end(args);
}
void LeftPrintStringFont(SDL_Surface *Surface, BFont_Info *Font, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
LeftPutStringFont(Surface, Font, y, temp);
free (temp);
}
va_end(args);
}
void JustifiedPrintString(SDL_Surface *Surface, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
JustifiedPutString( Surface, y,temp);
free (temp);
}
va_end(args);
}
void JustifiedPrintStringFont(SDL_Surface *Surface, BFont_Info *Font, int y, char *fmt, ...)
{
va_list args;
char *temp;
va_start (args,fmt);
if ( (temp = (char *) malloc(1000+1)) != NULL) {
vsprintf(temp,fmt,args);
JustifiedPutStringFont( Surface, Font, y,temp);
free (temp);
}
va_end(args);
}
/*********************************************************************************************************/
/*********************************************************************************************************/
/*********************************************************************************************************/
void PutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
{
Uint8 *bits;
Uint32 Bpp;
if (X<0) puts("x too small in GetPixel!");
if (X>=Surface->w) puts("x too big in GetPixel!");
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;
}