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 20 void 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 164 void 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 204 U_NAMESPACE_END 205