Index: icu46/source/test/letest/FontObject.cpp |
=================================================================== |
--- icu46/source/test/letest/FontObject.cpp (revision 0) |
+++ icu46/source/test/letest/FontObject.cpp (revision 0) |
@@ -0,0 +1,240 @@ |
+/*************************************************************************** |
+* |
+* Copyright (C) 1998-2002, International Business Machines |
+* Corporation and others. All Rights Reserved. |
+* |
+************************************************************************/ |
+ |
+#include <stdio.h> |
+ |
+#include "LETypes.h" |
+#include "FontObject.h" |
+#include "LESwaps.h" |
+ |
+FontObject::FontObject(char *fileName) |
+ : directory(NULL), numTables(0), searchRange(0),entrySelector(0), |
+ cmapTable(NULL), cmSegCount(0), cmSearchRange(0), cmEntrySelector(0), |
+ cmEndCodes(NULL), cmStartCodes(NULL), cmIdDelta(0), cmIdRangeOffset(0), |
+ headTable(NULL), hmtxTable(NULL), numGlyphs(0), numOfLongHorMetrics(0), file(NULL) |
+{ |
+ file = fopen(fileName, "rb"); |
+ |
+ if (file == NULL) { |
+ printf("?? Couldn't open %s", fileName); |
+ return; |
+ } |
+ |
+ SFNTDirectory tempDir; |
+ |
+ fread(&tempDir, sizeof tempDir, 1, file); |
+ |
+ numTables = SWAPW(tempDir.numTables); |
+ searchRange = SWAPW(tempDir.searchRange) >> 4; |
+ entrySelector = SWAPW(tempDir.entrySelector); |
+ rangeShift = SWAPW(tempDir.rangeShift) >> 4; |
+ |
+ int dirSize = sizeof tempDir + ((numTables - ANY_NUMBER) * sizeof(DirectoryEntry)); |
+ |
+ directory = (SFNTDirectory *) new char[dirSize]; |
+ |
+ fseek(file, 0L, SEEK_SET); |
+ fread(directory, sizeof(char), dirSize, file); |
+ |
+ initUnicodeCMAP(); |
+} |
+ |
+FontObject::~FontObject() |
+{ |
+ fclose(file); |
+ delete[] directory; |
+ delete[] cmapTable; |
+ delete[] headTable; |
+ delete[] hmtxTable; |
+} |
+ |
+void FontObject::deleteTable(void *table) |
+{ |
+ delete[] (char *) table; |
+} |
+ |
+DirectoryEntry *FontObject::findTable(LETag tag) |
+{ |
+ le_uint16 table = 0; |
+ le_uint16 probe = 1 << entrySelector; |
+ |
+ if (SWAPL(directory->tableDirectory[rangeShift].tag) <= tag) { |
+ table = rangeShift; |
+ } |
+ |
+ while (probe > (1 << 0)) { |
+ probe >>= 1; |
+ |
+ if (SWAPL(directory->tableDirectory[table + probe].tag) <= tag) { |
+ table += probe; |
+ } |
+ } |
+ |
+ if (SWAPL(directory->tableDirectory[table].tag) == tag) { |
+ return &directory->tableDirectory[table]; |
+ } |
+ |
+ return NULL; |
+} |
+ |
+void *FontObject::readTable(LETag tag, le_uint32 *length) |
+{ |
+ DirectoryEntry *entry = findTable(tag); |
+ |
+ if (entry == NULL) { |
+ *length = 0; |
+ return NULL; |
+ } |
+ |
+ *length = SWAPL(entry->length); |
+ |
+ void *table = new char[*length]; |
+ |
+ fseek(file, SWAPL(entry->offset), SEEK_SET); |
+ fread(table, sizeof(char), *length, file); |
+ |
+ return table; |
+} |
+ |
+CMAPEncodingSubtable *FontObject::findCMAP(le_uint16 platformID, le_uint16 platformSpecificID) |
+{ |
+ LETag cmapTag = 0x636D6170; // 'cmap' |
+ |
+ if (cmapTable == NULL) { |
+ le_uint32 length; |
+ |
+ cmapTable = (CMAPTable *) readTable(cmapTag, &length); |
+ } |
+ |
+ if (cmapTable != NULL) { |
+ le_uint16 i; |
+ le_uint16 nSubtables = SWAPW(cmapTable->numberSubtables); |
+ |
+ |
+ for (i = 0; i < nSubtables; i += 1) { |
+ CMAPEncodingSubtableHeader *esh = &cmapTable->encodingSubtableHeaders[i]; |
+ |
+ if (SWAPW(esh->platformID) == platformID && |
+ SWAPW(esh->platformSpecificID) == platformSpecificID) { |
+ return (CMAPEncodingSubtable *) ((char *) cmapTable + SWAPL(esh->encodingOffset)); |
+ } |
+ } |
+ } |
+ |
+ return NULL; |
+} |
+ |
+void FontObject::initUnicodeCMAP() |
+{ |
+ CMAPEncodingSubtable *encodingSubtable = findCMAP(3, 1); |
+ |
+ if (encodingSubtable == 0 || |
+ SWAPW(encodingSubtable->format) != 4) { |
+ printf("Can't find unicode 'cmap'"); |
+ return; |
+ } |
+ |
+ CMAPFormat4Encoding *header = (CMAPFormat4Encoding *) encodingSubtable; |
+ |
+ cmSegCount = SWAPW(header->segCountX2) / 2; |
+ cmSearchRange = SWAPW(header->searchRange); |
+ cmEntrySelector = SWAPW(header->entrySelector); |
+ cmRangeShift = SWAPW(header->rangeShift) / 2; |
+ cmEndCodes = &header->endCodes[0]; |
+ cmStartCodes = &header->endCodes[cmSegCount + 1]; // + 1 for reservedPad... |
+ cmIdDelta = &cmStartCodes[cmSegCount]; |
+ cmIdRangeOffset = &cmIdDelta[cmSegCount]; |
+} |
+ |
+LEGlyphID FontObject::unicodeToGlyph(LEUnicode32 unicode32) |
+{ |
+ if (unicode32 >= 0x10000) { |
+ return 0; |
+ } |
+ |
+ LEUnicode16 unicode = (LEUnicode16) unicode32; |
+ le_uint16 index = 0; |
+ le_uint16 probe = 1 << cmEntrySelector; |
+ LEGlyphID result = 0; |
+ |
+ if (SWAPW(cmStartCodes[cmRangeShift]) <= unicode) { |
+ index = cmRangeShift; |
+ } |
+ |
+ while (probe > (1 << 0)) { |
+ probe >>= 1; |
+ |
+ if (SWAPW(cmStartCodes[index + probe]) <= unicode) { |
+ index += probe; |
+ } |
+ } |
+ |
+ if (unicode >= SWAPW(cmStartCodes[index]) && unicode <= SWAPW(cmEndCodes[index])) { |
+ if (cmIdRangeOffset[index] == 0) { |
+ result = (LEGlyphID) unicode; |
+ } else { |
+ le_uint16 offset = unicode - SWAPW(cmStartCodes[index]); |
+ le_uint16 rangeOffset = SWAPW(cmIdRangeOffset[index]); |
+ le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &cmIdRangeOffset[index] + rangeOffset); |
+ |
+ result = SWAPW(glyphIndexTable[offset]); |
+ } |
+ |
+ result += SWAPW(cmIdDelta[index]); |
+ } else { |
+ result = 0; |
+ } |
+ |
+ return result; |
+} |
+ |
+le_uint16 FontObject::getUnitsPerEM() |
+{ |
+ if (headTable == NULL) { |
+ LETag headTag = 0x68656164; // 'head' |
+ le_uint32 length; |
+ |
+ headTable = (HEADTable *) readTable(headTag, &length); |
+ } |
+ |
+ return SWAPW(headTable->unitsPerEm); |
+} |
+ |
+le_uint16 FontObject::getGlyphAdvance(LEGlyphID glyph) |
+{ |
+ if (hmtxTable == NULL) { |
+ LETag maxpTag = 0x6D617870; // 'maxp' |
+ LETag hheaTag = 0x68686561; // 'hhea' |
+ LETag hmtxTag = 0x686D7478; // 'hmtx' |
+ le_uint32 length; |
+ HHEATable *hheaTable; |
+ MAXPTable *maxpTable = (MAXPTable *) readTable(maxpTag, &length); |
+ |
+ numGlyphs = SWAPW(maxpTable->numGlyphs); |
+ deleteTable(maxpTable); |
+ |
+ hheaTable = (HHEATable *) readTable(hheaTag, &length); |
+ numOfLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics); |
+ deleteTable(hheaTable); |
+ |
+ hmtxTable = (HMTXTable *) readTable(hmtxTag, &length); |
+ } |
+ |
+ le_uint16 index = glyph; |
+ |
+ if (glyph >= numGlyphs) { |
+ return 0; |
+ } |
+ |
+ if (glyph >= numOfLongHorMetrics) { |
+ index = numOfLongHorMetrics - 1; |
+ } |
+ |
+ return SWAPW(hmtxTable->hMetrics[index].advanceWidth); |
+} |
+ |
+ |
Property changes on: icu46/source/test/letest/FontObject.cpp |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |