3 * (C) Copyright IBM Corp. 1998-2013 - 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(const LEReferenceTo
<PairPositioningSubtable
> &base
, GlyphIterator
*glyphIterator
, const LEFontInstance
*fontInstance
, LEErrorCode
&success
) const
21 switch(SWAPW(subtableFormat
))
28 const LEReferenceTo
<PairPositioningFormat1Subtable
> subtable(base
, success
, (const PairPositioningFormat1Subtable
*) this);
30 if(LE_SUCCESS(success
))
31 return subtable
->process(subtable
, glyphIterator
, fontInstance
, success
);
38 const LEReferenceTo
<PairPositioningFormat2Subtable
> subtable(base
, success
, (const PairPositioningFormat2Subtable
*) this);
40 if(LE_SUCCESS(success
))
41 return subtable
->process(subtable
, glyphIterator
, fontInstance
, success
);
50 le_uint32
PairPositioningFormat1Subtable::process(const LEReferenceTo
<PairPositioningFormat1Subtable
> &base
, GlyphIterator
*glyphIterator
, const LEFontInstance
*fontInstance
, LEErrorCode
&success
) const
52 LEGlyphID firstGlyph
= glyphIterator
->getCurrGlyphID();
53 le_int32 coverageIndex
= getGlyphCoverage(base
, firstGlyph
, success
);
54 GlyphIterator
tempIterator(*glyphIterator
);
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
;
66 if (pairValueCount
!= 0) {
67 pairValueRecord
= findPairValueRecord((TTGlyphID
) LE_GET_GLYPH(secondGlyph
), pairSetTable
->pairValueRecordArray
, pairValueCount
, recordSize
);
70 if (pairValueRecord
== NULL
) {
74 if (valueFormat1
!= 0) {
75 pairValueRecord
->valueRecord1
.adjustPosition(SWAPW(valueFormat1
), (char *) this, tempIterator
, fontInstance
);
78 if (valueFormat2
!= 0) {
79 const ValueRecord
*valueRecord2
= (const ValueRecord
*) ((char *) &pairValueRecord
->valueRecord1
+ valueRecord1Size
);
81 valueRecord2
->adjustPosition(SWAPW(valueFormat2
), (char *) this, *glyphIterator
, fontInstance
);
84 // back up glyphIterator so second glyph can be
85 // first glyph in the next pair
86 glyphIterator
->prev();
93 le_uint32
PairPositioningFormat2Subtable::process(const LEReferenceTo
<PairPositioningFormat2Subtable
> &base
, GlyphIterator
*glyphIterator
, const LEFontInstance
*fontInstance
, LEErrorCode
&success
) const
95 LEGlyphID firstGlyph
= glyphIterator
->getCurrGlyphID();
96 le_int32 coverageIndex
= getGlyphCoverage(base
, firstGlyph
, success
);
97 GlyphIterator
tempIterator(*glyphIterator
);
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
));
113 if (valueFormat1
!= 0) {
114 class2Record
->valueRecord1
.adjustPosition(SWAPW(valueFormat1
), (char *) this, tempIterator
, fontInstance
);
117 if (valueFormat2
!= 0) {
118 const ValueRecord
*valueRecord2
= (const ValueRecord
*) ((char *) &class2Record
->valueRecord1
+ valueRecord1Size
);
120 valueRecord2
->adjustPosition(SWAPW(valueFormat2
), (const char *) this, *glyphIterator
, fontInstance
);
123 // back up glyphIterator so second glyph can be
124 // first glyph in the next pair
125 glyphIterator
->prev();
132 const PairValueRecord
*PairPositioningFormat1Subtable::findPairValueRecord(TTGlyphID glyphID
, const PairValueRecord
*records
, le_uint16 recordCount
, le_uint16 recordSize
) const
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
;
140 for(le_int32 r
= 0; r
< recordCount
; r
+= 1) {
141 if (SWAPW(record
->secondGlyph
) == glyphID
) {
145 record
= (const PairValueRecord
*) ((char *) record
+ recordSize
);
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
);
155 if (SWAPW(trial
->secondGlyph
) <= glyphID
) {
159 while (probe
> recordSize
) {
161 trial
= (const PairValueRecord
*) ((char *) record
+ probe
);
163 if (SWAPW(trial
->secondGlyph
) <= glyphID
) {
168 if (SWAPW(record
->secondGlyph
) == glyphID
) {