| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 ******************************************************************************* | |
| 3 * | |
| 4 * Copyright (C) 1999-2015, International Business Machines | |
| 5 * Corporation and others. All Rights Reserved. | |
| 6 * | |
| 7 ******************************************************************************* | |
| 8 * file name: PortableFontInstance.cpp | |
| 9 * | |
| 10 * created on: 11/22/1999 | |
| 11 * created by: Eric R. Mader | |
| 12 */ | |
| 13 | |
| 14 #include <stdio.h> | |
| 15 | |
| 16 #include "layout/LETypes.h" | |
| 17 #include "layout/LEFontInstance.h" | |
| 18 #include "layout/LESwaps.h" | |
| 19 | |
| 20 #include "PortableFontInstance.h" | |
| 21 | |
| 22 //#include "letest.h" | |
| 23 #include "sfnt.h" | |
| 24 | |
| 25 #include <string.h> | |
| 26 #include <stdio.h> | |
| 27 | |
| 28 #if 0 | |
| 29 static const char *letagToStr(LETag tag, char *str) { | |
| 30 str[0]= 0xFF & (tag>>24); | |
| 31 str[1]= 0xFF & (tag>>16); | |
| 32 str[2]= 0xFF & (tag>>8); | |
| 33 str[3]= 0xFF & (tag>>0); | |
| 34 str[4]= 0; | |
| 35 return str; | |
| 36 } | |
| 37 #endif | |
| 38 | |
| 39 // | |
| 40 // Finds the high bit by binary searching | |
| 41 // through the bits in n. | |
| 42 // | |
| 43 le_int8 PortableFontInstance::highBit(le_int32 value) | |
| 44 { | |
| 45 if (value <= 0) { | |
| 46 return -32; | |
| 47 } | |
| 48 | |
| 49 le_uint8 bit = 0; | |
| 50 | |
| 51 if (value >= 1 << 16) { | |
| 52 value >>= 16; | |
| 53 bit += 16; | |
| 54 } | |
| 55 | |
| 56 if (value >= 1 << 8) { | |
| 57 value >>= 8; | |
| 58 bit += 8; | |
| 59 } | |
| 60 | |
| 61 if (value >= 1 << 4) { | |
| 62 value >>= 4; | |
| 63 bit += 4; | |
| 64 } | |
| 65 | |
| 66 if (value >= 1 << 2) { | |
| 67 value >>= 2; | |
| 68 bit += 2; | |
| 69 } | |
| 70 | |
| 71 if (value >= 1 << 1) { | |
| 72 value >>= 1; | |
| 73 bit += 1; | |
| 74 } | |
| 75 | |
| 76 return bit; | |
| 77 } | |
| 78 | |
| 79 PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize
, LEErrorCode &status) | |
| 80 : fFile(NULL), fPointSize(pointSize), fUnitsPerEM(0), fFontChecksum(0), fAsc
ent(0), fDescent(0), fLeading(0), | |
| 81 fDirectory(NULL), fNAMETable(NULL), fNameCount(0), fNameStringOffset(0), f
CMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0) | |
| 82 { | |
| 83 if (LE_FAILURE(status)) { | |
| 84 return; | |
| 85 } | |
| 86 | |
| 87 // open the font file | |
| 88 fFile = fopen(fileName, "rb"); | |
| 89 //printf("Open Font: %s\n", fileName); | |
| 90 | |
| 91 if (fFile == NULL) { | |
| 92 printf("%s:%d: %s: FNF\n", __FILE__, __LINE__, fileName); | |
| 93 status = LE_FONT_FILE_NOT_FOUND_ERROR; | |
| 94 return; | |
| 95 } | |
| 96 | |
| 97 // read in the directory | |
| 98 SFNTDirectory tempDir; | |
| 99 | |
| 100 size_t numRead = fread(&tempDir, sizeof tempDir, 1, fFile); | |
| 101 (void)numRead; | |
| 102 | |
| 103 le_int32 dirSize = sizeof tempDir + ((SWAPW(tempDir.numTables) - ANY_NUMBER)
* sizeof(DirectoryEntry)); | |
| 104 const LETag headTag = LE_HEAD_TABLE_TAG; | |
| 105 const LETag hheaTag = LE_HHEA_TABLE_TAG; | |
| 106 const HEADTable *headTable = NULL; | |
| 107 const HHEATable *hheaTable = NULL; | |
| 108 // const NAMETable *nameTable = NULL; | |
| 109 le_uint16 numTables = 0; | |
| 110 | |
| 111 fDirectory = (const SFNTDirectory *) LE_NEW_ARRAY(char, dirSize); | |
| 112 | |
| 113 if (fDirectory == NULL) { | |
| 114 printf("%s:%d: %s: malloc err\n", __FILE__, __LINE__, fileName); | |
| 115 status = LE_MEMORY_ALLOCATION_ERROR; | |
| 116 goto error_exit; | |
| 117 } | |
| 118 | |
| 119 fseek(fFile, 0L, SEEK_SET); | |
| 120 numRead = fread((void *) fDirectory, sizeof(char), dirSize, fFile); | |
| 121 | |
| 122 // | |
| 123 // We calculate these numbers 'cause some fonts | |
| 124 // have bogus values for them in the directory header. | |
| 125 // | |
| 126 numTables = SWAPW(fDirectory->numTables); | |
| 127 fDirPower = 1 << highBit(numTables); | |
| 128 fDirExtra = numTables - fDirPower; | |
| 129 | |
| 130 // read unitsPerEm from 'head' table | |
| 131 headTable = (const HEADTable *) readFontTable(headTag); | |
| 132 | |
| 133 if (headTable == NULL) { | |
| 134 status = LE_MISSING_FONT_TABLE_ERROR; | |
| 135 printf("%s:%d: %s: missing head table\n", __FILE__, __LINE__, fileName); | |
| 136 goto error_exit; | |
| 137 } | |
| 138 | |
| 139 fUnitsPerEM = SWAPW(headTable->unitsPerEm); | |
| 140 fFontChecksum = SWAPL(headTable->checksumAdjustment); | |
| 141 freeFontTable(headTable); | |
| 142 | |
| 143 //nameTable = (NAMETable *) readFontTable(nameTag); | |
| 144 | |
| 145 //if (nameTable == NULL) { | |
| 146 // status = LE_MISSING_FONT_TABLE_ERROR; | |
| 147 // goto error_exit; | |
| 148 //} | |
| 149 | |
| 150 //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MAC
INTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH); | |
| 151 | |
| 152 //if (fFontVersionString == NULL) { | |
| 153 // status = LE_MISSING_FONT_TABLE_ERROR; | |
| 154 // goto error_exit; | |
| 155 //} | |
| 156 | |
| 157 //freeFontTable(nameTable); | |
| 158 | |
| 159 hheaTable = (HHEATable *) readFontTable(hheaTag); | |
| 160 | |
| 161 if (hheaTable == NULL) { | |
| 162 printf("%s:%d: %s: missing hhea table\n", __FILE__, __LINE__, fileName); | |
| 163 status = LE_MISSING_FONT_TABLE_ERROR; | |
| 164 goto error_exit; | |
| 165 } | |
| 166 | |
| 167 fAscent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent)); | |
| 168 fDescent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->descent)); | |
| 169 fLeading = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->lineGap)); | |
| 170 | |
| 171 fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics); | |
| 172 | |
| 173 freeFontTable((void *) hheaTable); | |
| 174 | |
| 175 fCMAPMapper = findUnicodeMapper(); | |
| 176 | |
| 177 if (fCMAPMapper == NULL) { | |
| 178 printf("%s:%d: %s: can't load cmap\n", __FILE__, __LINE__, fileName); | |
| 179 status = LE_MISSING_FONT_TABLE_ERROR; | |
| 180 goto error_exit; | |
| 181 } | |
| 182 | |
| 183 return; | |
| 184 | |
| 185 error_exit: | |
| 186 fclose(fFile); | |
| 187 fFile = NULL; | |
| 188 return; | |
| 189 } | |
| 190 | |
| 191 PortableFontInstance::~PortableFontInstance() | |
| 192 { | |
| 193 if (fFile != NULL) { | |
| 194 fclose(fFile); | |
| 195 | |
| 196 freeFontTable(fHMTXTable); | |
| 197 freeFontTable(fNAMETable); | |
| 198 | |
| 199 delete fCMAPMapper; | |
| 200 | |
| 201 LE_DELETE_ARRAY(fDirectory); | |
| 202 } | |
| 203 } | |
| 204 | |
| 205 const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const | |
| 206 { | |
| 207 if (fDirectory != NULL) { | |
| 208 le_uint16 table = 0; | |
| 209 le_uint16 probe = fDirPower; | |
| 210 | |
| 211 if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) { | |
| 212 table = fDirExtra; | |
| 213 } | |
| 214 | |
| 215 while (probe > (1 << 0)) { | |
| 216 probe >>= 1; | |
| 217 | |
| 218 if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) { | |
| 219 table += probe; | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) { | |
| 224 return &fDirectory->tableDirectory[table]; | |
| 225 } | |
| 226 } | |
| 227 | |
| 228 return NULL; | |
| 229 } | |
| 230 | |
| 231 const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const | |
| 232 { | |
| 233 const DirectoryEntry *entry = findTable(tag); | |
| 234 | |
| 235 if (entry == NULL) { | |
| 236 *length = 0; | |
| 237 return NULL; | |
| 238 } | |
| 239 | |
| 240 *length = SWAPL(entry->length); | |
| 241 | |
| 242 void *table = LE_NEW_ARRAY(char, *length); | |
| 243 | |
| 244 if (table != NULL) { | |
| 245 fseek(fFile, SWAPL(entry->offset), SEEK_SET); | |
| 246 size_t numRead = fread(table, sizeof(char), *length, fFile); | |
| 247 (void)numRead; | |
| 248 } | |
| 249 | |
| 250 return table; | |
| 251 } | |
| 252 | |
| 253 const void *PortableFontInstance::getFontTable(LETag tableTag, size_t &length) c
onst | |
| 254 { | |
| 255 return FontTableCache::find(tableTag, length); | |
| 256 } | |
| 257 | |
| 258 const void *PortableFontInstance::readFontTable(LETag tableTag, size_t &length)
const | |
| 259 { | |
| 260 le_uint32 len; | |
| 261 | |
| 262 const void *data= readTable(tableTag, &len); | |
| 263 length = len; | |
| 264 //char tag5[5]; | |
| 265 //printf("Read %s, result %p #%d\n", letagToStr(tableTag,tag5), data,len); | |
| 266 return data; | |
| 267 } | |
| 268 | |
| 269 CMAPMapper *PortableFontInstance::findUnicodeMapper() | |
| 270 { | |
| 271 LETag cmapTag = LE_CMAP_TABLE_TAG; | |
| 272 const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag); | |
| 273 | |
| 274 if (cmap == NULL) { | |
| 275 return NULL; | |
| 276 } | |
| 277 | |
| 278 return CMAPMapper::createUnicodeMapper(cmap); | |
| 279 } | |
| 280 | |
| 281 const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 plat
formID, le_uint16 encodingID, le_uint16 languageID) const | |
| 282 { | |
| 283 if (fNAMETable == NULL) { | |
| 284 LETag nameTag = LE_NAME_TABLE_TAG; | |
| 285 PortableFontInstance *realThis = (PortableFontInstance *) this; | |
| 286 | |
| 287 realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag); | |
| 288 | |
| 289 if (realThis->fNAMETable != NULL) { | |
| 290 realThis->fNameCount = SWAPW(realThis->fNAMETable->count); | |
| 291 realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffs
et); | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 for(le_int32 i = 0; i < fNameCount; i += 1) { | |
| 296 const NameRecord *nameRecord = &fNAMETable->nameRecords[i]; | |
| 297 | |
| 298 if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->enc
odingID) == encodingID && | |
| 299 SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nam
eID) == nameID) { | |
| 300 char *name = ((char *) fNAMETable) + fNameStringOffset + SWAPW(nameR
ecord->offset); | |
| 301 le_uint16 length = SWAPW(nameRecord->length); | |
| 302 char *result = LE_NEW_ARRAY(char, length + 2); | |
| 303 | |
| 304 LE_ARRAY_COPY(result, name, length); | |
| 305 result[length] = result[length + 1] = 0; | |
| 306 | |
| 307 return result; | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 return NULL; | |
| 312 } | |
| 313 | |
| 314 const LEUnicode16 *PortableFontInstance::getUnicodeNameString(le_uint16 nameID,
le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const | |
| 315 { | |
| 316 if (fNAMETable == NULL) { | |
| 317 LETag nameTag = LE_NAME_TABLE_TAG; | |
| 318 PortableFontInstance *realThis = (PortableFontInstance *) this; | |
| 319 | |
| 320 realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag); | |
| 321 | |
| 322 if (realThis->fNAMETable != NULL) { | |
| 323 realThis->fNameCount = SWAPW(realThis->fNAMETable->count); | |
| 324 realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffs
et); | |
| 325 } | |
| 326 } | |
| 327 | |
| 328 for(le_int32 i = 0; i < fNameCount; i += 1) { | |
| 329 const NameRecord *nameRecord = &fNAMETable->nameRecords[i]; | |
| 330 | |
| 331 if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->enc
odingID) == encodingID && | |
| 332 SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nam
eID) == nameID) { | |
| 333 LEUnicode16 *name = (LEUnicode16 *) (((char *) fNAMETable) + fNameSt
ringOffset + SWAPW(nameRecord->offset)); | |
| 334 le_uint16 length = SWAPW(nameRecord->length) / 2; | |
| 335 LEUnicode16 *result = LE_NEW_ARRAY(LEUnicode16, length + 2); | |
| 336 | |
| 337 for (le_int32 c = 0; c < length; c += 1) { | |
| 338 result[c] = SWAPW(name[c]); | |
| 339 } | |
| 340 | |
| 341 result[length] = 0; | |
| 342 | |
| 343 return result; | |
| 344 } | |
| 345 } | |
| 346 | |
| 347 return NULL; | |
| 348 } | |
| 349 | |
| 350 void PortableFontInstance::deleteNameString(const char *name) const | |
| 351 { | |
| 352 LE_DELETE_ARRAY(name); | |
| 353 } | |
| 354 | |
| 355 void PortableFontInstance::deleteNameString(const LEUnicode16 *name) const | |
| 356 { | |
| 357 LE_DELETE_ARRAY(name); | |
| 358 } | |
| 359 | |
| 360 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) co
nst | |
| 361 { | |
| 362 TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph); | |
| 363 | |
| 364 if (fHMTXTable == NULL) { | |
| 365 LETag maxpTag = LE_MAXP_TABLE_TAG; | |
| 366 LETag hmtxTag = LE_HMTX_TABLE_TAG; | |
| 367 const MAXPTable *maxpTable = (MAXPTable *) readFontTable(maxpTag); | |
| 368 PortableFontInstance *realThis = (PortableFontInstance *) this; | |
| 369 | |
| 370 if (maxpTable != NULL) { | |
| 371 realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs); | |
| 372 freeFontTable(maxpTable); | |
| 373 } | |
| 374 | |
| 375 realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag); | |
| 376 } | |
| 377 | |
| 378 le_uint16 index = ttGlyph; | |
| 379 | |
| 380 if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) { | |
| 381 advance.fX = advance.fY = 0; | |
| 382 return; | |
| 383 } | |
| 384 | |
| 385 if (ttGlyph >= fNumLongHorMetrics) { | |
| 386 index = fNumLongHorMetrics - 1; | |
| 387 } | |
| 388 | |
| 389 advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth))
; | |
| 390 advance.fY = 0; | |
| 391 } | |
| 392 | |
| 393 le_bool PortableFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*poin
tNumber*/, LEPoint &/*point*/) const | |
| 394 { | |
| 395 return FALSE; | |
| 396 } | |
| 397 | |
| 398 le_int32 PortableFontInstance::getUnitsPerEM() const | |
| 399 { | |
| 400 return fUnitsPerEM; | |
| 401 } | |
| 402 | |
| 403 le_uint32 PortableFontInstance::getFontChecksum() const | |
| 404 { | |
| 405 return fFontChecksum; | |
| 406 } | |
| 407 | |
| 408 le_uint32 PortableFontInstance::getRawChecksum() const | |
| 409 { | |
| 410 // how big is it? | |
| 411 // fseek(fFile, 0L, SEEK_END); | |
| 412 // long size = ftell(fFile); | |
| 413 le_int32 chksum = 0; | |
| 414 // now, calculate | |
| 415 fseek(fFile, 0L, SEEK_SET); | |
| 416 int r; | |
| 417 int count =0; | |
| 418 while((r = fgetc(fFile)) != EOF) { | |
| 419 chksum += r; | |
| 420 count ++; | |
| 421 } | |
| 422 return (le_uint32) chksum; // cast to signed | |
| 423 } | |
| 424 | |
| 425 le_int32 PortableFontInstance::getAscent() const | |
| 426 { | |
| 427 return fAscent; | |
| 428 } | |
| 429 | |
| 430 le_int32 PortableFontInstance::getDescent() const | |
| 431 { | |
| 432 return fDescent; | |
| 433 } | |
| 434 | |
| 435 le_int32 PortableFontInstance::getLeading() const | |
| 436 { | |
| 437 return fLeading; | |
| 438 } | |
| 439 | |
| 440 // We really want to inherit this method from the superclass, but some compilers | |
| 441 // issue a warning if we don't implement it... | |
| 442 LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMappe
r *mapper, le_bool filterZeroWidth) const | |
| 443 { | |
| 444 return LEFontInstance::mapCharToGlyph(ch, mapper, filterZeroWidth); | |
| 445 } | |
| 446 | |
| 447 // We really want to inherit this method from the superclass, but some compilers | |
| 448 // issue a warning if we don't implement it... | |
| 449 LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMappe
r *mapper) const | |
| 450 { | |
| 451 return LEFontInstance::mapCharToGlyph(ch, mapper); | |
| 452 } | |
| 453 | |
| 454 LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const | |
| 455 { | |
| 456 return fCMAPMapper->unicodeToGlyph(ch); | |
| 457 } | |
| 458 | |
| 459 float PortableFontInstance::getXPixelsPerEm() const | |
| 460 { | |
| 461 return fPointSize; | |
| 462 } | |
| 463 | |
| 464 float PortableFontInstance::getYPixelsPerEm() const | |
| 465 { | |
| 466 return fPointSize; | |
| 467 } | |
| 468 | |
| 469 float PortableFontInstance::getScaleFactorX() const | |
| 470 { | |
| 471 return 1.0; | |
| 472 } | |
| 473 | |
| 474 float PortableFontInstance::getScaleFactorY() const | |
| 475 { | |
| 476 return 1.0; | |
| 477 } | |
| OLD | NEW |