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(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 178void 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 223U_NAMESPACE_END 224