2 * (C) Copyright IBM Corp. and others 1998 - 2015 - All Rights Reserved
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"
20 void MorphTableHeader2::process(const LEReferenceTo
<MorphTableHeader2
> &base
, LEGlyphStorage
&glyphStorage
,
21 le_int32 typoFlags
, LEErrorCode
&success
) const
23 if(LE_FAILURE(success
)) return;
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.
34 for (chain
= 0; LE_SUCCESS(success
) && (chain
< chainCount
); chain
++) {
36 le_uint32 chainLength
= SWAPL(chainHeader
->chainLength
);
37 chainHeader
.addOffset(chainLength
, success
); // Don't increment the first time
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
]);
45 if(LE_FAILURE(success
)) break; // malformed table
48 le_uint32 featureEntry
;
49 LEReferenceToArrayOf
<FeatureTableEntry
> featureTableRef(chainHeader
, success
, &chainHeader
->featureTable
[0], nFeatureEntries
);
50 if(LE_FAILURE(success
)) break;
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
) {
60 if ((typoFlags
& LE_Ligatures_FEATURE_ENUM
) && (featureSetting
^ 0x1)){
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
)) {
74 if ((typoFlags
& LE_SMCP_FEATURE_FLAG
) && featureSetting
== smallCapsSelector
) {
79 case verticalSubstitutionType
:
81 case linguisticRearrangementType
:
83 case numberSpacingType
:
86 if ((typoFlags
& LE_SWSH_FEATURE_FLAG
) && (featureSetting
^ 0x1)){
93 case verticalPositionType
:
96 if (((typoFlags
& LE_FRAC_FEATURE_FLAG
) && featureSetting
== diagonalFractionsSelector
) ||
97 ((typoFlags
& LE_AFRC_FEATURE_FLAG
) && featureSetting
== verticalFractionsSelector
)) {
101 flag
&= disableFlags
;
104 case typographicExtrasType
:
105 if ((typoFlags
& LE_ZERO_FEATURE_FLAG
) && featureSetting
== slashedZeroOnSelector
) {
106 flag
&= disableFlags
;
110 case mathematicalExtrasType
:
112 case ornamentSetsType
:
114 case characterAlternativesType
:
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
)) {
125 flag
&= disableFlags
;
129 case styleOptionsType
:
131 case characterShapeType
:
135 case textSpacingType
:
137 case transliterationType
:
140 if ((typoFlags
& LE_NALT_FEATURE_FLAG
) && featureSetting
== circleAnnotationSelector
) {
141 flag
&= disableFlags
;
145 case kanaSpacingType
:
147 case ideographicSpacingType
:
150 if ((typoFlags
& LE_RUBY_FEATURE_FLAG
) && featureSetting
== rubyKanaOnSelector
) {
151 flag
&= disableFlags
;
155 case cjkRomanSpacingType
:
163 for (subtable
= 0; LE_SUCCESS(success
) && subtable
< nSubtables
; subtable
++) {
165 le_uint32 length
= SWAPL(subtableHeader
->length
);
166 subtableHeader
.addOffset(length
, success
); // Don't addOffset for the last entry.
167 if (LE_FAILURE(success
)) break;
169 le_uint32 coverage
= SWAPL(subtableHeader
->coverage
);
170 FeatureFlags subtableFeatures
= SWAPL(subtableHeader
->subtableFeatures
);
171 // should check coverage more carefully...
172 if (((coverage
& scfIgnoreVt2
) || !(coverage
& scfVertical2
)) && (subtableFeatures
& flag
) != 0) {
173 subtableHeader
->process(subtableHeader
, glyphStorage
, success
);
179 void MorphSubtableHeader2::process(const LEReferenceTo
<MorphSubtableHeader2
> &base
, LEGlyphStorage
&glyphStorage
, LEErrorCode
&success
) const
181 SubtableProcessor2
*processor
= NULL
;
183 if (LE_FAILURE(success
)) return;
185 switch (SWAPL(coverage
) & scfTypeMask2
)
187 case mstIndicRearrangement
:
188 processor
= new IndicRearrangementProcessor2(base
, success
);
191 case mstContextualGlyphSubstitution
:
192 processor
= new ContextualGlyphSubstitutionProcessor2(base
, success
);
195 case mstLigatureSubstitution
:
196 processor
= new LigatureSubstitutionProcessor2(base
, success
);
199 case mstReservedUnused
:
202 case mstNonContextualGlyphSubstitution
:
203 processor
= NonContextualGlyphSubstitutionProcessor2::createInstance(base
, success
);
207 case mstContextualGlyphInsertion
:
208 processor
= new ContextualGlyphInsertionProcessor2(base
, success
);
213 break; /*NOTREACHED*/
216 if (processor
!= NULL
) {
217 processor
->process(glyphStorage
, success
);
220 if(LE_SUCCESS(success
)) {
221 success
= LE_MEMORY_ALLOCATION_ERROR
; // because ptr is null and we didn't break out.