1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 1999-2008, 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 27 // 28 // Finds the high bit by binary searching 29 // through the bits in n. 30 // 31 le_int8 PortableFontInstance::highBit(le_int32 value) 32 { 33 if (value <= 0) { 34 return -32; 35 } 36 37 le_uint8 bit = 0; 38 39 if (value >= 1 << 16) { 40 value >>= 16; 41 bit += 16; 42 } 43 44 if (value >= 1 << 8) { 45 value >>= 8; 46 bit += 8; 47 } 48 49 if (value >= 1 << 4) { 50 value >>= 4; 51 bit += 4; 52 } 53 54 if (value >= 1 << 2) { 55 value >>= 2; 56 bit += 2; 57 } 58 59 if (value >= 1 << 1) { 60 value >>= 1; 61 bit += 1; 62 } 63 64 return bit; 65 } 66 67 PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize, LEErrorCode &status) 68 : fFile(NULL), fPointSize(pointSize), fUnitsPerEM(0), fFontChecksum(0), fAscent(0), fDescent(0), fLeading(0), 69 fDirectory(NULL), fNAMETable(NULL), fNameCount(0), fNameStringOffset(0), fCMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0) 70 { 71 if (LE_FAILURE(status)) { 72 return; 73 } 74 75 // open the font file 76 fFile = fopen(fileName, "rb"); 77 78 if (fFile == NULL) { 79 status = LE_FONT_FILE_NOT_FOUND_ERROR; 80 return; 81 } 82 83 // read in the directory 84 SFNTDirectory tempDir; 85 86 fread(&tempDir, sizeof tempDir, 1, fFile); 87 88 le_int32 dirSize = sizeof tempDir + ((SWAPW(tempDir.numTables) - ANY_NUMBER) * sizeof(DirectoryEntry)); 89 const LETag headTag = LE_HEAD_TABLE_TAG; 90 const LETag hheaTag = LE_HHEA_TABLE_TAG; 91 const HEADTable *headTable = NULL; 92 const HHEATable *hheaTable = NULL; 93 // const NAMETable *nameTable = NULL; 94 le_uint16 numTables = 0; 95 96 fDirectory = (const SFNTDirectory *) NEW_ARRAY(char, dirSize); 97 98 if (fDirectory == NULL) { 99 status = LE_MEMORY_ALLOCATION_ERROR; 100 goto error_exit; 101 } 102 103 fseek(fFile, 0L, SEEK_SET); 104 fread((void *) fDirectory, sizeof(char), dirSize, fFile); 105 106 // 107 // We calculate these numbers 'cause some fonts 108 // have bogus values for them in the directory header. 109 // 110 numTables = SWAPW(fDirectory->numTables); 111 fDirPower = 1 << highBit(numTables); 112 fDirExtra = numTables - fDirPower; 113 114 // read unitsPerEm from 'head' table 115 headTable = (const HEADTable *) readFontTable(headTag); 116 117 if (headTable == NULL) { 118 status = LE_MISSING_FONT_TABLE_ERROR; 119 goto error_exit; 120 } 121 122 fUnitsPerEM = SWAPW(headTable->unitsPerEm); 123 fFontChecksum = SWAPL(headTable->checksumAdjustment); 124 freeFontTable(headTable); 125 126 //nameTable = (NAMETable *) readFontTable(nameTag); 127 128 //if (nameTable == NULL) { 129 // status = LE_MISSING_FONT_TABLE_ERROR; 130 // goto error_exit; 131 //} 132 133 //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH); 134 135 //if (fFontVersionString == NULL) { 136 // status = LE_MISSING_FONT_TABLE_ERROR; 137 // goto error_exit; 138 //} 139 140 //freeFontTable(nameTable); 141 142 hheaTable = (HHEATable *) readFontTable(hheaTag); 143 144 if (hheaTable == NULL) { 145 status = LE_MISSING_FONT_TABLE_ERROR; 146 goto error_exit; 147 } 148 149 fAscent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent)); 150 fDescent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->descent)); 151 fLeading = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->lineGap)); 152 153 fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics); 154 155 freeFontTable((void *) hheaTable); 156 157 fCMAPMapper = findUnicodeMapper(); 158 159 if (fCMAPMapper == NULL) { 160 status = LE_MISSING_FONT_TABLE_ERROR; 161 goto error_exit; 162 } 163 164 return; 165 166 error_exit: 167 fclose(fFile); 168 fFile = NULL; 169 return; 170 } 171 172 PortableFontInstance::~PortableFontInstance() 173 { 174 if (fFile != NULL) { 175 fclose(fFile); 176 177 freeFontTable(fHMTXTable); 178 freeFontTable(fNAMETable); 179 180 delete fCMAPMapper; 181 182 DELETE_ARRAY(fDirectory); 183 } 184 } 185 186 const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const 187 { 188 if (fDirectory != NULL) { 189 le_uint16 table = 0; 190 le_uint16 probe = fDirPower; 191 192 if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) { 193 table = fDirExtra; 194 } 195 196 while (probe > (1 << 0)) { 197 probe >>= 1; 198 199 if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) { 200 table += probe; 201 } 202 } 203 204 if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) { 205 return &fDirectory->tableDirectory[table]; 206 } 207 } 208 209 return NULL; 210 } 211 212 const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const 213 { 214 const DirectoryEntry *entry = findTable(tag); 215 216 if (entry == NULL) { 217 *length = 0; 218 return NULL; 219 } 220 221 *length = SWAPL(entry->length); 222 223 void *table = NEW_ARRAY(char, *length); 224 225 if (table != NULL) { 226 fseek(fFile, SWAPL(entry->offset), SEEK_SET); 227 fread(table, sizeof(char), *length, fFile); 228 } 229 230 return table; 231 } 232 233 const void *PortableFontInstance::getFontTable(LETag tableTag) const 234 { 235 return FontTableCache::find(tableTag); 236 } 237 238 const void *PortableFontInstance::readFontTable(LETag tableTag) const 239 { 240 le_uint32 len; 241 242 return readTable(tableTag, &len); 243 } 244 245 CMAPMapper *PortableFontInstance::findUnicodeMapper() 246 { 247 LETag cmapTag = LE_CMAP_TABLE_TAG; 248 const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag); 249 250 if (cmap == NULL) { 251 return NULL; 252 } 253 254 return CMAPMapper::createUnicodeMapper(cmap); 255 } 256 257 const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const 258 { 259 if (fNAMETable == NULL) { 260 LETag nameTag = LE_NAME_TABLE_TAG; 261 PortableFontInstance *realThis = (PortableFontInstance *) this; 262 263 realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag); 264 265 if (realThis->fNAMETable != NULL) { 266 realThis->fNameCount = SWAPW(realThis->fNAMETable->count); 267 realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset); 268 } 269 } 270 271 for(le_int32 i = 0; i < fNameCount; i += 1) { 272 const NameRecord *nameRecord = &fNAMETable->nameRecords[i]; 273 274 if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID && 275 SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) { 276 char *name = ((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset); 277 le_uint16 length = SWAPW(nameRecord->length); 278 char *result = NEW_ARRAY(char, length + 2); 279 280 ARRAY_COPY(result, name, length); 281 result[length] = result[length + 1] = 0; 282 283 return result; 284 } 285 } 286 287 return NULL; 288 } 289 290 const LEUnicode16 *PortableFontInstance::getUnicodeNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const 291 { 292 if (fNAMETable == NULL) { 293 LETag nameTag = LE_NAME_TABLE_TAG; 294 PortableFontInstance *realThis = (PortableFontInstance *) this; 295 296 realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag); 297 298 if (realThis->fNAMETable != NULL) { 299 realThis->fNameCount = SWAPW(realThis->fNAMETable->count); 300 realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset); 301 } 302 } 303 304 for(le_int32 i = 0; i < fNameCount; i += 1) { 305 const NameRecord *nameRecord = &fNAMETable->nameRecords[i]; 306 307 if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID && 308 SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) { 309 LEUnicode16 *name = (LEUnicode16 *) (((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset)); 310 le_uint16 length = SWAPW(nameRecord->length) / 2; 311 LEUnicode16 *result = NEW_ARRAY(LEUnicode16, length + 2); 312 313 for (le_int32 c = 0; c < length; c += 1) { 314 result[c] = SWAPW(name[c]); 315 } 316 317 result[length] = 0; 318 319 return result; 320 } 321 } 322 323 return NULL; 324 } 325 326 void PortableFontInstance::deleteNameString(const char *name) const 327 { 328 DELETE_ARRAY(name); 329 } 330 331 void PortableFontInstance::deleteNameString(const LEUnicode16 *name) const 332 { 333 DELETE_ARRAY(name); 334 } 335 336 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const 337 { 338 TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph); 339 340 if (fHMTXTable == NULL) { 341 LETag maxpTag = LE_MAXP_TABLE_TAG; 342 LETag hmtxTag = LE_HMTX_TABLE_TAG; 343 const MAXPTable *maxpTable = (MAXPTable *) readFontTable(maxpTag); 344 PortableFontInstance *realThis = (PortableFontInstance *) this; 345 346 if (maxpTable != NULL) { 347 realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs); 348 freeFontTable(maxpTable); 349 } 350 351 realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag); 352 } 353 354 le_uint16 index = ttGlyph; 355 356 if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) { 357 advance.fX = advance.fY = 0; 358 return; 359 } 360 361 if (ttGlyph >= fNumLongHorMetrics) { 362 index = fNumLongHorMetrics - 1; 363 } 364 365 advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth)); 366 advance.fY = 0; 367 } 368 369 le_bool PortableFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*pointNumber*/, LEPoint &/*point*/) const 370 { 371 return FALSE; 372 } 373 374 le_int32 PortableFontInstance::getUnitsPerEM() const 375 { 376 return fUnitsPerEM; 377 } 378 379 le_uint32 PortableFontInstance::getFontChecksum() const 380 { 381 return fFontChecksum; 382 } 383 384 le_int32 PortableFontInstance::getAscent() const 385 { 386 return fAscent; 387 } 388 389 le_int32 PortableFontInstance::getDescent() const 390 { 391 return fDescent; 392 } 393 394 le_int32 PortableFontInstance::getLeading() const 395 { 396 return fLeading; 397 } 398 399 // We really want to inherit this method from the superclass, but some compilers 400 // issue a warning if we don't implement it... 401 LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const 402 { 403 return LEFontInstance::mapCharToGlyph(ch, mapper, filterZeroWidth); 404 } 405 406 // We really want to inherit this method from the superclass, but some compilers 407 // issue a warning if we don't implement it... 408 LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const 409 { 410 return LEFontInstance::mapCharToGlyph(ch, mapper); 411 } 412 413 LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const 414 { 415 return fCMAPMapper->unicodeToGlyph(ch); 416 } 417 418 float PortableFontInstance::getXPixelsPerEm() const 419 { 420 return fPointSize; 421 } 422 423 float PortableFontInstance::getYPixelsPerEm() const 424 { 425 return fPointSize; 426 } 427 428 float PortableFontInstance::getScaleFactorX() const 429 { 430 return 1.0; 431 } 432 433 float PortableFontInstance::getScaleFactorY() const 434 { 435 return 1.0; 436 } 437