1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*************************************************************************** 2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Copyright (C) 1998-2002, International Business Machines 4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Corporation and others. All Rights Reserved. 5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)************************************************************************/ 7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <stdio.h> 9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "LETypes.h" 11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "FontObject.h" 12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "LESwaps.h" 13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)FontObject::FontObject(char *fileName) 15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) : directory(NULL), numTables(0), searchRange(0),entrySelector(0), 16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmapTable(NULL), cmSegCount(0), cmSearchRange(0), cmEntrySelector(0), 17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmEndCodes(NULL), cmStartCodes(NULL), cmIdDelta(0), cmIdRangeOffset(0), 18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) headTable(NULL), hmtxTable(NULL), numGlyphs(0), numOfLongHorMetrics(0), file(NULL) 19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) file = fopen(fileName, "rb"); 21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (file == NULL) { 23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) printf("?? Couldn't open %s", fileName); 24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) SFNTDirectory tempDir; 28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fread(&tempDir, sizeof tempDir, 1, file); 30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) numTables = SWAPW(tempDir.numTables); 32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) searchRange = SWAPW(tempDir.searchRange) >> 4; 33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entrySelector = SWAPW(tempDir.entrySelector); 34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) rangeShift = SWAPW(tempDir.rangeShift) >> 4; 35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int dirSize = sizeof tempDir + ((numTables - ANY_NUMBER) * sizeof(DirectoryEntry)); 37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) directory = (SFNTDirectory *) new char[dirSize]; 39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fseek(file, 0L, SEEK_SET); 41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fread(directory, sizeof(char), dirSize, file); 42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) initUnicodeCMAP(); 44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)FontObject::~FontObject() 47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fclose(file); 49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete[] directory; 50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete[] cmapTable; 51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete[] headTable; 52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete[] hmtxTable; 53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void FontObject::deleteTable(void *table) 56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete[] (char *) table; 58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)DirectoryEntry *FontObject::findTable(LETag tag) 61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 table = 0; 63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 probe = 1 << entrySelector; 64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (SWAPL(directory->tableDirectory[rangeShift].tag) <= tag) { 66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) table = rangeShift; 67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (probe > (1 << 0)) { 70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) probe >>= 1; 71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (SWAPL(directory->tableDirectory[table + probe].tag) <= tag) { 73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) table += probe; 74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (SWAPL(directory->tableDirectory[table].tag) == tag) { 78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return &directory->tableDirectory[table]; 79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void *FontObject::readTable(LETag tag, le_uint32 *length) 85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DirectoryEntry *entry = findTable(tag); 87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry == NULL) { 89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *length = 0; 90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *length = SWAPL(entry->length); 94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) void *table = new char[*length]; 96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fseek(file, SWAPL(entry->offset), SEEK_SET); 98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fread(table, sizeof(char), *length, file); 99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return table; 101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)CMAPEncodingSubtable *FontObject::findCMAP(le_uint16 platformID, le_uint16 platformSpecificID) 104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LETag cmapTag = 0x636D6170; // 'cmap' 106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (cmapTable == NULL) { 108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint32 length; 109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmapTable = (CMAPTable *) readTable(cmapTag, &length); 111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (cmapTable != NULL) { 114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 i; 115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 nSubtables = SWAPW(cmapTable->numberSubtables); 116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (i = 0; i < nSubtables; i += 1) { 119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) CMAPEncodingSubtableHeader *esh = &cmapTable->encodingSubtableHeaders[i]; 120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (SWAPW(esh->platformID) == platformID && 122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) SWAPW(esh->platformSpecificID) == platformSpecificID) { 123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return (CMAPEncodingSubtable *) ((char *) cmapTable + SWAPL(esh->encodingOffset)); 124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void FontObject::initUnicodeCMAP() 132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) CMAPEncodingSubtable *encodingSubtable = findCMAP(3, 1); 134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (encodingSubtable == 0 || 136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) SWAPW(encodingSubtable->format) != 4) { 137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) printf("Can't find unicode 'cmap'"); 138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) CMAPFormat4Encoding *header = (CMAPFormat4Encoding *) encodingSubtable; 142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmSegCount = SWAPW(header->segCountX2) / 2; 144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmSearchRange = SWAPW(header->searchRange); 145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmEntrySelector = SWAPW(header->entrySelector); 146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmRangeShift = SWAPW(header->rangeShift) / 2; 147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmEndCodes = &header->endCodes[0]; 148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmStartCodes = &header->endCodes[cmSegCount + 1]; // + 1 for reservedPad... 149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmIdDelta = &cmStartCodes[cmSegCount]; 150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cmIdRangeOffset = &cmIdDelta[cmSegCount]; 151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)LEGlyphID FontObject::unicodeToGlyph(LEUnicode32 unicode32) 154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (unicode32 >= 0x10000) { 156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LEUnicode16 unicode = (LEUnicode16) unicode32; 160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 index = 0; 161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 probe = 1 << cmEntrySelector; 162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LEGlyphID result = 0; 163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (SWAPW(cmStartCodes[cmRangeShift]) <= unicode) { 165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) index = cmRangeShift; 166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (probe > (1 << 0)) { 169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) probe >>= 1; 170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (SWAPW(cmStartCodes[index + probe]) <= unicode) { 172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) index += probe; 173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (unicode >= SWAPW(cmStartCodes[index]) && unicode <= SWAPW(cmEndCodes[index])) { 177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (cmIdRangeOffset[index] == 0) { 178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result = (LEGlyphID) unicode; 179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 offset = unicode - SWAPW(cmStartCodes[index]); 181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 rangeOffset = SWAPW(cmIdRangeOffset[index]); 182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &cmIdRangeOffset[index] + rangeOffset); 183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result = SWAPW(glyphIndexTable[offset]); 185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result += SWAPW(cmIdDelta[index]); 188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result = 0; 190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)le_uint16 FontObject::getUnitsPerEM() 196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (headTable == NULL) { 198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LETag headTag = 0x68656164; // 'head' 199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint32 length; 200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) headTable = (HEADTable *) readTable(headTag, &length); 202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return SWAPW(headTable->unitsPerEm); 205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)le_uint16 FontObject::getGlyphAdvance(LEGlyphID glyph) 208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (hmtxTable == NULL) { 210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LETag maxpTag = 0x6D617870; // 'maxp' 211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LETag hheaTag = 0x68686561; // 'hhea' 212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LETag hmtxTag = 0x686D7478; // 'hmtx' 213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint32 length; 214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) HHEATable *hheaTable; 215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) MAXPTable *maxpTable = (MAXPTable *) readTable(maxpTag, &length); 216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) numGlyphs = SWAPW(maxpTable->numGlyphs); 218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) deleteTable(maxpTable); 219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) hheaTable = (HHEATable *) readTable(hheaTag, &length); 221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) numOfLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics); 222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) deleteTable(hheaTable); 223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) hmtxTable = (HMTXTable *) readTable(hmtxTag, &length); 225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) le_uint16 index = glyph; 228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (glyph >= numGlyphs) { 230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (glyph >= numOfLongHorMetrics) { 234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) index = numOfLongHorMetrics - 1; 235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return SWAPW(hmtxTable->hMetrics[index].advanceWidth); 238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 241