]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
b75a7d8f | 2 | * |
57a6839d | 3 | * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved |
b75a7d8f A |
4 | * |
5 | */ | |
6 | ||
7 | #include "LETypes.h" | |
8 | #include "OpenTypeTables.h" | |
9 | #include "ArabicShaping.h" | |
374ca955 | 10 | #include "LEGlyphStorage.h" |
73c04bcf | 11 | #include "ClassDefinitionTables.h" |
b75a7d8f A |
12 | |
13 | U_NAMESPACE_BEGIN | |
14 | ||
73c04bcf A |
15 | // This table maps Unicode joining types to |
16 | // ShapeTypes. | |
b75a7d8f A |
17 | const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] = |
18 | { | |
73c04bcf A |
19 | ArabicShaping::ST_NOSHAPE_NONE, // [U] |
20 | ArabicShaping::ST_NOSHAPE_DUAL, // [C] | |
21 | ArabicShaping::ST_DUAL, // [D] | |
22 | ArabicShaping::ST_LEFT, // [L] | |
23 | ArabicShaping::ST_RIGHT, // [R] | |
24 | ArabicShaping::ST_TRANSPARENT // [T] | |
b75a7d8f A |
25 | }; |
26 | ||
27 | /* | |
374ca955 | 28 | shaping array holds types for Arabic chars between 0610 and 0700 |
b75a7d8f | 29 | other values are either unshaped, or transparent if a mark or format |
57a6839d | 30 | code, except for format codes 200c (zero-width non-joiner) and 200d |
b75a7d8f A |
31 | (dual-width joiner) which are both unshaped and non_joining or |
32 | dual-joining, respectively. | |
33 | */ | |
34 | ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c) | |
35 | { | |
57a6839d A |
36 | LEErrorCode success = LE_NO_ERROR; |
37 | const LEReferenceTo<ClassDefinitionTable> joiningTypes((const ClassDefinitionTable *) ArabicShaping::shapingTypeTable, | |
38 | ArabicShaping::shapingTypeTableLen); | |
39 | le_int32 joiningType = joiningTypes->getGlyphClass(joiningTypes, c, success); | |
73c04bcf | 40 | |
57a6839d A |
41 | if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT && LE_SUCCESS(success)) { |
42 | return ArabicShaping::shapeTypes[joiningType]; | |
43 | } | |
b75a7d8f | 44 | |
57a6839d | 45 | return ArabicShaping::ST_NOSHAPE_NONE; |
b75a7d8f A |
46 | } |
47 | ||
73c04bcf A |
48 | #define isolFeatureTag LE_ISOL_FEATURE_TAG |
49 | #define initFeatureTag LE_INIT_FEATURE_TAG | |
50 | #define mediFeatureTag LE_MEDI_FEATURE_TAG | |
51 | #define finaFeatureTag LE_FINA_FEATURE_TAG | |
52 | #define ligaFeatureTag LE_LIGA_FEATURE_TAG | |
53 | #define msetFeatureTag LE_MSET_FEATURE_TAG | |
54 | #define markFeatureTag LE_MARK_FEATURE_TAG | |
55 | #define ccmpFeatureTag LE_CCMP_FEATURE_TAG | |
56 | #define rligFeatureTag LE_RLIG_FEATURE_TAG | |
57 | #define caltFeatureTag LE_CALT_FEATURE_TAG | |
58 | #define dligFeatureTag LE_DLIG_FEATURE_TAG | |
59 | #define cswhFeatureTag LE_CSWH_FEATURE_TAG | |
60 | #define cursFeatureTag LE_CURS_FEATURE_TAG | |
61 | #define kernFeatureTag LE_KERN_FEATURE_TAG | |
62 | #define mkmkFeatureTag LE_MKMK_FEATURE_TAG | |
63 | ||
64 | // NOTE: | |
65 | // The isol, fina, init and medi features must be | |
66 | // defined in the above order, and have masks that | |
67 | // are all in the same nibble. | |
68 | #define isolFeatureMask 0x80000000UL | |
69 | #define finaFeatureMask 0x40000000UL | |
70 | #define initFeatureMask 0x20000000UL | |
71 | #define mediFeatureMask 0x10000000UL | |
72 | #define ccmpFeatureMask 0x08000000UL | |
73 | #define rligFeatureMask 0x04000000UL | |
74 | #define caltFeatureMask 0x02000000UL | |
75 | #define ligaFeatureMask 0x01000000UL | |
76 | #define dligFeatureMask 0x00800000UL | |
77 | #define cswhFeatureMask 0x00400000UL | |
78 | #define msetFeatureMask 0x00200000UL | |
79 | #define cursFeatureMask 0x00100000UL | |
80 | #define kernFeatureMask 0x00080000UL | |
81 | #define markFeatureMask 0x00040000UL | |
82 | #define mkmkFeatureMask 0x00020000UL | |
83 | ||
46f4442e | 84 | #define NO_FEATURES 0 |
73c04bcf A |
85 | #define ISOL_FEATURES (isolFeatureMask | ligaFeatureMask | msetFeatureMask | markFeatureMask | ccmpFeatureMask | rligFeatureMask | caltFeatureMask | dligFeatureMask | cswhFeatureMask | cursFeatureMask | kernFeatureMask | mkmkFeatureMask) |
86 | ||
87 | #define SHAPE_MASK 0xF0000000UL | |
88 | ||
89 | static const FeatureMap featureMap[] = { | |
90 | {ccmpFeatureTag, ccmpFeatureMask}, | |
91 | {isolFeatureTag, isolFeatureMask}, | |
92 | {finaFeatureTag, finaFeatureMask}, | |
93 | {mediFeatureTag, mediFeatureMask}, | |
94 | {initFeatureTag, initFeatureMask}, | |
95 | {rligFeatureTag, rligFeatureMask}, | |
96 | {caltFeatureTag, caltFeatureMask}, | |
97 | {ligaFeatureTag, ligaFeatureMask}, | |
98 | {dligFeatureTag, dligFeatureMask}, | |
99 | {cswhFeatureTag, cswhFeatureMask}, | |
100 | {msetFeatureTag, msetFeatureMask}, | |
101 | {cursFeatureTag, cursFeatureMask}, | |
102 | {kernFeatureTag, kernFeatureMask}, | |
103 | {markFeatureTag, markFeatureMask}, | |
104 | {mkmkFeatureTag, mkmkFeatureMask} | |
b75a7d8f A |
105 | }; |
106 | ||
73c04bcf | 107 | const FeatureMap *ArabicShaping::getFeatureMap(le_int32 &count) |
b75a7d8f | 108 | { |
73c04bcf | 109 | count = LE_ARRAY_SIZE(featureMap); |
b75a7d8f | 110 | |
73c04bcf | 111 | return featureMap; |
b75a7d8f A |
112 | } |
113 | ||
374ca955 A |
114 | void ArabicShaping::adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage) |
115 | { | |
116 | LEErrorCode success = LE_NO_ERROR; | |
73c04bcf A |
117 | FeatureMask featureMask = (FeatureMask) glyphStorage.getAuxData(outIndex, success); |
118 | FeatureMask shape = featureMask & SHAPE_MASK; | |
119 | ||
120 | shape >>= shapeOffset; | |
374ca955 | 121 | |
73c04bcf | 122 | glyphStorage.setAuxData(outIndex, ((featureMask & ~SHAPE_MASK) | shape), success); |
374ca955 A |
123 | } |
124 | ||
b75a7d8f | 125 | void ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 charCount, le_int32 charMax, |
374ca955 | 126 | le_bool rightToLeft, LEGlyphStorage &glyphStorage) |
b75a7d8f A |
127 | { |
128 | // iterate in logical order, store tags in visible order | |
57a6839d A |
129 | // |
130 | // the effective right char is the most recently encountered | |
b75a7d8f A |
131 | // non-transparent char |
132 | // | |
133 | // four boolean states: | |
134 | // the effective right char shapes | |
135 | // the effective right char causes left shaping | |
136 | // the current char shapes | |
137 | // the current char causes right shaping | |
57a6839d | 138 | // |
b75a7d8f A |
139 | // if both cause shaping, then |
140 | // shaper.shape(errout, 2) (isolate to initial, or final to medial) | |
141 | // shaper.shape(out, 1) (isolate to final) | |
142 | ||
143 | ShapeType rightType = ST_NOSHAPE_NONE, leftType = ST_NOSHAPE_NONE; | |
374ca955 | 144 | LEErrorCode success = LE_NO_ERROR; |
b75a7d8f A |
145 | le_int32 i; |
146 | ||
147 | for (i = offset - 1; i >= 0; i -= 1) { | |
148 | rightType = getShapeType(chars[i]); | |
57a6839d | 149 | |
b75a7d8f A |
150 | if (rightType != ST_TRANSPARENT) { |
151 | break; | |
152 | } | |
153 | } | |
154 | ||
155 | for (i = offset + charCount; i < charMax; i += 1) { | |
156 | leftType = getShapeType(chars[i]); | |
157 | ||
158 | if (leftType != ST_TRANSPARENT) { | |
159 | break; | |
160 | } | |
161 | } | |
162 | ||
163 | // erout is effective right logical index | |
164 | le_int32 erout = -1; | |
374ca955 | 165 | le_bool rightShapes = FALSE; |
b75a7d8f A |
166 | le_bool rightCauses = (rightType & MASK_SHAPE_LEFT) != 0; |
167 | le_int32 in, e, out = 0, dir = 1; | |
168 | ||
169 | if (rightToLeft) { | |
170 | out = charCount - 1; | |
171 | erout = charCount; | |
172 | dir = -1; | |
173 | } | |
174 | ||
175 | for (in = offset, e = offset + charCount; in < e; in += 1, out += dir) { | |
176 | LEUnicode c = chars[in]; | |
177 | ShapeType t = getShapeType(c); | |
178 | ||
46f4442e A |
179 | if (t == ST_NOSHAPE_NONE) { |
180 | glyphStorage.setAuxData(out, NO_FEATURES, success); | |
181 | } else { | |
182 | glyphStorage.setAuxData(out, ISOL_FEATURES, success); | |
183 | } | |
b75a7d8f A |
184 | |
185 | if ((t & MASK_TRANSPARENT) != 0) { | |
186 | continue; | |
187 | } | |
188 | ||
189 | le_bool curShapes = (t & MASK_NOSHAPE) == 0; | |
190 | le_bool curCauses = (t & MASK_SHAPE_RIGHT) != 0; | |
191 | ||
192 | if (rightCauses && curCauses) { | |
193 | if (rightShapes) { | |
374ca955 | 194 | adjustTags(erout, 2, glyphStorage); |
b75a7d8f A |
195 | } |
196 | ||
197 | if (curShapes) { | |
374ca955 | 198 | adjustTags(out, 1, glyphStorage); |
b75a7d8f A |
199 | } |
200 | } | |
201 | ||
202 | rightShapes = curShapes; | |
203 | rightCauses = (t & MASK_SHAPE_LEFT) != 0; | |
204 | erout = out; | |
205 | } | |
206 | ||
207 | if (rightShapes && rightCauses && (leftType & MASK_SHAPE_RIGHT) != 0) { | |
374ca955 | 208 | adjustTags(erout, 2, glyphStorage); |
b75a7d8f A |
209 | } |
210 | } | |
211 | ||
b75a7d8f | 212 | U_NAMESPACE_END |