From f314041b6b37bb9274d9fc79946858341befa0f2 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 8 Apr 2015 08:40:05 -0600 Subject: Added image goo + font support. --- src/font.cpp | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 src/font.cpp (limited to 'src/font.cpp') diff --git a/src/font.cpp b/src/font.cpp new file mode 100644 index 0000000..27204a7 --- /dev/null +++ b/src/font.cpp @@ -0,0 +1,192 @@ +#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; + } + } +} + -- cgit v1.2.3