87 |
87 |
88 GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments, |
88 GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments, |
89 rightToLeft, 0, 0, glyphDefinitionTableHeader); |
89 rightToLeft, 0, 0, glyphDefinitionTableHeader); |
90 le_int32 newGlyphCount = glyphCount; |
90 le_int32 newGlyphCount = glyphCount; |
91 |
91 |
92 for (le_uint16 order = 0; order < lookupOrderCount; order += 1) { |
92 for (le_uint16 order = 0; order < lookupOrderCount && LE_SUCCESS(success); order += 1) { |
93 le_uint16 lookup = lookupOrderArray[order]; |
93 le_uint16 lookup = lookupOrderArray[order]; |
94 FeatureMask selectMask = lookupSelectArray[lookup]; |
94 FeatureMask selectMask = lookupSelectArray[lookup]; |
95 |
95 |
96 if (selectMask != 0) { |
96 if (selectMask != 0) { |
97 const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup); |
97 const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookup, success); |
98 if (!lookupTable) { |
98 if (!lookupTable.isValid() ||LE_FAILURE(success) ) { |
99 continue; |
99 continue; |
100 } |
100 } |
101 le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); |
101 le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); |
102 |
102 |
103 glyphIterator.reset(lookupFlags, selectMask); |
103 glyphIterator.reset(lookupFlags, selectMask); |
104 |
104 |
105 while (glyphIterator.findFeatureTag()) { |
105 while (glyphIterator.findFeatureTag()) { |
106 applyLookupTable(lookupTable, &glyphIterator, fontInstance, success); |
106 applyLookupTable(lookupTable, &glyphIterator, fontInstance, success); // TODO |
107 if (LE_FAILURE(success)) { |
107 if (LE_FAILURE(success)) { |
108 return 0; |
108 return 0; |
109 } |
109 } |
110 } |
110 } |
111 |
111 |
121 { |
121 { |
122 if (LE_FAILURE(success)) { |
122 if (LE_FAILURE(success)) { |
123 return 0; |
123 return 0; |
124 } |
124 } |
125 |
125 |
126 const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex); |
126 const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookupTableIndex, success); |
127 if (lookupTable == NULL) { |
127 if (!lookupTable.isValid()) { |
128 success = LE_INTERNAL_ERROR; |
128 success = LE_INTERNAL_ERROR; |
129 return 0; |
129 return 0; |
130 } |
130 } |
131 le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); |
131 le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); |
132 GlyphIterator tempIterator(*glyphIterator, lookupFlags); |
132 GlyphIterator tempIterator(*glyphIterator, lookupFlags); |
133 le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success); |
133 le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success); |
134 |
134 |
135 return delta; |
135 return delta; |
136 } |
136 } |
137 |
137 |
138 le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, FeatureMask featureMask, le_int32 order) |
138 le_int32 LookupProcessor::selectLookups(const LEReferenceTo<FeatureTable> &featureTable, FeatureMask featureMask, le_int32 order, LEErrorCode &success) |
139 { |
139 { |
140 le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0; |
140 le_uint16 lookupCount = featureTable.isValid()? SWAPW(featureTable->lookupCount) : 0; |
141 le_int32 store = order; |
141 le_int32 store = order; |
142 |
142 |
143 for (le_uint16 lookup = 0; lookup < lookupCount; lookup += 1) { |
143 LEReferenceToArrayOf<le_uint16> lookupListIndexArray(featureTable, success, featureTable->lookupListIndexArray, lookupCount); |
144 le_uint16 lookupListIndex = SWAPW(featureTable->lookupListIndexArray[lookup]); |
144 |
145 if (lookupListIndex >= lookupSelectCount) { |
145 for (le_uint16 lookup = 0; LE_SUCCESS(success) && lookup < lookupCount; lookup += 1) { |
146 continue; |
146 le_uint16 lookupListIndex = SWAPW(lookupListIndexArray.getObject(lookup,success)); |
147 } |
147 if (lookupListIndex >= lookupSelectCount) { |
148 |
148 continue; |
149 lookupSelectArray[lookupListIndex] |= featureMask; |
149 } |
150 lookupOrderArray[store++] = lookupListIndex; |
150 |
|
151 lookupSelectArray[lookupListIndex] |= featureMask; |
|
152 lookupOrderArray[store++] = lookupListIndex; |
151 } |
153 } |
152 |
154 |
153 return store - order; |
155 return store - order; |
154 } |
156 } |
155 |
157 |
156 LookupProcessor::LookupProcessor(const char *baseAddress, |
158 LookupProcessor::LookupProcessor(const LETableReference &baseAddress, |
157 Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset, |
159 Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset, |
158 LETag scriptTag, LETag languageTag, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool orderFeatures, |
160 LETag scriptTag, LETag languageTag, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool orderFeatures, |
159 LEErrorCode& success) |
161 LEErrorCode& success) |
160 : lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL), lookupSelectCount(0), |
162 : lookupListTable(), featureListTable(), lookupSelectArray(NULL), lookupSelectCount(0), |
161 lookupOrderArray(NULL), lookupOrderCount(0) |
163 lookupOrderArray(NULL), lookupOrderCount(0), fReference(baseAddress) |
162 { |
164 { |
163 const ScriptListTable *scriptListTable = NULL; |
165 LEReferenceTo<ScriptListTable> scriptListTable; |
164 const LangSysTable *langSysTable = NULL; |
166 LEReferenceTo<LangSysTable> langSysTable; |
165 le_uint16 featureCount = 0; |
167 le_uint16 featureCount = 0; |
166 le_uint16 lookupListCount = 0; |
168 le_uint16 lookupListCount = 0; |
167 le_uint16 requiredFeatureIndex; |
169 le_uint16 requiredFeatureIndex; |
168 |
170 |
169 if (LE_FAILURE(success)) { |
171 if (LE_FAILURE(success)) { |
170 return; |
172 return; |
171 } |
173 } |
172 |
174 |
173 if (scriptListOffset != 0) { |
175 if (scriptListOffset != 0) { |
174 scriptListTable = (const ScriptListTable *) (baseAddress + scriptListOffset); |
176 scriptListTable = LEReferenceTo<ScriptListTable>(baseAddress, success, scriptListOffset); |
175 langSysTable = scriptListTable->findLanguage(scriptTag, languageTag); |
177 langSysTable = scriptListTable->findLanguage(scriptListTable, scriptTag, languageTag, success); |
176 |
178 |
177 if (langSysTable != 0) { |
179 if (langSysTable.isValid() && LE_SUCCESS(success)) { |
178 featureCount = SWAPW(langSysTable->featureCount); |
180 featureCount = SWAPW(langSysTable->featureCount); |
179 } |
181 } |
180 } |
182 } |
181 |
183 |
182 if (featureListOffset != 0) { |
184 if (featureListOffset != 0) { |
183 featureListTable = (const FeatureListTable *) (baseAddress + featureListOffset); |
185 featureListTable = LEReferenceTo<FeatureListTable>(baseAddress, success, featureListOffset); |
184 } |
186 } |
185 |
187 |
186 if (lookupListOffset != 0) { |
188 if (lookupListOffset != 0) { |
187 lookupListTable = (const LookupListTable *) (baseAddress + lookupListOffset); |
189 lookupListTable = LEReferenceTo<LookupListTable>(baseAddress,success, lookupListOffset); |
|
190 if(LE_SUCCESS(success) && lookupListTable.isValid()) { |
188 lookupListCount = SWAPW(lookupListTable->lookupCount); |
191 lookupListCount = SWAPW(lookupListTable->lookupCount); |
189 } |
192 } |
190 |
193 } |
191 if (langSysTable == NULL || featureListTable == NULL || lookupListTable == NULL || |
194 |
|
195 if (langSysTable.isEmpty() || featureListTable.isEmpty() || lookupListTable.isEmpty() || |
192 featureCount == 0 || lookupListCount == 0) { |
196 featureCount == 0 || lookupListCount == 0) { |
193 return; |
197 return; |
194 } |
198 } |
195 |
199 |
196 requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex); |
200 if(langSysTable.isValid()) { |
|
201 requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex); |
|
202 } |
197 |
203 |
198 lookupSelectArray = LE_NEW_ARRAY(FeatureMask, lookupListCount); |
204 lookupSelectArray = LE_NEW_ARRAY(FeatureMask, lookupListCount); |
199 if (lookupSelectArray == NULL) { |
205 if (lookupSelectArray == NULL) { |
200 success = LE_MEMORY_ALLOCATION_ERROR; |
206 success = LE_MEMORY_ALLOCATION_ERROR; |
201 return; |
207 return; |
207 |
213 |
208 lookupSelectCount = lookupListCount; |
214 lookupSelectCount = lookupListCount; |
209 |
215 |
210 le_int32 count, order = 0; |
216 le_int32 count, order = 0; |
211 le_uint32 featureReferences = 0; |
217 le_uint32 featureReferences = 0; |
212 const FeatureTable *featureTable = NULL; |
218 LEReferenceTo<FeatureTable> featureTable; |
213 LETag featureTag; |
219 LETag featureTag; |
214 |
220 |
215 const FeatureTable *requiredFeatureTable = NULL; |
221 LEReferenceTo<FeatureTable> requiredFeatureTable; |
216 LETag requiredFeatureTag = 0x00000000U; |
222 LETag requiredFeatureTag = 0x00000000U; |
217 |
223 |
218 // Count the total number of lookups referenced by all features. This will |
224 // Count the total number of lookups referenced by all features. This will |
219 // be the maximum number of entries in the lookupOrderArray. We can't use |
225 // be the maximum number of entries in the lookupOrderArray. We can't use |
220 // lookupListCount because some lookups might be referenced by more than |
226 // lookupListCount because some lookups might be referenced by more than |
221 // one feature. |
227 // one feature. |
222 for (le_uint32 feature = 0; feature < featureCount; feature += 1) { |
228 if(featureListTable.isValid() && LE_SUCCESS(success)) { |
223 le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); |
229 LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount); |
224 |
230 |
225 featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); |
231 for (le_uint32 feature = 0; LE_SUCCESS(success)&&(feature < featureCount); feature += 1) { |
226 if (!featureTable) { |
232 le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature, success)); |
227 continue; |
233 |
|
234 featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success); |
|
235 if (!featureTable.isValid() || LE_FAILURE(success)) { |
|
236 continue; |
228 } |
237 } |
229 featureReferences += SWAPW(featureTable->lookupCount); |
238 featureReferences += SWAPW(featureTable->lookupCount); |
230 } |
239 } |
231 |
240 } |
232 if (!featureTable) { |
241 |
|
242 if (!featureTable.isValid() || LE_FAILURE(success)) { |
233 success = LE_INTERNAL_ERROR; |
243 success = LE_INTERNAL_ERROR; |
234 return; |
244 return; |
235 } |
245 } |
236 |
246 |
237 if (requiredFeatureIndex != 0xFFFF) { |
247 if (requiredFeatureIndex != 0xFFFF) { |
238 requiredFeatureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &requiredFeatureTag); |
248 requiredFeatureTable = featureListTable->getFeatureTable(featureListTable, requiredFeatureIndex, &requiredFeatureTag, success); |
239 featureReferences += SWAPW(featureTable->lookupCount); |
249 featureReferences += SWAPW(featureTable->lookupCount); |
240 } |
250 } |
241 |
251 |
242 lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences); |
252 lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences); |
243 if (lookupOrderArray == NULL) { |
253 if (lookupOrderArray == NULL) { |
244 success = LE_MEMORY_ALLOCATION_ERROR; |
254 success = LE_MEMORY_ALLOCATION_ERROR; |
249 FeatureMap fm = featureMap[f]; |
259 FeatureMap fm = featureMap[f]; |
250 count = 0; |
260 count = 0; |
251 |
261 |
252 // If this is the required feature, add its lookups |
262 // If this is the required feature, add its lookups |
253 if (requiredFeatureTag == fm.tag) { |
263 if (requiredFeatureTag == fm.tag) { |
254 count += selectLookups(requiredFeatureTable, fm.mask, order); |
264 count += selectLookups(requiredFeatureTable, fm.mask, order, success); |
255 } |
265 } |
256 |
266 |
257 if (orderFeatures) { |
267 if (orderFeatures) { |
258 // If we added lookups from the required feature, sort them |
268 // If we added lookups from the required feature, sort them |
259 if (count > 1) { |
269 if (count > 1) { |
260 OpenTypeUtilities::sort(lookupOrderArray, order); |
270 OpenTypeUtilities::sort(lookupOrderArray, order); |
261 } |
271 } |
262 |
272 |
263 for (le_uint16 feature = 0; feature < featureCount; feature += 1) { |
273 for (le_uint16 feature = 0; feature < featureCount; feature += 1) { |
264 le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); |
274 LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount); |
|
275 le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success)); |
265 |
276 |
266 // don't add the required feature to the list more than once... |
277 // don't add the required feature to the list more than once... |
267 // TODO: Do we need this check? (Spec. says required feature won't be in feature list...) |
278 // TODO: Do we need this check? (Spec. says required feature won't be in feature list...) |
268 if (featureIndex == requiredFeatureIndex) { |
279 if (featureIndex == requiredFeatureIndex) { |
269 continue; |
280 continue; |
270 } |
281 } |
271 |
282 |
272 featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); |
283 featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success); |
273 |
284 |
274 if (featureTag == fm.tag) { |
285 if (featureTag == fm.tag) { |
275 count += selectLookups(featureTable, fm.mask, order + count); |
286 count += selectLookups(featureTable, fm.mask, order + count, success); |
276 } |
287 } |
277 } |
288 } |
278 |
289 |
279 if (count > 1) { |
290 if (count > 1) { |
280 OpenTypeUtilities::sort(&lookupOrderArray[order], count); |
291 OpenTypeUtilities::sort(&lookupOrderArray[order], count); |
281 } |
292 } |
282 |
293 |
283 order += count; |
294 order += count; |
284 } else { |
295 } else if(langSysTable.isValid()) { |
285 for (le_uint16 feature = 0; feature < featureCount; feature += 1) { |
296 LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount); |
286 le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); |
297 for (le_uint16 feature = 0; LE_SUCCESS(success)&& (feature < featureCount); feature += 1) { |
|
298 le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success)); |
287 |
299 |
288 // don't add the required feature to the list more than once... |
300 // don't add the required feature to the list more than once... |
289 // NOTE: This check is commented out because the spec. says that |
301 // NOTE: This check is commented out because the spec. says that |
290 // the required feature won't be in the feature list, and because |
302 // the required feature won't be in the feature list, and because |
291 // any duplicate entries will be removed below. |
303 // any duplicate entries will be removed below. |