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