]> git.saurik.com Git - apple/icu.git/blob - icuSources/layout/ArabicShaping.cpp
ICU-6.2.4.tar.gz
[apple/icu.git] / icuSources / layout / ArabicShaping.cpp
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