#include "font.h" #include #include #include #define fh (( (FILE *)rawfh )) Font::Font( const char *sSrcFile ) : iTableTop( 0 ), pTable( NULL ) { iTableTop = 128; pTable = new Glyph*[iTableTop]; memset( pTable, 0, sizeof(Glyph*)*iTableTop ); Parser p( sSrcFile, *this ); p.parse(); } Font::~Font() { } Font::Parser::Parser( const char *sSrcFile, Font &rFont ) : rFont( rFont ), rawfh( NULL ), sLine( NULL ), bDone( false ) { sLine = new char[1024]; rawfh = fopen( sSrcFile, "rt" ); } Font::Parser::~Parser() { delete[] sLine; fclose( fh ); } void Font::Parser::parse() { header(); characters(); if( strncasecmp("ENDFONT", sLine, 7 ) ) { printf("End of file reached, but no end marker.\n"); throw std::exception(); } } void Font::Parser::getLine() { for(;;) { if( fgets( sLine, 1024, fh ) == NULL ) { sLine[0] = '\0'; bDone = true; printf("Premature end of file.\n"); throw std::exception(); return; } if( strncasecmp("COMMENT ", sLine, 8 ) ) { return; } } } void Font::Parser::header() { getLine(); if( strncasecmp("STARTFONT 2.1", sLine, 13 ) ) { printf("Bad format: %s\n", sLine); throw std::exception(); } for(;;) { getLine(); if( strncasecmp("SIZE ", sLine, 5 ) == 0 ) { } else if( strncasecmp("FONTBOUNDINGBOX ", sLine, 16 ) == 0 ) { } else if( strncasecmp("STARTPROPERTIES ", sLine, 16 ) == 0 ) { properties(); } else if( strncasecmp("CHARS ", sLine, 6 ) == 0 ) { return; } } } void Font::Parser::properties() { for(;;) { getLine(); if( strncasecmp("ENDPROPERTIES", sLine, 13 ) == 0 ) return; } } void Font::Parser::characters() { for(;;) { getLine(); if( strncasecmp("STARTCHAR ", sLine, 10 ) == 0 ) character(); else return; } } uint8_t hex2byte( const char *str ) { uint8_t ret = 0; ret |= ((*str >= '0' && *str <= '9')?(*str-'0'):( (*str >= 'a' && *str <= 'f')?(*str-'a'+10):( (*str >= 'A' && *str <= 'F')?(*str-'A'+10):0 )))<<4; str++; ret |= (*str >= '0' && *str <= '9')?(*str-'0'):( (*str >= 'a' && *str <= 'f')?(*str-'a'+10):( (*str >= 'A' && *str <= 'F')?(*str-'A'+10):0 )); return ret; } void Font::Parser::character() { char sName[1024]; int32_t iIdx = -1; strcpy( sName, sLine+10 ); Glyph *pChar = new Glyph(); for(;;) { getLine(); if( strncasecmp("ENCODING ", sLine, 9 ) == 0 ) { sscanf( sLine+9, "%d", &iIdx ); } else if( strncasecmp("DWIDTH ", sLine, 7 ) == 0 ) { sscanf( sLine+7, "%d %d", &pChar->pDevOff.x, &pChar->pDevOff.y ); } else if( strncasecmp("BBX ", sLine, 4 ) == 0 ) { sscanf( sLine+4, "%d %d %d %d", &pChar->pBox.x, &pChar->pBox.y, &pChar->pOff.x, &pChar->pOff.y ); } else if( strncasecmp("BITMAP", sLine, 6 ) == 0 ) { pChar->iRowBytes = pChar->pBox.x/8 + ((pChar->pBox.x%8)==0?0:1); pChar->pData = new uint8_t[pChar->iRowBytes*pChar->pBox.y]; // Read bitmap for( int y = 0; y < pChar->pBox.y; y++ ) { getLine(); for( int x = 0; x < pChar->iRowBytes; x++ ) { pChar->pData[x+y*pChar->iRowBytes] = hex2byte( sLine+(2*x) ); } } } else if( strncasecmp("ENDCHAR", sLine, 7 ) == 0 ) { if( iIdx >= 0 && iIdx < rFont.iTableTop ) { rFont.pTable[iIdx] = pChar; //printf("Char %d: %s\n", iIdx, sName ); } else delete pChar; return; } } }