Created
February 14, 2013 22:11
-
-
Save robotarmy/4956885 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
175 bool getEOTHeader(unsigned char* fontData, size_t fontSize, vector<uint8_t>& eotHeader, size_t& overlayDst, size_t& overlaySrc, size_t& overlayLength) | |
176 { | |
177 overlayDst = 0; | |
178 overlaySrc = 0; | |
179 overlayLength = 0; | |
180 | |
181 size_t dataLength = fontSize; | |
182 const char* data = (const char *) fontData; | |
183 | |
184 eotHeader.resize(sizeof(EOTPrefix)); | |
185 EOTPrefix* prefix = reinterpret_cast<EOTPrefix*>(&eotHeader[0]); | |
186 | |
187 prefix->fontDataSize = dataLength; | |
188 prefix->version = 0x00020001; | |
189 prefix->flags = 0; | |
190 | |
191 if (dataLength < offsetof(sfntHeader, tables)) | |
192 return false; | |
193 | |
194 const sfntHeader* sfnt = reinterpret_cast<const sfntHeader*>(data); | |
195 | |
196 if (dataLength < offsetof(sfntHeader, tables) + sfnt->numTables * sizeof(TableDirectoryEntry)) | |
197 return false; | |
198 | |
199 bool haveOS2 = false; | |
200 bool haveHead = false; | |
201 bool haveName = false; | |
202 | |
203 const BigEndianUShort* familyName = 0; | |
204 unsigned short familyNameLength = 0; | |
205 const BigEndianUShort* subfamilyName = 0; | |
206 unsigned short subfamilyNameLength = 0; | |
207 const BigEndianUShort* fullName = 0; | |
208 unsigned short fullNameLength = 0; | |
209 const BigEndianUShort* versionString = 0; | |
210 unsigned short versionStringLength = 0; | |
211 | |
212 for (unsigned i = 0; i < sfnt->numTables; i++) { | |
213 unsigned tableOffset = sfnt->tables[i].offset; | |
214 unsigned tableLength = sfnt->tables[i].length; | |
215 | |
216 if (dataLength < tableOffset || dataLength < tableLength || dataLength < tableOffset + tableLength) | |
217 return false; | |
218 | |
219 unsigned tableTag = sfnt->tables[i].tag; | |
220 switch (tableTag) { | |
221 case 'OS/2': | |
222 { | |
223 if (dataLength < tableOffset + sizeof(OS2Table)) | |
224 return false; | |
225 | |
226 haveOS2 = true; | |
227 const OS2Table* OS2 = reinterpret_cast<const OS2Table*>(data + tableOffset); | |
228 for (unsigned j = 0; j < 10; j++) | |
229 prefix->fontPANOSE[j] = OS2->panose[j]; | |
230 prefix->italic = OS2->fsSelection & 0x01; | |
231 prefix->weight = OS2->weightClass; | |
232 // FIXME: Should use OS2->fsType, but some TrueType fonts set it to an over-restrictive value. | |
233 // Since ATS does not enforce this on Mac OS X, we do not enforce it either. | |
234 prefix->fsType = 0; | |
235 for (unsigned j = 0; j < 4; j++) | |
236 prefix->unicodeRange[j] = OS2->unicodeRange[j]; | |
237 for (unsigned j = 0; j < 2; j++) | |
238 prefix->codePageRange[j] = OS2->codePageRange[j]; | |
239 break; | |
240 } | |
241 case 'head': | |
242 { | |
243 if (dataLength < tableOffset + sizeof(headTable)) | |
244 return false; | |
245 | |
246 haveHead = true; | |
247 const headTable* head = reinterpret_cast<const headTable*>(data + tableOffset); | |
248 prefix->checkSumAdjustment = head->checkSumAdjustment; | |
249 break; | |
250 } | |
251 case 'name': | |
252 { | |
253 if (dataLength < tableOffset + offsetof(nameTable, nameRecords)) | |
254 return false; | |
255 | |
256 haveName = true; | |
257 const nameTable* name = reinterpret_cast<const nameTable*>(data + tableOffset); | |
258 for (int j = 0; j < name->count; j++) { | |
259 if (dataLength < tableOffset + offsetof(nameTable, nameRecords) + (j + 1) * sizeof(nameRecord)) | |
260 return false; | |
261 if (name->nameRecords[j].platformID == 3 && name->nameRecords[j].encodingID == 1 && name->nameRecords[j].languageID == 0x0409) { | |
262 if (dataLength < tableOffset + name->stringOffset + name->nameRecords[j].offset + name->nameRecords[j].length) | |
263 return false; | |
264 | |
265 unsigned short nameLength = name->nameRecords[j].length; | |
266 const BigEndianUShort* nameString = reinterpret_cast<const BigEndianUShort*>(data + tableOffset + name->stringOffset + name->nameRecords[j].offset); | |
267 | |
268 switch (name->nameRecords[j].nameID) { | |
269 case 1: | |
270 familyNameLength = nameLength; | |
271 familyName = nameString; | |
272 break; | |
273 case 2: | |
274 subfamilyNameLength = nameLength; | |
275 subfamilyName = nameString; | |
276 break; | |
277 case 4: | |
278 fullNameLength = nameLength; | |
279 fullName = nameString; | |
280 break; | |
281 case 5: | |
282 versionStringLength = nameLength; | |
283 versionString = nameString; | |
284 break; | |
285 default: | |
286 break; | |
287 } | |
288 } | |
289 } | |
290 break; | |
291 } | |
292 default: | |
293 break; | |
294 } | |
295 if (haveOS2 && haveHead && haveName) | |
296 break; | |
297 } | |
298 | |
299 prefix->charset = DEFAULT_CHARSET; | |
300 prefix->magicNumber = 0x504c; | |
301 prefix->reserved[0] = 0; | |
302 prefix->reserved[1] = 0; | |
303 prefix->reserved[2] = 0; | |
304 prefix->reserved[3] = 0; | |
305 prefix->padding1 = 0; | |
306 | |
307 appendBigEndianStringToEOTHeader(eotHeader, familyName, familyNameLength); | |
308 appendBigEndianStringToEOTHeader(eotHeader, subfamilyName, subfamilyNameLength); | |
309 appendBigEndianStringToEOTHeader(eotHeader, versionString, versionStringLength); | |
310 | |
311 // If possible, ensure that the family name is a prefix of the full name. | |
312 if (fullNameLength >= familyNameLength && memcmp(familyName, fullName, familyNameLength)) { | |
313 overlaySrc = reinterpret_cast<const char*>(fullName) - data; | |
314 overlayDst = reinterpret_cast<const char*>(familyName) - data; | |
315 overlayLength = familyNameLength; | |
316 } | |
317 | |
318 appendBigEndianStringToEOTHeader(eotHeader, fullName, fullNameLength); | |
319 | |
320 unsigned short padding = 0; | |
321 eotHeader.push_back(padding); | |
322 eotHeader.push_back(padding); | |
323 | |
324 prefix = reinterpret_cast<EOTPrefix*>(&eotHeader[0]); | |
325 prefix->eotSize = eotHeader.size() + fontSize; | |
326 | |
327 return true; | |
328 } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment