1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/*
*
* (C) Copyright IBM Corp. 1998-2006 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "LEFontInstance.h"
#include "OpenTypeTables.h"
#include "GlyphPositioningTables.h"
#include "PairPositioningSubtables.h"
#include "ValueRecords.h"
#include "GlyphIterator.h"
#include "OpenTypeUtilities.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
le_uint32 PairPositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
{
switch(SWAPW(subtableFormat))
{
case 0:
return 0;
case 1:
{
const PairPositioningFormat1Subtable *subtable = (const PairPositioningFormat1Subtable *) this;
return subtable->process(glyphIterator, fontInstance);
}
case 2:
{
const PairPositioningFormat2Subtable *subtable = (const PairPositioningFormat2Subtable *) this;
return subtable->process(glyphIterator, fontInstance);
}
default:
return 0;
}
}
le_uint32 PairPositioningFormat1Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
{
LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
GlyphIterator tempIterator(*glyphIterator);
if (coverageIndex >= 0 && glyphIterator->next()) {
Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]);
PairSetTable *pairSetTable = (PairSetTable *) ((char *) this + pairSetTableOffset);
le_uint16 pairValueCount = SWAPW(pairSetTable->pairValueCount);
le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size;
LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
const PairValueRecord *pairValueRecord = NULL;
if (pairValueCount != 0) {
pairValueRecord = findPairValueRecord((TTGlyphID) LE_GET_GLYPH(secondGlyph), pairSetTable->pairValueRecordArray, pairValueCount, recordSize);
}
if (pairValueRecord == NULL) {
return 0;
}
if (valueFormat1 != 0) {
pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance);
}
if (valueFormat2 != 0) {
const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size);
valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, *glyphIterator, fontInstance);
}
// back up glyphIterator so second glyph can be
// first glyph in the next pair
glyphIterator->prev();
return 1;
}
return 0;
}
le_uint32 PairPositioningFormat2Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
{
LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
GlyphIterator tempIterator(*glyphIterator);
if (coverageIndex >= 0 && glyphIterator->next()) {
LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
const ClassDefinitionTable *classDef1 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef1Offset));
const ClassDefinitionTable *classDef2 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef2Offset));
le_int32 class1 = classDef1->getGlyphClass(firstGlyph);
le_int32 class2 = classDef2->getGlyphClass(secondGlyph);
le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
le_int16 class2RecordSize = valueRecord1Size + valueRecord2Size;
le_int16 class1RecordSize = class2RecordSize * SWAPW(class2Count);
const Class1Record *class1Record = (const Class1Record *) ((char *) class1RecordArray + (class1RecordSize * class1));
const Class2Record *class2Record = (const Class2Record *) ((char *) class1Record->class2RecordArray + (class2RecordSize * class2));
if (valueFormat1 != 0) {
class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance);
}
if (valueFormat2 != 0) {
const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &class2Record->valueRecord1 + valueRecord1Size);
valueRecord2->adjustPosition(SWAPW(valueFormat2), (const char *) this, *glyphIterator, fontInstance);
}
// back up glyphIterator so second glyph can be
// first glyph in the next pair
glyphIterator->prev();
return 1;
}
return 0;
}
const PairValueRecord *PairPositioningFormat1Subtable::findPairValueRecord(TTGlyphID glyphID, const PairValueRecord *records, le_uint16 recordCount, le_uint16 recordSize) const
{
#if 1
// The OpenType spec. says that the ValueRecord table is
// sorted by secondGlyph. Unfortunately, there are fonts
// around that have an unsorted ValueRecord table.
const PairValueRecord *record = records;
for(le_int32 r = 0; r < recordCount; r += 1) {
if (SWAPW(record->secondGlyph) == glyphID) {
return record;
}
record = (const PairValueRecord *) ((char *) record + recordSize);
}
#else
le_uint8 bit = OpenTypeUtilities::highBit(recordCount);
le_uint16 power = 1 << bit;
le_uint16 extra = (recordCount - power) * recordSize;
le_uint16 probe = power * recordSize;
const PairValueRecord *record = records;
const PairValueRecord *trial = (const PairValueRecord *) ((char *) record + extra);
if (SWAPW(trial->secondGlyph) <= glyphID) {
record = trial;
}
while (probe > recordSize) {
probe >>= 1;
trial = (const PairValueRecord *) ((char *) record + probe);
if (SWAPW(trial->secondGlyph) <= glyphID) {
record = trial;
}
}
if (SWAPW(record->secondGlyph) == glyphID) {
return record;
}
#endif
return NULL;
}
U_NAMESPACE_END
|