3 * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
8 #include "LEGlyphFilter.h"
9 #include "OpenTypeTables.h"
10 #include "LEGlyphStorage.h"
11 #include "ThaiShaping.h"
18 CH_MAI_HANAKAT
= 0x0E31,
22 CH_MAITAIKHU
= 0x0E47,
28 CH_DOTTED_CIRCLE
= 0x25CC
31 le_uint8
ThaiShaping::getCharClass(LEUnicode ch
)
33 le_uint8 charClass
= NON
;
35 if (ch
>= 0x0E00 && ch
<= 0x0E5B) {
36 charClass
= classTable
[ch
- 0x0E00];
43 LEUnicode
ThaiShaping::leftAboveVowel(LEUnicode vowel
, le_uint8 glyphSet
)
45 static const LEUnicode leftAboveVowels
[][7] = {
46 {0x0E61, 0x0E32, 0x0E33, 0x0E64, 0x0E65, 0x0E66, 0x0E67},
47 {0xF710, 0x0E32, 0x0E33, 0xF701, 0xF702, 0xF703, 0xF704},
48 {0xF884, 0x0E32, 0x0E33, 0xF885, 0xF886, 0xF887, 0xF788},
49 {0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37}
52 if (vowel
>= CH_MAI_HANAKAT
&& vowel
<= CH_SARA_UEE
) {
53 return leftAboveVowels
[glyphSet
][vowel
- CH_MAI_HANAKAT
];
56 if (vowel
== CH_YAMAKKAN
&& glyphSet
== 0) {
63 LEUnicode
ThaiShaping::lowerRightTone(LEUnicode tone
, le_uint8 glyphSet
)
65 static const LEUnicode lowerRightTones
[][7] = {
66 {0x0E68, 0x0E69, 0x0E6A, 0x0E6B, 0x0E6C, 0x0E6D, 0x0E6E},
67 {0x0E47, 0xF70A, 0xF70B, 0xF70C, 0xF70D, 0xF70E, 0x0E4D},
68 {0x0E47, 0xF88B, 0xF88E, 0xF891, 0xF894, 0xF897, 0x0E4D},
69 {0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
72 if (tone
>= CH_MAITAIKHU
&& tone
<= CH_NIKHAHIT
) {
73 return lowerRightTones
[glyphSet
][tone
- CH_MAITAIKHU
];
79 LEUnicode
ThaiShaping::lowerLeftTone(LEUnicode tone
, le_uint8 glyphSet
)
81 static const LEUnicode lowerLeftTones
[][7] = {
82 {0x0E76, 0x0E77, 0x0E78, 0x0E79, 0x0E7A, 0x0E7B, 0x0E7C},
83 {0xF712, 0xF705, 0xF706, 0xF707, 0xF708, 0xF709, 0xF711},
84 {0xF889, 0xF88C, 0xF88F, 0xF892, 0xF895, 0xF898, 0xF899},
85 {0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
88 if (tone
>= CH_MAITAIKHU
&& tone
<= CH_NIKHAHIT
) {
89 return lowerLeftTones
[glyphSet
][tone
- CH_MAITAIKHU
];
95 LEUnicode
ThaiShaping::upperLeftTone(LEUnicode tone
, le_uint8 glyphSet
)
97 static const LEUnicode upperLeftTones
[][7] = {
98 {0x0E6F, 0x0E70, 0x0E71, 0x0E72, 0x0E73, 0x0E74, 0x0E75},
99 {0xF712, 0xF713, 0xF714, 0xF715, 0xF716, 0xF717, 0xF711},
100 {0xF889, 0xF88A, 0xF88D, 0xF890, 0xF893, 0xF896, 0xF899},
101 {0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
104 if (tone
>= CH_MAITAIKHU
&& tone
<= CH_NIKHAHIT
) {
105 return upperLeftTones
[glyphSet
][tone
- CH_MAITAIKHU
];
111 LEUnicode
ThaiShaping::lowerBelowVowel(LEUnicode vowel
, le_uint8 glyphSet
)
113 static const LEUnicode lowerBelowVowels
[][3] = {
114 {0x0E3C, 0x0E3D, 0x0E3E},
115 {0xF718, 0xF719, 0xF71A},
116 {0x0E38, 0x0E39, 0x0E3A},
117 {0x0E38, 0x0E39, 0x0E3A}
121 if (vowel
>= CH_SARA_U
&& vowel
<= CH_PHINTHU
) {
122 return lowerBelowVowels
[glyphSet
][vowel
- CH_SARA_U
];
128 LEUnicode
ThaiShaping::noDescenderCOD(LEUnicode cod
, le_uint8 glyphSet
)
130 static const LEUnicode noDescenderCODs
[][4] = {
131 {0x0E60, 0x0E0E, 0x0E0F, 0x0E63},
132 {0xF70F, 0x0E0E, 0x0E0F, 0xF700},
133 {0x0E0D, 0x0E0E, 0x0E0F, 0x0E10},
134 {0x0E0D, 0x0E0E, 0x0E0F, 0x0E10}
138 if (cod
>= CH_YO_YING
&& cod
<= CH_THO_THAN
) {
139 return noDescenderCODs
[glyphSet
][cod
- CH_YO_YING
];
145 le_uint8
ThaiShaping::doTransition (StateTransition transition
, LEUnicode currChar
, le_int32 inputIndex
, le_uint8 glyphSet
,
146 LEUnicode errorChar
, LEUnicode
*outputBuffer
, LEGlyphStorage
&glyphStorage
, le_int32
&outputIndex
)
148 LEErrorCode success
= LE_NO_ERROR
;
150 switch (transition
.action
) {
152 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
153 outputBuffer
[outputIndex
++] = currChar
;
157 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
158 outputBuffer
[outputIndex
++] = currChar
;
162 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
163 outputBuffer
[outputIndex
++] = leftAboveVowel(currChar
, glyphSet
);
167 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
168 outputBuffer
[outputIndex
++] = lowerRightTone(currChar
, glyphSet
);
172 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
173 outputBuffer
[outputIndex
++] = lowerLeftTone(currChar
, glyphSet
);
177 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
178 outputBuffer
[outputIndex
++] = upperLeftTone(currChar
, glyphSet
);
183 LEUnicode cod
= outputBuffer
[outputIndex
- 1];
184 LEUnicode coa
= noDescenderCOD(cod
, glyphSet
);
187 outputBuffer
[outputIndex
- 1] = coa
;
189 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
190 outputBuffer
[outputIndex
++] = currChar
;
194 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
195 outputBuffer
[outputIndex
++] = lowerBelowVowel(currChar
, glyphSet
);
200 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
201 outputBuffer
[outputIndex
++] = errorChar
;
203 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
204 outputBuffer
[outputIndex
++] = currChar
;
208 if (currChar
== CH_SARA_AM
) {
209 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
210 outputBuffer
[outputIndex
++] = errorChar
;
213 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
214 outputBuffer
[outputIndex
++] = currChar
;
218 // FIXME: if we get here, there's an error
219 // in the state table!
220 glyphStorage
.setCharIndex(outputIndex
, inputIndex
, success
);
221 outputBuffer
[outputIndex
++] = currChar
;
225 return transition
.nextState
;
228 le_uint8
ThaiShaping::getNextState(LEUnicode ch
, le_uint8 prevState
, le_int32 inputIndex
, le_uint8 glyphSet
, LEUnicode errorChar
,
229 le_uint8
&charClass
, LEUnicode
*output
, LEGlyphStorage
&glyphStorage
, le_int32
&outputIndex
)
231 StateTransition transition
;
233 charClass
= getCharClass(ch
);
234 transition
= getTransition(prevState
, charClass
);
236 return doTransition(transition
, ch
, inputIndex
, glyphSet
, errorChar
, output
, glyphStorage
, outputIndex
);
239 le_bool
ThaiShaping::isLegalHere(LEUnicode ch
, le_uint8 prevState
)
241 le_uint8 charClass
= getCharClass(ch
);
242 StateTransition transition
= getTransition(prevState
, charClass
);
244 switch (transition
.action
) {
259 // FIXME: if we get here, there's an error
260 // in the state table!
265 le_int32
ThaiShaping::compose(const LEUnicode
*input
, le_int32 offset
, le_int32 charCount
, le_uint8 glyphSet
,
266 LEUnicode errorChar
, LEUnicode
*output
, LEGlyphStorage
&glyphStorage
)
270 le_int32 outputIndex
= 0;
271 le_uint8 conState
= 0xFF;
272 le_int32 conInput
= -1;
273 le_int32 conOutput
= -1;
275 for (inputIndex
= 0; inputIndex
< charCount
; inputIndex
+= 1) {
276 LEUnicode ch
= input
[inputIndex
+ offset
];
279 // Decompose SARA AM into NIKHAHIT + SARA AA
280 if (ch
== CH_SARA_AM
&& isLegalHere(ch
, state
)) {
281 outputIndex
= conOutput
;
282 state
= getNextState(CH_NIKHAHIT
, conState
, inputIndex
, glyphSet
, errorChar
, charClass
,
283 output
, glyphStorage
, outputIndex
);
285 for (int j
= conInput
+ 1; j
< inputIndex
; j
+= 1) {
286 ch
= input
[j
+ offset
];
287 state
= getNextState(ch
, state
, j
, glyphSet
, errorChar
, charClass
,
288 output
, glyphStorage
, outputIndex
);
294 state
= getNextState(ch
, state
, inputIndex
, glyphSet
, errorChar
, charClass
,
295 output
, glyphStorage
, outputIndex
);
297 if (charClass
>= CON
&& charClass
<= COD
) {
299 conInput
= inputIndex
;
300 conOutput
= outputIndex
;