• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
4  *
5  */
6 
7 #include "LETypes.h"
8 #include "OpenTypeUtilities.h"
9 #include "LEFontInstance.h"
10 #include "OpenTypeTables.h"
11 #include "ICUFeatures.h"
12 #include "Lookups.h"
13 #include "ScriptAndLanguage.h"
14 #include "GlyphDefinitionTables.h"
15 #include "GlyphIterator.h"
16 #include "LookupProcessor.h"
17 #include "LEGlyphStorage.h"
18 #include "LESwaps.h"
19 
20 U_NAMESPACE_BEGIN
21 
applyLookupTable(const LookupTable * lookupTable,GlyphIterator * glyphIterator,const LEFontInstance * fontInstance,LEErrorCode & success) const22 le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator,
23                                          const LEFontInstance *fontInstance, LEErrorCode& success) const
24 {
25     if (LE_FAILURE(success)) {
26         return 0;
27     }
28 
29     le_uint16 lookupType = SWAPW(lookupTable->lookupType);
30     le_uint16 subtableCount = SWAPW(lookupTable->subTableCount);
31     le_int32 startPosition = glyphIterator->getCurrStreamPosition();
32     le_uint32 delta;
33 
34     for (le_uint16 subtable = 0; subtable < subtableCount; subtable += 1) {
35         const LookupSubtable *lookupSubtable = lookupTable->getLookupSubtable(subtable);
36 
37         delta = applySubtable(lookupSubtable, lookupType, glyphIterator, fontInstance, success);
38 
39         if (delta > 0 && LE_FAILURE(success)) {
40             return 1;
41         }
42 
43         glyphIterator->setCurrStreamPosition(startPosition);
44     }
45 
46     return 1;
47 }
48 
process(LEGlyphStorage & glyphStorage,GlyphPositionAdjustments * glyphPositionAdjustments,le_bool rightToLeft,const GlyphDefinitionTableHeader * glyphDefinitionTableHeader,const LEFontInstance * fontInstance,LEErrorCode & success) const49 le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
50                               le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
51                               const LEFontInstance *fontInstance, LEErrorCode& success) const
52 {
53     if (LE_FAILURE(success)) {
54         return 0;
55     }
56 
57     le_int32 glyphCount = glyphStorage.getGlyphCount();
58 
59     if (lookupSelectArray == NULL) {
60         return glyphCount;
61     }
62 
63     GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments,
64                                 rightToLeft, 0, 0, glyphDefinitionTableHeader);
65     le_int32 newGlyphCount = glyphCount;
66 
67     for (le_uint16 order = 0; order < lookupOrderCount; order += 1) {
68         le_uint16 lookup = lookupOrderArray[order];
69         FeatureMask selectMask = lookupSelectArray[lookup];
70 
71         if (selectMask != 0) {
72             const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup);
73             le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
74 
75             glyphIterator.reset(lookupFlags, selectMask);
76 
77             while (glyphIterator.findFeatureTag()) {
78                 applyLookupTable(lookupTable, &glyphIterator, fontInstance, success);
79                 if (LE_FAILURE(success)) {
80                     return 0;
81                 }
82             }
83 
84             newGlyphCount = glyphIterator.applyInsertions();
85         }
86     }
87 
88     return newGlyphCount;
89 }
90 
applySingleLookup(le_uint16 lookupTableIndex,GlyphIterator * glyphIterator,const LEFontInstance * fontInstance,LEErrorCode & success) const91 le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator,
92                                           const LEFontInstance *fontInstance, LEErrorCode& success) const
93 {
94     if (LE_FAILURE(success)) {
95         return 0;
96     }
97 
98     const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex);
99     le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
100     GlyphIterator tempIterator(*glyphIterator, lookupFlags);
101     le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success);
102 
103     return delta;
104 }
105 
selectLookups(const FeatureTable * featureTable,FeatureMask featureMask,le_int32 order)106 le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, FeatureMask featureMask, le_int32 order)
107 {
108     le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0;
109     le_int32  store = order;
110 
111     for (le_uint16 lookup = 0; lookup < lookupCount; lookup += 1) {
112         le_uint16 lookupListIndex = SWAPW(featureTable->lookupListIndexArray[lookup]);
113 
114         lookupSelectArray[lookupListIndex] |= featureMask;
115         lookupOrderArray[store++] = lookupListIndex;
116     }
117 
118     return store - order;
119 }
120 
LookupProcessor(const char * baseAddress,Offset scriptListOffset,Offset featureListOffset,Offset lookupListOffset,LETag scriptTag,LETag languageTag,const FeatureMap * featureMap,le_int32 featureMapCount,le_bool orderFeatures,LEErrorCode & success)121 LookupProcessor::LookupProcessor(const char *baseAddress,
122         Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset,
123         LETag scriptTag, LETag languageTag, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool orderFeatures,
124         LEErrorCode& success)
125     : lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL),
126       lookupOrderArray(NULL), lookupOrderCount(0)
127 {
128     const ScriptListTable *scriptListTable = NULL;
129     const LangSysTable *langSysTable = NULL;
130     le_uint16 featureCount = 0;
131     le_uint16 lookupListCount = 0;
132     le_uint16 requiredFeatureIndex;
133 
134     if (LE_FAILURE(success)) {
135         return;
136     }
137 
138     if (scriptListOffset != 0) {
139         scriptListTable = (const ScriptListTable *) (baseAddress + scriptListOffset);
140         langSysTable = scriptListTable->findLanguage(scriptTag, languageTag);
141 
142         if (langSysTable != 0) {
143             featureCount = SWAPW(langSysTable->featureCount);
144         }
145     }
146 
147     if (featureListOffset != 0) {
148         featureListTable = (const FeatureListTable *) (baseAddress + featureListOffset);
149     }
150 
151     if (lookupListOffset != 0) {
152         lookupListTable = (const LookupListTable *) (baseAddress + lookupListOffset);
153         lookupListCount = SWAPW(lookupListTable->lookupCount);
154     }
155 
156     if (langSysTable == NULL || featureListTable == NULL || lookupListTable == NULL ||
157         featureCount == 0 || lookupListCount == 0) {
158         return;
159     }
160 
161     requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex);
162 
163     lookupSelectArray = LE_NEW_ARRAY(FeatureMask, lookupListCount);
164     if (lookupSelectArray == NULL) {
165         success = LE_MEMORY_ALLOCATION_ERROR;
166         return;
167     }
168 
169     for (int i = 0; i < lookupListCount; i += 1) {
170         lookupSelectArray[i] = 0;
171     }
172 
173     le_int32 count, order = 0;
174     le_int32 featureReferences = 0;
175     const FeatureTable *featureTable = NULL;
176     LETag featureTag;
177 
178     const FeatureTable *requiredFeatureTable = NULL;
179     LETag requiredFeatureTag = 0x00000000U;
180 
181     // Count the total number of lookups referenced by all features. This will
182     // be the maximum number of entries in the lookupOrderArray. We can't use
183     // lookupListCount because some lookups might be referenced by more than
184     // one feature.
185     for (le_int32 feature = 0; feature < featureCount; feature += 1) {
186         le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
187 
188         featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
189         featureReferences += SWAPW(featureTable->lookupCount);
190     }
191 
192     if (requiredFeatureIndex != 0xFFFF) {
193         requiredFeatureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &requiredFeatureTag);
194         featureReferences += SWAPW(featureTable->lookupCount);
195     }
196 
197     lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences);
198     if (lookupOrderArray == NULL) {
199         success = LE_MEMORY_ALLOCATION_ERROR;
200         return;
201     }
202 
203     for (le_int32 f = 0; f < featureMapCount; f += 1) {
204         FeatureMap fm = featureMap[f];
205         count = 0;
206 
207         // If this is the required feature, add its lookups
208         if (requiredFeatureTag == fm.tag) {
209             count += selectLookups(requiredFeatureTable, fm.mask, order);
210         }
211 
212         if (orderFeatures) {
213             // If we added lookups from the required feature, sort them
214             if (count > 1) {
215                 OpenTypeUtilities::sort(lookupOrderArray, order);
216             }
217 
218             for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
219                 le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
220 
221                 // don't add the required feature to the list more than once...
222                 // TODO: Do we need this check? (Spec. says required feature won't be in feature list...)
223                 if (featureIndex == requiredFeatureIndex) {
224                     continue;
225                 }
226 
227                 featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
228 
229                 if (featureTag == fm.tag) {
230                     count += selectLookups(featureTable, fm.mask, order + count);
231                 }
232             }
233 
234             if (count > 1) {
235                 OpenTypeUtilities::sort(&lookupOrderArray[order], count);
236             }
237 
238             order += count;
239         } else {
240             for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
241                 le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
242 
243                 // don't add the required feature to the list more than once...
244                 // NOTE: This check is commented out because the spec. says that
245                 // the required feature won't be in the feature list, and because
246                 // any duplicate entries will be removed below.
247 #if 0
248                 if (featureIndex == requiredFeatureIndex) {
249                     continue;
250                 }
251 #endif
252 
253                 featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
254 
255                 if (featureTag == fm.tag) {
256                     order += selectLookups(featureTable, fm.mask, order);
257                 }
258             }
259         }
260     }
261 
262     if (!orderFeatures && (order > 1)) {
263         OpenTypeUtilities::sort(lookupOrderArray, order);
264 
265         // If there's no specified feature order,
266         // we will apply the lookups in the order
267         // that they're in the font. If a particular
268         // lookup may be referenced by more than one feature,
269         // it will apprear in the lookupOrderArray more than
270         // once, so remove any duplicate entries in the sorted array.
271         le_int32 out = 1;
272 
273         for (le_int32 in = 1; in < order; in += 1) {
274             if (lookupOrderArray[out - 1] != lookupOrderArray[in]) {
275                 if (out != in) {
276                     lookupOrderArray[out] = lookupOrderArray[in];
277                 }
278 
279                 out += 1;
280             }
281         }
282 
283         order = out;
284     }
285 
286     lookupOrderCount = order;
287 }
288 
LookupProcessor()289 LookupProcessor::LookupProcessor()
290 {
291 	lookupOrderArray = NULL;
292 	lookupSelectArray = NULL;
293 }
294 
~LookupProcessor()295 LookupProcessor::~LookupProcessor()
296 {
297     LE_DELETE_ARRAY(lookupOrderArray);
298     LE_DELETE_ARRAY(lookupSelectArray);
299 }
300 
301 U_NAMESPACE_END
302