1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/fontservices/textshaperplugin/test/letest/FontObject.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,240 @@
1.4 +/***************************************************************************
1.5 +*
1.6 +* Copyright (C) 1998-2002, International Business Machines
1.7 +* Corporation and others. All Rights Reserved.
1.8 +*
1.9 +************************************************************************/
1.10 +
1.11 +#include <stdio.h>
1.12 +
1.13 +#include "LETypes.h"
1.14 +#include "FontObject.h"
1.15 +#include "LESwaps.h"
1.16 +
1.17 +FontObject::FontObject(char *fileName)
1.18 + : directory(NULL), numTables(0), searchRange(0),entrySelector(0),
1.19 + cmapTable(NULL), cmSegCount(0), cmSearchRange(0), cmEntrySelector(0),
1.20 + cmEndCodes(NULL), cmStartCodes(NULL), cmIdDelta(0), cmIdRangeOffset(0),
1.21 + headTable(NULL), hmtxTable(NULL), numGlyphs(0), numOfLongHorMetrics(0), file(NULL)
1.22 +{
1.23 + file = fopen(fileName, "rb");
1.24 +
1.25 + if (file == NULL) {
1.26 + printf("?? Couldn't open %s", fileName);
1.27 + return;
1.28 + }
1.29 +
1.30 + SFNTDirectory tempDir;
1.31 +
1.32 + fread(&tempDir, sizeof tempDir, 1, file);
1.33 +
1.34 + numTables = SWAPW(tempDir.numTables);
1.35 + searchRange = SWAPW(tempDir.searchRange) >> 4;
1.36 + entrySelector = SWAPW(tempDir.entrySelector);
1.37 + rangeShift = SWAPW(tempDir.rangeShift) >> 4;
1.38 +
1.39 + int dirSize = sizeof tempDir + ((numTables - ANY_NUMBER) * sizeof(DirectoryEntry));
1.40 +
1.41 + directory = (SFNTDirectory *) new char[dirSize];
1.42 +
1.43 + fseek(file, 0L, SEEK_SET);
1.44 + fread(directory, sizeof(char), dirSize, file);
1.45 +
1.46 + initUnicodeCMAP();
1.47 +}
1.48 +
1.49 +FontObject::~FontObject()
1.50 +{
1.51 + fclose(file);
1.52 + delete[] directory;
1.53 + delete[] cmapTable;
1.54 + delete[] headTable;
1.55 + delete[] hmtxTable;
1.56 +}
1.57 +
1.58 +void FontObject::deleteTable(void *table)
1.59 +{
1.60 + delete[] (char *) table;
1.61 +}
1.62 +
1.63 +DirectoryEntry *FontObject::findTable(LETag tag)
1.64 +{
1.65 + le_uint16 table = 0;
1.66 + le_uint16 probe = 1 << entrySelector;
1.67 +
1.68 + if (SWAPL(directory->tableDirectory[rangeShift].tag) <= tag) {
1.69 + table = rangeShift;
1.70 + }
1.71 +
1.72 + while (probe > (1 << 0)) {
1.73 + probe >>= 1;
1.74 +
1.75 + if (SWAPL(directory->tableDirectory[table + probe].tag) <= tag) {
1.76 + table += probe;
1.77 + }
1.78 + }
1.79 +
1.80 + if (SWAPL(directory->tableDirectory[table].tag) == tag) {
1.81 + return &directory->tableDirectory[table];
1.82 + }
1.83 +
1.84 + return NULL;
1.85 +}
1.86 +
1.87 +void *FontObject::readTable(LETag tag, le_uint32 *length)
1.88 +{
1.89 + DirectoryEntry *entry = findTable(tag);
1.90 +
1.91 + if (entry == NULL) {
1.92 + *length = 0;
1.93 + return NULL;
1.94 + }
1.95 +
1.96 + *length = SWAPL(entry->length);
1.97 +
1.98 + void *table = new char[*length];
1.99 +
1.100 + fseek(file, SWAPL(entry->offset), SEEK_SET);
1.101 + fread(table, sizeof(char), *length, file);
1.102 +
1.103 + return table;
1.104 +}
1.105 +
1.106 +CMAPEncodingSubtable *FontObject::findCMAP(le_uint16 platformID, le_uint16 platformSpecificID)
1.107 +{
1.108 + LETag cmapTag = 0x636D6170; // 'cmap'
1.109 +
1.110 + if (cmapTable == NULL) {
1.111 + le_uint32 length;
1.112 +
1.113 + cmapTable = (CMAPTable *) readTable(cmapTag, &length);
1.114 + }
1.115 +
1.116 + if (cmapTable != NULL) {
1.117 + le_uint16 i;
1.118 + le_uint16 nSubtables = SWAPW(cmapTable->numberSubtables);
1.119 +
1.120 +
1.121 + for (i = 0; i < nSubtables; i += 1) {
1.122 + CMAPEncodingSubtableHeader *esh = &cmapTable->encodingSubtableHeaders[i];
1.123 +
1.124 + if (SWAPW(esh->platformID) == platformID &&
1.125 + SWAPW(esh->platformSpecificID) == platformSpecificID) {
1.126 + return (CMAPEncodingSubtable *) ((char *) cmapTable + SWAPL(esh->encodingOffset));
1.127 + }
1.128 + }
1.129 + }
1.130 +
1.131 + return NULL;
1.132 +}
1.133 +
1.134 +void FontObject::initUnicodeCMAP()
1.135 +{
1.136 + CMAPEncodingSubtable *encodingSubtable = findCMAP(3, 1);
1.137 +
1.138 + if (encodingSubtable == 0 ||
1.139 + SWAPW(encodingSubtable->format) != 4) {
1.140 + printf("Can't find unicode 'cmap'");
1.141 + return;
1.142 + }
1.143 +
1.144 + CMAPFormat4Encoding *header = (CMAPFormat4Encoding *) encodingSubtable;
1.145 +
1.146 + cmSegCount = SWAPW(header->segCountX2) / 2;
1.147 + cmSearchRange = SWAPW(header->searchRange);
1.148 + cmEntrySelector = SWAPW(header->entrySelector);
1.149 + cmRangeShift = SWAPW(header->rangeShift) / 2;
1.150 + cmEndCodes = &header->endCodes[0];
1.151 + cmStartCodes = &header->endCodes[cmSegCount + 1]; // + 1 for reservedPad...
1.152 + cmIdDelta = &cmStartCodes[cmSegCount];
1.153 + cmIdRangeOffset = &cmIdDelta[cmSegCount];
1.154 +}
1.155 +
1.156 +LEGlyphID FontObject::unicodeToGlyph(LEUnicode32 unicode32)
1.157 +{
1.158 + if (unicode32 >= 0x10000) {
1.159 + return 0;
1.160 + }
1.161 +
1.162 + LEUnicode16 unicode = (LEUnicode16) unicode32;
1.163 + le_uint16 index = 0;
1.164 + le_uint16 probe = 1 << cmEntrySelector;
1.165 + LEGlyphID result = 0;
1.166 +
1.167 + if (SWAPW(cmStartCodes[cmRangeShift]) <= unicode) {
1.168 + index = cmRangeShift;
1.169 + }
1.170 +
1.171 + while (probe > (1 << 0)) {
1.172 + probe >>= 1;
1.173 +
1.174 + if (SWAPW(cmStartCodes[index + probe]) <= unicode) {
1.175 + index += probe;
1.176 + }
1.177 + }
1.178 +
1.179 + if (unicode >= SWAPW(cmStartCodes[index]) && unicode <= SWAPW(cmEndCodes[index])) {
1.180 + if (cmIdRangeOffset[index] == 0) {
1.181 + result = (LEGlyphID) unicode;
1.182 + } else {
1.183 + le_uint16 offset = unicode - SWAPW(cmStartCodes[index]);
1.184 + le_uint16 rangeOffset = SWAPW(cmIdRangeOffset[index]);
1.185 + le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &cmIdRangeOffset[index] + rangeOffset);
1.186 +
1.187 + result = SWAPW(glyphIndexTable[offset]);
1.188 + }
1.189 +
1.190 + result += SWAPW(cmIdDelta[index]);
1.191 + } else {
1.192 + result = 0;
1.193 + }
1.194 +
1.195 + return result;
1.196 +}
1.197 +
1.198 +le_uint16 FontObject::getUnitsPerEM()
1.199 +{
1.200 + if (headTable == NULL) {
1.201 + LETag headTag = 0x68656164; // 'head'
1.202 + le_uint32 length;
1.203 +
1.204 + headTable = (HEADTable *) readTable(headTag, &length);
1.205 + }
1.206 +
1.207 + return SWAPW(headTable->unitsPerEm);
1.208 +}
1.209 +
1.210 +le_uint16 FontObject::getGlyphAdvance(LEGlyphID glyph)
1.211 +{
1.212 + if (hmtxTable == NULL) {
1.213 + LETag maxpTag = 0x6D617870; // 'maxp'
1.214 + LETag hheaTag = 0x68686561; // 'hhea'
1.215 + LETag hmtxTag = 0x686D7478; // 'hmtx'
1.216 + le_uint32 length;
1.217 + HHEATable *hheaTable;
1.218 + MAXPTable *maxpTable = (MAXPTable *) readTable(maxpTag, &length);
1.219 +
1.220 + numGlyphs = SWAPW(maxpTable->numGlyphs);
1.221 + deleteTable(maxpTable);
1.222 +
1.223 + hheaTable = (HHEATable *) readTable(hheaTag, &length);
1.224 + numOfLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
1.225 + deleteTable(hheaTable);
1.226 +
1.227 + hmtxTable = (HMTXTable *) readTable(hmtxTag, &length);
1.228 + }
1.229 +
1.230 + le_uint16 index = glyph;
1.231 +
1.232 + if (glyph >= numGlyphs) {
1.233 + return 0;
1.234 + }
1.235 +
1.236 + if (glyph >= numOfLongHorMetrics) {
1.237 + index = numOfLongHorMetrics - 1;
1.238 + }
1.239 +
1.240 + return SWAPW(hmtxTable->hMetrics[index].advanceWidth);
1.241 +}
1.242 +
1.243 +