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