summaryrefslogtreecommitdiff
path: root/src/font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/font.cpp')
-rw-r--r--src/font.cpp192
1 files changed, 192 insertions, 0 deletions
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 @@
1#include "font.h"
2
3#include <stdio.h>
4#include <string.h>
5
6#include <exception>
7
8#define fh (( (FILE *)rawfh ))
9
10Font::Font( const char *sSrcFile ) :
11 iTableTop( 0 ),
12 pTable( NULL )
13{
14 iTableTop = 128;
15 pTable = new Glyph*[iTableTop];
16 memset( pTable, 0, sizeof(Glyph*)*iTableTop );
17 Parser p( sSrcFile, *this );
18 p.parse();
19}
20
21Font::~Font()
22{
23}
24
25Font::Parser::Parser( const char *sSrcFile, Font &rFont ) :
26 rFont( rFont ),
27 rawfh( NULL ),
28 sLine( NULL ),
29 bDone( false )
30{
31 sLine = new char[1024];
32 rawfh = fopen( sSrcFile, "rt" );
33}
34
35Font::Parser::~Parser()
36{
37 delete[] sLine;
38 fclose( fh );
39}
40
41void Font::Parser::parse()
42{
43 header();
44 characters();
45 if( strncasecmp("ENDFONT", sLine, 7 ) )
46 {
47 printf("End of file reached, but no end marker.\n");
48 throw std::exception();
49 }
50}
51
52void Font::Parser::getLine()
53{
54 for(;;)
55 {
56 if( fgets( sLine, 1024, fh ) == NULL )
57 {
58 sLine[0] = '\0';
59 bDone = true;
60 printf("Premature end of file.\n");
61 throw std::exception();
62 return;
63 }
64
65 if( strncasecmp("COMMENT ", sLine, 8 ) )
66 {
67 return;
68 }
69 }
70}
71
72void Font::Parser::header()
73{
74 getLine();
75 if( strncasecmp("STARTFONT 2.1", sLine, 13 ) )
76 {
77 printf("Bad format: %s\n", sLine);
78 throw std::exception();
79 }
80
81 for(;;)
82 {
83 getLine();
84 if( strncasecmp("SIZE ", sLine, 5 ) == 0 )
85 {
86 }
87 else if( strncasecmp("FONTBOUNDINGBOX ", sLine, 16 ) == 0 )
88 {
89 }
90 else if( strncasecmp("STARTPROPERTIES ", sLine, 16 ) == 0 )
91 {
92 properties();
93 }
94 else if( strncasecmp("CHARS ", sLine, 6 ) == 0 )
95 {
96 return;
97 }
98 }
99}
100
101void Font::Parser::properties()
102{
103 for(;;)
104 {
105 getLine();
106 if( strncasecmp("ENDPROPERTIES", sLine, 13 ) == 0 )
107 return;
108 }
109}
110
111void Font::Parser::characters()
112{
113 for(;;)
114 {
115 getLine();
116 if( strncasecmp("STARTCHAR ", sLine, 10 ) == 0 )
117 character();
118 else
119 return;
120 }
121}
122
123uint8_t hex2byte( const char *str )
124{
125 uint8_t ret = 0;
126
127 ret |= ((*str >= '0' && *str <= '9')?(*str-'0'):(
128 (*str >= 'a' && *str <= 'f')?(*str-'a'+10):(
129 (*str >= 'A' && *str <= 'F')?(*str-'A'+10):0
130 )))<<4;
131 str++;
132 ret |= (*str >= '0' && *str <= '9')?(*str-'0'):(
133 (*str >= 'a' && *str <= 'f')?(*str-'a'+10):(
134 (*str >= 'A' && *str <= 'F')?(*str-'A'+10):0
135 ));
136 return ret;
137}
138
139void Font::Parser::character()
140{
141 char sName[1024];
142 int32_t iIdx = -1;
143 strcpy( sName, sLine+10 );
144 Glyph *pChar = new Glyph();
145
146 for(;;)
147 {
148 getLine();
149 if( strncasecmp("ENCODING ", sLine, 9 ) == 0 )
150 {
151 sscanf( sLine+9, "%d", &iIdx );
152 }
153 else if( strncasecmp("DWIDTH ", sLine, 7 ) == 0 )
154 {
155 sscanf( sLine+7, "%d %d", &pChar->pDevOff.x, &pChar->pDevOff.y );
156 }
157 else if( strncasecmp("BBX ", sLine, 4 ) == 0 )
158 {
159 sscanf( sLine+4, "%d %d %d %d",
160 &pChar->pBox.x, &pChar->pBox.y,
161 &pChar->pOff.x, &pChar->pOff.y
162 );
163 }
164 else if( strncasecmp("BITMAP", sLine, 6 ) == 0 )
165 {
166 pChar->iRowBytes = pChar->pBox.x/8 + ((pChar->pBox.x%8)==0?0:1);
167
168 pChar->pData = new uint8_t[pChar->iRowBytes*pChar->pBox.y];
169 // Read bitmap
170 for( int y = 0; y < pChar->pBox.y; y++ )
171 {
172 getLine();
173 for( int x = 0; x < pChar->iRowBytes; x++ )
174 {
175 pChar->pData[x+y*pChar->iRowBytes] = hex2byte( sLine+(2*x) );
176 }
177 }
178 }
179 else if( strncasecmp("ENDCHAR", sLine, 7 ) == 0 )
180 {
181 if( iIdx >= 0 && iIdx < rFont.iTableTop )
182 {
183 rFont.pTable[iIdx] = pChar;
184 //printf("Char %d: %s\n", iIdx, sName );
185 }
186 else
187 delete pChar;
188 return;
189 }
190 }
191}
192