Update contrib.
1 // Copyright (c) 2003-2010 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.
22 //#include <textbase.h>
28 // ThaiGlyph Namespace definition
33 This namespace holds functions used to evaluate a glyph character code
34 against a given Thai related prediciate. The 'code' argument is a glyph
35 from the current output cluster and so may be a Thai glyph, Thai PUA glyph,
36 the dotted circle glyph or 0xffff. Therefore it was decided not to implement
37 these routines using a data driven table approach as it would be inefficient.
42 const TText16 KYoYing = 0x0E0D;
43 const TText16 KYoYingPua = 0xF70F;
44 const TText16 KThoThan = 0x0E10;
45 const TText16 KThoThanPua = 0xF700;
46 const TText16 KNikhahit = 0x0E4D;
47 const TText16 KNikhahitPua = 0xF711;
48 const TText16 KSaraAa = 0x0E32;
49 const TText16 KSaraAm = 0x0E33;
52 TBool IsThaiGlyph(TUint code)
54 return ((code > 0x0E00 && code < 0x0E3B) ||
55 (code > 0x0E3E && code < 0x0E5C) ||
56 (code >= 0xF700 && code <= 0xF71A));
59 TBool IsThaiConsonant(TUint code)
61 return (code >= 0x0E01 && code <= 0x0E2E);
64 TBool IsThaiTallConsonant(TUint code)
66 return (//code == 0x0E0A || // CHO CHANG not tall at all
67 //code == 0x0E0B || // SO SO not tall at all
68 code == 0x0E1B || // PO PLA
69 code == 0x0E1D || // FO FA
70 code == 0x0E1F || // FO FAN
71 code == 0x0E2C); // LO CHULA in some fonts, Unicode tables show it as tall
74 TBool IsThaiShortConsonant(TUint code)
76 return (((code >= 0x0E01 && code <= 0x0E2E) || (code == KUnicodeDottedCircle)) &&
77 code != 0x0E1B && // PO PLA
78 code != 0x0E1D && // FO FA
79 code != 0x0E1F && // FO FAN
80 code != 0x0E2C); // LO CHULA in some fonts, Unicode tables show it as tall
83 TBool IsThaiConsonantWithDisjointDescender(TUint code)
85 return (code == ThaiGlyph::KYoYing || code == ThaiGlyph::KThoThan);
88 TBool IsThaiConsonantWithJointDescender(TUint code)
90 return (code == 0x0E0E || // DO CHADA
91 code == 0x0E0F || // PO PATAK
92 code == 0x0E24 || // RU
93 code == 0x0E26); // LU
96 TBool IsThaiVowel(TUint code)
98 return ((code >= 0x0E30 && code <= 0x0E3A) ||
99 (code >= 0x0E40 && code <= 0x0E44) ||
100 code == 0x0E47); // MAITAIKHU
103 TBool IsThaiDepVowel(TUint code)
105 return (code == 0x0E31 || // MAI HAN-AKAT
106 (code >= 0x0E34 && code <= 0x0E3A) ||
107 code == 0x0E47); // MAITAIKHU
110 TBool IsThaiDepVowelAbove(TUint code)
112 return (code == 0x0E31 || // MAI HAN-AKAT
113 (code >= 0x0E34 && code <= 0x0E37) ||
114 code == 0x0E47); // MAITAIKHU
117 TBool IsThaiDepVowelAbovePUA(TUint code)
119 return (code == 0xF710 || // MAI HAN-AKAT
120 (code >= 0xF701 && code <= 0xF704) ||
121 code == 0xF712); // MAITAIKHU
124 TBool IsThaiDepVowelBelow(TUint code)
126 return (code >= 0x0E38 && code <= 0x0E3A);
129 TBool IsThaiIndepVowel(TUint code)
131 return (code == 0x0E30 || // SARA A
132 code == 0x0E32 || // SARA AA
133 code == 0x0E33 || // SARA AM
134 (code >= 0x0E40 && code <= 0x0E44));
137 TBool IsThaiToneMark(TUint code)
139 return (code >= 0x0E48 && code <= 0x0E4B);
146 // ThaiCharRules Namespace definition
152 ThaiCharRules namespace holds the data and lookup methods
153 implementing the WTT 2.0 input/output validation matrix.
156 namespace ThaiCharRules
158 const TUint KThaiCodePageStart = 0x0E00;
159 const TUint KThaiCodePageEnd = 0x0E5C;
160 const TUint KNumThaiCharacters = KThaiCodePageEnd-KThaiCodePageStart;
172 This enumeration holds the set of classification values a Thai
173 character can be categorised as in the WTT2.0 specification.
175 enum CharClassification
182 EOrdinaryFollowingVowel,
183 EDependentFollowingVowel,
184 ESpecialFollowingVowel,
202 Data table holding the classification of each character.
204 static const TUint8 iCharClassifications[KNumThaiCharacters] =
206 ENull, // No entry in code page
207 EConsonant, // 0x0E01
208 EConsonant, // 0x0E02
209 EConsonant, // 0x0E03
210 EConsonant, // 0x0E04
211 EConsonant, // 0x0E05
212 EConsonant, // 0x0E06
213 EConsonant, // 0x0E07
214 EConsonant, // 0x0E08
215 EConsonant, // 0x0E09
216 EConsonant, // 0x0E0A
217 EConsonant, // 0x0E0B
218 EConsonant, // 0x0E0C
219 EConsonant, // 0x0E0D
220 EConsonant, // 0x0E0E
221 EConsonant, // 0x0E0F
223 EConsonant, // 0x0E10
224 EConsonant, // 0x0E11
225 EConsonant, // 0x0E12
226 EConsonant, // 0x0E13
227 EConsonant, // 0x0E14
228 EConsonant, // 0x0E15
229 EConsonant, // 0x0E16
230 EConsonant, // 0x0E17
231 EConsonant, // 0x0E18
232 EConsonant, // 0x0E19
233 EConsonant, // 0x0E1A
234 EConsonant, // 0x0E1B
235 EConsonant, // 0x0E1C
236 EConsonant, // 0x0E1D
237 EConsonant, // 0x0E1E
238 EConsonant, // 0x0E1F
240 EConsonant, // 0x0E20
241 EConsonant, // 0x0E21
242 EConsonant, // 0x0E22
243 EConsonant, // 0x0E23
244 EConsonant, // 0x0E24
245 EConsonant, // 0x0E25
246 EConsonant, // 0x0E26
247 EConsonant, // 0x0E27
248 EConsonant, // 0x0E28
249 EConsonant, // 0x0E29
250 EConsonant, // 0x0E2A
251 EConsonant, // 0x0E2B
252 EConsonant, // 0x0E2C
253 EConsonant, // 0x0E2D
254 EConsonant, // 0x0E2E
255 ENonPrintable, // 0x0E2F
257 EOrdinaryFollowingVowel,// 0x0E30
258 EAboveVowel2, // 0x0E31
259 EOrdinaryFollowingVowel,// 0x0E32
260 EOrdinaryFollowingVowel,// 0x0E33
261 EAboveVowel1, // 0x0E34
262 EAboveVowel3, // 0x0E35
263 EAboveVowel2, // 0x0E36
264 EAboveVowel3, // 0x0E37
265 EShortBelowVowel, // 0x0E38
266 ELongBelowVowel, // 0x0E39
267 EBelowDiacritic, // 0x0E3A
272 ENonPrintable, // 0x0E3F
274 ELeadingVowel, // 0x0E40
275 ELeadingVowel, // 0x0E41
276 ELeadingVowel, // 0x0E42
277 ELeadingVowel, // 0x0E43
278 ELeadingVowel, // 0x0E44
279 EDependentFollowingVowel,//0x0E45
280 ENonPrintable, // 0x0E46
281 EAboveDiacritic2, // 0x0E47
286 EAboveDiacritic1, // 0x0E4C
287 EAboveDiacritic0, // 0x0E4D
288 EAboveDiacritic3, // 0x0E4E
289 ENonPrintable, // 0x0E4F
291 ENonPrintable, // 0x0E50
292 ENonPrintable, // 0x0E51
293 ENonPrintable, // 0x0E52
294 ENonPrintable, // 0x0E53
295 ENonPrintable, // 0x0E54
296 ENonPrintable, // 0x0E55
297 ENonPrintable, // 0x0E56
298 ENonPrintable, // 0x0E57
299 ENonPrintable, // 0x0E58
300 ENonPrintable, // 0x0E59
301 ENonPrintable, // 0x0E5A
302 ENonPrintable, // 0x0E5B
304 // Value at last measurement was 92 bytes. 27/6/2003
309 WTT 2.0 Rules data table of prev to next character
311 static const TUint8 iInputRules[EMaxClassification][EMaxClassification] =
313 /* Previous character ENull */
315 EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
316 EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
317 EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
318 EUndefined, EUndefined, EUndefined, EUndefined
321 /* Previous character EControl */
323 EUndefined, EUndefined, EAccept, EAccept, EAccept,
324 EAccept, EAccept, EAccept, EReject, EReject,
325 EReject, EReject, EReject, EReject, EReject, EReject,
326 EReject, EReject, EReject,
329 /* Previous character ENonPrintable */
331 EUndefined, EUndefined, EAccept, EAccept, EAccept,
332 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
333 EReject, EReject, EReject, EReject, EReject, EReject,
334 EReject, EReject, EReject,
337 /* Previous character EConsonant */
339 EUndefined, EUndefined, EAccept, EAccept, EAccept,
340 EAccept, ERejectStrict, EAccept, EComposite, EComposite,
341 EComposite, EComposite, EComposite, EComposite, EComposite, EComposite,
342 EComposite, EComposite, EComposite,
345 /* Previous character ELeadingVowel */
347 EUndefined, EUndefined, ERejectStrict, EAccept, ERejectStrict,
348 ERejectStrict, ERejectStrict, ERejectStrict, EReject, EReject,
349 EReject, EReject, EReject, EReject, EReject, EReject,
350 EReject, EReject, EReject,
353 /* Previous character EOrdinaryFollowingVowel */
355 EUndefined, EUndefined, ERejectStrict, EAccept, ERejectStrict,
356 EAccept, ERejectStrict, EAccept, EReject, EReject,
357 EReject, EReject, EReject, EReject, EReject, EReject,
358 EReject, EReject, EReject,
361 /* Previous character EDependentFollowingVowel */
363 EUndefined, EUndefined, EAccept, EAccept, EAccept,
364 EAccept, ERejectStrict, EAccept, EReject, EReject,
365 EReject, EReject, EReject, EReject, EReject, EReject,
366 EReject, EReject, EReject,
369 /* Previous character ESpecialFollowingVowel */
371 EUndefined, EUndefined, EAccept, EAccept, EAccept,
372 ERejectStrict, EAccept, ERejectStrict, EReject, EReject,
373 EReject, EReject, EReject, EReject, EReject, EReject,
374 EReject, EReject, EReject,
377 /* Previous character EShortBelowVowel */
379 EUndefined, EUndefined, EAccept, EAccept, EAccept,
380 EAccept, ERejectStrict, EAccept, EReject, EReject,
381 EReject, EComposite, EComposite, EComposite, EReject, EReject,
382 EReject, EReject, EReject,
385 /* Previous character ELongBelowVowel */
387 EUndefined, EUndefined, EAccept, EAccept, EAccept,
388 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
389 EReject, EComposite, EReject, EReject, EReject, EReject,
390 EReject, EReject, EReject,
393 /* Previous character EBelowDiacritic */
395 EUndefined, EUndefined, EAccept, EAccept, EAccept,
396 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
397 EReject, EReject, EReject, EReject, EReject, EReject,
398 EReject, EReject, EReject,
401 /* Previous character EToneMark */
403 EUndefined, EUndefined, EAccept, EAccept, EAccept,
404 EAccept, EAccept, EAccept, EReject, EReject,
405 EReject, EReject, EReject, EReject, EReject, EReject,
406 EReject, EReject, EReject,
409 /* Previous character EAboveDiacritic0 */
411 EUndefined, EUndefined, EAccept, EAccept, EAccept,
412 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
413 EReject, EReject, EReject, EReject, EReject, EReject,
414 EReject, EReject, EReject,
417 /* Previous character EAboveDiacritic1 */
419 EUndefined, EUndefined, EAccept, EAccept, EAccept,
420 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
421 EReject, EReject, EReject, EReject, EReject, EReject,
422 EReject, EReject, EReject,
425 /* Previous character EAboveDiacritic2 */
427 EUndefined, EUndefined, EAccept, EAccept, EAccept,
428 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
429 EReject, EReject, EReject, EReject, EReject, EReject,
430 EReject, EReject, EReject,
433 /* Previous character EAboveDiacritic3 */
435 EUndefined, EUndefined, EAccept, EAccept, EAccept,
436 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
437 EReject, EReject, EReject, EReject, EReject, EReject,
438 EReject, EReject, EReject,
441 /* Previous character EAboveVowel1 */
443 EUndefined, EUndefined, EAccept, EAccept, EAccept,
444 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
445 EReject, EComposite, EReject, EComposite, EReject, EReject,
446 // EReject, EComposite, EComposite, EComposite, EReject, EReject,
447 EReject, EReject, EReject,
450 /* Previous character EAboveVowel2 */
452 EUndefined, EUndefined, EAccept, EAccept, EAccept,
453 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
454 EReject, EComposite, EReject, EReject, EReject, EReject,
455 EReject, EReject, EReject,
458 /* Previous character EAboveVowel3 */
460 EUndefined, EUndefined, EAccept, EAccept, EAccept,
461 ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
462 EReject, EComposite, EReject, EReject, EReject, EReject,
463 // EReject, EComposite, EReject, EComposite, EReject,
464 EReject, EReject, EReject,
467 // Value at last measurement was 324 bytes. 27/6/2003
472 This routine looks up the WTT 2.0 rule for the given
473 Thai character codes provided in the WTT 2.0 data table.
475 Unicode character code preceding the assumed position.
477 Unicode character code proceeding the assumed position.
479 The rule value found in data table.
481 Wtt2Rule LookupWtt2Rule(TUint aPrevChar, TUint aChar)
483 const CharClassification prevCharClassification =
484 static_cast<CharClassification>(
485 (aPrevChar > KThaiCodePageStart && aPrevChar < KThaiCodePageEnd) ?
486 iCharClassifications[aPrevChar - KThaiCodePageStart] :
488 const CharClassification charClassification =
489 static_cast<CharClassification>(
490 (aChar > KThaiCodePageStart && aChar < KThaiCodePageEnd) ?
491 iCharClassifications[aChar - KThaiCodePageStart] :
494 return static_cast<Wtt2Rule>
495 (iInputRules[prevCharClassification][charClassification]);
500 using namespace ThaiCharRules;
505 // ThaiGlyphPUASubstitution Namespace definition
511 This utility namespace holds the data and lookup mechanisms to support
512 the GlyphSelector_Thai glyph selection class in choosing Private User
513 Area (PUA) Thai character positional variant glyphs. Use of the PUA glyphs
514 results in a satisfactory rendition of Thai writing in Symbian OS.
517 namespace ThaiGlyphPUASubstitution
520 typedef TBool (*UnicodeCharValidator)(const TGlyphSelectionState& aGss);
522 struct PUASubstTableEntry
526 UnicodeCharValidator iRuleFunc;
531 ThaiGlyphPUASubstitution rule method which checks the context for
532 short consonant preceding char OR
533 short consonant & dependent vowel below preceding char.
535 Container object holds the glyph selection context for the method.
537 ETrue when the rule context is satisfied, EFalse if not.
539 TBool RuleShortConsonant(const TGlyphSelectionState& aGss)
541 if (aGss.iParam.iOutputGlyphs == 1) {
542 //check the context for short consonant preceding char
543 TUint consonantGss = aGss.iParam.iOutput[0].iCode;
544 if (ThaiGlyph::IsThaiShortConsonant(consonantGss) ||
545 consonantGss == ThaiGlyph::KYoYingPua ||
546 consonantGss == ThaiGlyph::KThoThanPua)
551 if (aGss.iParam.iOutputGlyphs == 2) {
552 //check the context for short consonant & dependent vowel below preceding char
553 TUint consonantGss = aGss.iParam.iOutput[0].iCode;
554 TUint depVowelGss = aGss.iParam.iOutput[1].iCode;
555 if ((ThaiGlyph::IsThaiShortConsonant(consonantGss) ||
556 consonantGss == ThaiGlyph::KYoYingPua ||
557 consonantGss == ThaiGlyph::KThoThanPua) &&
558 (ThaiGlyph::IsThaiDepVowelBelow(depVowelGss) ||
559 (depVowelGss >= 0xF718 &&
560 depVowelGss <= 0xF71A)))
569 ThaiGlyphPUASubstitution rule method which checks the context for
570 tall consonant preceding char.
572 Container object holds the glyph selection context for the method.
574 ETrue when the rule context is satisfied, EFalse if not.
576 TBool RuleTallConsonant(const TGlyphSelectionState& aGss)
578 if ((aGss.iParam.iOutputGlyphs == 1) &&
579 ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode))
586 ThaiGlyphPUASubstitution rule method which checks the context for a tall
587 consonant which does not have a dependent vowel above or a nikhahit or a
590 Container object holds the glyph selection context for the method.
592 ETrue when the rule context is satisfied, EFalse if not.
594 TBool RuleTallConsonantNoVowelAbove(const TGlyphSelectionState& aGss)
596 if (aGss.iParam.iOutputGlyphs == 0)
598 if (!ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode))
600 if (aGss.iParam.iOutputGlyphs == 1)
602 if (aGss.iParam.iOutputGlyphs != 2)
604 TUint wantDepVowel = aGss.iParam.iOutput[1].iCode;
605 if (ThaiGlyph::IsThaiDepVowelAbove(wantDepVowel)
606 || ThaiGlyph::IsThaiDepVowelAbovePUA(wantDepVowel)
607 || wantDepVowel == ThaiGlyph::KNikhahit
608 || wantDepVowel == ThaiGlyph::KNikhahitPua)
614 ThaiGlyphPUASubstitution rule method which checks the context for tall
615 consonant with either a dependent vowel above or nikhahit.
617 Container object holds the glyph selection context for the method.
619 ETrue when the rule context is satisfied, EFalse if not.
621 TBool RuleTallConsonantVowelAbove(const TGlyphSelectionState& aGss)
623 if ((aGss.iParam.iOutputGlyphs == 2) &&
624 ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode) &&
625 (ThaiGlyph::IsThaiDepVowelAbovePUA(aGss.iParam.iOutput[1].iCode))
626 || aGss.iParam.iOutput[1].iCode == ThaiGlyph::KNikhahitPua)
633 ThaiGlyphPUASubstitution rule method which checks the context for
634 consonant with joined descender preceding char.
636 Container object holds the glyph selection context for the method.
638 ETrue when the rule context is satisfied, EFalse if not.
640 TBool RuleConsonantWithJointDescender(const TGlyphSelectionState& aGss)
642 if ((aGss.iParam.iOutputGlyphs == 1) &&
643 ThaiGlyph::IsThaiConsonantWithJointDescender(aGss.iParam.iOutput[0].iCode))
650 const PUASubstTableEntry RuleTable[] = {
652 This data member of the ThaiGlyphPUASubstitution class holds rules
653 on when a given PUA glyph should be substituted for the original
654 0x0Exx glyph. Table lookup returns the first match found from the
655 start of the table, therefore duplicate match situations must be
656 avoided in the rule set logic.
658 /* iOrigGlyph, iPUAGlyph, iRuleFunc */
660 // Substitutions for a tone or sign mark above a short consonant
661 { 0x0E48, 0xF70A, RuleShortConsonant },
662 { 0x0E49, 0xF70B, RuleShortConsonant },
663 { 0x0E4A, 0xF70C, RuleShortConsonant },
664 { 0x0E4B, 0xF70D, RuleShortConsonant },
665 { 0x0E4C, 0xF70E, RuleShortConsonant },
667 // Substitutions for a vowel or sign mark above a tall consonant
668 { 0x0E34, 0xF701, RuleTallConsonant },
669 { 0x0E35, 0xF702, RuleTallConsonant },
670 { 0x0E36, 0xF703, RuleTallConsonant },
671 { 0x0E37, 0xF704, RuleTallConsonant },
672 { 0x0E31, 0xF710, RuleTallConsonant },
673 { 0x0E4D, 0xF711, RuleTallConsonant },
674 { 0x0E47, 0xF712, RuleTallConsonant },
676 // Substitutions for a tone or sign mark above a tall consonant
677 { 0x0E48, 0xF705, RuleTallConsonantNoVowelAbove },
678 { 0x0E49, 0xF706, RuleTallConsonantNoVowelAbove },
679 { 0x0E4A, 0xF707, RuleTallConsonantNoVowelAbove },
680 { 0x0E4B, 0xF708, RuleTallConsonantNoVowelAbove },
681 { 0x0E4C, 0xF709, RuleTallConsonantNoVowelAbove },
683 // Substitutions for a tone or sign mark above a vowel which is
684 // above a tall consonant
685 { 0x0E48, 0xF713, RuleTallConsonantVowelAbove },
686 { 0x0E49, 0xF714, RuleTallConsonantVowelAbove },
687 { 0x0E4A, 0xF715, RuleTallConsonantVowelAbove },
688 { 0x0E4B, 0xF716, RuleTallConsonantVowelAbove },
689 { 0x0E4C, 0xF717, RuleTallConsonantVowelAbove },
691 // Substitutions for a vowel or sign mark below a consonant with a
693 { 0x0E38, 0xF718, RuleConsonantWithJointDescender },
694 { 0x0E39, 0xF719, RuleConsonantWithJointDescender },
695 { 0x0E3A, 0xF71A, RuleConsonantWithJointDescender },
699 // Size of table at last measurement was 312 bytes. 27/6/2003
704 This is the lookup method to determine if the current character being
705 processed needs to be substituted for a glyph in the PUA area given the
706 supplied context. It scans the rule table and returns when it finds it's
707 first match. Therefore duplicate match situations must be avoided in
710 On input it is the character to lookup, on exit it is either unchanged
711 or a code in the PUA 0xF700..0xF71A.
713 Container object holds the glyph selection context for the method.
715 ETrue when a match is found and aCode has changed, EFalse otherwise.
717 TBool Lookup(TUint& aCode, const TGlyphSelectionState& aGss)
719 const PUASubstTableEntry* tablePtr = RuleTable;
720 while (tablePtr->iOrigGlyph)
722 if ((aCode == tablePtr->iOrigGlyph) && tablePtr->iRuleFunc(aGss))
724 aCode = tablePtr->iPUAGlyph;
725 return ETrue; // Rule match, substitute glyph code
729 return EFalse; // No match in table
736 // GlyphSelector_Thai Class definition
742 This is the default glyph processing method for the Thai characters in the
743 range 0x0E00..0x0E7F and is invoked from the Glyph selection algorithm in
744 CFont::GetCharacterPosition() method. It is capable of processing base
745 Thai characters as well as Thai combining vowels, signs a tone marks.
747 Container object holds the input/output parameters of the method.
749 ETrue when glyph cluster updated successfully, EFalse on error condition.
751 The method GlyphSelector_Thai::Process() also handles it for other cases.
753 TBool GlyphSelector_Thai::Process(TGlyphSelectionState& aGss, RShapeInfo&)
755 // Get the Unicode character codes we need to process the current
756 // glyph and increment the iterator onto th next character.
757 TUint prevCode = (aGss.iText.LengthToStart() > 0) ? aGss.iText.Get(-1) : 0xFFFF;
758 TUint code = aGss.iText.GetThenNext(); // Inc to next char
759 TUint nextCode = !aGss.iText.AtEnd() ? aGss.iText.Get(0) : 0xFFFF;
761 // Is it a Thai base char or a mark (combining) char?
762 if ((aGss.iCats & 0xF0) == TChar::EMarkGroup)
765 // Thai character is combining mark but first check to see if it
766 // follows a Thai base character before processing it.
767 if ((aGss.iParam.iOutputGlyphs > 0) &&
768 !ThaiGlyph::IsThaiGlyph(prevCode))
770 (void) aGss.iText.Prev();
771 aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
775 // Missing base glyph? Insert a dotted circle glyph if true.
776 if (aGss.iParam.iOutputGlyphs == 0)
778 if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
780 aGss.iParam.iPen += aGss.iAdvance;
783 // Test if SARA AM follows this current Thai mark, since it is
784 // a SPECIAL CASE. If present we need NIKHAHIT glyph before this
785 // current Thai mark char.
786 if (nextCode == ThaiGlyph::KSaraAm &&
787 (aGss.iParam.iOutputGlyphs == 1) && ThaiGlyph::IsThaiToneMark(code))
789 TUint nikhahit = ThaiGlyph::KNikhahit;
790 // Check and do PUA glyph substitution on Nikhahit
791 ThaiGlyphPUASubstitution::Lookup(nikhahit, aGss);
793 if (!aGss.AppendGlyphToCluster(nikhahit))
796 // Check and do PUA glyph substitution on combining mark
797 ThaiGlyphPUASubstitution::Lookup(code, aGss);
799 // Append the curernt Thai Mark to the output stack of glyphs.
800 if (!aGss.AppendGlyphToCluster(code))
803 // We now need to add SARA AA glyph after the current Thai mark char.
804 aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
805 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAa))
808 // Skip the following SARA AM character since we've added
809 // its glyphs to it's previous character's glyph cluster.
810 // As we've added a base char to the end of the glyph cluster
811 // make sure the pen is moved on by the caller.
812 (void) aGss.iText.Next();
813 aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
817 // Check and do PUA glyph substitution on combining mark
818 ThaiGlyphPUASubstitution::Lookup(code, aGss);
820 // Append the curernt Thai Mark to the output stack of glyphs.
821 if (!aGss.AppendGlyphToCluster(code))
824 aGss.iPen = TGlyphSelectionState::EPenAdvance_No;
830 // Thai character is an independent consonant, digit or sign
832 // Handle disjoint descender consonants followed by below vowel.
833 // In these two cases we substitute consonant with PUA
834 // consonant that the descender removed. Check code not last one.
835 if (code == ThaiGlyph::KYoYing && nextCode != 0xffff &&
836 ThaiGlyph::IsThaiDepVowelBelow(nextCode))
837 code = ThaiGlyph::KYoYingPua;
838 else if (code == ThaiGlyph::KThoThan && nextCode != 0xffff &&
839 ThaiGlyph::IsThaiDepVowelBelow(nextCode))
840 code = ThaiGlyph::KThoThanPua;
842 // Append the glyph details for the Thai character onto the output
844 if (!aGss.AppendGlyphToCluster(code))
847 // Make sure the caller advances the pen for a base char!
848 aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
851 // Lookup in rule table to determine if the current glyph and cluster is
853 if (ThaiCharRules::LookupWtt2Rule(aGss.iCodePt, nextCode) == ThaiCharRules::EComposite)
854 aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
856 aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
864 // GlyphSelector_ThaiSaraAm Class definition
870 This is the glyph processing method for the Thai SARA AM (U+0E33) character
871 which is handled as a special case since it is decomposed into two glyphs
872 - the combining NIKHAHIT mark & SARA AA following vowel in some cases.
873 It is invoked from the Glyph selection algorithm in
874 CFont::GetCharacterPosition() method for all cases where SARA AM is not
875 following a tone mark and thus be a glyph cluster of its own.
877 Container object holds the input/output parameters of the method.
879 ETrue when glyph cluster updated successfully, EFalse on error condition.
881 The method GlyphSelector_Thai::Process() also handles it for other cases.
883 TBool GlyphSelector_ThaiSaraAm::Process(TGlyphSelectionState& aGss, RShapeInfo&)
885 if (aGss.iCodePt != ThaiGlyph::KSaraAm) //could have got here via
886 { //FindLocalisedProcessFunc in font.cpp
888 return GlyphSelector_Thai::Process(aGss, dummy);
891 // Pen advance accumulator local variable
892 TSize compoundAdvance;
894 if (aGss.iText.LengthToStart() == 0)
896 // If at the start of a line then render it with a preceding
897 // dotted circle as this is invalid positioning for SARA AM.
899 if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
901 aGss.iParam.iPen += aGss.iAdvance;
903 aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
904 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
906 compoundAdvance += aGss.iAdvance;
910 // Normal condition - text iterator now some way into the text line
913 TUint prevChar = aGss.iText.Get(-1);
914 if (ThaiGlyph::IsThaiShortConsonant(prevChar))
916 // SARA AM is following normal height consonant so we can output
917 // non-decomposed SARA AM glyph.
919 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
921 compoundAdvance = aGss.iAdvance;
923 else if (ThaiGlyph::IsThaiTallConsonant(prevChar))
925 // SARA AM is following tall consonant so we output decomposed
926 // version of SARA AM but with NIKHAHIT taken from the PUA.
928 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KNikhahitPua))
930 compoundAdvance = aGss.iAdvance;
931 aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
932 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAa))
934 compoundAdvance += aGss.iAdvance;
938 // SARA AM is a following vowel but is not following a valid
939 // consonant char and so default is to render with dotted circle.
940 if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
942 aGss.iParam.iPen += aGss.iAdvance;
944 aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
945 if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
947 compoundAdvance += aGss.iAdvance;
952 // Update output parameters resulting from above processing.
953 // Move text iterator onto next character to process.
956 // Advance pen just for the SARA AA char as advance for dotted
957 // circle is done above.
958 aGss.iAdvance = compoundAdvance;
959 aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
961 if (!aGss.iText.AtEnd() &&
962 (ThaiCharRules::LookupWtt2Rule(aGss.iCodePt, aGss.iText.Get()) ==
963 ThaiCharRules::EComposite))
964 aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
966 aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;