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