]> git.saurik.com Git - apple/icu.git/blob - icuSources/layout/PairPositioningSubtables.cpp
ICU-6.2.22.tar.gz
[apple/icu.git] / icuSources / layout / PairPositioningSubtables.cpp
1 /*
2 *
3 * (C) Copyright IBM Corp. 1998-2004 - 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 "GlyphPositionAdjustments.h"
15 #include "OpenTypeUtilities.h"
16 #include "LESwaps.h"
17
18 U_NAMESPACE_BEGIN
19
20 le_uint32 PairPositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
21 {
22 switch(SWAPW(subtableFormat))
23 {
24 case 0:
25 return 0;
26
27 case 1:
28 {
29 const PairPositioningFormat1Subtable *subtable = (const PairPositioningFormat1Subtable *) this;
30
31 return subtable->process(glyphIterator, fontInstance);
32 }
33
34 case 2:
35 {
36 const PairPositioningFormat2Subtable *subtable = (const PairPositioningFormat2Subtable *) this;
37
38 return subtable->process(glyphIterator, fontInstance);
39 }
40
41 default:
42 return 0;
43 }
44 }
45
46 le_uint32 PairPositioningFormat1Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
47 {
48 LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
49 le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
50 GlyphIterator tempIterator(*glyphIterator);
51
52 if (coverageIndex >= 0 && glyphIterator->next()) {
53 Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]);
54 PairSetTable *pairSetTable = (PairSetTable *) ((char *) this + pairSetTableOffset);
55 le_uint16 pairValueCount = SWAPW(pairSetTable->pairValueCount);
56 le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
57 le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
58 le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size;
59 LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
60 const PairValueRecord *pairValueRecord = NULL;
61
62 if (pairValueCount != 0) {
63 pairValueRecord = findPairValueRecord((TTGlyphID) LE_GET_GLYPH(secondGlyph), pairSetTable->pairValueRecordArray, pairValueCount, recordSize);
64 }
65
66 if (pairValueRecord == NULL) {
67 return 0;
68 }
69
70 if (valueFormat1 != 0) {
71 GlyphPositionAdjustment adjustment;
72
73 tempIterator.getCurrGlyphPositionAdjustment(adjustment);
74 pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, adjustment, fontInstance);
75 tempIterator.setCurrGlyphPositionAdjustment(&adjustment);
76 }
77
78 if (valueFormat2 != 0) {
79 const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size);
80 GlyphPositionAdjustment adjustment;
81
82 glyphIterator->getCurrGlyphPositionAdjustment(adjustment);
83 valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, adjustment, fontInstance);
84 glyphIterator->setCurrGlyphPositionAdjustment(&adjustment);
85 }
86
87 return 2;
88 }
89
90 return 0;
91 }
92
93 le_uint32 PairPositioningFormat2Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
94 {
95 LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
96 le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
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 GlyphPositionAdjustment adjustment;
115
116 tempIterator.getCurrGlyphPositionAdjustment(adjustment);
117 class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, adjustment, fontInstance);
118 tempIterator.setCurrGlyphPositionAdjustment(&adjustment);
119 }
120
121 if (valueFormat2 != 0) {
122 const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &class2Record->valueRecord1 + valueRecord1Size);
123 GlyphPositionAdjustment adjustment;
124
125 glyphIterator->getCurrGlyphPositionAdjustment(adjustment);
126 valueRecord2->adjustPosition(SWAPW(valueFormat2), (const char *) this, adjustment, fontInstance);
127 glyphIterator->setCurrGlyphPositionAdjustment(&adjustment);
128 }
129
130 return 2;
131 }
132
133 return 0;
134 }
135
136 const PairValueRecord *PairPositioningFormat1Subtable::findPairValueRecord(TTGlyphID glyphID, const PairValueRecord *records, le_uint16 recordCount, le_uint16 recordSize) const
137 {
138 le_uint8 bit = OpenTypeUtilities::highBit(recordCount);
139 le_uint16 power = 1 << bit;
140 le_uint16 extra = (recordCount - power) * recordSize;
141 le_uint16 probe = power * recordSize;
142 const PairValueRecord *record = records;
143 const PairValueRecord *trial = (const PairValueRecord *) ((char *) record + extra);
144
145 if (SWAPW(trial->secondGlyph) <= glyphID) {
146 record = trial;
147 }
148
149 while (probe > recordSize) {
150 probe >>= 1;
151 trial = (const PairValueRecord *) ((char *) record + probe);
152
153 if (SWAPW(trial->secondGlyph) <= glyphID) {
154 record = trial;
155 }
156 }
157
158 if (SWAPW(record->secondGlyph) == glyphID) {
159 return record;
160 }
161
162 return NULL;
163 }
164
165 U_NAMESPACE_END