diff options
Diffstat (limited to 'src/font.cpp')
-rw-r--r-- | src/font.cpp | 192 |
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 | |||
10 | Font::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 | |||
21 | Font::~Font() | ||
22 | { | ||
23 | } | ||
24 | |||
25 | Font::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 | |||
35 | Font::Parser::~Parser() | ||
36 | { | ||
37 | delete[] sLine; | ||
38 | fclose( fh ); | ||
39 | } | ||
40 | |||
41 | void 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 | |||
52 | void 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 | |||
72 | void 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 | |||
101 | void Font::Parser::properties() | ||
102 | { | ||
103 | for(;;) | ||
104 | { | ||
105 | getLine(); | ||
106 | if( strncasecmp("ENDPROPERTIES", sLine, 13 ) == 0 ) | ||
107 | return; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | void 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 | |||
123 | uint8_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 | |||
139 | void 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 | |||