3 * (C) Copyright IBM Corp. 1998-2006 - All Rights Reserved
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"
19 le_uint32
PairPositioningSubtable::process(GlyphIterator
*glyphIterator
, const LEFontInstance
*fontInstance
) const
21 switch(SWAPW(subtableFormat
))
28 const PairPositioningFormat1Subtable
*subtable
= (const PairPositioningFormat1Subtable
*) this;
30 return subtable
->process(glyphIterator
, fontInstance
);
35 const PairPositioningFormat2Subtable
*subtable
= (const PairPositioningFormat2Subtable
*) this;
37 return subtable
->process(glyphIterator
, fontInstance
);
45 le_uint32
PairPositioningFormat1Subtable::process(GlyphIterator
*glyphIterator
, const LEFontInstance
*fontInstance
) const
47 LEGlyphID firstGlyph
= glyphIterator
->getCurrGlyphID();
48 le_int32 coverageIndex
= getGlyphCoverage(firstGlyph
);
49 GlyphIterator
tempIterator(*glyphIterator
);
51 if (coverageIndex
>= 0 && glyphIterator
->next()) {
52 Offset pairSetTableOffset
= SWAPW(pairSetTableOffsetArray
[coverageIndex
]);
53 PairSetTable
*pairSetTable
= (PairSetTable
*) ((char *) this + pairSetTableOffset
);
54 le_uint16 pairValueCount
= SWAPW(pairSetTable
->pairValueCount
);
55 le_int16 valueRecord1Size
= ValueRecord::getSize(SWAPW(valueFormat1
));
56 le_int16 valueRecord2Size
= ValueRecord::getSize(SWAPW(valueFormat2
));
57 le_int16 recordSize
= sizeof(PairValueRecord
) - sizeof(ValueRecord
) + valueRecord1Size
+ valueRecord2Size
;
58 LEGlyphID secondGlyph
= glyphIterator
->getCurrGlyphID();
59 const PairValueRecord
*pairValueRecord
= NULL
;
61 if (pairValueCount
!= 0) {
62 pairValueRecord
= findPairValueRecord((TTGlyphID
) LE_GET_GLYPH(secondGlyph
), pairSetTable
->pairValueRecordArray
, pairValueCount
, recordSize
);
65 if (pairValueRecord
== NULL
) {
69 if (valueFormat1
!= 0) {
70 pairValueRecord
->valueRecord1
.adjustPosition(SWAPW(valueFormat1
), (char *) this, tempIterator
, fontInstance
);
73 if (valueFormat2
!= 0) {
74 const ValueRecord
*valueRecord2
= (const ValueRecord
*) ((char *) &pairValueRecord
->valueRecord1
+ valueRecord1Size
);
76 valueRecord2
->adjustPosition(SWAPW(valueFormat2
), (char *) this, *glyphIterator
, fontInstance
);
79 // back up glyphIterator so second glyph can be
80 // first glyph in the next pair
81 glyphIterator
->prev();
88 le_uint32
PairPositioningFormat2Subtable::process(GlyphIterator
*glyphIterator
, const LEFontInstance
*fontInstance
) const
90 LEGlyphID firstGlyph
= glyphIterator
->getCurrGlyphID();
91 le_int32 coverageIndex
= getGlyphCoverage(firstGlyph
);
92 GlyphIterator
tempIterator(*glyphIterator
);
94 if (coverageIndex
>= 0 && glyphIterator
->next()) {
95 LEGlyphID secondGlyph
= glyphIterator
->getCurrGlyphID();
96 const ClassDefinitionTable
*classDef1
= (const ClassDefinitionTable
*) ((char *) this + SWAPW(classDef1Offset
));
97 const ClassDefinitionTable
*classDef2
= (const ClassDefinitionTable
*) ((char *) this + SWAPW(classDef2Offset
));
98 le_int32 class1
= classDef1
->getGlyphClass(firstGlyph
);
99 le_int32 class2
= classDef2
->getGlyphClass(secondGlyph
);
100 le_int16 valueRecord1Size
= ValueRecord::getSize(SWAPW(valueFormat1
));
101 le_int16 valueRecord2Size
= ValueRecord::getSize(SWAPW(valueFormat2
));
102 le_int16 class2RecordSize
= valueRecord1Size
+ valueRecord2Size
;
103 le_int16 class1RecordSize
= class2RecordSize
* SWAPW(class2Count
);
104 const Class1Record
*class1Record
= (const Class1Record
*) ((char *) class1RecordArray
+ (class1RecordSize
* class1
));
105 const Class2Record
*class2Record
= (const Class2Record
*) ((char *) class1Record
->class2RecordArray
+ (class2RecordSize
* class2
));
108 if (valueFormat1
!= 0) {
109 class2Record
->valueRecord1
.adjustPosition(SWAPW(valueFormat1
), (char *) this, tempIterator
, fontInstance
);
112 if (valueFormat2
!= 0) {
113 const ValueRecord
*valueRecord2
= (const ValueRecord
*) ((char *) &class2Record
->valueRecord1
+ valueRecord1Size
);
115 valueRecord2
->adjustPosition(SWAPW(valueFormat2
), (const char *) this, *glyphIterator
, fontInstance
);
118 // back up glyphIterator so second glyph can be
119 // first glyph in the next pair
120 glyphIterator
->prev();
127 const PairValueRecord
*PairPositioningFormat1Subtable::findPairValueRecord(TTGlyphID glyphID
, const PairValueRecord
*records
, le_uint16 recordCount
, le_uint16 recordSize
) const
130 // The OpenType spec. says that the ValueRecord table is
131 // sorted by secondGlyph. Unfortunately, there are fonts
132 // around that have an unsorted ValueRecord table.
133 const PairValueRecord
*record
= records
;
135 for(le_int32 r
= 0; r
< recordCount
; r
+= 1) {
136 if (SWAPW(record
->secondGlyph
) == glyphID
) {
140 record
= (const PairValueRecord
*) ((char *) record
+ recordSize
);
143 le_uint8 bit
= OpenTypeUtilities::highBit(recordCount
);
144 le_uint16 power
= 1 << bit
;
145 le_uint16 extra
= (recordCount
- power
) * recordSize
;
146 le_uint16 probe
= power
* recordSize
;
147 const PairValueRecord
*record
= records
;
148 const PairValueRecord
*trial
= (const PairValueRecord
*) ((char *) record
+ extra
);
150 if (SWAPW(trial
->secondGlyph
) <= glyphID
) {
154 while (probe
> recordSize
) {
156 trial
= (const PairValueRecord
*) ((char *) record
+ probe
);
158 if (SWAPW(trial
->secondGlyph
) <= glyphID
) {
163 if (SWAPW(record
->secondGlyph
) == glyphID
) {