]>
Commit | Line | Data |
---|---|---|
51004dcb | 1 | /* |
2ca993e8 | 2 | * (C) Copyright IBM Corp. and others 1998 - 2015 - All Rights Reserved |
51004dcb A |
3 | * |
4 | */ | |
5 | ||
6 | #include "LETypes.h" | |
7 | #include "LayoutTables.h" | |
8 | #include "MorphTables.h" | |
9 | #include "SubtableProcessor2.h" | |
10 | #include "IndicRearrangementProcessor2.h" | |
11 | #include "ContextualGlyphSubstProc2.h" | |
12 | #include "LigatureSubstProc2.h" | |
13 | #include "NonContextualGlyphSubstProc2.h" | |
14 | #include "ContextualGlyphInsertionProc2.h" | |
15 | #include "LEGlyphStorage.h" | |
16 | #include "LESwaps.h" | |
17 | ||
18 | U_NAMESPACE_BEGIN | |
19 | ||
57a6839d A |
20 | void MorphTableHeader2::process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage, |
21 | le_int32 typoFlags, LEErrorCode &success) const | |
51004dcb | 22 | { |
57a6839d A |
23 | if(LE_FAILURE(success)) return; |
24 | ||
25 | le_uint32 chainCount = SWAPL(this->nChains); | |
26 | LEReferenceTo<ChainHeader2> chainHeader(base, success, &chains[0]); | |
27 | /* chainHeader and subtableHeader are implemented as a moving pointer rather than an array dereference | |
28 | * to (slightly) reduce code churn. However, must be careful to preincrement them the 2nd time through. | |
29 | * We don't want to increment them at the end of the loop, as that would attempt to dereference | |
30 | * out of range memory. | |
31 | */ | |
32 | le_uint32 chain; | |
33 | ||
34 | for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain++) { | |
35 | if (chain>0) { | |
36 | le_uint32 chainLength = SWAPL(chainHeader->chainLength); | |
37 | chainHeader.addOffset(chainLength, success); // Don't increment the first time | |
38 | } | |
51004dcb | 39 | FeatureFlags flag = SWAPL(chainHeader->defaultFlags); |
51004dcb A |
40 | le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries); |
41 | le_uint32 nSubtables = SWAPL(chainHeader->nSubtables); | |
57a6839d A |
42 | LEReferenceTo<MorphSubtableHeader2> subtableHeader(chainHeader, |
43 | success, (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]); | |
51004dcb | 44 | le_uint32 subtable; |
57a6839d | 45 | if(LE_FAILURE(success)) break; // malformed table |
51004dcb A |
46 | |
47 | if (typoFlags != 0) { | |
48 | le_uint32 featureEntry; | |
57a6839d A |
49 | LEReferenceToArrayOf<FeatureTableEntry> featureTableRef(chainHeader, success, &chainHeader->featureTable[0], nFeatureEntries); |
50 | if(LE_FAILURE(success)) break; | |
51004dcb A |
51 | // Feature subtables |
52 | for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) { | |
57a6839d | 53 | const FeatureTableEntry &featureTableEntry = featureTableRef(featureEntry, success); |
51004dcb A |
54 | le_int16 featureType = SWAPW(featureTableEntry.featureType); |
55 | le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting); | |
56 | le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags); | |
57 | le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags); | |
58 | switch (featureType) { | |
59 | case ligaturesType: | |
60 | if ((typoFlags & LE_Ligatures_FEATURE_ENUM ) && (featureSetting ^ 0x1)){ | |
61 | flag &= disableFlags; | |
62 | flag |= enableFlags; | |
63 | } else { | |
64 | if (((typoFlags & LE_RLIG_FEATURE_FLAG) && featureSetting == requiredLigaturesOnSelector) || | |
65 | ((typoFlags & LE_CLIG_FEATURE_FLAG) && featureSetting == contextualLigaturesOnSelector) || | |
66 | ((typoFlags & LE_HLIG_FEATURE_FLAG) && featureSetting == historicalLigaturesOnSelector) || | |
67 | ((typoFlags & LE_LIGA_FEATURE_FLAG) && featureSetting == commonLigaturesOnSelector)) { | |
68 | flag &= disableFlags; | |
69 | flag |= enableFlags; | |
70 | } | |
71 | } | |
72 | break; | |
73 | case letterCaseType: | |
74 | if ((typoFlags & LE_SMCP_FEATURE_FLAG) && featureSetting == smallCapsSelector) { | |
75 | flag &= disableFlags; | |
76 | flag |= enableFlags; | |
77 | } | |
78 | break; | |
79 | case verticalSubstitutionType: | |
80 | break; | |
81 | case linguisticRearrangementType: | |
82 | break; | |
83 | case numberSpacingType: | |
84 | break; | |
85 | case smartSwashType: | |
86 | if ((typoFlags & LE_SWSH_FEATURE_FLAG) && (featureSetting ^ 0x1)){ | |
87 | flag &= disableFlags; | |
88 | flag |= enableFlags; | |
89 | } | |
90 | break; | |
91 | case diacriticsType: | |
92 | break; | |
93 | case verticalPositionType: | |
94 | break; | |
95 | case fractionsType: | |
96 | if (((typoFlags & LE_FRAC_FEATURE_FLAG) && featureSetting == diagonalFractionsSelector) || | |
97 | ((typoFlags & LE_AFRC_FEATURE_FLAG) && featureSetting == verticalFractionsSelector)) { | |
98 | flag &= disableFlags; | |
99 | flag |= enableFlags; | |
100 | } else { | |
101 | flag &= disableFlags; | |
102 | } | |
103 | break; | |
104 | case typographicExtrasType: | |
105 | if ((typoFlags & LE_ZERO_FEATURE_FLAG) && featureSetting == slashedZeroOnSelector) { | |
106 | flag &= disableFlags; | |
107 | flag |= enableFlags; | |
108 | } | |
109 | break; | |
110 | case mathematicalExtrasType: | |
111 | break; | |
112 | case ornamentSetsType: | |
113 | break; | |
114 | case characterAlternativesType: | |
115 | break; | |
116 | case designComplexityType: | |
117 | if (((typoFlags & LE_SS01_FEATURE_FLAG) && featureSetting == designLevel1Selector) || | |
118 | ((typoFlags & LE_SS02_FEATURE_FLAG) && featureSetting == designLevel2Selector) || | |
119 | ((typoFlags & LE_SS03_FEATURE_FLAG) && featureSetting == designLevel3Selector) || | |
120 | ((typoFlags & LE_SS04_FEATURE_FLAG) && featureSetting == designLevel4Selector) || | |
121 | ((typoFlags & LE_SS05_FEATURE_FLAG) && featureSetting == designLevel5Selector) || | |
122 | ((typoFlags & LE_SS06_FEATURE_FLAG) && featureSetting == designLevel6Selector) || | |
123 | ((typoFlags & LE_SS07_FEATURE_FLAG) && featureSetting == designLevel7Selector)) { | |
124 | ||
125 | flag &= disableFlags; | |
126 | flag |= enableFlags; | |
127 | } | |
128 | break; | |
129 | case styleOptionsType: | |
130 | break; | |
131 | case characterShapeType: | |
132 | break; | |
133 | case numberCaseType: | |
134 | break; | |
135 | case textSpacingType: | |
136 | break; | |
137 | case transliterationType: | |
138 | break; | |
139 | case annotationType: | |
140 | if ((typoFlags & LE_NALT_FEATURE_FLAG) && featureSetting == circleAnnotationSelector) { | |
141 | flag &= disableFlags; | |
142 | flag |= enableFlags; | |
143 | } | |
144 | break; | |
145 | case kanaSpacingType: | |
146 | break; | |
147 | case ideographicSpacingType: | |
148 | break; | |
149 | case rubyKanaType: | |
150 | if ((typoFlags & LE_RUBY_FEATURE_FLAG) && featureSetting == rubyKanaOnSelector) { | |
151 | flag &= disableFlags; | |
152 | flag |= enableFlags; | |
153 | } | |
154 | break; | |
155 | case cjkRomanSpacingType: | |
156 | break; | |
157 | default: | |
158 | break; | |
159 | } | |
160 | } | |
161 | } | |
162 | ||
57a6839d A |
163 | for (subtable = 0; LE_SUCCESS(success) && subtable < nSubtables; subtable++) { |
164 | if(subtable>0) { | |
165 | le_uint32 length = SWAPL(subtableHeader->length); | |
166 | subtableHeader.addOffset(length, success); // Don't addOffset for the last entry. | |
2ca993e8 | 167 | if (LE_FAILURE(success)) break; |
57a6839d | 168 | } |
51004dcb A |
169 | le_uint32 coverage = SWAPL(subtableHeader->coverage); |
170 | FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures); | |
171 | // should check coverage more carefully... | |
172 | if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) { | |
57a6839d | 173 | subtableHeader->process(subtableHeader, glyphStorage, success); |
51004dcb | 174 | } |
51004dcb | 175 | } |
51004dcb A |
176 | } |
177 | } | |
178 | ||
57a6839d | 179 | void MorphSubtableHeader2::process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const |
51004dcb A |
180 | { |
181 | SubtableProcessor2 *processor = NULL; | |
182 | ||
2ca993e8 A |
183 | if (LE_FAILURE(success)) return; |
184 | ||
51004dcb A |
185 | switch (SWAPL(coverage) & scfTypeMask2) |
186 | { | |
187 | case mstIndicRearrangement: | |
57a6839d | 188 | processor = new IndicRearrangementProcessor2(base, success); |
51004dcb A |
189 | break; |
190 | ||
191 | case mstContextualGlyphSubstitution: | |
57a6839d | 192 | processor = new ContextualGlyphSubstitutionProcessor2(base, success); |
51004dcb A |
193 | break; |
194 | ||
195 | case mstLigatureSubstitution: | |
57a6839d | 196 | processor = new LigatureSubstitutionProcessor2(base, success); |
51004dcb A |
197 | break; |
198 | ||
199 | case mstReservedUnused: | |
200 | break; | |
201 | ||
202 | case mstNonContextualGlyphSubstitution: | |
57a6839d | 203 | processor = NonContextualGlyphSubstitutionProcessor2::createInstance(base, success); |
51004dcb A |
204 | break; |
205 | ||
206 | ||
207 | case mstContextualGlyphInsertion: | |
57a6839d | 208 | processor = new ContextualGlyphInsertionProcessor2(base, success); |
51004dcb A |
209 | break; |
210 | ||
211 | default: | |
57a6839d A |
212 | return; |
213 | break; /*NOTREACHED*/ | |
51004dcb A |
214 | } |
215 | ||
216 | if (processor != NULL) { | |
57a6839d | 217 | processor->process(glyphStorage, success); |
51004dcb | 218 | delete processor; |
57a6839d A |
219 | } else { |
220 | if(LE_SUCCESS(success)) { | |
221 | success = LE_MEMORY_ALLOCATION_ERROR; // because ptr is null and we didn't break out. | |
222 | } | |
51004dcb A |
223 | } |
224 | } | |
225 | ||
226 | U_NAMESPACE_END |