Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Fonts.cpp

Go to the documentation of this file.
00001 /*
00002  * Fonts.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * Copyright 2004 Chris Wallace
00007  *
00008  * Fly! Legacy is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  * Fly! Legacy is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  *   along with Fly! Legacy; if not, write to the Free Software
00020  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00027 #include "../Include/FlyLegacy.h"
00028 #include "../Include/Utility.h"
00029 #include "../Include/Globals.h"
00030 #include <vector>
00031 using namespace std;
00032 
00033 //
00034 // CBitmappedFontChar
00035 //
00036 typedef struct {
00037   int     x, y;
00038 } SFontCharBit;
00039 
00040 class CBitmappedFontChar {
00041 public:
00042   CBitmappedFontChar (void);
00043   ~CBitmappedFontChar (void);
00044   
00045   void SetBit (int x, int y);
00046   void Draw (SSurface *surface, int x, int y, unsigned int colour);
00047   int  GetWidth (void);
00048   int  GetHeight (void);
00049 
00050 public:
00051   unsigned char         ascii;       
00052   int                   start, end;  
00053   int                   w, h;        
00054   vector<SFontCharBit*> bits;        
00055 };
00056 
00057 CBitmappedFontChar::CBitmappedFontChar (void)
00058 {
00059   ascii = 0;
00060   start = end = 0;
00061   w = h = 0;
00062 }
00063 
00064 CBitmappedFontChar::~CBitmappedFontChar (void)
00065 {
00066   vector<SFontCharBit*>::iterator i;
00067   for (i=bits.begin(); i!=bits.end(); i++) {
00068     SFontCharBit *bit = *i;
00069     delete bit;
00070   }
00071 }
00072 
00073 void CBitmappedFontChar::SetBit (int x, int y)
00074 {
00075   SFontCharBit *bit = new SFontCharBit;
00076   bit->x = x;
00077   bit->y = y;
00078   bits.push_back (bit);
00079 }
00080 
00081 void CBitmappedFontChar::Draw (SSurface *surface, int x, int y, unsigned int colour)
00082 {
00083   vector<SFontCharBit*>::iterator i;
00084   for (i=bits.begin(); i!=bits.end(); i++) {
00085     SFontCharBit *bit = *i;
00086     DrawDot (surface, (x + bit->x), (y + bit->y), colour);
00087   }
00088 }
00089 
00090 inline int CBitmappedFontChar::GetWidth (void) { return w; }
00091 inline int CBitmappedFontChar::GetHeight (void) { return h; }
00092 
00093 
00094 
00095 //
00096 // CBitmappedFont
00097 //
00098 // This class represents a Fly! II bitmapped font.  Data members are public for a
00099 //   couple of reasons:
00100 //     - access needed by font utility functions
00101 //     - some default fonts are not loaded from FNT control files, so function
00102 //         init_default_fonts() in Main/Main.cpp initializes the members directly
00103 //
00104 class CBitmappedFont {
00105 public:
00106   // Constructors
00107   CBitmappedFont (const char* fntFilename = NULL);
00108   ~CBitmappedFont (void);
00109 
00110   // CBitmappedFont methods
00111   int       Load (const char* fntFilename);
00112   int       LoadRaw (const char* rawFilename);
00113   bool      IsCharValid (unsigned char c);
00114   int       MaxCharHeight (void);
00115   int       MaxCharWidth (void);
00116   int       TextWidth (const char* text);
00117   int       TextHeight (const char* text);
00118   int       CharWidth (unsigned char c);
00119   int       CharHeight (unsigned char c);
00120   CBitmappedFontChar *GetAscii (unsigned char c);
00121 
00122 public:
00123   bool   valid;                // Whether the font is valid for use
00124 
00125   char   rawFilename[64];      // Filename of .RAW image data
00126   int    w, h;                 // RAW image width/height
00127   int    start, end;           // ASCII character bounds of font data
00128   unsigned char   transparent;          // Palette index of background
00129   int    space;                // Width of a space character in pixels
00130   int    shadow_x, shadow_y;   // Shadow offset x, y
00131 
00132   int    maxCharHeight;
00133   int    maxCharWidth;
00134   CBitmappedFontChar  *chars;     // Array of font characters
00135 };
00136 
00137 
00138 //
00139 // CBitmappedFont
00140 //
00141 
00142 CBitmappedFont::CBitmappedFont (const char* fntFilename)
00143 {
00144   // Initialize
00145   valid = false;
00146   strcpy (rawFilename, "");
00147   w = h = 0;
00148   start = end = 0;
00149   transparent = 255;
00150   space = 0;
00151   shadow_x = shadow_y = 0;
00152   chars = NULL;
00153   maxCharHeight = maxCharWidth = 0;
00154 
00155   // If .FNT filename was supplied, re-initialize from it
00156   if (fntFilename && (strlen(fntFilename) > 0)) {
00157     Load (fntFilename);
00158   }
00159 }
00160 
00161 CBitmappedFont::~CBitmappedFont (void)
00162 {
00163   delete[] chars;
00164 }
00165 
00166 
00167 /*
00168  * Load in the details of a bitmapped font from the specified FNT file
00169  *  Example .FNT file (ART\FTTINY7W.FNT in Startup.pod):
00170 
00171 -------- font bitmap name --------
00172 fttiny7w.raw
00173 -------- width, height -----------
00174 126,68
00175 -------- start, end range --------
00176 32,126
00177 -------- transparency index ------
00178 0
00179 -------- space width -------------
00180 2
00181 -------- shadow offset x,y -------
00182 0,0
00183 
00184   */
00185 int CBitmappedFont::Load (const char* fntFilename)
00186 {
00187   int rc = 0;
00188 
00189   return rc;
00190 }
00191 
00192 //
00193 // This method loads the bitmapped font image data from the specified .RAW
00194 //   file.  All relevant members of the class instance must have been
00195 //   initialized before calling this method.
00196 //
00197 int CBitmappedFont::LoadRaw (const char* rawFilename)
00198 {
00199   int i, j, k, m;
00200   int rc = 0;
00201 
00202   // Load RAW image data
00203   PODFILE *pRaw = popen (&globals->pfs, rawFilename);
00204   if (pRaw != NULL) {
00205     // Allocate array of font characters
00206     int nChars = end - start + 1;
00207     chars = new CBitmappedFontChar[nChars];
00208 
00209     // Declare temporary storage for raw image data
00210     unsigned char *rawdata = new unsigned char[w * h];
00211     pread (rawdata, 1, (w * h), pRaw);
00212     pclose (pRaw);
00213 
00214     int iChar = 0;                // Index of current bitmapped font char
00215     int iRowStart = 0;            // Index to first char in a pixel row
00216     int iRowEnd = 0;              // Index to last char in a pixel row
00217     int iRowCount = 0;            // Pixel row count for each char
00218     unsigned char *p = rawdata;   // Pointer to next byte of RAW image data
00219     unsigned char ciHighlight = 0;          // Colour index value for highlight
00220     bool highlightSet = false;    // Whether highlight colour has been determined yet
00221     bool done = false;
00222     for (i=0; (i<h) && !done; i++) {
00223       // At start of each row, initialize:
00224       //    - previous colour index to background
00225       //    - start of char range for row to current char index
00226       //    - flag to indicate that the next character (if found) is first in the row
00227       unsigned char ciPrev = transparent;
00228       bool firstCharInRow = true;
00229       iChar = iRowStart;
00230 
00231       for (j=0; (j<w) && !done; j++) {
00232         // Get pixel colour index from raw data
00233         unsigned char ci = *p;
00234         p++;
00235 
00236         // Start tests against colour index
00237         if (ci != transparent) {
00238           // First check to see if highlight colour has been set.  If not, then
00239           //   this colour is the highlight colour
00240           if (!highlightSet) {
00241             ciHighlight = ci;
00242             highlightSet = true;
00243           }
00244 
00245           // Check if this colour is the highlight
00246           if (ci == ciHighlight) {
00247             // If the previous colour was background then this is the start of a new
00248             //   character marker
00249             if (ciPrev == transparent) {
00250               if (firstCharInRow) {
00251                 // Start of a new row of highlights.  Set heights of all chars
00252                 //   in the previous row (if applicable) and reset the row
00253                 //   control variables
00254                 for (m=iRowStart; m<iRowEnd; m++) {
00255                   chars[m].h = iRowCount;
00256                 }
00257 
00258                 // Check if all characters have been read
00259                 if (iRowEnd >= nChars) {
00260                   done = true;
00261                   break;
00262                 }
00263 
00264                 // Initialize control variables for this row of chars
00265                 iRowStart = iRowEnd;
00266                 iRowCount = 0;
00267                 iChar = iRowStart;
00268                 firstCharInRow = false;
00269               }
00270               // Set current column as starting column for this character
00271               chars[iChar].ascii = start + iChar;
00272               chars[iChar].start = j;
00273               iRowEnd++;
00274             }
00275           } else {
00276             // Neither background nor highlight, this is a font image bit
00277             // Check for transition to subsequent char
00278             for (k = iRowStart; k < iRowEnd; k++) {
00279               if (j >= chars[k].start) iChar = k;
00280             }
00281 
00282             // Add bit to char
00283             if (j > chars[iChar].end) {
00284               globals->logWarning->Write ("Font bit out of range : %s @ (%d,%d), char=%d",
00285                 rawFilename, j, i, iChar);
00286             } else {
00287               chars[iChar].SetBit (j - chars[iChar].start, iRowCount);
00288             }
00289           }
00290         } else {
00291           // Pixel is transparent (background colour).  If previous pixel was
00292           //   highlight, then we have just transitioned out of a character marker,
00293           //   otherwise ignore
00294           if (ciPrev == ciHighlight) {
00295             chars[iChar].end = j-1;
00296             chars[iChar].w = chars[iChar].end - chars[iChar].start + 1;
00297             iChar++;
00298             if (iChar > nChars) {
00299               gtfo ("CBitmappedFont : Font character %d out of range for %s",
00300                 iChar, rawFilename);
00301             }
00302           }
00303         }
00304         ciPrev = ci;
00305       } // for j = 0..w
00306 
00307       // Check for highlight that ends at right hand side of image
00308       if ((ciPrev == ciHighlight) && (iChar < nChars)) {
00309         chars[iChar].end = j-1;
00310         chars[iChar].w = chars[iChar].end - chars[iChar].start + 1;
00311         iChar++;
00312       }
00313 
00314       if (iRowEnd > nChars) {
00315         gtfo ("CBitmappedFont : Font character %d out of range for %s",
00316           iChar, rawFilename);
00317       }
00318 
00319       iRowCount++;
00320     } // for i = 0..h
00321 
00322 /*
00323     // DEBUG : Dump font contents to text file
00324     if (stricmp (rawFilename, "Art\\ftthin24.raw") == 0) {
00325       FILE *f = fopen ("Debug\\fontdebug.txt", "w");
00326       for (i=0; i<nChars; i++) {
00327         CBitmappedFontChar *c = &(chars[i]);
00328         fprintf (f, "Char : %d\n", c->ascii);
00329         fprintf (f, "  Columns   :  start=%d\tend=%d\n", c->start, c->end);
00330         fprintf (f, "  Extents   :  W = %d\tH=%d\n", c->w, c->h);
00331         fprintf (f, "  Bits (%d) :\n", c->bits.size());
00332         fprintf (f, "\n");
00333       }
00334       fprintf (f, "Rawdata (first 16 bytes) :\n");
00335       for (j=0; j<16; j++) {
00336         fprintf (f, "  %02X", rawdata[j]);
00337       }
00338       fclose (f);
00339     }
00340 */
00341 
00342     delete rawdata;
00343 
00344     rc = 1;
00345   }
00346 
00347   return rc;
00348 }
00349 
00350 inline bool CBitmappedFont::IsCharValid (unsigned char c)
00351 {
00352   return ((c >= start) && (c <= end));
00353 }
00354 
00355 inline int CBitmappedFont::MaxCharHeight (void)
00356 {
00357   return maxCharHeight;
00358 }
00359 
00360 inline int CBitmappedFont::MaxCharWidth (void)
00361 {
00362   return maxCharWidth;
00363 }
00364 
00365 int CBitmappedFont::TextWidth (const char* text)
00366 {
00367   int rc = 0;
00368 
00369   for (unsigned int i=0; i<strlen(text); i++) {
00370     // Increment by char length (plus 1 for inter-char space)
00371     rc += CharWidth (text[i]) + 1;
00372   }
00373 
00374   return rc;
00375 }
00376 
00377 int CBitmappedFont::TextHeight (const char* text)
00378 {
00379   int rc = 0;
00380 
00381   for (unsigned int i=0; i<strlen(text); i++) {
00382     int height = CharHeight (text[i]);
00383     if (height > rc) { rc = height; }
00384   }
00385 
00386   return rc;
00387 }
00388 
00389 int CBitmappedFont::CharWidth (unsigned char c)
00390 {
00391   int rc = 0;
00392 
00393   if (c == ' ') {
00394     rc = space;
00395   } else if (IsCharValid (c)) {
00396     rc = chars[c - start].w;
00397   }
00398 
00399   return rc;
00400 }
00401 
00402 int CBitmappedFont::CharHeight (unsigned char c)
00403 {
00404   int rc = 0;
00405 
00406   if (IsCharValid (c)) {
00407     rc = chars[c - start].h;
00408   }
00409 
00410   return rc;
00411 }
00412 
00413 CBitmappedFontChar *CBitmappedFont::GetAscii (unsigned char c)
00414 {
00415   CBitmappedFontChar *rc = NULL;
00416 
00417   if (IsCharValid (c)) {
00418     rc = &(chars[c - start]);
00419   }
00420 
00421   return rc;
00422 }
00423 
00424 
00425 
00426 
00427 typedef struct {
00428   char      rawFilename[64];
00429   int       w, h;
00430   int       start, end;
00431   int       space;
00432 } SDefaultFont;
00433 
00434 SDefaultFont defaultFonts[] =
00435 {
00436   //     RAW Filename      w       h     start   end    space
00437   {"ART\\FTASCI10.RAW",   272,    188,    33,    255,     5},
00438   {"ART\\FTASCM10.RAW",   224,    224,    33,    255,     5},
00439   {"ART\\FTDIGI9.RAW",     72,    110,    33,    133,     6},
00440   {"ART\\FTDIGI9B.RAW",    69,     41,    45,     90,     6},
00441   {"ART\\FTDIGI9D.RAW",    69,     41,    45,     90,     6},
00442   {"ART\\FTDIGI13.RAW",    97,    130,    33,    134,     8},
00443   {"ART\\FTDOS12.RAW",    221,     79,    33,    126,     7},
00444   {"ART\\FTMICRO5.RAW",   100,    100,    33,    126,     4},
00445   {"ART\\FTMNO14B.RAW",   193,     97,    33,    126,    12},
00446   {"ART\\FTMONO12.RAW",   222,     79,    33,    126,     7},
00447   {"ART\\FTNORM14.RAW",   275,    147,    33,    126,    14},
00448   {"ART\\FTNORM28.RAW",   463,    238,    33,    126,    22},
00449   {"ART\\FTSMAL10.RAW",   162,     73,    33,    127,     8},
00450   {"ART\\FTTHIN24.RAW",   215,    151,    33,    126,     6},
00451   {"ART\\FTTINY7.RAW",    126,     68,   33,     126,     5},
00452   {"ART\\FTTINY7W.RAW",   126,     68,   33,     126,     5},
00453 };
00454 
00455 
00456 //
00457 // Load the bitmapped font.  The font->fontName attribute of the SFont struct
00458 //   must be populated with the name of the .RAW font image data, including
00459 //   the pod filesystem path name (typically ART\\)
00460 //
00461 // Return code:
00462 //  0 (false) = Error encountered during font loading
00463 //  1 (true)  = Font loaded successfully
00464 //
00465 int LoadFont (SFont *font)
00466 {
00467   int i;
00468   int rc = 0;
00469 
00470   if (font == NULL) return rc;
00471 
00472   // Initialize *font member of SFont class
00473   font->font = NULL;
00474 
00475   // If this is a default font, create "empty" CBitmappedFont class instance,
00476   //   populate the members from the predefined table above, and load
00477   //   the RAW data.
00478   int nDefaultFonts = sizeof(defaultFonts) / sizeof (SDefaultFont);
00479   for (i=0; i<nDefaultFonts; i++) {
00480     SDefaultFont *d = &(defaultFonts[i]);
00481     if (stricmp (d->rawFilename, font->fontName) == 0) {
00482       // Instantiate blank SBitmappedFont
00483       CBitmappedFont *newfont = new CBitmappedFont ();
00484 
00485       // Populate with required data
00486       strcpy (newfont->rawFilename, font->fontName);
00487       newfont->w = d->w;
00488       newfont->h = d->h;
00489       newfont->start = d->start;
00490       newfont->end = d->end;
00491       newfont->space = d->space;
00492 
00493       // Store CBitmappedFont pointer in return struct
00494       font->font = newfont;
00495       
00496       // Load image data for font
00497       newfont->LoadRaw (font->fontName);
00498       rc = 1;
00499       break;
00500     }
00501   }
00502 
00504   if (font->font == NULL) {
00505   }
00506 
00507   return rc;
00508 }
00509 
00510 
00511 //
00512 // Unload (free) a font when it is no longer needed
00513 //
00514 void FreeFont (SFont *font)
00515 {
00516   if (font == NULL) return;
00517   CBitmappedFont *f = (CBitmappedFont *)font->font;
00518   delete f;
00519   font->font = NULL;
00520 }
00521 
00522 void DrawChar (SSurface *surface, SFont *font,
00523                int x, int y, unsigned int rgbColour,
00524                char ascii)
00525 {
00526   if (font == NULL) return;
00527   if (font->font == NULL) return;
00528 
00529   CBitmappedFont *f = (CBitmappedFont *)(font->font);
00530   CBitmappedFontChar *fc = f->GetAscii (ascii);
00531   if (fc != NULL) {
00532     fc->Draw (surface, x, y, rgbColour);
00533   }
00534 }
00535 
00536 //
00537 // Render bitmapped text onto the drawing surface using the specified font.
00538 //   The text is left-justified with the upper-left corner at surface offset (x,y)
00539 //
00540 void DrawText (SSurface *surface, SFont *font,
00541                int x, int y, unsigned int rgbColour,
00542                const char* text)
00543 {
00544   if (font == NULL) return;
00545   if (font->font == NULL) return;
00546 
00547   CBitmappedFont *f = (CBitmappedFont *)(font->font);
00548   for (unsigned int i=0; i<strlen(text); i++) {
00549     unsigned char ascii = text[i];
00550     if (ascii == 0x20) {
00551       x += f->space;
00552     } else {
00553       CBitmappedFontChar *fc = f->GetAscii (ascii);
00554       if (fc != NULL) {
00555         fc->Draw (surface, x, y, rgbColour);
00556         x += fc->GetWidth () + 1;
00557       }
00558     }
00559   }
00560 }
00561 
00562 //
00563 // Render bitmapped text onto the drawing surface using the specified font.
00564 //   The text is centered with the top-center at surface offset (x,y)
00565 //
00566 void DrawTextC (SSurface *surface, SFont *font,
00567                 int x, int y, unsigned int rgbColour,
00568                 const char* text)
00569 {
00570   if (font == NULL) return;
00571   if (font->font == NULL) return;
00572 
00573   // Adjust x-offset by half of string length and call DrawText
00574   CBitmappedFont *f = (CBitmappedFont *)(font->font);
00575   int offset = f->TextWidth (text) / 2;
00576   DrawText (surface, font, (x - offset), y, rgbColour, text);
00577 }
00578 
00579 //
00580 // Render bitmapped text onto the drawing surface using the specified font.
00581 //   The text is left-justified with the top-right corner at surface offset (x,y)
00582 //
00583 void DrawTextR (SSurface *surface, SFont *font,
00584                 int x, int y, unsigned int rgbColour,
00585                 const char* text)
00586 {
00587   if (font == NULL) return;
00588   if (font->font == NULL) return;
00589 
00590   // Adjust x-offset for string length and call DrawText
00591   CBitmappedFont *f = (CBitmappedFont *)(font->font);
00592   int offset = f->TextWidth (text);
00593   DrawText (surface, font, (x - offset), y, rgbColour, text);
00594 }
00595 
00596 
00597 //
00598 // Returns the height (in pixels) of the specified character string (i.e. the
00599 //   height of the tallest character in the string)
00600 //
00601 int TextHeight(SFont *font, const char *text)
00602 {
00603   int rc = 0;
00604 
00605   if (font != NULL) {
00606     if (font->font != NULL) {
00607       CBitmappedFont *f = (CBitmappedFont *)(font->font);
00608       rc = f->TextHeight (text);
00609     }
00610   }
00611 
00612   return rc;
00613 }
00614 
00615 
00616 //
00617 // Return the width (in pixels) of the specified character string
00618 //
00619 int TextWidth(SFont *font, const char *text)
00620 {
00621   int rc = 0;
00622 
00623   if (font != NULL) {
00624     if (font->font != NULL) {
00625       CBitmappedFont *f = (CBitmappedFont *)(font->font);
00626       rc = f->TextWidth (text);
00627     }
00628   }
00629   return rc;
00630 }
00631 
00632 //
00633 // Return the height of the specified character in the bitmapped font
00634 //
00635 int CharHeight(SFont *font, char c)
00636 {
00637   int rc = 0;
00638 
00639   if (font != NULL) {
00640     if (font->font != NULL) {
00641       CBitmappedFont *f = (CBitmappedFont *)(font->font);
00642       rc = f->CharHeight (c);
00643     }
00644   }
00645   return rc;
00646 }
00647 
00648 
00649 //
00650 // Return the width (in pixels) of the specified character in the bitmapped font
00651 //
00652 int CharWidth(SFont *font, char c)
00653 {
00654   int rc = 0;
00655 
00656   if (font != NULL) {
00657     if (font->font != NULL) {
00658       CBitmappedFont *f = (CBitmappedFont *)(font->font);
00659       rc = f->CharWidth (c);
00660     }
00661   }
00662   return rc;
00663 }
00664 
00665 
00666 //
00667 // Return the maximum character height (in pixels) for all defined characters
00668 //   in the bitmapped font
00669 //
00670 int MaxCharHeight(SFont *font)
00671 {
00672   int rc = 0;
00673 
00674   if (font != NULL) {
00675     if (font->font != NULL) {
00676       CBitmappedFont *f = (CBitmappedFont *)(font->font);
00677       rc = f->MaxCharHeight();
00678     }
00679   }
00680 
00681   return rc;
00682 }
00683 
00684 
00685 //
00686 // Return the maximum character width (in pixels) for all defined characters
00687 //   in the bitmapped font
00688 //
00689 int MaxCharWidth(SFont *font)
00690 {
00691   int rc = 0;
00692 
00693   if (font != NULL) {
00694     if (font->font != NULL) {
00695       CBitmappedFont *f = (CBitmappedFont *)(font->font);
00696       rc = f->MaxCharWidth ();
00697     }
00698   }
00699 
00700   return rc;
00701 }
00702 
SourceForge.net Logo Documentation generated by doxygen