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