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