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