fontservices/textbase/sgdi/FontThai.cpp
changeset 45 662fa7de7023
equal deleted inserted replaced
41:ea44a32a96bc 45:662fa7de7023
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19 */
       
    20 
       
    21 
       
    22 //#include <textbase.h>
       
    23 #include <gdi.h>
       
    24 #include "FontThai.h"
       
    25 
       
    26 
       
    27 //
       
    28 // ThaiGlyph Namespace definition
       
    29 //
       
    30 
       
    31 
       
    32 /**
       
    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.
       
    38 @internalComponent.
       
    39 */
       
    40 namespace ThaiGlyph
       
    41     {
       
    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;
       
    50 
       
    51     
       
    52      TBool IsThaiGlyph(TUint code)
       
    53     	{
       
    54        	return ((code > 0x0E00 && code < 0x0E3B) ||
       
    55     			(code > 0x0E3E && code < 0x0E5C) ||
       
    56     			(code >= 0xF700 && code <= 0xF71A));
       
    57     	}
       
    58 
       
    59      TBool IsThaiConsonant(TUint code)
       
    60     	{
       
    61     	return (code >= 0x0E01 && code <= 0x0E2E);
       
    62     	}
       
    63 
       
    64      TBool IsThaiTallConsonant(TUint code)
       
    65     	{
       
    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
       
    72     	}
       
    73 
       
    74      TBool IsThaiShortConsonant(TUint code)
       
    75     	{
       
    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
       
    81     	}
       
    82 
       
    83      TBool IsThaiConsonantWithDisjointDescender(TUint code)
       
    84     	{
       
    85     	return (code == ThaiGlyph::KYoYing || code == ThaiGlyph::KThoThan);
       
    86     	}
       
    87 
       
    88      TBool IsThaiConsonantWithJointDescender(TUint code)
       
    89     	{
       
    90     	return (code == 0x0E0E || // DO CHADA
       
    91     			code == 0x0E0F || // PO PATAK
       
    92     			code == 0x0E24 || // RU
       
    93        			code == 0x0E26);  // LU
       
    94     	}
       
    95 
       
    96      TBool IsThaiVowel(TUint code)
       
    97     	{
       
    98     	return ((code >= 0x0E30 && code <= 0x0E3A) ||
       
    99     			(code >= 0x0E40 && code <= 0x0E44) ||
       
   100     			code == 0x0E47);	// MAITAIKHU
       
   101     	}
       
   102 
       
   103      TBool IsThaiDepVowel(TUint code)
       
   104     	{
       
   105     	return (code == 0x0E31 ||	// MAI HAN-AKAT
       
   106     			(code >= 0x0E34 && code <= 0x0E3A) ||
       
   107     			code == 0x0E47);	// MAITAIKHU
       
   108     	}
       
   109 
       
   110      TBool IsThaiDepVowelAbove(TUint code)
       
   111     	{
       
   112     	return (code == 0x0E31 ||	// MAI HAN-AKAT
       
   113     			(code >= 0x0E34 && code <= 0x0E37) ||
       
   114     			code == 0x0E47);	// MAITAIKHU
       
   115     	}
       
   116 
       
   117      TBool IsThaiDepVowelAbovePUA(TUint code)
       
   118     	{
       
   119     	return (code == 0xF710 ||	// MAI HAN-AKAT
       
   120     			(code >= 0xF701 && code <= 0xF704) ||
       
   121     			code == 0xF712);	// MAITAIKHU
       
   122     	}
       
   123 
       
   124      TBool IsThaiDepVowelBelow(TUint code)
       
   125     	{
       
   126     	return (code >= 0x0E38 && code <= 0x0E3A);
       
   127     	}
       
   128 
       
   129      TBool IsThaiIndepVowel(TUint code)
       
   130     	{
       
   131     	return (code == 0x0E30 ||	// SARA A
       
   132       			code == 0x0E32 ||	// SARA AA
       
   133     			code == 0x0E33 ||	// SARA AM
       
   134     			(code >= 0x0E40 && code <= 0x0E44));
       
   135     	}
       
   136 
       
   137      TBool IsThaiToneMark(TUint code)
       
   138     	{
       
   139     	return (code >= 0x0E48 && code <= 0x0E4B);
       
   140     	}
       
   141     }
       
   142 
       
   143     
       
   144 //
       
   145 //
       
   146 // ThaiCharRules Namespace definition
       
   147 //
       
   148 //
       
   149 
       
   150 
       
   151 /**
       
   152  ThaiCharRules namespace holds the data and lookup methods
       
   153  implementing the WTT 2.0 input/output validation matrix.
       
   154 @internalComponent
       
   155 */
       
   156 namespace ThaiCharRules
       
   157 	{
       
   158   	const TUint KThaiCodePageStart      = 0x0E00;
       
   159 	const TUint KThaiCodePageEnd        = 0x0E5C;
       
   160 	const TUint KNumThaiCharacters      = KThaiCodePageEnd-KThaiCodePageStart;
       
   161 
       
   162 	enum Wtt2Rule
       
   163 		{
       
   164 		EUndefined,
       
   165 		EAccept,
       
   166 		EComposite,
       
   167 		EReject,
       
   168 		ERejectStrict,
       
   169 		};
       
   170 
       
   171 	/**
       
   172 	This enumeration holds the set of classification values a Thai
       
   173 	character can be categorised as in the WTT2.0 specification.
       
   174 	*/
       
   175 	enum CharClassification
       
   176 		{
       
   177 		ENull,
       
   178 		EControl,
       
   179 		ENonPrintable,
       
   180 		EConsonant,
       
   181 		ELeadingVowel,
       
   182 		EOrdinaryFollowingVowel,
       
   183 		EDependentFollowingVowel,
       
   184 		ESpecialFollowingVowel,
       
   185 		EShortBelowVowel,
       
   186 		ELongBelowVowel,
       
   187 		EBelowDiacritic,
       
   188 		EToneMark,
       
   189 		EAboveDiacritic0,
       
   190 		EAboveDiacritic1,
       
   191 		EAboveDiacritic2,
       
   192 		EAboveDiacritic3,
       
   193 		EAboveVowel1,
       
   194 		EAboveVowel2,
       
   195 		EAboveVowel3,
       
   196 		// marker for end
       
   197 		EMaxClassification
       
   198 		};
       
   199 
       
   200 
       
   201 	/**
       
   202 	 Data table holding the classification of each character.
       
   203 	*/
       
   204 	static const TUint8 iCharClassifications[KNumThaiCharacters] = 
       
   205         {
       
   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
       
   222 
       
   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
       
   239 
       
   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
       
   256 
       
   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
       
   268     	ENull,					// 0x0E3B
       
   269     	ENull,					// 0x0E3C
       
   270     	ENull,					// 0x0E3D
       
   271     	ENull,					// 0x0E3E
       
   272     	ENonPrintable,			// 0x0E3F
       
   273 
       
   274     	ELeadingVowel,			// 0x0E40
       
   275     	ELeadingVowel,			// 0x0E41
       
   276     	ELeadingVowel,			// 0x0E42
       
   277     	ELeadingVowel,			// 0x0E43
       
   278     	ELeadingVowel,			// 0x0E44
       
   279     	EDependentFollowingVowel,//0x0E45
       
   280     	ENonPrintable,			// 0x0E46
       
   281     	EAboveDiacritic2,		// 0x0E47
       
   282     	EToneMark,				// 0x0E48
       
   283     	EToneMark,				// 0x0E49
       
   284     	EToneMark,				// 0x0E4A
       
   285     	EToneMark,				// 0x0E4B
       
   286     	EAboveDiacritic1,		// 0x0E4C
       
   287     	EAboveDiacritic0,		// 0x0E4D
       
   288     	EAboveDiacritic3,		// 0x0E4E
       
   289     	ENonPrintable,			// 0x0E4F
       
   290 
       
   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
       
   303 
       
   304     	// Value at last measurement was 92 bytes. 27/6/2003
       
   305         };
       
   306 
       
   307 
       
   308 	/**
       
   309 	 WTT 2.0 Rules data table of prev to next character
       
   310 	*/
       
   311 	static const TUint8 iInputRules[EMaxClassification][EMaxClassification] =
       
   312         {
       
   313     	/* Previous character ENull */
       
   314     	    {
       
   315     		EUndefined, EUndefined, EUndefined, EUndefined, EUndefined, 
       
   316     		EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
       
   317     		EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
       
   318     		EUndefined, EUndefined, EUndefined, EUndefined 
       
   319     	    },
       
   320 
       
   321     	/* Previous character EControl */
       
   322     	    {
       
   323     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   324     		EAccept, EAccept, EAccept, EReject, EReject,
       
   325     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   326     		EReject, EReject, EReject,
       
   327     	    },
       
   328 
       
   329     	/* Previous character ENonPrintable */
       
   330     	    {
       
   331     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   332     		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
       
   333     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   334     		EReject, EReject, EReject,
       
   335     	    },
       
   336 
       
   337     	/* Previous character EConsonant */
       
   338     	    {
       
   339     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   340     		EAccept, ERejectStrict, EAccept, EComposite, EComposite,
       
   341     		EComposite, EComposite, EComposite, EComposite, EComposite, EComposite,
       
   342     		EComposite, EComposite, EComposite,
       
   343     	    },
       
   344 
       
   345     	/* Previous character ELeadingVowel */
       
   346     	    {
       
   347     		EUndefined, EUndefined, ERejectStrict, EAccept, ERejectStrict, 
       
   348     		ERejectStrict, ERejectStrict, ERejectStrict, EReject, EReject,
       
   349     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   350     		EReject, EReject, EReject,
       
   351     	    },
       
   352 
       
   353     	/* Previous character EOrdinaryFollowingVowel */
       
   354     	    {
       
   355     		EUndefined, EUndefined, ERejectStrict, EAccept, ERejectStrict, 
       
   356     		EAccept, ERejectStrict, EAccept, EReject, EReject,
       
   357     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   358     		EReject, EReject, EReject,
       
   359     	    },
       
   360 
       
   361     	/* Previous character EDependentFollowingVowel */
       
   362     	    {
       
   363     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   364     		EAccept, ERejectStrict, EAccept, EReject, EReject,
       
   365     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   366     		EReject, EReject, EReject,
       
   367     	    },
       
   368 
       
   369     	/* Previous character ESpecialFollowingVowel */
       
   370     	    {
       
   371     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   372     		ERejectStrict, EAccept, ERejectStrict, EReject, EReject,
       
   373     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   374     		EReject, EReject, EReject,
       
   375     	    },
       
   376 
       
   377     	/* Previous character EShortBelowVowel */
       
   378     	    {
       
   379     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   380     		EAccept, ERejectStrict, EAccept, EReject, EReject,
       
   381     		EReject, EComposite, EComposite, EComposite, EReject, EReject,
       
   382     		EReject, EReject, EReject,
       
   383     	    },
       
   384     		
       
   385     	/* Previous character ELongBelowVowel */
       
   386     	    {
       
   387     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   388     		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
       
   389     		EReject, EComposite, EReject, EReject, EReject, EReject,
       
   390     		EReject, EReject, EReject,
       
   391     	    },
       
   392 
       
   393     	/* Previous character EBelowDiacritic */
       
   394     	    {
       
   395     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   396     		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
       
   397     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   398     		EReject, EReject, EReject,
       
   399     	    },
       
   400     	
       
   401     	/* Previous character EToneMark */
       
   402     	    {
       
   403     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   404     		EAccept, EAccept, EAccept, EReject, EReject,
       
   405     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   406     		EReject, EReject, EReject,
       
   407     	    },
       
   408     	
       
   409 	   	/* Previous character EAboveDiacritic0 */
       
   410     	    {
       
   411     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   412     		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
       
   413     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   414     		EReject, EReject, EReject,
       
   415     	    },
       
   416     	
       
   417     	/* Previous character EAboveDiacritic1 */
       
   418     	    {
       
   419     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   420     		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
       
   421     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   422     		EReject, EReject, EReject,
       
   423     	    },
       
   424     	
       
   425     	/* Previous character EAboveDiacritic2 */
       
   426     	    {
       
   427     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   428     		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
       
   429     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   430     		EReject, EReject, EReject,
       
   431     	    },
       
   432     	
       
   433     	/* Previous character EAboveDiacritic3 */
       
   434     	    {
       
   435     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   436     		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
       
   437     		EReject, EReject, EReject, EReject, EReject, EReject,
       
   438     		EReject, EReject, EReject,
       
   439     	    },
       
   440     	
       
   441     	/* Previous character EAboveVowel1 */
       
   442     	    {
       
   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,
       
   448     	    },
       
   449     	
       
   450     	/* Previous character EAboveVowel2 */
       
   451     	    {
       
   452     		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
       
   453     		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
       
   454     		EReject, EComposite, EReject, EReject, EReject, EReject,
       
   455     		EReject, EReject, EReject,
       
   456     	    },
       
   457     	
       
   458     	/* Previous character EAboveVowel3 */
       
   459     	    {
       
   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,
       
   465     	    },
       
   466 
       
   467     	// Value at last measurement was 324 bytes. 27/6/2003
       
   468         };
       
   469 
       
   470 
       
   471     /**
       
   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.
       
   474     @param aPrevChar 
       
   475      Unicode character code preceding the assumed position.
       
   476     @param aChar
       
   477      Unicode character code proceeding the assumed position.
       
   478     @return Wtt2Rule
       
   479      The rule value found in data table.
       
   480     */
       
   481     Wtt2Rule LookupWtt2Rule(TUint aPrevChar, TUint aChar)
       
   482         {
       
   483     	const CharClassification prevCharClassification = 
       
   484     	    static_cast<CharClassification>(
       
   485     		(aPrevChar > KThaiCodePageStart && aPrevChar < KThaiCodePageEnd) ?
       
   486     			iCharClassifications[aPrevChar - KThaiCodePageStart] :
       
   487     			ENonPrintable);
       
   488     	const CharClassification charClassification = 
       
   489     	    static_cast<CharClassification>(
       
   490     		(aChar > KThaiCodePageStart && aChar < KThaiCodePageEnd) ?
       
   491     			iCharClassifications[aChar - KThaiCodePageStart] :
       
   492     			ENonPrintable);
       
   493 
       
   494     	return static_cast<Wtt2Rule>
       
   495     	    (iInputRules[prevCharClassification][charClassification]);
       
   496         }
       
   497 
       
   498     }
       
   499 
       
   500 using namespace ThaiCharRules;
       
   501     
       
   502     
       
   503 //
       
   504 //
       
   505 // ThaiGlyphPUASubstitution Namespace definition
       
   506 //
       
   507 //
       
   508 
       
   509 
       
   510 /**
       
   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.
       
   515 @internalComponent
       
   516 */
       
   517 namespace ThaiGlyphPUASubstitution
       
   518 	{
       
   519 	
       
   520 	typedef TBool (*UnicodeCharValidator)(const TGlyphSelectionState& aGss);
       
   521 
       
   522 	struct PUASubstTableEntry
       
   523 		{
       
   524 		TUint	iOrigGlyph;
       
   525 		TUint	iPUAGlyph;
       
   526 		UnicodeCharValidator	iRuleFunc;
       
   527 		};
       
   528 
       
   529 
       
   530     /**
       
   531      ThaiGlyphPUASubstitution rule method which checks the context for
       
   532      short consonant preceding char OR 
       
   533      short consonant & dependent vowel below preceding char.
       
   534     @param aGss
       
   535      Container object holds the glyph selection context for the method.
       
   536     @return TBool
       
   537      ETrue when the rule context is satisfied, EFalse if not. 
       
   538     */
       
   539      TBool RuleShortConsonant(const TGlyphSelectionState& aGss)
       
   540    	{
       
   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)
       
   547     			return ETrue;
       
   548     		else 
       
   549     			return EFalse;
       
   550     	}
       
   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)))
       
   561     			return ETrue;
       
   562     		else
       
   563     			return EFalse;
       
   564     	}
       
   565     	return EFalse;
       
   566     }
       
   567 
       
   568     /**
       
   569      ThaiGlyphPUASubstitution rule method which checks the context for
       
   570      tall consonant preceding char.
       
   571     @param aGss
       
   572      Container object holds the glyph selection context for the method.
       
   573     @return TBool
       
   574      ETrue when the rule context is satisfied, EFalse if not. 
       
   575     */
       
   576     TBool RuleTallConsonant(const TGlyphSelectionState& aGss)
       
   577     	{
       
   578     	if ((aGss.iParam.iOutputGlyphs == 1) &&
       
   579     	 	ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode))
       
   580     		return ETrue;
       
   581     	else
       
   582     		return EFalse;
       
   583     	}
       
   584 
       
   585     /**
       
   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
       
   588      following sara am.
       
   589     @param aGss
       
   590      Container object holds the glyph selection context for the method.
       
   591     @return TBool
       
   592      ETrue when the rule context is satisfied, EFalse if not.
       
   593     */
       
   594     TBool RuleTallConsonantNoVowelAbove(const TGlyphSelectionState& aGss)
       
   595     	{
       
   596     	if (aGss.iParam.iOutputGlyphs == 0)
       
   597     		return EFalse;
       
   598     	if (!ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode))
       
   599     		return EFalse;
       
   600     	if (aGss.iParam.iOutputGlyphs == 1)
       
   601     		return ETrue;
       
   602     	if (aGss.iParam.iOutputGlyphs != 2)
       
   603     		return EFalse;
       
   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)
       
   609     		return EFalse;
       
   610 	return ETrue;
       
   611     	}
       
   612 
       
   613     /**
       
   614      ThaiGlyphPUASubstitution rule method which checks the context for tall
       
   615      consonant with either a dependent vowel above or nikhahit.
       
   616     @param aGss
       
   617      Container object holds the glyph selection context for the method.
       
   618     @return TBool
       
   619      ETrue when the rule context is satisfied, EFalse if not.
       
   620     */
       
   621     TBool RuleTallConsonantVowelAbove(const TGlyphSelectionState& aGss)
       
   622     	{
       
   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)
       
   627     		return ETrue;
       
   628     	else
       
   629     		return EFalse;
       
   630     	}
       
   631 
       
   632     /**
       
   633      ThaiGlyphPUASubstitution rule method which checks the context for
       
   634      consonant with joined descender preceding char.
       
   635     @param aGss
       
   636      Container object holds the glyph selection context for the method.
       
   637     @return TBool
       
   638      ETrue when the rule context is satisfied, EFalse if not. 
       
   639     */
       
   640      TBool RuleConsonantWithJointDescender(const TGlyphSelectionState& aGss)
       
   641    	{
       
   642     	if ((aGss.iParam.iOutputGlyphs == 1) &&
       
   643     	 	ThaiGlyph::IsThaiConsonantWithJointDescender(aGss.iParam.iOutput[0].iCode))
       
   644     		return ETrue;
       
   645     	else
       
   646     		return EFalse;
       
   647     	}
       
   648 
       
   649 
       
   650     const PUASubstTableEntry RuleTable[] = {
       
   651     /**
       
   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.
       
   657     */
       
   658     /*    iOrigGlyph, iPUAGlyph, iRuleFunc                                     */
       
   659 
       
   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 },
       
   666 
       
   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 },
       
   675 
       
   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 },	
       
   682 
       
   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 },	
       
   690 
       
   691     	// Substitutions for a vowel or sign mark below a consonant with a  
       
   692     	// joined descender
       
   693     	{ 0x0E38,	  0xF718,	 RuleConsonantWithJointDescender },
       
   694     	{ 0x0E39,	  0xF719,	 RuleConsonantWithJointDescender },
       
   695     	{ 0x0E3A,	  0xF71A,	 RuleConsonantWithJointDescender },
       
   696 
       
   697     	{ 0, 0, 0}
       
   698 
       
   699     	// Size of table at last measurement was 312 bytes. 27/6/2003
       
   700     	};
       
   701 
       
   702 
       
   703     /**
       
   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
       
   708      the rule set logic.
       
   709     @param aCode
       
   710      On input it is the character to lookup, on exit it is either unchanged
       
   711      or a code in the PUA 0xF700..0xF71A.
       
   712     @param aGss
       
   713      Container object holds the glyph selection context for the method.
       
   714     @return TBool
       
   715      ETrue when a match is found and aCode has changed, EFalse otherwise.
       
   716     */
       
   717     TBool Lookup(TUint& aCode, const TGlyphSelectionState& aGss)
       
   718     	{
       
   719     	const PUASubstTableEntry* tablePtr = RuleTable;
       
   720     	while (tablePtr->iOrigGlyph)
       
   721     		{
       
   722     		if ((aCode == tablePtr->iOrigGlyph) && tablePtr->iRuleFunc(aGss))
       
   723     			{
       
   724     			aCode = tablePtr->iPUAGlyph;
       
   725     			return ETrue; // Rule match, substitute glyph code
       
   726     			}
       
   727     		tablePtr++;
       
   728     		}
       
   729     	return EFalse; // No match in table
       
   730     	}
       
   731     }
       
   732 
       
   733 
       
   734 // 
       
   735 //
       
   736 // GlyphSelector_Thai Class definition
       
   737 //
       
   738 //
       
   739 
       
   740 
       
   741 /**
       
   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.
       
   746 @param aGss
       
   747  Container object holds the input/output parameters of the method.
       
   748 @return TBool
       
   749  ETrue when glyph cluster updated successfully, EFalse on error condition.
       
   750 @see 
       
   751  The method GlyphSelector_Thai::Process() also handles it for other cases.
       
   752 */
       
   753 TBool GlyphSelector_Thai::Process(TGlyphSelectionState& aGss, RShapeInfo&) 
       
   754 	{
       
   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;
       
   760 	
       
   761 	// Is it a Thai base char or a mark (combining) char?
       
   762 	if ((aGss.iCats & 0xF0) == TChar::EMarkGroup)
       
   763 		{
       
   764     
       
   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))
       
   769 			{
       
   770 			(void) aGss.iText.Prev();
       
   771 			aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
       
   772 			return ETrue;
       
   773 			}
       
   774 		
       
   775 		// Missing base glyph? Insert a dotted circle glyph if true.
       
   776 		if (aGss.iParam.iOutputGlyphs == 0) 
       
   777 			{
       
   778 			if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
       
   779 				return EFalse;
       
   780 			aGss.iParam.iPen += aGss.iAdvance;
       
   781 			}
       
   782 
       
   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))
       
   788 			{
       
   789 			TUint nikhahit = ThaiGlyph::KNikhahit;
       
   790 			// Check and do PUA glyph substitution on Nikhahit
       
   791 			ThaiGlyphPUASubstitution::Lookup(nikhahit, aGss);
       
   792 
       
   793 			if (!aGss.AppendGlyphToCluster(nikhahit))
       
   794 				return EFalse;
       
   795 	
       
   796 			// Check and do PUA glyph substitution on combining mark
       
   797 			ThaiGlyphPUASubstitution::Lookup(code, aGss);
       
   798 
       
   799 			// Append the curernt Thai Mark to the output stack of glyphs.
       
   800 			if (!aGss.AppendGlyphToCluster(code))
       
   801 				return EFalse;
       
   802 
       
   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))
       
   806 				return EFalse;
       
   807 			
       
   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;
       
   814 			}
       
   815 		else
       
   816 			{
       
   817 			// Check and do PUA glyph substitution on combining mark
       
   818 			ThaiGlyphPUASubstitution::Lookup(code, aGss);
       
   819 
       
   820 			// Append the curernt Thai Mark to the output stack of glyphs.
       
   821 			if (!aGss.AppendGlyphToCluster(code))
       
   822 				return EFalse;
       
   823 
       
   824 			aGss.iPen = TGlyphSelectionState::EPenAdvance_No;
       
   825 			}
       
   826 		}
       
   827 	else
       
   828 
       
   829 		{
       
   830 		// Thai character is an independent consonant, digit or sign
       
   831 
       
   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;
       
   841 			
       
   842 		// Append the glyph details for the Thai character onto the output 
       
   843 		// stack of glyphs.
       
   844 		if (!aGss.AppendGlyphToCluster(code))
       
   845 			return EFalse;
       
   846 
       
   847 		// Make sure the caller advances the pen for a base char!
       
   848 		aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
       
   849 		}
       
   850 
       
   851 	// Lookup in rule table to determine if the current glyph and cluster is 
       
   852 	// now complete? 
       
   853 	if (ThaiCharRules::LookupWtt2Rule(aGss.iCodePt, nextCode) == ThaiCharRules::EComposite)
       
   854 		aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
       
   855 	else
       
   856 		aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
       
   857 
       
   858 	return ETrue;
       
   859 	}
       
   860 
       
   861 
       
   862 // 
       
   863 //
       
   864 // GlyphSelector_ThaiSaraAm Class definition
       
   865 //
       
   866 //
       
   867 
       
   868 
       
   869 /**
       
   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.
       
   876 @param aGss
       
   877  Container object holds the input/output parameters of the method.
       
   878 @return TBool
       
   879  ETrue when glyph cluster updated successfully, EFalse on error condition.
       
   880 @see 
       
   881  The method GlyphSelector_Thai::Process() also handles it for other cases.
       
   882 */ 
       
   883 TBool GlyphSelector_ThaiSaraAm::Process(TGlyphSelectionState& aGss, RShapeInfo&)
       
   884 	{
       
   885 	if (aGss.iCodePt != ThaiGlyph::KSaraAm) //could have got here via
       
   886 		{                    //FindLocalisedProcessFunc in font.cpp
       
   887 		RShapeInfo dummy;
       
   888 		return GlyphSelector_Thai::Process(aGss, dummy);
       
   889 		}
       
   890 	
       
   891 	// Pen advance accumulator local variable
       
   892 	TSize compoundAdvance;
       
   893 
       
   894 	if (aGss.iText.LengthToStart() == 0)
       
   895 		{
       
   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. 
       
   898 		
       
   899 		if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
       
   900 			return EFalse;
       
   901 		aGss.iParam.iPen += aGss.iAdvance;
       
   902 
       
   903 		aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
       
   904 		if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
       
   905 			return EFalse;
       
   906 		compoundAdvance += aGss.iAdvance;
       
   907 		}
       
   908 	else
       
   909 		{
       
   910 		// Normal condition - text iterator now some way into the text line
       
   911 		// being processed.
       
   912 		
       
   913 		TUint prevChar = aGss.iText.Get(-1);
       
   914 		if (ThaiGlyph::IsThaiShortConsonant(prevChar))
       
   915 			{
       
   916 			// SARA AM is following normal height consonant so we can output
       
   917 			// non-decomposed SARA AM glyph.
       
   918 
       
   919 			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
       
   920 				return EFalse;
       
   921 			compoundAdvance = aGss.iAdvance;
       
   922 			}
       
   923 		else if (ThaiGlyph::IsThaiTallConsonant(prevChar))
       
   924 			{
       
   925 			// SARA AM is following tall consonant so we output decomposed
       
   926 			// version of SARA AM but with NIKHAHIT taken from the PUA.
       
   927 
       
   928 			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KNikhahitPua))
       
   929 				return EFalse;
       
   930 			compoundAdvance = aGss.iAdvance;
       
   931 			aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
       
   932 			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAa))
       
   933 				return EFalse;
       
   934 			compoundAdvance += aGss.iAdvance;
       
   935 			}
       
   936 		else
       
   937 			{
       
   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))
       
   941 				return EFalse;
       
   942 			aGss.iParam.iPen += aGss.iAdvance;
       
   943 
       
   944 			aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
       
   945 			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
       
   946 				return EFalse;
       
   947 			compoundAdvance += aGss.iAdvance;
       
   948 			}
       
   949 
       
   950 		}
       
   951 
       
   952 	// Update output parameters resulting from above processing.
       
   953 	// Move text iterator onto next character to process.
       
   954 	aGss.iText.Next();
       
   955 
       
   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;
       
   960 
       
   961 	if (!aGss.iText.AtEnd() &&
       
   962 		(ThaiCharRules::LookupWtt2Rule(aGss.iCodePt, aGss.iText.Get()) == 
       
   963 		 ThaiCharRules::EComposite))
       
   964 		aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
       
   965 	else
       
   966 		aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
       
   967 
       
   968 	return ETrue;
       
   969 	}