1 /*
2 * (C) Copyright IBM Corp. and others 1998 - 2013 - All Rights Reserved
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
process(const LEReferenceTo<MorphTableHeader2> & base,LEGlyphStorage & glyphStorage,le_int32 typoFlags,LEErrorCode & success) const20 void MorphTableHeader2::process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage,
21 le_int32 typoFlags, LEErrorCode &success) const
22 {
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 }
39 FeatureFlags flag = SWAPL(chainHeader->defaultFlags);
40 le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries);
41 le_uint32 nSubtables = SWAPL(chainHeader->nSubtables);
42 LEReferenceTo<MorphSubtableHeader2> subtableHeader(chainHeader,
43 success, (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]);
44 le_uint32 subtable;
45 if(LE_FAILURE(success)) break; // malformed table
46
47 if (typoFlags != 0) {
48 le_uint32 featureEntry;
49 LEReferenceToArrayOf<FeatureTableEntry> featureTableRef(chainHeader, success, &chainHeader->featureTable[0], nFeatureEntries);
50 if(LE_FAILURE(success)) break;
51 // Feature subtables
52 for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) {
53 const FeatureTableEntry &featureTableEntry = featureTableRef(featureEntry, success);
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
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.
167 }
168 le_uint32 coverage = SWAPL(subtableHeader->coverage);
169 FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
170 // should check coverage more carefully...
171 if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) {
172 subtableHeader->process(subtableHeader, glyphStorage, success);
173 }
174 }
175 }
176 }
177
process(const LEReferenceTo<MorphSubtableHeader2> & base,LEGlyphStorage & glyphStorage,LEErrorCode & success) const178 void MorphSubtableHeader2::process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
179 {
180 SubtableProcessor2 *processor = NULL;
181
182 switch (SWAPL(coverage) & scfTypeMask2)
183 {
184 case mstIndicRearrangement:
185 processor = new IndicRearrangementProcessor2(base, success);
186 break;
187
188 case mstContextualGlyphSubstitution:
189 processor = new ContextualGlyphSubstitutionProcessor2(base, success);
190 break;
191
192 case mstLigatureSubstitution:
193 processor = new LigatureSubstitutionProcessor2(base, success);
194 break;
195
196 case mstReservedUnused:
197 break;
198
199 case mstNonContextualGlyphSubstitution:
200 processor = NonContextualGlyphSubstitutionProcessor2::createInstance(base, success);
201 break;
202
203
204 case mstContextualGlyphInsertion:
205 processor = new ContextualGlyphInsertionProcessor2(base, success);
206 break;
207
208 default:
209 return;
210 break; /*NOTREACHED*/
211 }
212
213 if (processor != NULL) {
214 processor->process(glyphStorage, success);
215 delete processor;
216 } else {
217 if(LE_SUCCESS(success)) {
218 success = LE_MEMORY_ALLOCATION_ERROR; // because ptr is null and we didn't break out.
219 }
220 }
221 }
222
223 U_NAMESPACE_END
224