]>
git.saurik.com Git - apple/icu.git/blob - icuSources/layout/ArabicShaping.cpp
3 * (C) Copyright IBM Corp. 1998-2013 - 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 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
);
41 if (joiningType
>= 0 && joiningType
< ArabicShaping::JT_COUNT
&& LE_SUCCESS(success
)) {
42 return ArabicShaping::shapeTypes
[joiningType
];
45 return ArabicShaping::ST_NOSHAPE_NONE
;
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
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
85 #define ISOL_FEATURES (isolFeatureMask | ligaFeatureMask | msetFeatureMask | markFeatureMask | ccmpFeatureMask | rligFeatureMask | caltFeatureMask | dligFeatureMask | cswhFeatureMask | cursFeatureMask | kernFeatureMask | mkmkFeatureMask)
87 #define SHAPE_MASK 0xF0000000UL
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
}
107 const FeatureMap
*ArabicShaping::getFeatureMap(le_int32
&count
)
109 count
= LE_ARRAY_SIZE(featureMap
);
114 void ArabicShaping::adjustTags(le_int32 outIndex
, le_int32 shapeOffset
, LEGlyphStorage
&glyphStorage
)
116 LEErrorCode success
= LE_NO_ERROR
;
117 FeatureMask featureMask
= (FeatureMask
) glyphStorage
.getAuxData(outIndex
, success
);
118 FeatureMask shape
= featureMask
& SHAPE_MASK
;
120 shape
>>= shapeOffset
;
122 glyphStorage
.setAuxData(outIndex
, ((featureMask
& ~SHAPE_MASK
) | shape
), success
);
125 void ArabicShaping::shape(const LEUnicode
*chars
, le_int32 offset
, le_int32 charCount
, le_int32 charMax
,
126 le_bool rightToLeft
, LEGlyphStorage
&glyphStorage
)
128 // iterate in logical order, store tags in visible order
130 // the effective right char is the most recently encountered
131 // non-transparent char
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
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)
143 ShapeType rightType
= ST_NOSHAPE_NONE
, leftType
= ST_NOSHAPE_NONE
;
144 LEErrorCode success
= LE_NO_ERROR
;
147 for (i
= offset
- 1; i
>= 0; i
-= 1) {
148 rightType
= getShapeType(chars
[i
]);
150 if (rightType
!= ST_TRANSPARENT
) {
155 for (i
= offset
+ charCount
; i
< charMax
; i
+= 1) {
156 leftType
= getShapeType(chars
[i
]);
158 if (leftType
!= ST_TRANSPARENT
) {
163 // erout is effective right logical index
165 le_bool rightShapes
= FALSE
;
166 le_bool rightCauses
= (rightType
& MASK_SHAPE_LEFT
) != 0;
167 le_int32 in
, e
, out
= 0, dir
= 1;
175 for (in
= offset
, e
= offset
+ charCount
; in
< e
; in
+= 1, out
+= dir
) {
176 LEUnicode c
= chars
[in
];
177 ShapeType t
= getShapeType(c
);
179 if (t
== ST_NOSHAPE_NONE
) {
180 glyphStorage
.setAuxData(out
, NO_FEATURES
, success
);
182 glyphStorage
.setAuxData(out
, ISOL_FEATURES
, success
);
185 if ((t
& MASK_TRANSPARENT
) != 0) {
189 le_bool curShapes
= (t
& MASK_NOSHAPE
) == 0;
190 le_bool curCauses
= (t
& MASK_SHAPE_RIGHT
) != 0;
192 if (rightCauses
&& curCauses
) {
194 adjustTags(erout
, 2, glyphStorage
);
198 adjustTags(out
, 1, glyphStorage
);
202 rightShapes
= curShapes
;
203 rightCauses
= (t
& MASK_SHAPE_LEFT
) != 0;
207 if (rightShapes
&& rightCauses
&& (leftType
& MASK_SHAPE_RIGHT
) != 0) {
208 adjustTags(erout
, 2, glyphStorage
);