]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
b75a7d8f | 2 | * |
374ca955 | 3 | * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved |
b75a7d8f A |
4 | * |
5 | */ | |
6 | ||
7 | #include "LETypes.h" | |
8 | #include "OpenTypeUtilities.h" | |
9 | #include "LEFontInstance.h" | |
10 | #include "OpenTypeTables.h" | |
11 | #include "Features.h" | |
12 | #include "Lookups.h" | |
13 | #include "ScriptAndLanguage.h" | |
14 | #include "GlyphDefinitionTables.h" | |
15 | #include "GlyphPositionAdjustments.h" | |
16 | #include "LookupProcessor.h" | |
374ca955 | 17 | #include "LEGlyphStorage.h" |
b75a7d8f A |
18 | #include "LESwaps.h" |
19 | ||
20 | U_NAMESPACE_BEGIN | |
21 | ||
22 | const LETag LookupProcessor::notSelected = 0x00000000; | |
23 | const LETag LookupProcessor::defaultFeature = 0xFFFFFFFF; | |
24 | ||
374ca955 | 25 | static const LETag emptyTag = 0x00000000; |
b75a7d8f A |
26 | |
27 | ||
28 | le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator, | |
29 | const LEFontInstance *fontInstance) const | |
30 | { | |
31 | le_uint16 lookupType = SWAPW(lookupTable->lookupType); | |
32 | le_uint16 subtableCount = SWAPW(lookupTable->subTableCount); | |
33 | le_int32 startPosition = glyphIterator->getCurrStreamPosition(); | |
34 | le_uint32 delta; | |
35 | ||
36 | for (le_uint16 subtable = 0; subtable < subtableCount; subtable += 1) { | |
37 | const LookupSubtable *lookupSubtable = lookupTable->getLookupSubtable(subtable); | |
38 | ||
39 | delta = applySubtable(lookupSubtable, lookupType, glyphIterator, fontInstance); | |
40 | ||
41 | if (delta > 0) { | |
42 | return 1; | |
43 | } | |
44 | ||
45 | glyphIterator->setCurrStreamPosition(startPosition); | |
46 | } | |
47 | ||
48 | return 1; | |
49 | } | |
50 | ||
374ca955 | 51 | le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustment *glyphPositionAdjustments, |
b75a7d8f A |
52 | le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, |
53 | const LEFontInstance *fontInstance) const | |
54 | { | |
374ca955 A |
55 | le_int32 glyphCount = glyphStorage.getGlyphCount(); |
56 | ||
b75a7d8f | 57 | if (lookupSelectArray == NULL) { |
374ca955 | 58 | return glyphCount; |
b75a7d8f A |
59 | } |
60 | ||
374ca955 A |
61 | GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments, |
62 | rightToLeft, 0, 0, glyphDefinitionTableHeader); | |
63 | le_int32 newGlyphCount = glyphCount; | |
64 | ||
b75a7d8f A |
65 | for (le_uint16 order = 0; order < lookupOrderCount; order += 1) { |
66 | le_uint16 lookup = lookupOrderArray[order]; | |
67 | LETag selectTag = lookupSelectArray[lookup]; | |
68 | ||
69 | if (selectTag != notSelected) { | |
70 | const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup); | |
71 | le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); | |
374ca955 A |
72 | |
73 | glyphIterator.reset(lookupFlags, selectTag); | |
b75a7d8f A |
74 | |
75 | while (glyphIterator.findFeatureTag()) { | |
76 | le_uint32 delta = 1; | |
77 | ||
78 | while (glyphIterator.next(delta)) { | |
79 | delta = applyLookupTable(lookupTable, &glyphIterator, fontInstance); | |
80 | } | |
81 | } | |
374ca955 A |
82 | |
83 | newGlyphCount = glyphIterator.applyInsertions(); | |
b75a7d8f A |
84 | } |
85 | } | |
374ca955 A |
86 | |
87 | return newGlyphCount; | |
b75a7d8f A |
88 | } |
89 | ||
90 | le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator, | |
91 | const LEFontInstance *fontInstance) const | |
92 | { | |
93 | const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex); | |
94 | le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); | |
95 | GlyphIterator tempIterator(*glyphIterator, lookupFlags); | |
96 | le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance); | |
97 | ||
98 | return delta; | |
99 | } | |
100 | ||
101 | le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, LETag featureTag, le_int32 order) | |
102 | { | |
103 | le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0; | |
374ca955 | 104 | le_int32 store = order; |
b75a7d8f A |
105 | |
106 | for (le_uint16 lookup = 0; lookup < lookupCount; lookup += 1) { | |
107 | le_uint16 lookupListIndex = SWAPW(featureTable->lookupListIndexArray[lookup]); | |
108 | ||
374ca955 A |
109 | if (lookupSelectArray[lookupListIndex] == notSelected) { |
110 | lookupSelectArray[lookupListIndex] = featureTag; | |
111 | lookupOrderArray[store++] = lookupListIndex; | |
112 | } | |
b75a7d8f A |
113 | } |
114 | ||
374ca955 | 115 | return store - order; |
b75a7d8f A |
116 | } |
117 | ||
118 | LookupProcessor::LookupProcessor(const char *baseAddress, | |
119 | Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset, | |
120 | LETag scriptTag, LETag languageTag, const LETag *featureOrder) | |
121 | : lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL), | |
122 | requiredFeatureTag(notSelected), lookupOrderArray(NULL), lookupOrderCount(0) | |
123 | { | |
124 | const ScriptListTable *scriptListTable = NULL; | |
125 | const LangSysTable *langSysTable = NULL; | |
126 | le_uint16 featureCount = 0; | |
127 | le_uint16 lookupListCount = 0; | |
128 | le_uint16 requiredFeatureIndex; | |
129 | ||
130 | if (scriptListOffset != 0) { | |
131 | scriptListTable = (const ScriptListTable *) (baseAddress + scriptListOffset); | |
132 | langSysTable = scriptListTable->findLanguage(scriptTag, languageTag); | |
133 | ||
134 | if (langSysTable != 0) { | |
135 | featureCount = SWAPW(langSysTable->featureCount); | |
136 | } | |
137 | } | |
138 | ||
139 | if (featureListOffset != 0) { | |
140 | featureListTable = (const FeatureListTable *) (baseAddress + featureListOffset); | |
141 | } | |
142 | ||
143 | if (lookupListOffset != 0) { | |
144 | lookupListTable = (const LookupListTable *) (baseAddress + lookupListOffset); | |
145 | lookupListCount = SWAPW(lookupListTable->lookupCount); | |
146 | } | |
147 | ||
148 | if (langSysTable == NULL || featureListTable == NULL || lookupListTable == NULL || | |
149 | featureCount == 0 || lookupListCount == 0) { | |
150 | return; | |
151 | } | |
152 | ||
153 | requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex); | |
154 | ||
155 | lookupSelectArray = LE_NEW_ARRAY(LETag, lookupListCount); | |
156 | ||
157 | for (int i = 0; i < lookupListCount; i += 1) { | |
158 | lookupSelectArray[i] = notSelected; | |
159 | } | |
160 | ||
161 | le_int32 count, order = 0; | |
162 | const FeatureTable *featureTable = 0; | |
163 | LETag featureTag; | |
164 | ||
165 | lookupOrderArray = LE_NEW_ARRAY(le_uint16, lookupListCount); | |
166 | ||
167 | if (requiredFeatureIndex != 0xFFFF) { | |
168 | featureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &featureTag); | |
169 | order += selectLookups(featureTable, defaultFeature, order); | |
170 | } | |
171 | ||
172 | if (featureOrder != NULL) { | |
173 | if (order > 1) { | |
174 | OpenTypeUtilities::sort(lookupOrderArray, order); | |
175 | } | |
176 | ||
177 | for (le_int32 tag = 0; featureOrder[tag] != emptyTag; tag += 1) { | |
178 | featureTag = featureOrder[tag]; | |
179 | count = 0; | |
180 | ||
181 | for (le_uint16 feature = 0; feature < featureCount; feature += 1) { | |
182 | le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); | |
183 | ||
184 | featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); | |
185 | ||
186 | if (featureTag == featureOrder[tag]) { | |
187 | count += selectLookups(featureTable, featureTag, order + count); | |
188 | } | |
189 | } | |
190 | ||
191 | if (count > 1) { | |
192 | OpenTypeUtilities::sort(&lookupOrderArray[order], count); | |
193 | } | |
194 | ||
195 | order += count; | |
196 | } | |
197 | } else { | |
198 | for (le_uint16 feature = 0; feature < featureCount; feature += 1) { | |
199 | le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); | |
200 | ||
374ca955 A |
201 | // don't add the required feature to the list more than once... |
202 | if (featureIndex == requiredFeatureIndex) { | |
203 | continue; | |
204 | } | |
205 | ||
b75a7d8f A |
206 | featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); |
207 | count = selectLookups(featureTable, featureTag, order); | |
208 | order += count; | |
209 | } | |
210 | ||
211 | if (order > 1) { | |
212 | OpenTypeUtilities::sort(lookupOrderArray, order); | |
213 | } | |
214 | } | |
215 | ||
216 | lookupOrderCount = order; | |
217 | } | |
218 | ||
219 | LookupProcessor::LookupProcessor() | |
220 | { | |
221 | } | |
222 | ||
223 | LookupProcessor::~LookupProcessor() | |
224 | { | |
225 | LE_DELETE_ARRAY(lookupOrderArray); | |
226 | LE_DELETE_ARRAY(lookupSelectArray); | |
227 | }; | |
228 | ||
229 | U_NAMESPACE_END |