45 #define SignBit(m) ((ExtendedComplement(m) >> 1) & (le_int32)(m)) |
45 #define SignBit(m) ((ExtendedComplement(m) >> 1) & (le_int32)(m)) |
46 #define SignExtend(v,m) (((v) & SignBit(m))? ((v) | ExtendedComplement(m)): (v)) |
46 #define SignExtend(v,m) (((v) & SignBit(m))? ((v) | ExtendedComplement(m)): (v)) |
47 |
47 |
48 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor2) |
48 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor2) |
49 |
49 |
50 LigatureSubstitutionProcessor2::LigatureSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader) |
50 LigatureSubstitutionProcessor2::LigatureSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success) |
51 : StateTableProcessor2(morphSubtableHeader) |
51 : StateTableProcessor2(morphSubtableHeader, success), |
|
52 ligActionOffset(0), |
|
53 ligatureSubstitutionHeader(morphSubtableHeader, success), componentOffset(0), ligatureOffset(0), entryTable() |
52 { |
54 { |
53 ligatureSubstitutionHeader = (const LigatureSubstitutionHeader2 *) morphSubtableHeader; |
55 if (LE_FAILURE(success)) return; |
|
56 |
54 ligActionOffset = SWAPL(ligatureSubstitutionHeader->ligActionOffset); |
57 ligActionOffset = SWAPL(ligatureSubstitutionHeader->ligActionOffset); |
55 componentOffset = SWAPL(ligatureSubstitutionHeader->componentOffset); |
58 componentOffset = SWAPL(ligatureSubstitutionHeader->componentOffset); |
56 ligatureOffset = SWAPL(ligatureSubstitutionHeader->ligatureOffset); |
59 ligatureOffset = SWAPL(ligatureSubstitutionHeader->ligatureOffset); |
57 |
60 |
58 entryTable = (const LigatureSubstitutionStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset); |
61 entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY); |
59 } |
62 } |
60 |
63 |
61 LigatureSubstitutionProcessor2::~LigatureSubstitutionProcessor2() |
64 LigatureSubstitutionProcessor2::~LigatureSubstitutionProcessor2() |
62 { |
65 { |
63 } |
66 } |
65 void LigatureSubstitutionProcessor2::beginStateTable() |
68 void LigatureSubstitutionProcessor2::beginStateTable() |
66 { |
69 { |
67 m = -1; |
70 m = -1; |
68 } |
71 } |
69 |
72 |
70 le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index) |
73 le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success) |
71 { |
74 { |
72 const LigatureSubstitutionStateEntry2 *entry = &entryTable[index]; |
75 const LigatureSubstitutionStateEntry2 *entry = entryTable.getAlias(index, success); |
|
76 if(LE_FAILURE(success)) return 0; |
|
77 |
73 le_uint16 nextStateIndex = SWAPW(entry->nextStateIndex); |
78 le_uint16 nextStateIndex = SWAPW(entry->nextStateIndex); |
74 le_uint16 flags = SWAPW(entry->entryFlags); |
79 le_uint16 flags = SWAPW(entry->entryFlags); |
75 le_uint16 ligActionIndex = SWAPW(entry->ligActionIndex); |
80 le_uint16 ligActionIndex = SWAPW(entry->ligActionIndex); |
76 |
81 |
77 if (flags & lsfSetComponent) { |
82 if (flags & lsfSetComponent) { |
79 m = 0; |
84 m = 0; |
80 } |
85 } |
81 componentStack[m] = currGlyph; |
86 componentStack[m] = currGlyph; |
82 } else if ( m == -1) { |
87 } else if ( m == -1) { |
83 // bad font- skip this glyph. |
88 // bad font- skip this glyph. |
84 LE_DEBUG_BAD_FONT("m==-1") |
89 //LE_DEBUG_BAD_FONT("m==-1 (componentCount went negative)") |
85 currGlyph+= dir; |
90 currGlyph+= dir; |
86 return nextStateIndex; |
91 return nextStateIndex; |
87 } |
92 } |
88 |
93 |
89 ByteOffset actionOffset = flags & lsfPerformAction; |
94 ByteOffset actionOffset = flags & lsfPerformAction; |
90 |
95 |
91 if (actionOffset != 0) { |
96 if (actionOffset != 0) { |
92 const LigatureActionEntry *ap = (const LigatureActionEntry *) ((char *) &ligatureSubstitutionHeader->stHeader + ligActionOffset) + ligActionIndex; |
97 LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset |
93 const TTGlyphID *ligatureTable = (const TTGlyphID *) ((char *) &ligatureSubstitutionHeader->stHeader + ligatureOffset); |
98 ap.addObject(ligActionIndex - 1, success); // index offset ( one before the actual start, because we will pre-increment) |
|
99 LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY); |
94 LigatureActionEntry action; |
100 LigatureActionEntry action; |
95 le_int32 offset, i = 0; |
101 le_int32 offset, i = 0; |
96 le_int32 stack[nComponents]; |
102 le_int32 stack[nComponents]; |
97 le_int16 mm = -1; |
103 le_int16 mm = -1; |
98 |
104 |
99 const le_uint16 *componentTable = (const le_uint16 *)((char *) &ligatureSubstitutionHeader->stHeader + componentOffset); |
105 LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY); |
100 |
106 if(LE_FAILURE(success)) { |
101 const le_uint16 *tableEnd = (const le_uint16 *)((char *) &ligatureSubstitutionHeader + SWAPL(ligatureSubstitutionHeader->length)); |
|
102 |
|
103 // Check if the font is internally consistent |
|
104 if(tableEnd < (const le_uint16*)&ligatureSubstitutionHeader // stated end wrapped around? |
|
105 || componentTable > tableEnd) { // offset past end of stated length? |
|
106 currGlyph+= dir; |
107 currGlyph+= dir; |
107 LE_DEBUG_BAD_FONT("ligatureSubstHeader off end of table") |
|
108 return nextStateIndex; // get out! bad font |
108 return nextStateIndex; // get out! bad font |
109 } |
109 } |
110 |
110 |
111 do { |
111 do { |
112 le_uint32 componentGlyph = componentStack[m--]; // pop off |
112 le_uint32 componentGlyph = componentStack[m--]; // pop off |
113 |
113 |
114 action = SWAPL(*ap++); |
114 ap.addObject(success); |
|
115 action = SWAPL(*ap.getAlias()); |
115 |
116 |
116 if (m < 0) { |
117 if (m < 0) { |
117 m = nComponents - 1; |
118 m = nComponents - 1; |
118 } |
119 } |
119 |
120 |
122 if(componentGlyph > glyphStorage.getGlyphCount()) { |
123 if(componentGlyph > glyphStorage.getGlyphCount()) { |
123 LE_DEBUG_BAD_FONT("preposterous componentGlyph"); |
124 LE_DEBUG_BAD_FONT("preposterous componentGlyph"); |
124 currGlyph+= dir; |
125 currGlyph+= dir; |
125 return nextStateIndex; // get out! bad font |
126 return nextStateIndex; // get out! bad font |
126 } |
127 } |
127 i += SWAPW(componentTable[LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask))]); |
128 i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success)); |
128 |
129 |
129 if (action & (lafLast | lafStore)) { |
130 if (action & (lafLast | lafStore)) { |
130 TTGlyphID ligatureGlyph = SWAPW(ligatureTable[i]); |
131 TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success)); |
131 glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); |
132 glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); |
132 if(mm==nComponents) { |
133 if(mm==nComponents) { |
133 LE_DEBUG_BAD_FONT("exceeded nComponents"); |
134 LE_DEBUG_BAD_FONT("exceeded nComponents"); |
134 mm--; // don't overrun the stack. |
135 mm--; // don't overrun the stack. |
135 } |
136 } |