sdlfont.cpp

00001 /*
00002   font.cpp
00003   Cone3D SDL font routines.
00004   Made by Marius Andra 2002
00005   http://cone3d.gamedev.net
00006 
00007   You can use the code for anything you like.
00008   Even in a commercial project.
00009   But please let me know where it ends up.
00010   I'm just curious. That's all.
00011 */
00012 
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <stdarg.h>
00016 #include <string.h>
00017 
00018 #include <SDL/SDL.h>
00019 
00020 #include "font.h"
00021 
00022 // this function draws one part of an image to some other part of an other image
00023 // it's only to be used inside the font.cpp file, so it's not available to any
00024 // other source files (no prototype in font.h)
00025 void fontDrawIMG(SDL_Surface *screen, SDL_Surface *img, int x, int y, int w,
00026                                                         int h, int x2, int y2)
00027 {
00028   SDL_Rect dest;
00029   dest.x = x;
00030   dest.y = y;
00031   SDL_Rect src;
00032   src.x = x2;
00033   src.y = y2;
00034   src.w = w;
00035   src.h = h;
00036   SDL_BlitSurface(img, &src, screen, &dest);
00037 }
00038 
00039 // this function loads in our font file
00040 SDLFont *initFont(char *fontdir, float r, float g, float b, float a)
00041 {
00042   // some variables
00043   SDLFont *tempFont;               // a temporary font
00044   FILE *fp;                        // file pointer - used when reading files
00045   char tempString[100];            // temporary string
00046   unsigned char tmp;               // temporary unsigned char
00047   int width;                       // the width of the font
00048   SDL_Surface *tempSurface;        // temporary surface
00049 
00050   // find out about the size of a font from the ini file
00051   sprintf(tempString,"%s/%s",fontdir,"font.ini");
00052   fp = fopen(tempString, "rb");
00053   if( fp == NULL )
00054   {
00055     return 0;
00056   }
00057   fscanf(fp, "%d", &width);
00058   fclose(fp);
00059 
00060   // let's create our font structure now
00061   tempFont = new SDLFont;
00062   tempFont->data = new unsigned char[width*width*4];
00063   tempFont->width = width;
00064   tempFont->charWidth = width/16;
00065 
00066   // open the font raw data file and read everything in
00067   sprintf(tempString,"%s/%s",fontdir,"font.raw");
00068   fp = fopen(tempString, "rb");
00069   if( fp != NULL )
00070   {
00071     for(int i=0;i<width*width;i++)
00072     {
00073       tmp = fgetc(fp);
00074       tempFont->data[i*4] = (unsigned char)255*(unsigned char)r;
00075       tempFont->data[i*4+1] = (unsigned char)255*(unsigned char)g;
00076       tempFont->data[i*4+2] = (unsigned char)255*(unsigned char)b;
00077       tempFont->data[i*4+3] = (unsigned char)(((float)tmp)*a);
00078     }
00079   } else {
00080     return 0;
00081   }
00082   fclose(fp);
00083   // now let's create a SDL surface for the font
00084   Uint32 rmask,gmask,bmask,amask;
00085   #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00086   rmask = 0xff000000;
00087   gmask = 0x00ff0000;
00088   bmask = 0x0000ff00;
00089   amask = 0x000000ff;
00090   #else
00091   rmask = 0x000000ff;
00092   gmask = 0x0000ff00;
00093   bmask = 0x00ff0000;
00094   amask = 0xff000000;
00095   #endif
00096   tempSurface = SDL_CreateRGBSurfaceFrom(tempFont->data, width, width,
00097                               32, width*4, rmask, gmask, bmask, amask);
00098   tempFont->font = SDL_DisplayFormatAlpha(tempSurface);
00099   SDL_FreeSurface(tempSurface);
00100 
00101   // let's create a variable to hold all the widths of the font
00102   tempFont->widths = new int[256];
00103 
00104   // now read in the information about the width of each character
00105   sprintf(tempString,"%s/%s",fontdir,"font.dat");
00106   fp = fopen(tempString, "rb");
00107   if( fp != NULL )
00108   {
00109     for(int i=0;i<256;i++)
00110     {
00111       tmp = fgetc(fp);
00112       tempFont->widths[i]=tmp;
00113     }
00114   }
00115   fclose(fp);
00116 
00118   return tempFont;
00119 }
00120 
00121 // here we draw the string
00122 void drawString(SDL_Surface *screen, SDLFont *font, int x, int y, char *str, ...)
00123 {
00124   char string[1024];                  // Temporary string
00125 
00126   va_list ap;                         // Pointer To List Of Arguments
00127   va_start(ap, str);                  // Parses The String For Variables
00128   vsprintf(string, str, ap);          // And Converts Symbols To Actual Numbers
00129   va_end(ap);                         // Results Are Stored In Text
00130 
00131   int len=strlen(string);             // Get the number of chars in the string
00132   int xx=0;            // This will hold the place where to draw the next char
00133   for(int i=0;i<len;i++)              // Loop through all the chars in the string
00134   {
00135     // This may look scary, but it's really not.
00136     // We only draw one character with this code.
00137     // At the next run of the loop we draw the next character.
00138 
00139     // Remember, the fontDrawIMG function looks like this:
00140         // void fontDrawIMG(SDL_Surface *screen, SDL_Surface *img, int x, int y,
00141     //                                         int w, int h, int x2, int y2)
00142 
00143     // We draw onto the screen SDL_Surface a part of the font SDL_Surface.
00144     fontDrawIMG(
00145       screen,
00146       font->font,
00147     // We draw the char at pos [x+xx,y].
00148     // x+xx: this function's parameter x + the width of all the characters before
00149     // this one, so we wouldn't overlap any of the previous characters in the string
00150     // y: this function's y parameter
00151       xx+x,
00152       y,
00153     // For the width of the to-be-drawn character we take it's real width + 2
00154       font->widths[string[i]]+2,
00155     // And for the height we take the height of the character (height of the font/16)
00156       font->charWidth,
00157     // Now comes the tricky part
00158     // The font image DOES consist of 16x16 grid of characters. From left to
00159     // right in the image, the ascii values of the characters increase:
00160     // The character at block 0x0 in the font image is the character with the
00161     // ascii code 0, the character at the pos 1x0 has the ascii code 1, the char
00162     // at the pos 15x0 has the ascii code 15. And that's the end of the first row
00163     // Now in the second row on the image, the first character (0x1) has the ascii
00164     // value 16, the fourth character on the second row of the image (3x1) has the ascii
00165     // value 19. To calculate the ascii value of the character 3x1, we use the
00166     // really simple equation: row*[number of thing in one row (=16)]+column pos.
00167     // So the position 3x1 has the ascii value 1*16+3 = 19. The character in the
00168     // image at the position 8x12 has the ascii value 12*16+8=200, and so on.
00169     // But this isn't much of use to us since we KNOW the ascii value of a character,
00170     // but we NEED to find out it's position on the image.
00171     // First we'll get the column on the image. For that we'll divide the ascii value
00172     // with 16 (the number of columns) and get it's remainder (we'll use the modulus
00173     // operator). We'll do this equation to get the column: [ascii value]%16.
00174     // Now to get to the position of the column in pixels, we multiply the ascii
00175     // value by the width of one column ([font image width]/16)
00176     // And so the equation to get the first pixel of the block becomes:
00177     // [font image width]%16*[1/16th of the font image width]
00178     // Now, since all the letters are centered in each cell (1/16th of the image),
00179     // we need to get the center of the cell. This is done by adding half the width
00180     // of the cell to the number we got before. And the only thing left to do is to
00181     // subtract half of the character's real width and we get the x position from where
00182     // to draw our character on the font map :)
00183       (string[i]%16*font->charWidth)+((font->charWidth/2)-(font->widths[string[i]])/2),
00184     // To get the row of the character in the image, we divide the ascii value of
00185     // the character by 16 and get rid of all the numbers after the point (.)
00186     // (if we get the number 7.125257.., we remove the .125157... and end up with 7)
00187     // We then multiply the result with the height of one cell and voila - we get
00188     // the y position!
00189       (((int)string[i]/16)*font->charWidth)
00190     );
00191 
00192     // Now we increase the xx printed string width counter by the width of the
00193     // drawn character
00194     xx+=font->widths[string[i]];
00195   }
00196 }
00197 
00198 // This function returns the width of a string
00199 int stringWidth(SDLFont *font,char *str,...)
00200 {
00201   char string[1024];                  // Temporary string
00202 
00203   va_list ap;                         // Pointer To List Of Arguments
00204   va_start(ap, str);                  // Parses The String For Variables
00205   vsprintf(string, str, ap);          // And Converts Symbols To Actual Numbers
00206   va_end(ap);                         // Results Are Stored In Text
00207 
00208   // Now we just count up the width of all the characters
00209   int xx=0;
00210   int len=strlen(string);
00211   for(int i=0;i<len;i++)
00212   {
00213     // Add their widths together
00214     xx+=font->widths[string[i]];
00215   }
00216 
00217   // and then return the sum
00218   return xx;
00219 }
00220 
00221 // Clear up
00222 void freeFont(SDLFont *font)
00223 {
00224   delete [] font->widths;
00225   delete [] font->data;
00226   SDL_FreeSurface(font->font);
00227   delete font;
00228 }
00229 
00230 
00231 
00232 

SourceForge.net Logo
generated with doxygen 1.5.3 on Mon Oct 29 18:09:26 2007