|
1 /* |
|
2 * |
|
3 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved |
|
4 * |
|
5 */ |
|
6 |
|
7 #include "LETypes.h" |
|
8 #include "OpenTypeTables.h" |
|
9 #include "ArabicShaping.h" |
|
10 #include "LEGlyphStorage.h" |
|
11 |
|
12 U_NAMESPACE_BEGIN |
|
13 |
|
14 enum { |
|
15 _c_ = ArabicShaping::ST_NOSHAPE_DUAL, |
|
16 _d_ = ArabicShaping::ST_DUAL, |
|
17 _n_ = ArabicShaping::ST_NONE, |
|
18 _r_ = ArabicShaping::ST_RIGHT, |
|
19 _t_ = ArabicShaping::ST_TRANSPARENT, |
|
20 _x_ = ArabicShaping::ST_NOSHAPE_NONE |
|
21 }; |
|
22 |
|
23 const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] = |
|
24 { |
|
25 _t_, _t_, _t_, _t_, _t_, _t_, _x_, _x_, _x_, _x_, _x_, _n_, _x_, _x_, _x_, _n_, // 0x610 - 0x61f |
|
26 _x_, _n_, _r_, _r_, _r_, _r_, _d_, _r_, _d_, _r_, _d_, _d_, _d_, _d_, _d_, _r_, // 0x620 - 0x62f |
|
27 _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _x_, _x_, _x_, _x_, _x_, // 0x630 - 0x63f |
|
28 _c_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _r_, _d_, _d_, _t_, _t_, _t_, _t_, _t_, // 0x640 - 0x64f |
|
29 _t_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _x_, _x_, _x_, _x_, _x_, _x_, _x_, // 0x650 - 0x65f |
|
30 _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _d_, _d_, // 0x660 - 0x66f |
|
31 _t_, _r_, _r_, _r_, _n_, _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x670 - 0x67f |
|
32 _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, // 0x680 - 0x68f |
|
33 _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x690 - 0x69f |
|
34 _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x6a0 - 0x6af |
|
35 _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x6b0 - 0x6bf |
|
36 _r_, _d_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _d_, _r_, _d_, _r_, // 0x6c0 - 0x6cf |
|
37 _d_, _d_, _r_, _r_, _n_, _r_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _x_, _t_, _t_, // 0x6d0 - 0x6df |
|
38 _t_, _t_, _t_, _t_, _t_, _n_, _n_, _t_, _t_, _n_, _t_, _t_, _t_, _t_, _r_, _r_, // 0x6e0 - 0x6ef |
|
39 _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _d_, _d_, _d_, _n_, _n_, _d_ // 0x6f0 - 0x6ff |
|
40 }; |
|
41 |
|
42 /* |
|
43 shaping array holds types for Arabic chars between 0610 and 0700 |
|
44 other values are either unshaped, or transparent if a mark or format |
|
45 code, except for format codes 200c (zero-width non-joiner) and 200d |
|
46 (dual-width joiner) which are both unshaped and non_joining or |
|
47 dual-joining, respectively. |
|
48 */ |
|
49 ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c) |
|
50 { |
|
51 if (c >= 0x0610 && c <= 0x206f) { |
|
52 if (c < 0x0700) { |
|
53 return shapeTypes[c - 0x0610]; |
|
54 } else if (c == 0x200c) { // ZWNJ |
|
55 return ST_NOSHAPE_NONE; |
|
56 } else if (c == 0x200d) { // ZWJ |
|
57 return ST_NOSHAPE_DUAL; |
|
58 } else if (c >= 0x202a && c <= 0x202e) { // LRE - RLO |
|
59 return ST_TRANSPARENT; |
|
60 } else if (c >= 0x206a && c <= 0x206f) { // Inhibit Symmetric Swapping - Nominal Digit Shapes |
|
61 return ST_TRANSPARENT; |
|
62 } |
|
63 } |
|
64 |
|
65 return ST_NOSHAPE_NONE; |
|
66 } |
|
67 |
|
68 static const LETag isolFeatureTag = LE_ISOL_FEATURE_TAG; |
|
69 static const LETag initFeatureTag = LE_INIT_FEATURE_TAG; |
|
70 static const LETag mediFeatureTag = LE_MEDI_FEATURE_TAG; |
|
71 static const LETag finaFeatureTag = LE_FINA_FEATURE_TAG; |
|
72 static const LETag ligaFeatureTag = LE_LIGA_FEATURE_TAG; |
|
73 static const LETag msetFeatureTag = LE_MSET_FEATURE_TAG; |
|
74 static const LETag markFeatureTag = LE_MARK_FEATURE_TAG; |
|
75 static const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG; |
|
76 static const LETag rligFeatureTag = LE_RLIG_FEATURE_TAG; |
|
77 static const LETag caltFeatureTag = LE_CALT_FEATURE_TAG; |
|
78 static const LETag dligFeatureTag = LE_DLIG_FEATURE_TAG; |
|
79 static const LETag cswhFeatureTag = LE_CSWH_FEATURE_TAG; |
|
80 static const LETag cursFeatureTag = LE_CURS_FEATURE_TAG; |
|
81 static const LETag kernFeatureTag = LE_KERN_FEATURE_TAG; |
|
82 static const LETag mkmkFeatureTag = LE_MKMK_FEATURE_TAG; |
|
83 |
|
84 static const LETag emptyTag = 0x00000000; // '' |
|
85 |
|
86 static const LETag featureOrder[] = |
|
87 { |
|
88 ccmpFeatureTag, isolFeatureTag, finaFeatureTag, mediFeatureTag, initFeatureTag, rligFeatureTag, |
|
89 caltFeatureTag, ligaFeatureTag, dligFeatureTag, cswhFeatureTag, msetFeatureTag, cursFeatureTag, |
|
90 kernFeatureTag, markFeatureTag, mkmkFeatureTag, emptyTag |
|
91 }; |
|
92 |
|
93 const LETag ArabicShaping::tagArray[] = |
|
94 { |
|
95 isolFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag, |
|
96 caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag, |
|
97 |
|
98 finaFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag, |
|
99 caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag, |
|
100 |
|
101 initFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag, |
|
102 caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag, |
|
103 |
|
104 mediFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag, |
|
105 caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag |
|
106 }; |
|
107 |
|
108 #define TAGS_PER_GLYPH ((sizeof ArabicShaping::tagArray / sizeof ArabicShaping::tagArray[0]) / 4) |
|
109 |
|
110 const LETag *ArabicShaping::getFeatureOrder() |
|
111 { |
|
112 return featureOrder; |
|
113 } |
|
114 |
|
115 void ArabicShaping::adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage) |
|
116 { |
|
117 LEErrorCode success = LE_NO_ERROR; |
|
118 const LETag *glyphTags = (const LETag *) glyphStorage.getAuxData(outIndex, success); |
|
119 |
|
120 glyphStorage.setAuxData(outIndex, (void *) &glyphTags[TAGS_PER_GLYPH * shapeOffset], success); |
|
121 } |
|
122 |
|
123 void ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 charCount, le_int32 charMax, |
|
124 le_bool rightToLeft, LEGlyphStorage &glyphStorage) |
|
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; |
|
142 LEErrorCode success = LE_NO_ERROR; |
|
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; |
|
163 le_bool rightShapes = FALSE; |
|
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 |
|
177 glyphStorage.setAuxData(out, (void *) tagArray, success); |
|
178 |
|
179 if ((t & MASK_TRANSPARENT) != 0) { |
|
180 continue; |
|
181 } |
|
182 |
|
183 le_bool curShapes = (t & MASK_NOSHAPE) == 0; |
|
184 le_bool curCauses = (t & MASK_SHAPE_RIGHT) != 0; |
|
185 |
|
186 if (rightCauses && curCauses) { |
|
187 if (rightShapes) { |
|
188 adjustTags(erout, 2, glyphStorage); |
|
189 } |
|
190 |
|
191 if (curShapes) { |
|
192 adjustTags(out, 1, glyphStorage); |
|
193 } |
|
194 } |
|
195 |
|
196 rightShapes = curShapes; |
|
197 rightCauses = (t & MASK_SHAPE_LEFT) != 0; |
|
198 erout = out; |
|
199 } |
|
200 |
|
201 if (rightShapes && rightCauses && (leftType & MASK_SHAPE_RIGHT) != 0) { |
|
202 adjustTags(erout, 2, glyphStorage); |
|
203 } |
|
204 } |
|
205 |
|
206 U_NAMESPACE_END |