Update contrib.
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
27 // ThaiGlyph Namespace definition
32 This namespace holds functions used to evaluate a glyph character code
33 against a given Thai related prediciate. The 'code' argument is a glyph
34 from the current output cluster and so may be a Thai glyph, Thai PUA glyph,
35 the dotted circle glyph or 0xffff. Therefore it was decided not to implement
36 these routines using a data driven table approach as it would be inefficient.
41 const TText16 KYoYing = 0x0E0D;
42 const TText16 KYoYingPua = 0xF70F;
43 const TText16 KThoThan = 0x0E10;
44 const TText16 KThoThanPua = 0xF700;
45 const TText16 KNikhahit = 0x0E4D;
46 const TText16 KNikhahitPua = 0xF711;
47 const TText16 KSaraAa = 0x0E32;
48 const TText16 KSaraAm = 0x0E33;
51 TBool IsThaiGlyph(TUint code)
53 return ((code > 0x0E00 && code < 0x0E3B) ||
54 (code > 0x0E3E && code < 0x0E5C) ||
55 (code >= 0xF700 && code <= 0xF71A));
58 TBool IsThaiConsonant(TUint code)
60 return (code >= 0x0E01 && code <= 0x0E2E);
63 TBool IsThaiTallConsonant(TUint code)
65 return (//code == 0x0E0A || // CHO CHANG not tall at all
66 //code == 0x0E0B || // SO SO not tall at all
67 code == 0x0E1B || // PO PLA
68 code == 0x0E1D || // FO FA
69 code == 0x0E1F || // FO FAN
70 code == 0x0E2C); // LO CHULA in some fonts, Unicode tables show it as tall
73 TBool IsThaiShortConsonant(TUint code)
75 return (((code >= 0x0E01 && code <= 0x0E2E) || (code == KUnicodeDottedCircle)) &&
76 code != 0x0E1B && // PO PLA
77 code != 0x0E1D && // FO FA
78 code != 0x0E1F && // FO FAN
79 code != 0x0E2C); // LO CHULA in some fonts, Unicode tables show it as tall
82 TBool IsThaiConsonantWithDisjointDescender(TUint code)
84 return (code == ThaiGlyph::KYoYing || code == ThaiGlyph::KThoThan);
87 TBool IsThaiConsonantWithJointDescender(TUint code)
89 return (code == 0x0E0E || // DO CHADA
90 code == 0x0E0F || // PO PATAK
91 code == 0x0E24 || // RU
92 code == 0x0E26); // LU
95 TBool IsThaiVowel(TUint code)
97 return ((code >= 0x0E30 && code <= 0x0E3A) ||
98 (code >= 0x0E40 && code <= 0x0E44) ||
99 code == 0x0E47); // MAITAIKHU
102 TBool IsThaiDepVowel(TUint code)
104 return (code == 0x0E31 || // MAI HAN-AKAT
105 (code >= 0x0E34 && code <= 0x0E3A) ||
106 code == 0x0E47); // MAITAIKHU
109 TBool IsThaiDepVowelAbove(TUint code)
111 return (code == 0x0E31 || // MAI HAN-AKAT
112 (code >= 0x0E34 && code <= 0x0E37) ||
113 code == 0x0E47); // MAITAIKHU
116 TBool IsThaiDepVowelAbovePUA(TUint code)
118 return (code == 0xF710 || // MAI HAN-AKAT
119 (code >= 0xF701 && code <= 0xF704) ||
120 code == 0xF712); // MAITAIKHU
123 TBool IsThaiDepVowelBelow(TUint code)
125 return (code >= 0x0E38 && code <= 0x0E3A);
128 TBool IsThaiIndepVowel(TUint code)
130 return (code == 0x0E30 || // SARA A
131 code == 0x0E32 || // SARA AA
132 code == 0x0E33 || // SARA AM
133 (code >= 0x0E40 && code <= 0x0E44));
136 TBool IsThaiToneMark(TUint code)
138 return (code >= 0x0E48 && code <= 0x0E4B);
145 // ThaiCharRules Namespace definition
151 ThaiCharRules namespace holds the data and lookup methods
152 implementing the WTT 2.0 input/output validation matrix.
155 namespace ThaiCharRules
157 const TUint KThaiCodePageStart = 0x0E00;
158 const TUint KThaiCodePageEnd = 0x0E5C;
159 const TUint KNumThaiCharacters = KThaiCodePageEnd-KThaiCodePageStart;
171 This enumeration holds the set of classification values a Thai
172 character can be categorised as in the WTT2.0 specification.
174 enum CharClassification
181 EOrdinaryFollowingVowel,
182 EDependentFollowingVowel,
183 ESpecialFollowingVowel,
201 Data table holding the classification of each character.
203 static const TUint8 iCharClassifications[KNumThaiCharacters] =
205 ENull, // No entry in code page
206 EConsonant, // 0x0E01
207 EConsonant, // 0x0E02
208 EConsonant, // 0x0E03
209 EConsonant, // 0x0E04
210 EConsonant, // 0x0E05
211 EConsonant, // 0x0E06
212 EConsonant, // 0x0E07
213 EConsonant, // 0x0E08
214 EConsonant, // 0x0E09
215 EConsonant, // 0x0E0A
216 EConsonant, // 0x0E0B
217 EConsonant, // 0x0E0C
218 EConsonant, // 0x0E0D
219 EConsonant, // 0x0E0E
220 EConsonant, // 0x0E0F
222 EConsonant, // 0x0E10
223 EConsonant, // 0x0E11
224 EConsonant, // 0x0E12
225 EConsonant, // 0x0E13
226 EConsonant, // 0x0E14
227 EConsonant, // 0x0E15
228 EConsonant, // 0x0E16
229 EConsonant, // 0x0E17
230 EConsonant, // 0x0E18
231 EConsonant, // 0x0E19
232 EConsonant, // 0x0E1A
233 EConsonant, // 0x0E1B
234 EConsonant, // 0x0E1C
235 EConsonant, // 0x0E1D
236 EConsonant, // 0x0E1E
237 EConsonant, // 0x0E1F
239 EConsonant, // 0x0E20
240 EConsonant, // 0x0E21
241 EConsonant, // 0x0E22
242 EConsonant, // 0x0E23
243 EConsonant, // 0x0E24
244 EConsonant, // 0x0E25
245 EConsonant, // 0x0E26
246 EConsonant, // 0x0E27
247 EConsonant, // 0x0E28
248 EConsonant, // 0x0E29
249 EConsonant, // 0x0E2A
250 EConsonant, // 0x0E2B
251 EConsonant, // 0x0E2C
252 EConsonant, // 0x0E2D
253 EConsonant, // 0x0E2E
254 ENonPrintable, // 0x0E2F
256 EOrdinaryFollowingVowel,// 0x0E30
257 EAboveVowel2, // 0x0E31
258 EOrdinaryFollowingVowel,// 0x0E32
259 EOrdinaryFollowingVowel,// 0x0E33
260 EAboveVowel1, // 0x0E34
261 EAboveVowel3, // 0x0E35
262 EAboveVowel2, // 0x0E36
263 EAboveVowel3, // 0x0E37
264 EShortBelowVowel, // 0x0E38
265 ELongBelowVowel, // 0x0E39
266 EBelowDiacritic, // 0x0E3A
271 ENonPrintable, // 0x0E3F
273 ELeadingVowel, // 0x0E40
274 ELeadingVowel, // 0x0E41
275 ELeadingVowel, // 0x0E42
276 ELeadingVowel, // 0x0E43
277 ELeadingVowel, // 0x0E44
278 EDependentFollowingVowel,//0x0E45
279 ENonPrintable, // 0x0E46
280 EAboveDiacritic2, // 0x0E47
285 EAboveDiacritic1, // 0x0E4C
286 EAboveDiacritic0, // 0x0E4D
287 EAboveDiacritic3, // 0x0E4E
288 ENonPrintable, // 0x0E4F
290 ENonPrintable, // 0x0E50
291 ENonPrintable, // 0x0E51
292 ENonPrintable, // 0x0E52
293 ENonPrintable, // 0x0E53
294 ENonPrintable, // 0x0E54
295 ENonPrintable, // 0x0E55
296 ENonPrintable, // 0x0E56
297 ENonPrintable, // 0x0E57
298 ENonPrintable, // 0x0E58
299 ENonPrintable, // 0x0E59
300 ENonPrintable, // 0x0E5A
301 ENonPrintable, // 0x0E5B
303 // Value at last measurement was 92 bytes. 27/6/2003
308 WTT 2.0 Rules data table of prev to next character
310 static const TUint8 iInputRules[EMaxClassification][EMaxClassification] =
312 /* Previous character ENull */
314 EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
315 EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
316 EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
317 EUndefined, EUndefined, EUndefined, EUndefined
320 /* Previous character EControl */
322 EUndefined, EUndefined, EAccept, EAccept, EAccept,
323 EAccept, EAccept, EAccept, EReject, EReject,
324 EReject, EReject, EReject, EReject, EReject, EReject,
325 EReject, EReject, EReject,
328 /* Previous character ENonPrintable */
330 EUndefined, EUndefined, EAccept, EAccept, EAccept,
331 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
332 EReject, EReject, EReject, EReject, EReject, EReject,
333 EReject, EReject, EReject,
336 /* Previous character EConsonant */
338 EUndefined, EUndefined, EAccept, EAccept, EAccept,
339 EAccept, ERejectStrict, EAccept, EComposite, EComposite,
340 EComposite, EComposite, EComposite, EComposite, EComposite, EComposite,
341 EComposite, EComposite, EComposite,
344 /* Previous character ELeadingVowel */
346 EUndefined, EUndefined, ERejectStrict, EAccept, ERejectStrict,
347 ERejectStrict, ERejectStrict, ERejectStrict, EReject, EReject,
348 EReject, EReject, EReject, EReject, EReject, EReject,
349 EReject, EReject, EReject,
352 /* Previous character EOrdinaryFollowingVowel */
354 EUndefined, EUndefined, ERejectStrict, EAccept, ERejectStrict,
355 EAccept, ERejectStrict, EAccept, EReject, EReject,
356 EReject, EReject, EReject, EReject, EReject, EReject,
357 EReject, EReject, EReject,
360 /* Previous character EDependentFollowingVowel */
362 EUndefined, EUndefined, EAccept, EAccept, EAccept,
363 EAccept, ERejectStrict, EAccept, EReject, EReject,
364 EReject, EReject, EReject, EReject, EReject, EReject,
365 EReject, EReject, EReject,
368 /* Previous character ESpecialFollowingVowel */
370 EUndefined, EUndefined, EAccept, EAccept, EAccept,
371 ERejectStrict, EAccept, ERejectStrict, EReject, EReject,
372 EReject, EReject, EReject, EReject, EReject, EReject,
373 EReject, EReject, EReject,
376 /* Previous character EShortBelowVowel */
378 EUndefined, EUndefined, EAccept, EAccept, EAccept,
379 EAccept, ERejectStrict, EAccept, EReject, EReject,
380 EReject, EComposite, EComposite, EComposite, EReject, EReject,
381 EReject, EReject, EReject,
384 /* Previous character ELongBelowVowel */
386 EUndefined, EUndefined, EAccept, EAccept, EAccept,
387 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
388 EReject, EComposite, EReject, EReject, EReject, EReject,
389 EReject, EReject, EReject,
392 /* Previous character EBelowDiacritic */
394 EUndefined, EUndefined, EAccept, EAccept, EAccept,
395 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
396 EReject, EReject, EReject, EReject, EReject, EReject,
397 EReject, EReject, EReject,
400 /* Previous character EToneMark */
402 EUndefined, EUndefined, EAccept, EAccept, EAccept,
403 EAccept, EAccept, EAccept, EReject, EReject,
404 EReject, EReject, EReject, EReject, EReject, EReject,
405 EReject, EReject, EReject,
408 /* Previous character EAboveDiacritic0 */
410 EUndefined, EUndefined, EAccept, EAccept, EAccept,
411 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
412 EReject, EReject, EReject, EReject, EReject, EReject,
413 EReject, EReject, EReject,
416 /* Previous character EAboveDiacritic1 */
418 EUndefined, EUndefined, EAccept, EAccept, EAccept,
419 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
420 EReject, EReject, EReject, EReject, EReject, EReject,
421 EReject, EReject, EReject,
424 /* Previous character EAboveDiacritic2 */
426 EUndefined, EUndefined, EAccept, EAccept, EAccept,
427 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
428 EReject, EReject, EReject, EReject, EReject, EReject,
429 EReject, EReject, EReject,
432 /* Previous character EAboveDiacritic3 */
434 EUndefined, EUndefined, EAccept, EAccept, EAccept,
435 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
436 EReject, EReject, EReject, EReject, EReject, EReject,
437 EReject, EReject, EReject,
440 /* Previous character EAboveVowel1 */
442 EUndefined, EUndefined, EAccept, EAccept, EAccept,
443 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
444 EReject, EComposite, EReject, EComposite, EReject, EReject,
445 // EReject, EComposite, EComposite, EComposite, EReject, EReject,
446 EReject, EReject, EReject,
449 /* Previous character EAboveVowel2 */
451 EUndefined, EUndefined, EAccept, EAccept, EAccept,
452 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
453 EReject, EComposite, EReject, EReject, EReject, EReject,
454 EReject, EReject, EReject,
457 /* Previous character EAboveVowel3 */
459 EUndefined, EUndefined, EAccept, EAccept, EAccept,
460 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
461 EReject, EComposite, EReject, EReject, EReject, EReject,
462 // EReject, EComposite, EReject, EComposite, EReject,
463 EReject, EReject, EReject,
466 // Value at last measurement was 324 bytes. 27/6/2003
471 This routine looks up the WTT 2.0 rule for the given
472 Thai character codes provided in the WTT 2.0 data table.
474 Unicode character code preceding the assumed position.
476 Unicode character code proceeding the assumed position.
478 The rule value found in data table.
480 Wtt2Rule LookupWtt2Rule(TUint aPrevChar, TUint aChar)
482 const CharClassification prevCharClassification =
483 static_cast<CharClassification>(
484 (aPrevChar > KThaiCodePageStart && aPrevChar < KThaiCodePageEnd) ?
485 iCharClassifications[aPrevChar - KThaiCodePageStart] :
487 const CharClassification charClassification =
488 static_cast<CharClassification>(
489 (aChar > KThaiCodePageStart && aChar < KThaiCodePageEnd) ?
490 iCharClassifications[aChar - KThaiCodePageStart] :
493 return static_cast<Wtt2Rule>
494 (iInputRules[prevCharClassification][charClassification]);
499 using namespace ThaiCharRules;
504 // ThaiGlyphPUASubstitution Namespace definition
510 This utility namespace holds the data and lookup mechanisms to support
511 the GlyphSelector_Thai glyph selection class in choosing Private User
512 Area (PUA) Thai character positional variant glyphs. Use of the PUA glyphs
513 results in a satisfactory rendition of Thai writing in Symbian OS.
516 namespace ThaiGlyphPUASubstitution
519 typedef TBool (*UnicodeCharValidator)(const TGlyphSelectionState& aGss);
521 struct PUASubstTableEntry
525 UnicodeCharValidator iRuleFunc;
530 ThaiGlyphPUASubstitution rule method which checks the context for
531 short consonant preceding char OR
532 short consonant & dependent vowel below preceding char.
534 Container object holds the glyph selection context for the method.
536 ETrue when the rule context is satisfied, EFalse if not.
538 TBool RuleShortConsonant(const TGlyphSelectionState& aGss)
540 if (aGss.iParam.iOutputGlyphs == 1) {
541 //check the context for short consonant preceding char
542 TUint consonantGss = aGss.iParam.iOutput[0].iCode;
543 if (ThaiGlyph::IsThaiShortConsonant(consonantGss) ||
544 consonantGss == ThaiGlyph::KYoYingPua ||
545 consonantGss == ThaiGlyph::KThoThanPua)
550 if (aGss.iParam.iOutputGlyphs == 2) {
551 //check the context for short consonant & dependent vowel below preceding char
552 TUint consonantGss = aGss.iParam.iOutput[0].iCode;
553 TUint depVowelGss = aGss.iParam.iOutput[1].iCode;
554 if ((ThaiGlyph::IsThaiShortConsonant(consonantGss) ||
555 consonantGss == ThaiGlyph::KYoYingPua ||
556 consonantGss == ThaiGlyph::KThoThanPua) &&
557 (ThaiGlyph::IsThaiDepVowelBelow(depVowelGss) ||
558 (depVowelGss >= 0xF718 &&
559 depVowelGss <= 0xF71A)))
568 ThaiGlyphPUASubstitution rule method which checks the context for
569 tall consonant preceding char.
571 Container object holds the glyph selection context for the method.
573 ETrue when the rule context is satisfied, EFalse if not.
575 TBool RuleTallConsonant(const TGlyphSelectionState& aGss)
577 if ((aGss.iParam.iOutputGlyphs == 1) &&
578 ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode))
585 ThaiGlyphPUASubstitution rule method which checks the context for a tall
586 consonant which does not have a dependent vowel above or a nikhahit or a
589 Container object holds the glyph selection context for the method.
591 ETrue when the rule context is satisfied, EFalse if not.
593 TBool RuleTallConsonantNoVowelAbove(const TGlyphSelectionState& aGss)
595 if (aGss.iParam.iOutputGlyphs == 0)
597 if (!ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode))
599 if (aGss.iParam.iOutputGlyphs == 1)
601 if (aGss.iParam.iOutputGlyphs != 2)
603 TUint wantDepVowel = aGss.iParam.iOutput[1].iCode;
604 if (ThaiGlyph::IsThaiDepVowelAbove(wantDepVowel)
605 || ThaiGlyph::IsThaiDepVowelAbovePUA(wantDepVowel)
606 || wantDepVowel == ThaiGlyph::KNikhahit
607 || wantDepVowel == ThaiGlyph::KNikhahitPua)
613 ThaiGlyphPUASubstitution rule method which checks the context for tall
614 consonant with either a dependent vowel above or nikhahit.
616 Container object holds the glyph selection context for the method.
618 ETrue when the rule context is satisfied, EFalse if not.
620 TBool RuleTallConsonantVowelAbove(const TGlyphSelectionState& aGss)
622 if ((aGss.iParam.iOutputGlyphs == 2) &&
623 ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode) &&
624 (ThaiGlyph::IsThaiDepVowelAbovePUA(aGss.iParam.iOutput[1].iCode))
625 || aGss.iParam.iOutput[1].iCode == ThaiGlyph::KNikhahitPua)
632 ThaiGlyphPUASubstitution rule method which checks the context for
633 consonant with joined descender preceding char.
635 Container object holds the glyph selection context for the method.
637 ETrue when the rule context is satisfied, EFalse if not.
639 TBool RuleConsonantWithJointDescender(const TGlyphSelectionState& aGss)
641 if ((aGss.iParam.iOutputGlyphs == 1) &&
642 ThaiGlyph::IsThaiConsonantWithJointDescender(aGss.iParam.iOutput[0].iCode))
649 const PUASubstTableEntry RuleTable[] = {
651 This data member of the ThaiGlyphPUASubstitution class holds rules
652 on when a given PUA glyph should be substituted for the original
653 0x0Exx glyph. Table lookup returns the first match found from the
654 start of the table, therefore duplicate match situations must be
655 avoided in the rule set logic.
657 /* iOrigGlyph, iPUAGlyph, iRuleFunc */
659 // Substitutions for a tone or sign mark above a short consonant
660 { 0x0E48, 0xF70A, RuleShortConsonant },
661 { 0x0E49, 0xF70B, RuleShortConsonant },
662 { 0x0E4A, 0xF70C, RuleShortConsonant },
663 { 0x0E4B, 0xF70D, RuleShortConsonant },
664 { 0x0E4C, 0xF70E, RuleShortConsonant },
666 // Substitutions for a vowel or sign mark above a tall consonant
667 { 0x0E34, 0xF701, RuleTallConsonant },
668 { 0x0E35, 0xF702, RuleTallConsonant },
669 { 0x0E36, 0xF703, RuleTallConsonant },
670 { 0x0E37, 0xF704, RuleTallConsonant },
671 { 0x0E31, 0xF710, RuleTallConsonant },
672 { 0x0E4D, 0xF711, RuleTallConsonant },
673 { 0x0E47, 0xF712, RuleTallConsonant },
675 // Substitutions for a tone or sign mark above a tall consonant
676 { 0x0E48, 0xF705, RuleTallConsonantNoVowelAbove },
677 { 0x0E49, 0xF706, RuleTallConsonantNoVowelAbove },
678 { 0x0E4A, 0xF707, RuleTallConsonantNoVowelAbove },
679 { 0x0E4B, 0xF708, RuleTallConsonantNoVowelAbove },
680 { 0x0E4C, 0xF709, RuleTallConsonantNoVowelAbove },
682 // Substitutions for a tone or sign mark above a vowel which is
683 // above a tall consonant
684 { 0x0E48, 0xF713, RuleTallConsonantVowelAbove },
685 { 0x0E49, 0xF714, RuleTallConsonantVowelAbove },
686 { 0x0E4A, 0xF715, RuleTallConsonantVowelAbove },
687 { 0x0E4B, 0xF716, RuleTallConsonantVowelAbove },
688 { 0x0E4C, 0xF717, RuleTallConsonantVowelAbove },
690 // Substitutions for a vowel or sign mark below a consonant with a
692 { 0x0E38, 0xF718, RuleConsonantWithJointDescender },
693 { 0x0E39, 0xF719, RuleConsonantWithJointDescender },
694 { 0x0E3A, 0xF71A, RuleConsonantWithJointDescender },
698 // Size of table at last measurement was 312 bytes. 27/6/2003
703 This is the lookup method to determine if the current character being
704 processed needs to be substituted for a glyph in the PUA area given the
705 supplied context. It scans the rule table and returns when it finds it's
706 first match. Therefore duplicate match situations must be avoided in
709 On input it is the character to lookup, on exit it is either unchanged
710 or a code in the PUA 0xF700..0xF71A.
712 Container object holds the glyph selection context for the method.
714 ETrue when a match is found and aCode has changed, EFalse otherwise.
716 TBool Lookup(TUint& aCode, const TGlyphSelectionState& aGss)
718 const PUASubstTableEntry* tablePtr = RuleTable;
719 while (tablePtr->iOrigGlyph)
721 if ((aCode == tablePtr->iOrigGlyph) && tablePtr->iRuleFunc(aGss))
723 aCode = tablePtr->iPUAGlyph;
724 return ETrue; // Rule match, substitute glyph code
728 return EFalse; // No match in table
735 // GlyphSelector_Thai Class definition
741 This is the default glyph processing method for the Thai characters in the
742 range 0x0E00..0x0E7F and is invoked from the Glyph selection algorithm in
743 CFont::GetCharacterPosition() method. It is capable of processing base
744 Thai characters as well as Thai combining vowels, signs a tone marks.
746 Container object holds the input/output parameters of the method.
748 ETrue when glyph cluster updated successfully, EFalse on error condition.
750 The method GlyphSelector_Thai::Process() also handles it for other cases.
752 TBool GlyphSelector_Thai::Process(TGlyphSelectionState& aGss, RShapeInfo&)
754 // Get the Unicode character codes we need to process the current
755 // glyph and increment the iterator onto th next character.
756 TUint prevCode = (aGss.iText.LengthToStart() > 0) ? aGss.iText.Get(-1) : 0xFFFF;
757 TUint code = aGss.iText.GetThenNext(); // Inc to next char
758 TUint nextCode = !aGss.iText.AtEnd() ? aGss.iText.Get(0) : 0xFFFF;
760 // Is it a Thai base char or a mark (combining) char?
761 if ((aGss.iCats & 0xF0) == TChar::EMarkGroup)
764 // Thai character is combining mark but first check to see if it
765 // follows a Thai base character before processing it.
766 if ((aGss.iParam.iOutputGlyphs > 0) &&
767 !ThaiGlyph::IsThaiGlyph(prevCode))
769 (void) aGss.iText.Prev();
770 aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
774 // Missing base glyph? Insert a dotted circle glyph if true.
775 if (aGss.iParam.iOutputGlyphs == 0)
777 if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
779 aGss.iParam.iPen += aGss.iAdvance;
782 // Test if SARA AM follows this current Thai mark, since it is
783 // a SPECIAL CASE. If present we need NIKHAHIT glyph before this
784 // current Thai mark char.
785 if (nextCode == ThaiGlyph::KSaraAm &&
786 (aGss.iParam.iOutputGlyphs == 1) && ThaiGlyph::IsThaiToneMark(code))
788 TUint nikhahit = ThaiGlyph::KNikhahit;
789 // Check and do PUA glyph substitution on Nikhahit
790 ThaiGlyphPUASubstitution::Lookup(nikhahit, aGss);
792 if (!aGss.AppendGlyphToCluster(nikhahit))
795 // Check and do PUA glyph substitution on combining mark
796 ThaiGlyphPUASubstitution::Lookup(code, aGss);
798 // Append the curernt Thai Mark to the output stack of glyphs.
799 if (!aGss.AppendGlyphToCluster(code))
802 // We now need to add SARA AA glyph after the current Thai mark char.
803 aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
804 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAa))
807 // Skip the following SARA AM character since we've added
808 // its glyphs to it's previous character's glyph cluster.
809 // As we've added a base char to the end of the glyph cluster
810 // make sure the pen is moved on by the caller.
811 (void) aGss.iText.Next();
812 aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
816 // Check and do PUA glyph substitution on combining mark
817 ThaiGlyphPUASubstitution::Lookup(code, aGss);
819 // Append the curernt Thai Mark to the output stack of glyphs.
820 if (!aGss.AppendGlyphToCluster(code))
823 aGss.iPen = TGlyphSelectionState::EPenAdvance_No;
829 // Thai character is an independent consonant, digit or sign
831 // Handle disjoint descender consonants followed by below vowel.
832 // In these two cases we substitute consonant with PUA
833 // consonant that the descender removed. Check code not last one.
834 if (code == ThaiGlyph::KYoYing && nextCode != 0xffff &&
835 ThaiGlyph::IsThaiDepVowelBelow(nextCode))
836 code = ThaiGlyph::KYoYingPua;
837 else if (code == ThaiGlyph::KThoThan && nextCode != 0xffff &&
838 ThaiGlyph::IsThaiDepVowelBelow(nextCode))
839 code = ThaiGlyph::KThoThanPua;
841 // Append the glyph details for the Thai character onto the output
843 if (!aGss.AppendGlyphToCluster(code))
846 // Make sure the caller advances the pen for a base char!
847 aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
850 // Lookup in rule table to determine if the current glyph and cluster is
852 if (ThaiCharRules::LookupWtt2Rule(aGss.iCodePt, nextCode) == ThaiCharRules::EComposite)
853 aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
855 aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
863 // GlyphSelector_ThaiSaraAm Class definition
869 This is the glyph processing method for the Thai SARA AM (U+0E33) character
870 which is handled as a special case since it is decomposed into two glyphs
871 - the combining NIKHAHIT mark & SARA AA following vowel in some cases.
872 It is invoked from the Glyph selection algorithm in
873 CFont::GetCharacterPosition() method for all cases where SARA AM is not
874 following a tone mark and thus be a glyph cluster of its own.
876 Container object holds the input/output parameters of the method.
878 ETrue when glyph cluster updated successfully, EFalse on error condition.
880 The method GlyphSelector_Thai::Process() also handles it for other cases.
882 TBool GlyphSelector_ThaiSaraAm::Process(TGlyphSelectionState& aGss, RShapeInfo&)
884 if (aGss.iCodePt != ThaiGlyph::KSaraAm) //could have got here via
885 { //FindLocalisedProcessFunc in font.cpp
887 return GlyphSelector_Thai::Process(aGss, dummy);
890 // Pen advance accumulator local variable
891 TSize compoundAdvance;
893 if (aGss.iText.LengthToStart() == 0)
895 // If at the start of a line then render it with a preceding
896 // dotted circle as this is invalid positioning for SARA AM.
898 if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
900 aGss.iParam.iPen += aGss.iAdvance;
902 aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
903 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
905 compoundAdvance += aGss.iAdvance;
909 // Normal condition - text iterator now some way into the text line
912 TUint prevChar = aGss.iText.Get(-1);
913 if (ThaiGlyph::IsThaiShortConsonant(prevChar))
915 // SARA AM is following normal height consonant so we can output
916 // non-decomposed SARA AM glyph.
918 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
920 compoundAdvance = aGss.iAdvance;
922 else if (ThaiGlyph::IsThaiTallConsonant(prevChar))
924 // SARA AM is following tall consonant so we output decomposed
925 // version of SARA AM but with NIKHAHIT taken from the PUA.
927 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KNikhahitPua))
929 compoundAdvance = aGss.iAdvance;
930 aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
931 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAa))
933 compoundAdvance += aGss.iAdvance;
937 // SARA AM is a following vowel but is not following a valid
938 // consonant char and so default is to render with dotted circle.
939 if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
941 aGss.iParam.iPen += aGss.iAdvance;
943 aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
944 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
946 compoundAdvance += aGss.iAdvance;
951 // Update output parameters resulting from above processing.
952 // Move text iterator onto next character to process.
955 // Advance pen just for the SARA AA char as advance for dotted
956 // circle is done above.
957 aGss.iAdvance = compoundAdvance;
958 aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
960 if (!aGss.iText.AtEnd() &&
961 (ThaiCharRules::LookupWtt2Rule(aGss.iCodePt, aGss.iText.Get()) ==
962 ThaiCharRules::EComposite))
963 aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
965 aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;