Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages   Examples  

glt/fonttex.cpp

Go to the documentation of this file.
00001 #include "fonttex.h"
00002 
00015 #include <algorithm>
00016 #include <iostream>
00017 #include <cstdio>
00018 #include <cassert>
00019 using namespace std;
00020 
00021 #include <misc/endian.h>
00022 #include <misc/image.h>
00023 #include <math/real.h>
00024 
00025 GltFontTexture::GltFontTexture(void *data)
00026 {
00027     if (data)
00028         init(data);
00029 }
00030 
00031 GltFontTexture::~GltFontTexture()
00032 {
00033     clear();
00034 }
00035 
00036 void
00037 GltFontTexture::init(void *data)
00038 {
00039     clear();
00040 
00041     if (data)
00042     {
00043         char *ptr = (char *) data;
00044 
00045         // Check the header
00046 
00047         if (strncmp(ptr,"\377txf",4))
00048         {
00049             cerr << "ERROR: Texture font not recognised" << endl;
00050             return;
00051         }
00052 
00053         ptr+=4;
00054 
00055         // Check endianness 
00056 
00057         const uint32 code = *reinterpret_cast<uint32 *>(ptr);
00058         if (code!=0x12345678 && code!=0x78563412)
00059         {
00060             cerr << "ERROR: Texture font not recognised" << endl;
00061             return;
00062         }
00063 
00064         const bool swap = code==0x78563412;
00065 
00066         ptr+=4;
00067 
00068         _init = true;
00069 
00070         // 
00071 
00072         int32 format = *reinterpret_cast<int32 *>(ptr); ptr+=4;
00073         int32 width  = *reinterpret_cast<int32 *>(ptr); ptr+=4;
00074         int32 height = *reinterpret_cast<int32 *>(ptr); ptr+=4;
00075 
00076         _maxAscent  = *reinterpret_cast<int32 *>(ptr); ptr+=4;
00077         _maxDescent = *reinterpret_cast<int32 *>(ptr); ptr+=4;
00078         _numGlyphs  = *reinterpret_cast<int32 *>(ptr); ptr+=4;
00079 
00080         if (swap)
00081         {
00082             format = flip(format);
00083             width  = flip(width);
00084             height = flip(height);
00085 
00086             _maxAscent  = flip(_maxAscent);
00087             _maxDescent = flip(_maxDescent);
00088             _numGlyphs  = flip(_numGlyphs);
00089         }
00090 
00091         // Read glyph info
00092 
00093         _glyph = new GlyphInfo[_numGlyphs];
00094         memcpy(_glyph,ptr,sizeof(GlyphInfo)*_numGlyphs);
00095         ptr += sizeof(GlyphInfo)*_numGlyphs;
00096 
00097         uint32 i;
00098             
00099         if (swap)
00100             for (i=0; i<_numGlyphs; i++)
00101             {
00102                 _glyph[i].glyph = flip(_glyph[i].glyph);
00103                 _glyph[i].x     = flip(_glyph[i].x);
00104                 _glyph[i].y     = flip(_glyph[i].y);
00105             }
00106 
00107         // Find first and last glyphs
00108 
00109         if (!_numGlyphs)
00110         {
00111             cerr << "ERROR: Texture font contains no glyphs" << endl;
00112             clear();
00113             return;
00114         }
00115 
00116         uint16 minGlyph = _glyph[0].glyph;
00117         uint16 maxGlyph = _glyph[0].glyph;
00118         
00119         _hStep = _glyph[0].advance;
00120         _vStep = _glyph[0].height;
00121 
00122         for (i=1; i<_numGlyphs; i++)
00123         {
00124             minGlyph = MIN(minGlyph,_glyph[i].glyph);
00125             maxGlyph = MAX(maxGlyph,_glyph[i].glyph);
00126             _hStep = MAX(_hStep,_glyph[i].advance);
00127             _vStep = MAX(_vStep,_glyph[i].height);
00128         }
00129 
00130         _minGlyph = minGlyph;
00131         _range    = maxGlyph - minGlyph + 1;
00132 
00133         // Initialise vertex info
00134 
00135         _glyphVertex = new GlyphVertexInfo[_numGlyphs];
00136         
00137         const GLfloat w = width;
00138         const GLfloat h = height;
00139         const GLfloat xstep = 0.5f/w;
00140         const GLfloat ystep = 0.5f/h;
00141 
00142         for (i=0; i<_numGlyphs; i++)
00143         {
00144             const GlyphInfo &tgi = _glyph[i];
00145             GlyphVertexInfo &vi  = _glyphVertex[i];
00146 
00147             // Texture co-ordinates
00148 
00149             {
00150                 const GLfloat left   = tgi.x/w + xstep;
00151                 const GLfloat right  = (tgi.x + tgi.width)/w + xstep;
00152                 const GLfloat bottom = (tgi.y + tgi.height)/h + ystep;
00153                 const GLfloat top    = tgi.y/h + ystep;
00154 
00155                 vi.t0[0]   = left;  vi.t0[1]   = top;
00156                 vi.t1[0]   = right; vi.t1[1]   = top;
00157                 vi.t2[0]   = right; vi.t2[1]   = bottom;
00158                 vi.t3[0]   = left;  vi.t3[1]   = bottom;
00159             }
00160 
00161             //
00162 
00163             {
00164                 const GLshort left   = 0;
00165                 const GLshort right  = tgi.width;
00166                 const GLshort bottom = _vStep - tgi.yoffset - tgi.height;
00167                 const GLshort top    = _vStep - tgi.yoffset;
00168 
00169                 vi.v0[0]   = left;  vi.v0[1]   = top;
00170                 vi.v1[0]   = right; vi.v1[1]   = top;
00171                 vi.v2[0]   = right; vi.v2[1]   = bottom;
00172                 vi.v3[0]   = left;  vi.v3[1]   = bottom;
00173 
00174                 vi.advance = tgi.advance;   
00175                 vi.width   = tgi.width;     // Need this for width()
00176             }
00177         }
00178 
00179         // Build LUT
00180 
00181         _glyphLut = new GlyphVertexInfo *[_range];
00182         memset(_glyphLut,0,_range*sizeof(GlyphVertexInfo *));
00183 
00184         for (i=0; i<_numGlyphs; i++) 
00185             _glyphLut[_glyph[i].glyph-_minGlyph] = _glyphVertex + i;
00186 
00187         //
00188         const bool mipmap = true;
00189 
00190         switch (format)
00191         {
00192         case 0:     // GREYSCALE
00193             {
00194                 byte *buffer = new byte[width*height*2];
00195                 for (i=0; i<width*height; i++)
00196                     buffer[i*2] = buffer[i*2+1] = ptr[i];
00197                 _texture.init(width,height,buffer,2,mipmap);
00198                 delete [] buffer;
00199             }
00200             break;
00201 
00202         case 1:     // BITMAP
00203             break;
00204         }
00205     }
00206 }
00207 
00208 void 
00209 GltFontTexture::clear()
00210 {
00211     if (_init)
00212     {
00213         _init = false;
00214 
00215         delete [] _glyph;
00216         delete [] _glyphVertex;
00217         delete [] _glyphLut;
00218 
00219         _glyph = NULL;
00220         _glyphVertex = NULL;
00221         _glyphLut = NULL;
00222 
00223         _texture.clear();
00224     }
00225 }
00226 
00227 void
00228 GltFontTexture::compileLists(void *data)
00229 {
00230 /*
00231     if (_listBase==-1 && data)
00232     {
00233         GLubyte *ptr = (GLubyte *) data;
00234         const int bytesPerChar = ((_width+7)>>3)*_height;
00235 
00236         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00237         _listBase = glGenLists(256);
00238         for (int i = 0; i < 255; i++) 
00239         {
00240             glNewList(i+_listBase, GL_COMPILE);
00241             glBitmap(_width,_height,0,_height-1,hStep(),0,(GLubyte *) ptr);
00242             glEndList();
00243             ptr += bytesPerChar;
00244         }
00245     }
00246 */
00247 }
00248 
00249 bool 
00250 GltFontTexture::print(const wchar_t ch) const
00251 {
00252     assert(_init);
00253 
00254     if (_init)
00255         return print(char(ch));
00256     else
00257         return false;
00258 }
00259 
00260 bool 
00261 GltFontTexture::print(const wstring &str) const
00262 {
00263     assert(_init);
00264 
00265     if (_init)
00266     {
00267         string s;
00268         wstring2string(s,str);
00269         return print(s);
00270     }
00271     else
00272         return false;
00273 }
00274 
00275 bool 
00276 GltFontTexture::print(const char ch) const
00277 {
00278     assert(_init);
00279 
00280     if (_init)
00281     {
00282         if (uint16(ch)<_minGlyph || uint16(ch)>=_minGlyph+_range)
00283             return false;
00284 
00285         const GlyphVertexInfo *vi = _glyphLut[uint16(ch)-_minGlyph];
00286 
00287         if (vi)
00288         {
00289             glPushAttrib(GL_ENABLE_BIT);
00290                 _texture.set();
00291                 glEnable(GL_TEXTURE_2D);
00292                 glEnable(GL_BLEND);
00293                 glBegin(GL_QUADS);
00294                     glTexCoord2fv(vi->t0); glVertex2sv(vi->v0);
00295                     glTexCoord2fv(vi->t1); glVertex2sv(vi->v1);
00296                     glTexCoord2fv(vi->t2); glVertex2sv(vi->v2);
00297                     glTexCoord2fv(vi->t3); glVertex2sv(vi->v3);
00298                 glEnd();
00299                 glTranslatef(vi->advance,0,0);
00300             glPopAttrib();
00301             return true;
00302         }
00303     }
00304 
00305     return false;
00306 }
00307 
00308 bool 
00309 GltFontTexture::print(const string &str) const
00310 {
00311     assert(_init);
00312 
00313     if (_init)
00314     {
00315         glPushMatrix();
00316             for (int i=0; i<str.size(); i++)
00317                 print(str[i]);
00318         glPopMatrix();
00319         glTranslatef(0,_vStep,0);
00320         return true;
00321     }
00322     else
00323         return false;
00324 }
00325 
00326 int
00327 GltFontTexture::width(const wchar_t ch) const
00328 {
00329     assert(_init);
00330 
00331     if (_init)
00332     {
00333         if (uint16(ch)<_minGlyph || uint16(ch)>=_minGlyph+_range)
00334             return false;
00335 
00336         const GlyphVertexInfo *vi = _glyphLut[uint16(ch)-_minGlyph];
00337         if (vi)
00338             return vi->advance;
00339     }
00340 
00341     return 0;
00342 }
00343 
00345 
00346 // Create variable-length header for font data
00347 
00348 bool 
00349 GltFontTexture::makeHeader
00350 (
00351     string &header,
00352     const int            width,
00353     const int            height
00354 )
00355 {
00356     // 11 characters is big enough for integer 2^32 + \0
00357 
00358     char buffer[5+11+11];
00359     sprintf(buffer,"GLTF %u %u",width,height);
00360     header = buffer;
00361     header += '\0';
00362 
00363     return true;
00364 }
00365 
00366 // Decode variable-length header for texture data
00367 
00368 void *
00369 GltFontTexture::getHeader
00370 (
00371     const void * const data,
00372     int            &width,
00373     int            &height
00374 )
00375 {
00376     const char * const h = (const char * const) data;
00377     
00378     if (h[0]=='G' && h[1]=='L' && h[2]=='T' && h[3]=='F' && h[4]==' ')
00379     {
00380         if (sscanf(h+5,"%i %i",&width,&height)==2)
00381             return (void *) (h + strlen(h) + 1);
00382     }
00383 
00384     return NULL;
00385 }

Generated on Tue Nov 5 11:11:03 2002 for GLT by doxygen1.2.18