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 
17 U_NAMESPACE_BEGIN
18 
process(const LEReferenceTo<PairPositioningSubtable> & base,GlyphIterator * glyphIterator,const LEFontInstance * fontInstance,LEErrorCode & success) const19 le_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 
process(const LEReferenceTo<PairPositioningFormat1Subtable> & base,GlyphIterator * glyphIterator,const LEFontInstance * fontInstance,LEErrorCode & success) const50 le_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 
process(const LEReferenceTo<PairPositioningFormat2Subtable> & base,GlyphIterator * glyphIterator,const LEFontInstance * fontInstance,LEErrorCode & success) const93 le_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 
findPairValueRecord(TTGlyphID glyphID,const PairValueRecord * records,le_uint16 recordCount,le_uint16 recordSize) const132 const 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 
176 U_NAMESPACE_END
177