43 |
43 |
44 StateTableProcessor2::StateTableProcessor2() |
44 StateTableProcessor2::StateTableProcessor2() |
45 { |
45 { |
46 } |
46 } |
47 |
47 |
48 StateTableProcessor2::StateTableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader) |
48 StateTableProcessor2::StateTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success) |
49 : SubtableProcessor2(morphSubtableHeader) |
49 : SubtableProcessor2(morphSubtableHeader, success), stateTableHeader(morphSubtableHeader, success), |
50 { |
50 stHeader(stateTableHeader, success, (const StateTableHeader2*)&stateTableHeader->stHeader), |
51 stateTableHeader = (const MorphStateTableHeader2 *) morphSubtableHeader; |
51 nClasses(0), classTableOffset(0), stateArrayOffset(0), entryTableOffset(0), classTable(), format(0), |
52 nClasses = SWAPL(stateTableHeader->stHeader.nClasses); |
52 stateArray() |
53 classTableOffset = SWAPL(stateTableHeader->stHeader.classTableOffset); |
53 { |
54 stateArrayOffset = SWAPL(stateTableHeader->stHeader.stateArrayOffset); |
54 if (LE_FAILURE(success)) { |
55 entryTableOffset = SWAPL(stateTableHeader->stHeader.entryTableOffset); |
55 return; |
56 |
56 } |
57 classTable = (LookupTable *) ((char *) &stateTableHeader->stHeader + classTableOffset); |
57 nClasses = SWAPL(stHeader->nClasses); |
58 format = SWAPW(classTable->format); |
58 classTableOffset = SWAPL(stHeader->classTableOffset); |
59 |
59 stateArrayOffset = SWAPL(stHeader->stateArrayOffset); |
60 stateArray = (const EntryTableIndex2 *) ((char *) &stateTableHeader->stHeader + stateArrayOffset); |
60 entryTableOffset = SWAPL(stHeader->entryTableOffset); |
|
61 |
|
62 classTable = LEReferenceTo<LookupTable>(stHeader, success, classTableOffset); |
|
63 format = SWAPW(classTable->format); |
|
64 |
|
65 stateArray = LEReferenceToArrayOf<EntryTableIndex2>(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY); |
61 } |
66 } |
62 |
67 |
63 StateTableProcessor2::~StateTableProcessor2() |
68 StateTableProcessor2::~StateTableProcessor2() |
64 { |
69 { |
65 } |
70 } |
66 |
71 |
67 void StateTableProcessor2::process(LEGlyphStorage &glyphStorage) |
72 void StateTableProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success) |
68 { |
73 { |
|
74 if (LE_FAILURE(success)) return; |
69 // Start at state 0 |
75 // Start at state 0 |
70 // XXX: How do we know when to start at state 1? |
76 // XXX: How do we know when to start at state 1? |
71 le_uint16 currentState = 0; |
77 le_uint16 currentState = 0; |
72 le_int32 glyphCount = glyphStorage.getGlyphCount(); |
78 le_int32 glyphCount = glyphStorage.getGlyphCount(); |
73 |
79 |
83 |
89 |
84 beginStateTable(); |
90 beginStateTable(); |
85 switch (format) { |
91 switch (format) { |
86 case ltfSimpleArray: { |
92 case ltfSimpleArray: { |
87 #ifdef TEST_FORMAT |
93 #ifdef TEST_FORMAT |
88 SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) classTable; |
94 LEReferenceTo<SimpleArrayLookupTable> lookupTable0(classTable, success); |
89 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
95 if(LE_FAILURE(success)) break; |
90 if(LE_STATE_PATIENCE_DECR()) { |
96 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
|
97 if (LE_FAILURE(success)) break; |
|
98 if (LE_STATE_PATIENCE_DECR()) { |
91 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") |
99 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") |
92 break; // patience exceeded. |
100 break; // patience exceeded. |
93 } |
101 } |
94 LookupValue classCode = classCodeOOB; |
102 LookupValue classCode = classCodeOOB; |
95 if (currGlyph == glyphCount || currGlyph == -1) { |
103 if (currGlyph == glyphCount || currGlyph == -1) { |
103 classCode = classCodeDEL; |
111 classCode = classCodeDEL; |
104 } else { |
112 } else { |
105 classCode = SWAPW(lookupTable0->valueArray[gid]); |
113 classCode = SWAPW(lookupTable0->valueArray[gid]); |
106 } |
114 } |
107 } |
115 } |
108 EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); |
116 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); |
109 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); |
117 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); |
110 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset |
118 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset |
111 LE_STATE_PATIENCE_INCR(currGlyph); |
119 LE_STATE_PATIENCE_INCR(currGlyph); |
112 } |
120 } |
113 #endif |
121 #endif |
114 break; |
122 break; |
115 } |
123 } |
116 case ltfSegmentSingle: { |
124 case ltfSegmentSingle: { |
117 SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) classTable; |
125 LEReferenceTo<SegmentSingleLookupTable> lookupTable2(classTable, success); |
118 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
126 if(LE_FAILURE(success)) break; |
119 if(LE_STATE_PATIENCE_DECR()) { |
127 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
120 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") |
128 if (LE_FAILURE(success)) break; |
|
129 if (LE_STATE_PATIENCE_DECR()) { |
|
130 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") |
121 break; // patience exceeded. |
131 break; // patience exceeded. |
122 } |
132 } |
123 LookupValue classCode = classCodeOOB; |
133 LookupValue classCode = classCodeOOB; |
124 if (currGlyph == glyphCount || currGlyph == -1) { |
134 if (currGlyph == glyphCount || currGlyph == -1) { |
125 // XXX: How do we handle EOT vs. EOL? |
135 // XXX: How do we handle EOT vs. EOL? |
129 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); |
139 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); |
130 |
140 |
131 if (glyphCode == 0xFFFF) { |
141 if (glyphCode == 0xFFFF) { |
132 classCode = classCodeDEL; |
142 classCode = classCodeDEL; |
133 } else { |
143 } else { |
134 const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid); |
144 const LookupSegment *segment = |
135 if (segment != NULL) { |
145 lookupTable2->lookupSegment(lookupTable2, lookupTable2->segments, gid, success); |
|
146 if (segment != NULL && LE_SUCCESS(success)) { |
136 classCode = SWAPW(segment->value); |
147 classCode = SWAPW(segment->value); |
137 } |
148 } |
138 } |
149 } |
139 } |
150 } |
140 EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); |
151 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses,success)); |
141 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); |
152 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); |
142 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); |
153 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); |
143 LE_STATE_PATIENCE_INCR(currGlyph); |
154 LE_STATE_PATIENCE_INCR(currGlyph); |
144 } |
155 } |
145 break; |
156 break; |
146 } |
157 } |
147 case ltfSegmentArray: { |
158 case ltfSegmentArray: { |
148 //printf("Lookup Table Format4: specific interpretation needed!\n"); |
159 //printf("Lookup Table Format4: specific interpretation needed!\n"); |
149 break; |
160 break; |
150 } |
161 } |
151 case ltfSingleTable: { |
162 case ltfSingleTable: { |
152 SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) classTable; |
163 LEReferenceTo<SingleTableLookupTable> lookupTable6(classTable, success); |
153 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
164 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
154 if(LE_STATE_PATIENCE_DECR()) { |
165 if (LE_FAILURE(success)) break; |
|
166 if (LE_STATE_PATIENCE_DECR()) { |
155 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") |
167 LE_DEBUG_BAD_FONT("patience exceeded - state table not moving") |
156 break; // patience exceeded. |
168 break; // patience exceeded. |
157 } |
169 } |
158 LookupValue classCode = classCodeOOB; |
170 LookupValue classCode = classCodeOOB; |
159 if (currGlyph == glyphCount || currGlyph == -1) { |
171 if (currGlyph == glyphCount || currGlyph == -1) { |
168 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); |
180 TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); |
169 |
181 |
170 if (glyphCode == 0xFFFF) { |
182 if (glyphCode == 0xFFFF) { |
171 classCode = classCodeDEL; |
183 classCode = classCodeDEL; |
172 } else { |
184 } else { |
173 const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6->entries, gid); |
185 const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6, lookupTable6->entries, gid, success); |
174 if (segment != NULL) { |
186 if (segment != NULL) { |
175 classCode = SWAPW(segment->value); |
187 classCode = SWAPW(segment->value); |
176 } |
188 } |
177 } |
189 } |
178 } |
190 } |
179 EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); |
191 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); |
180 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); |
192 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); |
181 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); |
193 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); |
182 LE_STATE_PATIENCE_INCR(currGlyph); |
194 LE_STATE_PATIENCE_INCR(currGlyph); |
183 } |
195 } |
184 break; |
196 break; |
185 } |
197 } |
186 case ltfTrimmedArray: { |
198 case ltfTrimmedArray: { |
187 TrimmedArrayLookupTable *lookupTable8 = (TrimmedArrayLookupTable *) classTable; |
199 LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(classTable, success); |
|
200 if (LE_FAILURE(success)) break; |
188 TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph); |
201 TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph); |
189 TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount); |
202 TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount); |
190 |
203 |
191 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
204 while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) { |
192 if(LE_STATE_PATIENCE_DECR()) { |
205 if(LE_STATE_PATIENCE_DECR()) { |
204 classCode = classCodeDEL; |
217 classCode = classCodeDEL; |
205 } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) { |
218 } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) { |
206 classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]); |
219 classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]); |
207 } |
220 } |
208 } |
221 } |
209 EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]); |
222 EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success)); |
210 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); |
223 LE_STATE_PATIENCE_CURR(le_int32, currGlyph); |
211 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); |
224 currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success); |
212 LE_STATE_PATIENCE_INCR(currGlyph); |
225 LE_STATE_PATIENCE_INCR(currGlyph); |
213 } |
226 } |
214 break; |
227 break; |
215 } |
228 } |
216 default: |
229 default: |