40 #include "LEGlyphStorage.h" |
40 #include "LEGlyphStorage.h" |
41 #include "LESwaps.h" |
41 #include "LESwaps.h" |
42 |
42 |
43 U_NAMESPACE_BEGIN |
43 U_NAMESPACE_BEGIN |
44 |
44 |
45 void MorphTableHeader2::process(LEGlyphStorage &glyphStorage, le_int32 typoFlags) const |
45 void MorphTableHeader2::process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage, |
|
46 le_int32 typoFlags, LEErrorCode &success) const |
46 { |
47 { |
47 const ChainHeader2 *chainHeader = chains; |
48 if(LE_FAILURE(success)) return; |
48 le_uint32 chainCount = SWAPL(this->nChains); |
49 |
49 le_uint32 chain; |
50 le_uint32 chainCount = SWAPL(this->nChains); |
50 |
51 LEReferenceTo<ChainHeader2> chainHeader(base, success, &chains[0]); |
51 for (chain = 0; chain < chainCount; chain++) { |
52 /* chainHeader and subtableHeader are implemented as a moving pointer rather than an array dereference |
|
53 * to (slightly) reduce code churn. However, must be careful to preincrement them the 2nd time through. |
|
54 * We don't want to increment them at the end of the loop, as that would attempt to dereference |
|
55 * out of range memory. |
|
56 */ |
|
57 le_uint32 chain; |
|
58 |
|
59 for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain++) { |
|
60 if (chain>0) { |
|
61 le_uint32 chainLength = SWAPL(chainHeader->chainLength); |
|
62 chainHeader.addOffset(chainLength, success); // Don't increment the first time |
|
63 } |
52 FeatureFlags flag = SWAPL(chainHeader->defaultFlags); |
64 FeatureFlags flag = SWAPL(chainHeader->defaultFlags); |
53 le_uint32 chainLength = SWAPL(chainHeader->chainLength); |
|
54 le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries); |
65 le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries); |
55 le_uint32 nSubtables = SWAPL(chainHeader->nSubtables); |
66 le_uint32 nSubtables = SWAPL(chainHeader->nSubtables); |
56 const MorphSubtableHeader2 *subtableHeader = |
67 LEReferenceTo<MorphSubtableHeader2> subtableHeader(chainHeader, |
57 (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]; |
68 success, (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]); |
58 le_uint32 subtable; |
69 le_uint32 subtable; |
|
70 if(LE_FAILURE(success)) break; // malformed table |
59 |
71 |
60 if (typoFlags != 0) { |
72 if (typoFlags != 0) { |
61 le_uint32 featureEntry; |
73 le_uint32 featureEntry; |
62 |
74 LEReferenceToArrayOf<FeatureTableEntry> featureTableRef(chainHeader, success, &chainHeader->featureTable[0], nFeatureEntries); |
|
75 if(LE_FAILURE(success)) break; |
63 // Feature subtables |
76 // Feature subtables |
64 for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) { |
77 for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) { |
65 FeatureTableEntry featureTableEntry = chains->featureTable[featureEntry]; |
78 const FeatureTableEntry &featureTableEntry = featureTableRef(featureEntry, success); |
66 le_int16 featureType = SWAPW(featureTableEntry.featureType); |
79 le_int16 featureType = SWAPW(featureTableEntry.featureType); |
67 le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting); |
80 le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting); |
68 le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags); |
81 le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags); |
69 le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags); |
82 le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags); |
70 switch (featureType) { |
83 switch (featureType) { |
170 break; |
183 break; |
171 } |
184 } |
172 } |
185 } |
173 } |
186 } |
174 |
187 |
175 for (subtable = 0; subtable < nSubtables; subtable++) { |
188 for (subtable = 0; LE_SUCCESS(success) && subtable < nSubtables; subtable++) { |
176 le_uint32 length = SWAPL(subtableHeader->length); |
189 if(subtable>0) { |
|
190 le_uint32 length = SWAPL(subtableHeader->length); |
|
191 subtableHeader.addOffset(length, success); // Don't addOffset for the last entry. |
|
192 } |
177 le_uint32 coverage = SWAPL(subtableHeader->coverage); |
193 le_uint32 coverage = SWAPL(subtableHeader->coverage); |
178 FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures); |
194 FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures); |
179 // should check coverage more carefully... |
195 // should check coverage more carefully... |
180 if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) { |
196 if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) { |
181 subtableHeader->process(glyphStorage); |
197 subtableHeader->process(subtableHeader, glyphStorage, success); |
182 } |
198 } |
183 subtableHeader = (const MorphSubtableHeader2 *) ((char *)subtableHeader + length); |
|
184 } |
199 } |
185 chainHeader = (const ChainHeader2 *)((char *)chainHeader + chainLength); |
|
186 } |
200 } |
187 } |
201 } |
188 |
202 |
189 void MorphSubtableHeader2::process(LEGlyphStorage &glyphStorage) const |
203 void MorphSubtableHeader2::process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const |
190 { |
204 { |
191 SubtableProcessor2 *processor = NULL; |
205 SubtableProcessor2 *processor = NULL; |
192 |
206 |
193 switch (SWAPL(coverage) & scfTypeMask2) |
207 switch (SWAPL(coverage) & scfTypeMask2) |
194 { |
208 { |
195 case mstIndicRearrangement: |
209 case mstIndicRearrangement: |
196 processor = new IndicRearrangementProcessor2(this); |
210 processor = new IndicRearrangementProcessor2(base, success); |
197 break; |
211 break; |
198 |
212 |
199 case mstContextualGlyphSubstitution: |
213 case mstContextualGlyphSubstitution: |
200 processor = new ContextualGlyphSubstitutionProcessor2(this); |
214 processor = new ContextualGlyphSubstitutionProcessor2(base, success); |
201 break; |
215 break; |
202 |
216 |
203 case mstLigatureSubstitution: |
217 case mstLigatureSubstitution: |
204 processor = new LigatureSubstitutionProcessor2(this); |
218 processor = new LigatureSubstitutionProcessor2(base, success); |
205 break; |
219 break; |
206 |
220 |
207 case mstReservedUnused: |
221 case mstReservedUnused: |
208 break; |
222 break; |
209 |
223 |
210 case mstNonContextualGlyphSubstitution: |
224 case mstNonContextualGlyphSubstitution: |
211 processor = NonContextualGlyphSubstitutionProcessor2::createInstance(this); |
225 processor = NonContextualGlyphSubstitutionProcessor2::createInstance(base, success); |
212 break; |
226 break; |
213 |
227 |
214 |
228 |
215 case mstContextualGlyphInsertion: |
229 case mstContextualGlyphInsertion: |
216 processor = new ContextualGlyphInsertionProcessor2(this); |
230 processor = new ContextualGlyphInsertionProcessor2(base, success); |
217 break; |
231 break; |
218 |
232 |
219 default: |
233 default: |
220 break; |
234 return; |
|
235 break; /*NOTREACHED*/ |
221 } |
236 } |
222 |
237 |
223 if (processor != NULL) { |
238 if (processor != NULL) { |
224 processor->process(glyphStorage); |
239 processor->process(glyphStorage, success); |
225 delete processor; |
240 delete processor; |
|
241 } else { |
|
242 if(LE_SUCCESS(success)) { |
|
243 success = LE_MEMORY_ALLOCATION_ERROR; // because ptr is null and we didn't break out. |
|
244 } |
226 } |
245 } |
227 } |
246 } |
228 |
247 |
229 U_NAMESPACE_END |
248 U_NAMESPACE_END |