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
18U_NAMESPACE_BEGIN
19
20void MorphTableHeader2::process(LEGlyphStorage &glyphStorage, le_int32 typoFlags) const
21{
22    const ChainHeader2 *chainHeader = chains;
23    le_uint32 chainCount = SWAPL(this->nChains);
24	le_uint32 chain;
25
26    for (chain = 0; chain < chainCount; chain++) {
27        FeatureFlags flag = SWAPL(chainHeader->defaultFlags);
28        le_uint32 chainLength = SWAPL(chainHeader->chainLength);
29        le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries);
30        le_uint32 nSubtables = SWAPL(chainHeader->nSubtables);
31        const MorphSubtableHeader2 *subtableHeader =
32            (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries];
33        le_uint32 subtable;
34
35        if (typoFlags != 0) {
36           le_uint32 featureEntry;
37
38            // Feature subtables
39            for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) {
40                FeatureTableEntry featureTableEntry = chains->featureTable[featureEntry];
41                le_int16 featureType = SWAPW(featureTableEntry.featureType);
42                le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting);
43                le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags);
44                le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags);
45                switch (featureType) {
46                    case ligaturesType:
47                        if ((typoFlags & LE_Ligatures_FEATURE_ENUM ) && (featureSetting ^ 0x1)){
48                            flag &= disableFlags;
49                            flag |= enableFlags;
50                        } else {
51                            if (((typoFlags & LE_RLIG_FEATURE_FLAG) && featureSetting == requiredLigaturesOnSelector) ||
52                                ((typoFlags & LE_CLIG_FEATURE_FLAG) && featureSetting == contextualLigaturesOnSelector) ||
53                                ((typoFlags & LE_HLIG_FEATURE_FLAG) && featureSetting == historicalLigaturesOnSelector) ||
54                                ((typoFlags & LE_LIGA_FEATURE_FLAG) && featureSetting == commonLigaturesOnSelector)) {
55                                flag &= disableFlags;
56                                flag |= enableFlags;
57                            }
58                        }
59                        break;
60                    case letterCaseType:
61                        if ((typoFlags & LE_SMCP_FEATURE_FLAG) && featureSetting == smallCapsSelector) {
62                            flag &= disableFlags;
63                            flag |= enableFlags;
64                        }
65                        break;
66                    case verticalSubstitutionType:
67                        break;
68                    case linguisticRearrangementType:
69                        break;
70                    case numberSpacingType:
71                        break;
72                    case smartSwashType:
73                        if ((typoFlags & LE_SWSH_FEATURE_FLAG) && (featureSetting ^ 0x1)){
74                            flag &= disableFlags;
75                            flag |= enableFlags;
76                        }
77                        break;
78                    case diacriticsType:
79                        break;
80                    case verticalPositionType:
81                        break;
82                    case fractionsType:
83                        if (((typoFlags & LE_FRAC_FEATURE_FLAG) && featureSetting == diagonalFractionsSelector) ||
84                            ((typoFlags & LE_AFRC_FEATURE_FLAG) && featureSetting == verticalFractionsSelector)) {
85                            flag &= disableFlags;
86                            flag |= enableFlags;
87                        } else {
88                            flag &= disableFlags;
89                        }
90                        break;
91                    case typographicExtrasType:
92                        if ((typoFlags & LE_ZERO_FEATURE_FLAG) && featureSetting == slashedZeroOnSelector) {
93                            flag &= disableFlags;
94                            flag |= enableFlags;
95                        }
96                        break;
97                    case mathematicalExtrasType:
98                        break;
99                    case ornamentSetsType:
100                        break;
101                    case characterAlternativesType:
102                        break;
103                    case designComplexityType:
104                        if (((typoFlags & LE_SS01_FEATURE_FLAG) && featureSetting == designLevel1Selector) ||
105                            ((typoFlags & LE_SS02_FEATURE_FLAG) && featureSetting == designLevel2Selector) ||
106                            ((typoFlags & LE_SS03_FEATURE_FLAG) && featureSetting == designLevel3Selector) ||
107                            ((typoFlags & LE_SS04_FEATURE_FLAG) && featureSetting == designLevel4Selector) ||
108                            ((typoFlags & LE_SS05_FEATURE_FLAG) && featureSetting == designLevel5Selector) ||
109                            ((typoFlags & LE_SS06_FEATURE_FLAG) && featureSetting == designLevel6Selector) ||
110                            ((typoFlags & LE_SS07_FEATURE_FLAG) && featureSetting == designLevel7Selector)) {
111
112                            flag &= disableFlags;
113                            flag |= enableFlags;
114                        }
115                        break;
116                    case styleOptionsType:
117                        break;
118                    case characterShapeType:
119                        break;
120                    case numberCaseType:
121                        break;
122                    case textSpacingType:
123                        break;
124                    case transliterationType:
125                        break;
126                    case annotationType:
127                        if ((typoFlags & LE_NALT_FEATURE_FLAG) && featureSetting == circleAnnotationSelector) {
128                            flag &= disableFlags;
129                            flag |= enableFlags;
130                        }
131                        break;
132                    case kanaSpacingType:
133                        break;
134                    case ideographicSpacingType:
135                        break;
136                    case rubyKanaType:
137                        if ((typoFlags & LE_RUBY_FEATURE_FLAG) && featureSetting == rubyKanaOnSelector) {
138                            flag &= disableFlags;
139                            flag |= enableFlags;
140                        }
141                        break;
142                    case cjkRomanSpacingType:
143                        break;
144                    default:
145                        break;
146                }
147            }
148        }
149
150        for (subtable = 0; subtable < nSubtables; subtable++) {
151            le_uint32 length = SWAPL(subtableHeader->length);
152            le_uint32 coverage = SWAPL(subtableHeader->coverage);
153            FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
154            // should check coverage more carefully...
155            if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) {
156                subtableHeader->process(glyphStorage);
157            }
158            subtableHeader = (const MorphSubtableHeader2 *) ((char *)subtableHeader + length);
159        }
160        chainHeader = (const ChainHeader2 *)((char *)chainHeader + chainLength);
161    }
162}
163
164void MorphSubtableHeader2::process(LEGlyphStorage &glyphStorage) const
165{
166    SubtableProcessor2 *processor = NULL;
167
168    switch (SWAPL(coverage) & scfTypeMask2)
169    {
170    case mstIndicRearrangement:
171        processor = new IndicRearrangementProcessor2(this);
172        break;
173
174    case mstContextualGlyphSubstitution:
175        processor = new ContextualGlyphSubstitutionProcessor2(this);
176        break;
177
178    case mstLigatureSubstitution:
179        processor = new LigatureSubstitutionProcessor2(this);
180        break;
181
182    case mstReservedUnused:
183        break;
184
185    case mstNonContextualGlyphSubstitution:
186        processor = NonContextualGlyphSubstitutionProcessor2::createInstance(this);
187        break;
188
189
190    case mstContextualGlyphInsertion:
191        processor = new ContextualGlyphInsertionProcessor2(this);
192        break;
193
194    default:
195        break;
196    }
197
198    if (processor != NULL) {
199        processor->process(glyphStorage);
200        delete processor;
201    }
202}
203
204U_NAMESPACE_END
205