1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
/*
* (C) Copyright IBM Corp. and others 1998 - 2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "LayoutTables.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "IndicRearrangementProcessor2.h"
#include "ContextualGlyphSubstProc2.h"
#include "LigatureSubstProc2.h"
#include "NonContextualGlyphSubstProc2.h"
#include "ContextualGlyphInsertionProc2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
void MorphTableHeader2::process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage,
le_int32 typoFlags, LEErrorCode &success) const
{
if(LE_FAILURE(success)) return;
le_uint32 chainCount = SWAPL(this->nChains);
LEReferenceTo<ChainHeader2> chainHeader(base, success, &chains[0]);
/* chainHeader and subtableHeader are implemented as a moving pointer rather than an array dereference
* to (slightly) reduce code churn. However, must be careful to preincrement them the 2nd time through.
* We don't want to increment them at the end of the loop, as that would attempt to dereference
* out of range memory.
*/
le_uint32 chain;
for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain++) {
if (chain>0) {
le_uint32 chainLength = SWAPL(chainHeader->chainLength);
chainHeader.addOffset(chainLength, success); // Don't increment the first time
}
FeatureFlags flag = SWAPL(chainHeader->defaultFlags);
le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries);
le_uint32 nSubtables = SWAPL(chainHeader->nSubtables);
LEReferenceTo<MorphSubtableHeader2> subtableHeader(chainHeader,
success, (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]);
le_uint32 subtable;
if(LE_FAILURE(success)) break; // malformed table
if (typoFlags != 0) {
le_uint32 featureEntry;
LEReferenceToArrayOf<FeatureTableEntry> featureTableRef(chainHeader, success, &chainHeader->featureTable[0], nFeatureEntries);
if(LE_FAILURE(success)) break;
// Feature subtables
for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) {
const FeatureTableEntry &featureTableEntry = featureTableRef(featureEntry, success);
le_int16 featureType = SWAPW(featureTableEntry.featureType);
le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting);
le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags);
le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags);
switch (featureType) {
case ligaturesType:
if ((typoFlags & LE_Ligatures_FEATURE_ENUM ) && (featureSetting ^ 0x1)){
flag &= disableFlags;
flag |= enableFlags;
} else {
if (((typoFlags & LE_RLIG_FEATURE_FLAG) && featureSetting == requiredLigaturesOnSelector) ||
((typoFlags & LE_CLIG_FEATURE_FLAG) && featureSetting == contextualLigaturesOnSelector) ||
((typoFlags & LE_HLIG_FEATURE_FLAG) && featureSetting == historicalLigaturesOnSelector) ||
((typoFlags & LE_LIGA_FEATURE_FLAG) && featureSetting == commonLigaturesOnSelector)) {
flag &= disableFlags;
flag |= enableFlags;
}
}
break;
case letterCaseType:
if ((typoFlags & LE_SMCP_FEATURE_FLAG) && featureSetting == smallCapsSelector) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case verticalSubstitutionType:
break;
case linguisticRearrangementType:
break;
case numberSpacingType:
break;
case smartSwashType:
if ((typoFlags & LE_SWSH_FEATURE_FLAG) && (featureSetting ^ 0x1)){
flag &= disableFlags;
flag |= enableFlags;
}
break;
case diacriticsType:
break;
case verticalPositionType:
break;
case fractionsType:
if (((typoFlags & LE_FRAC_FEATURE_FLAG) && featureSetting == diagonalFractionsSelector) ||
((typoFlags & LE_AFRC_FEATURE_FLAG) && featureSetting == verticalFractionsSelector)) {
flag &= disableFlags;
flag |= enableFlags;
} else {
flag &= disableFlags;
}
break;
case typographicExtrasType:
if ((typoFlags & LE_ZERO_FEATURE_FLAG) && featureSetting == slashedZeroOnSelector) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case mathematicalExtrasType:
break;
case ornamentSetsType:
break;
case characterAlternativesType:
break;
case designComplexityType:
if (((typoFlags & LE_SS01_FEATURE_FLAG) && featureSetting == designLevel1Selector) ||
((typoFlags & LE_SS02_FEATURE_FLAG) && featureSetting == designLevel2Selector) ||
((typoFlags & LE_SS03_FEATURE_FLAG) && featureSetting == designLevel3Selector) ||
((typoFlags & LE_SS04_FEATURE_FLAG) && featureSetting == designLevel4Selector) ||
((typoFlags & LE_SS05_FEATURE_FLAG) && featureSetting == designLevel5Selector) ||
((typoFlags & LE_SS06_FEATURE_FLAG) && featureSetting == designLevel6Selector) ||
((typoFlags & LE_SS07_FEATURE_FLAG) && featureSetting == designLevel7Selector)) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case styleOptionsType:
break;
case characterShapeType:
break;
case numberCaseType:
break;
case textSpacingType:
break;
case transliterationType:
break;
case annotationType:
if ((typoFlags & LE_NALT_FEATURE_FLAG) && featureSetting == circleAnnotationSelector) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case kanaSpacingType:
break;
case ideographicSpacingType:
break;
case rubyKanaType:
if ((typoFlags & LE_RUBY_FEATURE_FLAG) && featureSetting == rubyKanaOnSelector) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case cjkRomanSpacingType:
break;
default:
break;
}
}
}
for (subtable = 0; LE_SUCCESS(success) && subtable < nSubtables; subtable++) {
if(subtable>0) {
le_uint32 length = SWAPL(subtableHeader->length);
subtableHeader.addOffset(length, success); // Don't addOffset for the last entry.
}
le_uint32 coverage = SWAPL(subtableHeader->coverage);
FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
// should check coverage more carefully...
if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) {
subtableHeader->process(subtableHeader, glyphStorage, success);
}
}
}
}
void MorphSubtableHeader2::process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
{
SubtableProcessor2 *processor = NULL;
switch (SWAPL(coverage) & scfTypeMask2)
{
case mstIndicRearrangement:
processor = new IndicRearrangementProcessor2(base, success);
break;
case mstContextualGlyphSubstitution:
processor = new ContextualGlyphSubstitutionProcessor2(base, success);
break;
case mstLigatureSubstitution:
processor = new LigatureSubstitutionProcessor2(base, success);
break;
case mstReservedUnused:
break;
case mstNonContextualGlyphSubstitution:
processor = NonContextualGlyphSubstitutionProcessor2::createInstance(base, success);
break;
case mstContextualGlyphInsertion:
processor = new ContextualGlyphInsertionProcessor2(base, success);
break;
default:
return;
break; /*NOTREACHED*/
}
if (processor != NULL) {
processor->process(glyphStorage, success);
delete processor;
} else {
if(LE_SUCCESS(success)) {
success = LE_MEMORY_ALLOCATION_ERROR; // because ptr is null and we didn't break out.
}
}
}
U_NAMESPACE_END
|