/* PLIB - A Suite of Portable Game Libraries Copyright (C) 1998,2002 Steve Baker This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For further information visit http://plib.sourceforge.net $Id: fntTXF.cxx 1735 2002-12-01 18:21:48Z sjbaker $ */ #include "fntLocal.h" #include #include FILE *_fntCurrImageFd ; int _fntIsSwapped = FALSE ; static void tex_make_mip_maps ( GLubyte *image, int xsize, int ysize, int zsize ) { GLubyte *texels [ 20 ] ; /* One element per level of MIPmap */ for ( int l = 0 ; l < 20 ; l++ ) texels [ l ] = NULL ; texels [ 0 ] = image ; int lev ; for ( lev = 0 ; (( xsize >> (lev+1) ) != 0 || ( ysize >> (lev+1) ) != 0 ) ; lev++ ) { /* Suffix '1' is the higher level map, suffix '2' is the lower level. */ int l1 = lev ; int l2 = lev+1 ; int w1 = xsize >> l1 ; int h1 = ysize >> l1 ; int w2 = xsize >> l2 ; int h2 = ysize >> l2 ; if ( w1 <= 0 ) w1 = 1 ; if ( h1 <= 0 ) h1 = 1 ; if ( w2 <= 0 ) w2 = 1 ; if ( h2 <= 0 ) h2 = 1 ; texels [ l2 ] = new GLubyte [ w2 * h2 * zsize ] ; for ( int x2 = 0 ; x2 < w2 ; x2++ ) for ( int y2 = 0 ; y2 < h2 ; y2++ ) for ( int c = 0 ; c < zsize ; c++ ) { int x1 = x2 + x2 ; int x1_1 = ( x1 + 1 ) % w1 ; int y1 = y2 + y2 ; int y1_1 = ( y1 + 1 ) % h1 ; int t1 = texels [ l1 ] [ (y1 * w1 + x1 ) * zsize + c ] ; int t2 = texels [ l1 ] [ (y1_1 * w1 + x1 ) * zsize + c ] ; int t3 = texels [ l1 ] [ (y1 * w1 + x1_1) * zsize + c ] ; int t4 = texels [ l1 ] [ (y1_1 * w1 + x1_1) * zsize + c ] ; texels [ l2 ] [ (y2 * w2 + x2) * zsize + c ] = ( t1 + t2 + t3 + t4 ) / 4 ; } } texels [ lev+1 ] = NULL ; if ( ! ((xsize & (xsize-1))==0) || ! ((ysize & (ysize-1))==0) ) { fntSetError ( SG_ALERT, "TXFloader: TXF Map is not a power-of-two in size!" ) ; } glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ) ; int map_level = 0 ; #ifdef PROXY_TEXTURES_ARE_NOT_BROKEN int ww ; do { glTexImage2D ( GL_PROXY_TEXTURE_2D, map_level, zsize, xsize, ysize, FALSE /* Border */, (zsize==1)?GL_LUMINANCE: (zsize==2)?GL_LUMINANCE_ALPHA: (zsize==3)?GL_RGB: GL_RGBA, GL_UNSIGNED_BYTE, NULL ) ; glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D, 0,GL_TEXTURE_WIDTH, &ww ) ; if ( ww == 0 ) { delete [] texels [ 0 ] ; xsize >>= 1 ; ysize >>= 1 ; for ( int l = 0 ; texels [ l ] != NULL ; l++ ) texels [ l ] = texels [ l+1 ] ; if ( xsize < 64 && ysize < 64 ) { fntSetError ( SG_ALERT, "FNT: OpenGL will not accept a font texture?!?" ) ; } } } while ( ww == 0 ) ; #endif for ( int i = 0 ; texels [ i ] != NULL ; i++ ) { int w = xsize>>i ; int h = ysize>>i ; if ( w <= 0 ) w = 1 ; if ( h <= 0 ) h = 1 ; glTexImage2D ( GL_TEXTURE_2D, map_level, zsize, w, h, FALSE /* Border */, (zsize==1)?GL_LUMINANCE: (zsize==2)?GL_LUMINANCE_ALPHA: (zsize==3)?GL_RGB: GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) texels[i] ) ; map_level++ ; delete [] texels [ i ] ; } } int fntTexFont::loadTXF ( const SGPath& path, GLenum mag, GLenum min ) { FILE *fd ; const auto ps = path.utf8Str(); #if defined(SG_WINDOWS) std::wstring fp = path.wstr(); fd = _wfopen(fp.c_str(), L"rb"); #else fd = fopen(ps.c_str(), "rb"); #endif if ( fd == nullptr ) { fntSetError ( SG_WARN, "fntLoadTXF: Failed to open '%s' for reading.", ps.c_str() ) ; return FNT_FALSE ; } _fntCurrImageFd = fd ; unsigned char magic [ 4 ] ; if ( (int)fread ( &magic, sizeof (unsigned int), 1, fd ) != 1 ) { fntSetError ( SG_WARN, "fntLoadTXF: '%s' an empty file!", ps.c_str() ) ; return FNT_FALSE ; } if ( magic [ 0 ] != 0xFF || magic [ 1 ] != 't' || magic [ 2 ] != 'x' || magic [ 3 ] != 'f' ) { fntSetError ( SG_WARN, "fntLoadTXF: '%s' is not a 'txf' font file.", ps.c_str() ) ; return FNT_FALSE ; } _fntIsSwapped = FALSE ; int endianness = _fnt_readInt () ; _fntIsSwapped = ( endianness != 0x12345678 ) ; int format = _fnt_readInt () ; int tex_width = _fnt_readInt () ; int tex_height = _fnt_readInt () ; int max_height = _fnt_readInt () ; _fnt_readInt () ; int num_glyphs = _fnt_readInt () ; int w = tex_width ; int h = tex_height ; float xstep = 0.5f / (float) w ; float ystep = 0.5f / (float) h ; int i, j ; /* Load the TXF_Glyph array */ TXF_Glyph glyph ; for ( i = 0 ; i < num_glyphs ; i++ ) { glyph . ch = _fnt_readShort () ; glyph . w = _fnt_readByte () ; glyph . h = _fnt_readByte () ; glyph . x_off = _fnt_readByte () ; glyph . y_off = _fnt_readByte () ; glyph . step = _fnt_readByte () ; glyph . unknown = _fnt_readByte () ; glyph . x = _fnt_readShort () ; glyph . y = _fnt_readShort () ; setGlyph ( (char) glyph.ch, (float) glyph.step / (float) max_height, (float) glyph.x / (float) w + xstep, (float)( glyph.x + glyph.w ) / (float) w + xstep, (float) glyph.y / (float) h + ystep, (float)( glyph.y + glyph.h ) / (float) h + ystep, (float) glyph.x_off / (float) max_height, (float)( glyph.x_off + glyph.w ) / (float) max_height, (float) glyph.y_off / (float) max_height, (float)( glyph.y_off + glyph.h ) / (float) max_height ) ; } exists [ static_cast(' ') ] = FALSE ; /* Load the image part of the file */ int ntexels = w * h ; unsigned char *teximage ; unsigned char *texbitmap ; switch ( format ) { case FNT_BYTE_FORMAT: { unsigned char *orig = new unsigned char [ ntexels ] ; if ( (int)fread ( orig, 1, ntexels, fd ) != ntexels ) { fntSetError ( SG_WARN, "fntLoadTXF: Premature EOF in '%s'.", ps.c_str() ) ; return FNT_FALSE ; } teximage = new unsigned char [ 2 * ntexels ] ; for ( i = 0 ; i < ntexels ; i++ ) { teximage [ i*2 ] = orig [ i ] ; teximage [ i*2 + 1 ] = orig [ i ] ; } delete [] orig ; } break ; case FNT_BITMAP_FORMAT: { int stride = (w + 7) >> 3; texbitmap = new unsigned char [ stride * h ] ; if ( (int)fread ( texbitmap, 1, stride * h, fd ) != stride * h ) { delete [] texbitmap ; fntSetError ( SG_WARN, "fntLoadTXF: Premature EOF in '%s'.", ps.c_str() ) ; return FNT_FALSE ; } teximage = new unsigned char [ 2 * ntexels ] ; for ( i = 0 ; i < 2 * ntexels ; i++ ) teximage [ i ] = 0 ; for (i = 0; i < h; i++) for (j = 0; j < w; j++) if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) { teximage[(i * w + j) * 2 ] = 255; teximage[(i * w + j) * 2 + 1] = 255; } delete [] texbitmap ; } break ; default: fntSetError ( SG_WARN, "fntLoadTXF: Unrecognised format type in '%s'.", ps.c_str() ) ; return FNT_FALSE ; } fclose ( fd ) ; fixed_pitch = FALSE ; #ifdef GL_VERSION_1_1 glGenTextures ( 1, & texture ) ; glBindTexture ( GL_TEXTURE_2D, texture ) ; #else /* This is only useful on some ancient SGI hardware */ glGenTexturesEXT ( 1, & texture ) ; glBindTextureEXT ( GL_TEXTURE_2D, texture ) ; #endif tex_make_mip_maps ( teximage, w, h, 2 ) ; glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ; glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag ) ; glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min ) ; glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ) ; glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ) ; #ifdef GL_VERSION_1_1 glBindTexture ( GL_TEXTURE_2D, 0 ) ; #else glBindTextureEXT ( GL_TEXTURE_2D, 0 ) ; #endif return FNT_TRUE ; }