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