12e5b6d6dSopenharmony_ci/*************************************************************************** 22e5b6d6dSopenharmony_ci* 32e5b6d6dSopenharmony_ci* © 2016 and later: Unicode, Inc. and others. 42e5b6d6dSopenharmony_ci* License & terms of use: http://www.unicode.org/copyright.html 52e5b6d6dSopenharmony_ci* 62e5b6d6dSopenharmony_ci****************************************************************************/ 72e5b6d6dSopenharmony_ci/*************************************************************************** 82e5b6d6dSopenharmony_ci* 92e5b6d6dSopenharmony_ci* Copyright (C) 1998-2013, International Business Machines 102e5b6d6dSopenharmony_ci* Corporation and others. All Rights Reserved. 112e5b6d6dSopenharmony_ci* 122e5b6d6dSopenharmony_ci************************************************************************/ 132e5b6d6dSopenharmony_ci 142e5b6d6dSopenharmony_ci#include <stdio.h> 152e5b6d6dSopenharmony_ci 162e5b6d6dSopenharmony_ci#include "LETypes.h" 172e5b6d6dSopenharmony_ci#include "FontObject.h" 182e5b6d6dSopenharmony_ci#include "LESwaps.h" 192e5b6d6dSopenharmony_ci 202e5b6d6dSopenharmony_ciFontObject::FontObject(char *fileName) 212e5b6d6dSopenharmony_ci : directory(NULL), numTables(0), searchRange(0),entrySelector(0), 222e5b6d6dSopenharmony_ci cmapTable(NULL), cmSegCount(0), cmSearchRange(0), cmEntrySelector(0), 232e5b6d6dSopenharmony_ci cmEndCodes(NULL), cmStartCodes(NULL), cmIdDelta(0), cmIdRangeOffset(0), 242e5b6d6dSopenharmony_ci headTable(NULL), hmtxTable(NULL), numGlyphs(0), numOfLongHorMetrics(0), file(NULL) 252e5b6d6dSopenharmony_ci{ 262e5b6d6dSopenharmony_ci file = fopen(fileName, "rb"); 272e5b6d6dSopenharmony_ci 282e5b6d6dSopenharmony_ci if (file == NULL) { 292e5b6d6dSopenharmony_ci printf("?? Couldn't open %s", fileName); 302e5b6d6dSopenharmony_ci return; 312e5b6d6dSopenharmony_ci } 322e5b6d6dSopenharmony_ci 332e5b6d6dSopenharmony_ci SFNTDirectory tempDir; 342e5b6d6dSopenharmony_ci 352e5b6d6dSopenharmony_ci fread(&tempDir, sizeof tempDir, 1, file); 362e5b6d6dSopenharmony_ci 372e5b6d6dSopenharmony_ci numTables = SWAPW(tempDir.numTables); 382e5b6d6dSopenharmony_ci searchRange = SWAPW(tempDir.searchRange) >> 4; 392e5b6d6dSopenharmony_ci entrySelector = SWAPW(tempDir.entrySelector); 402e5b6d6dSopenharmony_ci rangeShift = SWAPW(tempDir.rangeShift) >> 4; 412e5b6d6dSopenharmony_ci 422e5b6d6dSopenharmony_ci int dirSize = sizeof tempDir + ((numTables - ANY_NUMBER) * sizeof(DirectoryEntry)); 432e5b6d6dSopenharmony_ci 442e5b6d6dSopenharmony_ci directory = (SFNTDirectory *) new char[dirSize]; 452e5b6d6dSopenharmony_ci 462e5b6d6dSopenharmony_ci fseek(file, 0L, SEEK_SET); 472e5b6d6dSopenharmony_ci fread(directory, sizeof(char), dirSize, file); 482e5b6d6dSopenharmony_ci 492e5b6d6dSopenharmony_ci initUnicodeCMAP(); 502e5b6d6dSopenharmony_ci} 512e5b6d6dSopenharmony_ci 522e5b6d6dSopenharmony_ciFontObject::~FontObject() 532e5b6d6dSopenharmony_ci{ 542e5b6d6dSopenharmony_ci fclose(file); 552e5b6d6dSopenharmony_ci delete[] directory; 562e5b6d6dSopenharmony_ci delete[] cmapTable; 572e5b6d6dSopenharmony_ci delete[] headTable; 582e5b6d6dSopenharmony_ci delete[] hmtxTable; 592e5b6d6dSopenharmony_ci} 602e5b6d6dSopenharmony_ci 612e5b6d6dSopenharmony_civoid FontObject::deleteTable(void *table) 622e5b6d6dSopenharmony_ci{ 632e5b6d6dSopenharmony_ci delete[] (char *) table; 642e5b6d6dSopenharmony_ci} 652e5b6d6dSopenharmony_ci 662e5b6d6dSopenharmony_ciDirectoryEntry *FontObject::findTable(LETag tag) 672e5b6d6dSopenharmony_ci{ 682e5b6d6dSopenharmony_ci le_uint16 table = 0; 692e5b6d6dSopenharmony_ci le_uint16 probe = 1 << entrySelector; 702e5b6d6dSopenharmony_ci 712e5b6d6dSopenharmony_ci if (SWAPL(directory->tableDirectory[rangeShift].tag) <= tag) { 722e5b6d6dSopenharmony_ci table = rangeShift; 732e5b6d6dSopenharmony_ci } 742e5b6d6dSopenharmony_ci 752e5b6d6dSopenharmony_ci while (probe > (1 << 0)) { 762e5b6d6dSopenharmony_ci probe >>= 1; 772e5b6d6dSopenharmony_ci 782e5b6d6dSopenharmony_ci if (SWAPL(directory->tableDirectory[table + probe].tag) <= tag) { 792e5b6d6dSopenharmony_ci table += probe; 802e5b6d6dSopenharmony_ci } 812e5b6d6dSopenharmony_ci } 822e5b6d6dSopenharmony_ci 832e5b6d6dSopenharmony_ci if (SWAPL(directory->tableDirectory[table].tag) == tag) { 842e5b6d6dSopenharmony_ci return &directory->tableDirectory[table]; 852e5b6d6dSopenharmony_ci } 862e5b6d6dSopenharmony_ci 872e5b6d6dSopenharmony_ci return NULL; 882e5b6d6dSopenharmony_ci} 892e5b6d6dSopenharmony_ci 902e5b6d6dSopenharmony_civoid *FontObject::readTable(LETag tag, le_uint32 *length) 912e5b6d6dSopenharmony_ci{ 922e5b6d6dSopenharmony_ci DirectoryEntry *entry = findTable(tag); 932e5b6d6dSopenharmony_ci 942e5b6d6dSopenharmony_ci if (entry == NULL) { 952e5b6d6dSopenharmony_ci *length = 0; 962e5b6d6dSopenharmony_ci return NULL; 972e5b6d6dSopenharmony_ci } 982e5b6d6dSopenharmony_ci 992e5b6d6dSopenharmony_ci *length = SWAPL(entry->length); 1002e5b6d6dSopenharmony_ci 1012e5b6d6dSopenharmony_ci void *table = new char[*length]; 1022e5b6d6dSopenharmony_ci 1032e5b6d6dSopenharmony_ci fseek(file, SWAPL(entry->offset), SEEK_SET); 1042e5b6d6dSopenharmony_ci fread(table, sizeof(char), *length, file); 1052e5b6d6dSopenharmony_ci 1062e5b6d6dSopenharmony_ci return table; 1072e5b6d6dSopenharmony_ci} 1082e5b6d6dSopenharmony_ci 1092e5b6d6dSopenharmony_ciCMAPEncodingSubtable *FontObject::findCMAP(le_uint16 platformID, le_uint16 platformSpecificID) 1102e5b6d6dSopenharmony_ci{ 1112e5b6d6dSopenharmony_ci LETag cmapTag = 0x636D6170; // 'cmap' 1122e5b6d6dSopenharmony_ci 1132e5b6d6dSopenharmony_ci if (cmapTable == NULL) { 1142e5b6d6dSopenharmony_ci le_uint32 length; 1152e5b6d6dSopenharmony_ci 1162e5b6d6dSopenharmony_ci cmapTable = (CMAPTable *) readTable(cmapTag, &length); 1172e5b6d6dSopenharmony_ci } 1182e5b6d6dSopenharmony_ci 1192e5b6d6dSopenharmony_ci if (cmapTable != NULL) { 1202e5b6d6dSopenharmony_ci le_uint16 i; 1212e5b6d6dSopenharmony_ci le_uint16 nSubtables = SWAPW(cmapTable->numberSubtables); 1222e5b6d6dSopenharmony_ci 1232e5b6d6dSopenharmony_ci 1242e5b6d6dSopenharmony_ci for (i = 0; i < nSubtables; i += 1) { 1252e5b6d6dSopenharmony_ci CMAPEncodingSubtableHeader *esh = &cmapTable->encodingSubtableHeaders[i]; 1262e5b6d6dSopenharmony_ci 1272e5b6d6dSopenharmony_ci if (SWAPW(esh->platformID) == platformID && 1282e5b6d6dSopenharmony_ci SWAPW(esh->platformSpecificID) == platformSpecificID) { 1292e5b6d6dSopenharmony_ci return (CMAPEncodingSubtable *) ((char *) cmapTable + SWAPL(esh->encodingOffset)); 1302e5b6d6dSopenharmony_ci } 1312e5b6d6dSopenharmony_ci } 1322e5b6d6dSopenharmony_ci } 1332e5b6d6dSopenharmony_ci 1342e5b6d6dSopenharmony_ci return NULL; 1352e5b6d6dSopenharmony_ci} 1362e5b6d6dSopenharmony_ci 1372e5b6d6dSopenharmony_civoid FontObject::initUnicodeCMAP() 1382e5b6d6dSopenharmony_ci{ 1392e5b6d6dSopenharmony_ci CMAPEncodingSubtable *encodingSubtable = findCMAP(3, 1); 1402e5b6d6dSopenharmony_ci 1412e5b6d6dSopenharmony_ci if (encodingSubtable == 0 || 1422e5b6d6dSopenharmony_ci SWAPW(encodingSubtable->format) != 4) { 1432e5b6d6dSopenharmony_ci printf("Can't find unicode 'cmap'"); 1442e5b6d6dSopenharmony_ci return; 1452e5b6d6dSopenharmony_ci } 1462e5b6d6dSopenharmony_ci 1472e5b6d6dSopenharmony_ci CMAPFormat4Encoding *header = (CMAPFormat4Encoding *) encodingSubtable; 1482e5b6d6dSopenharmony_ci 1492e5b6d6dSopenharmony_ci cmSegCount = SWAPW(header->segCountX2) / 2; 1502e5b6d6dSopenharmony_ci cmSearchRange = SWAPW(header->searchRange); 1512e5b6d6dSopenharmony_ci cmEntrySelector = SWAPW(header->entrySelector); 1522e5b6d6dSopenharmony_ci cmRangeShift = SWAPW(header->rangeShift) / 2; 1532e5b6d6dSopenharmony_ci cmEndCodes = &header->endCodes[0]; 1542e5b6d6dSopenharmony_ci cmStartCodes = &header->endCodes[cmSegCount + 1]; // + 1 for reservedPad... 1552e5b6d6dSopenharmony_ci cmIdDelta = &cmStartCodes[cmSegCount]; 1562e5b6d6dSopenharmony_ci cmIdRangeOffset = &cmIdDelta[cmSegCount]; 1572e5b6d6dSopenharmony_ci} 1582e5b6d6dSopenharmony_ci 1592e5b6d6dSopenharmony_ciLEGlyphID FontObject::unicodeToGlyph(LEUnicode32 unicode32) 1602e5b6d6dSopenharmony_ci{ 1612e5b6d6dSopenharmony_ci if (unicode32 >= 0x10000) { 1622e5b6d6dSopenharmony_ci return 0; 1632e5b6d6dSopenharmony_ci } 1642e5b6d6dSopenharmony_ci 1652e5b6d6dSopenharmony_ci LEUnicode16 unicode = (LEUnicode16) unicode32; 1662e5b6d6dSopenharmony_ci le_uint16 index = 0; 1672e5b6d6dSopenharmony_ci le_uint16 probe = 1 << cmEntrySelector; 1682e5b6d6dSopenharmony_ci LEGlyphID result = 0; 1692e5b6d6dSopenharmony_ci 1702e5b6d6dSopenharmony_ci if (SWAPW(cmStartCodes[cmRangeShift]) <= unicode) { 1712e5b6d6dSopenharmony_ci index = cmRangeShift; 1722e5b6d6dSopenharmony_ci } 1732e5b6d6dSopenharmony_ci 1742e5b6d6dSopenharmony_ci while (probe > (1 << 0)) { 1752e5b6d6dSopenharmony_ci probe >>= 1; 1762e5b6d6dSopenharmony_ci 1772e5b6d6dSopenharmony_ci if (SWAPW(cmStartCodes[index + probe]) <= unicode) { 1782e5b6d6dSopenharmony_ci index += probe; 1792e5b6d6dSopenharmony_ci } 1802e5b6d6dSopenharmony_ci } 1812e5b6d6dSopenharmony_ci 1822e5b6d6dSopenharmony_ci if (unicode >= SWAPW(cmStartCodes[index]) && unicode <= SWAPW(cmEndCodes[index])) { 1832e5b6d6dSopenharmony_ci if (cmIdRangeOffset[index] == 0) { 1842e5b6d6dSopenharmony_ci result = (LEGlyphID) unicode; 1852e5b6d6dSopenharmony_ci } else { 1862e5b6d6dSopenharmony_ci le_uint16 offset = unicode - SWAPW(cmStartCodes[index]); 1872e5b6d6dSopenharmony_ci le_uint16 rangeOffset = SWAPW(cmIdRangeOffset[index]); 1882e5b6d6dSopenharmony_ci le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &cmIdRangeOffset[index] + rangeOffset); 1892e5b6d6dSopenharmony_ci 1902e5b6d6dSopenharmony_ci result = SWAPW(glyphIndexTable[offset]); 1912e5b6d6dSopenharmony_ci } 1922e5b6d6dSopenharmony_ci 1932e5b6d6dSopenharmony_ci result += SWAPW(cmIdDelta[index]); 1942e5b6d6dSopenharmony_ci } else { 1952e5b6d6dSopenharmony_ci result = 0; 1962e5b6d6dSopenharmony_ci } 1972e5b6d6dSopenharmony_ci 1982e5b6d6dSopenharmony_ci return result; 1992e5b6d6dSopenharmony_ci} 2002e5b6d6dSopenharmony_ci 2012e5b6d6dSopenharmony_cile_uint16 FontObject::getUnitsPerEM() 2022e5b6d6dSopenharmony_ci{ 2032e5b6d6dSopenharmony_ci if (headTable == NULL) { 2042e5b6d6dSopenharmony_ci LETag headTag = 0x68656164; // 'head' 2052e5b6d6dSopenharmony_ci le_uint32 length; 2062e5b6d6dSopenharmony_ci 2072e5b6d6dSopenharmony_ci headTable = (HEADTable *) readTable(headTag, &length); 2082e5b6d6dSopenharmony_ci } 2092e5b6d6dSopenharmony_ci 2102e5b6d6dSopenharmony_ci return SWAPW(headTable->unitsPerEm); 2112e5b6d6dSopenharmony_ci} 2122e5b6d6dSopenharmony_ci 2132e5b6d6dSopenharmony_cile_uint16 FontObject::getGlyphAdvance(LEGlyphID glyph) 2142e5b6d6dSopenharmony_ci{ 2152e5b6d6dSopenharmony_ci if (hmtxTable == NULL) { 2162e5b6d6dSopenharmony_ci LETag maxpTag = 0x6D617870; // 'maxp' 2172e5b6d6dSopenharmony_ci LETag hheaTag = 0x68686561; // 'hhea' 2182e5b6d6dSopenharmony_ci LETag hmtxTag = 0x686D7478; // 'hmtx' 2192e5b6d6dSopenharmony_ci le_uint32 length; 2202e5b6d6dSopenharmony_ci HHEATable *hheaTable; 2212e5b6d6dSopenharmony_ci MAXPTable *maxpTable = (MAXPTable *) readTable(maxpTag, &length); 2222e5b6d6dSopenharmony_ci 2232e5b6d6dSopenharmony_ci numGlyphs = SWAPW(maxpTable->numGlyphs); 2242e5b6d6dSopenharmony_ci deleteTable(maxpTable); 2252e5b6d6dSopenharmony_ci 2262e5b6d6dSopenharmony_ci hheaTable = (HHEATable *) readTable(hheaTag, &length); 2272e5b6d6dSopenharmony_ci numOfLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics); 2282e5b6d6dSopenharmony_ci deleteTable(hheaTable); 2292e5b6d6dSopenharmony_ci 2302e5b6d6dSopenharmony_ci hmtxTable = (HMTXTable *) readTable(hmtxTag, &length); 2312e5b6d6dSopenharmony_ci } 2322e5b6d6dSopenharmony_ci 2332e5b6d6dSopenharmony_ci le_uint16 index = glyph; 2342e5b6d6dSopenharmony_ci 2352e5b6d6dSopenharmony_ci if (glyph >= numGlyphs) { 2362e5b6d6dSopenharmony_ci return 0; 2372e5b6d6dSopenharmony_ci } 2382e5b6d6dSopenharmony_ci 2392e5b6d6dSopenharmony_ci if (glyph >= numOfLongHorMetrics) { 2402e5b6d6dSopenharmony_ci index = numOfLongHorMetrics - 1; 2412e5b6d6dSopenharmony_ci } 2422e5b6d6dSopenharmony_ci 2432e5b6d6dSopenharmony_ci return SWAPW(hmtxTable->hMetrics[index].advanceWidth); 2442e5b6d6dSopenharmony_ci} 2452e5b6d6dSopenharmony_ci 2462e5b6d6dSopenharmony_ci 247