]>
git.saurik.com Git - apple/icu.git/blob - icuSources/layout/ArabicShaping.cpp
3 * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
8 #include "OpenTypeTables.h"
9 #include "ArabicShaping.h"
10 #include "LEGlyphStorage.h"
11 #include "ClassDefinitionTables.h"
15 // This table maps Unicode joining types to
17 const ArabicShaping::ShapeType
ArabicShaping::shapeTypes
[] =
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]
28 shaping array holds types for Arabic chars between 0610 and 0700
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.
34 ArabicShaping::ShapeType
ArabicShaping::getShapeType(LEUnicode c
)
36 const ClassDefinitionTable
*joiningTypes
= (const ClassDefinitionTable
*) ArabicShaping::shapingTypeTable
;
37 le_int32 joiningType
= joiningTypes
->getGlyphClass(c
);
39 if (joiningType
>= 0 && joiningType
< ArabicShaping::JT_COUNT
) {
40 return ArabicShaping::shapeTypes
[joiningType
];
43 return ArabicShaping::ST_NOSHAPE_NONE
;
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
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
83 #define ISOL_FEATURES (isolFeatureMask | ligaFeatureMask | msetFeatureMask | markFeatureMask | ccmpFeatureMask | rligFeatureMask | caltFeatureMask | dligFeatureMask | cswhFeatureMask | cursFeatureMask | kernFeatureMask | mkmkFeatureMask)
85 #define SHAPE_MASK 0xF0000000UL
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
}
105 const FeatureMap
*ArabicShaping::getFeatureMap(le_int32
&count
)
107 count
= LE_ARRAY_SIZE(featureMap
);
112 void ArabicShaping::adjustTags(le_int32 outIndex
, le_int32 shapeOffset
, LEGlyphStorage
&glyphStorage
)
114 LEErrorCode success
= LE_NO_ERROR
;
115 FeatureMask featureMask
= (FeatureMask
) glyphStorage
.getAuxData(outIndex
, success
);
116 FeatureMask shape
= featureMask
& SHAPE_MASK
;
118 shape
>>= shapeOffset
;
120 glyphStorage
.setAuxData(outIndex
, ((featureMask
& ~SHAPE_MASK
) | shape
), success
);
123 void ArabicShaping::shape(const LEUnicode
*chars
, le_int32 offset
, le_int32 charCount
, le_int32 charMax
,
124 le_bool rightToLeft
, LEGlyphStorage
&glyphStorage
)
126 // iterate in logical order, store tags in visible order
128 // the effective right char is the most recently encountered
129 // non-transparent char
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
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)
141 ShapeType rightType
= ST_NOSHAPE_NONE
, leftType
= ST_NOSHAPE_NONE
;
142 LEErrorCode success
= LE_NO_ERROR
;
145 for (i
= offset
- 1; i
>= 0; i
-= 1) {
146 rightType
= getShapeType(chars
[i
]);
148 if (rightType
!= ST_TRANSPARENT
) {
153 for (i
= offset
+ charCount
; i
< charMax
; i
+= 1) {
154 leftType
= getShapeType(chars
[i
]);
156 if (leftType
!= ST_TRANSPARENT
) {
161 // erout is effective right logical index
163 le_bool rightShapes
= FALSE
;
164 le_bool rightCauses
= (rightType
& MASK_SHAPE_LEFT
) != 0;
165 le_int32 in
, e
, out
= 0, dir
= 1;
173 for (in
= offset
, e
= offset
+ charCount
; in
< e
; in
+= 1, out
+= dir
) {
174 LEUnicode c
= chars
[in
];
175 ShapeType t
= getShapeType(c
);
177 if (t
== ST_NOSHAPE_NONE
) {
178 glyphStorage
.setAuxData(out
, NO_FEATURES
, success
);
180 glyphStorage
.setAuxData(out
, ISOL_FEATURES
, success
);
183 if ((t
& MASK_TRANSPARENT
) != 0) {
187 le_bool curShapes
= (t
& MASK_NOSHAPE
) == 0;
188 le_bool curCauses
= (t
& MASK_SHAPE_RIGHT
) != 0;
190 if (rightCauses
&& curCauses
) {
192 adjustTags(erout
, 2, glyphStorage
);
196 adjustTags(out
, 1, glyphStorage
);
200 rightShapes
= curShapes
;
201 rightCauses
= (t
& MASK_SHAPE_LEFT
) != 0;
205 if (rightShapes
&& rightCauses
&& (leftType
& MASK_SHAPE_RIGHT
) != 0) {
206 adjustTags(erout
, 2, glyphStorage
);