os/graphics/graphicsdeviceinterface/gdi/sgdi/FontThai.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
/**
sl@0
    17
 @file
sl@0
    18
 @internalComponent
sl@0
    19
*/
sl@0
    20
sl@0
    21
sl@0
    22
#include <gdi.h>
sl@0
    23
#include "FontThai.h"
sl@0
    24
sl@0
    25
sl@0
    26
//
sl@0
    27
// ThaiGlyph Namespace definition
sl@0
    28
//
sl@0
    29
sl@0
    30
sl@0
    31
/**
sl@0
    32
 This namespace holds functions used to evaluate a glyph character code
sl@0
    33
 against a given Thai related prediciate. The 'code' argument is a glyph
sl@0
    34
 from the current output cluster and so may be a Thai glyph, Thai PUA glyph, 
sl@0
    35
 the dotted circle glyph or 0xffff. Therefore it was decided not to implement
sl@0
    36
 these routines using a data driven table approach as it would be inefficient.
sl@0
    37
@internalComponent.
sl@0
    38
*/
sl@0
    39
namespace ThaiGlyph
sl@0
    40
    {
sl@0
    41
    const TText16 KYoYing		= 0x0E0D;
sl@0
    42
    const TText16 KYoYingPua	= 0xF70F;
sl@0
    43
    const TText16 KThoThan		= 0x0E10;
sl@0
    44
    const TText16 KThoThanPua	= 0xF700;
sl@0
    45
    const TText16 KNikhahit	    = 0x0E4D;
sl@0
    46
    const TText16 KNikhahitPua	= 0xF711;
sl@0
    47
    const TText16 KSaraAa		= 0x0E32;
sl@0
    48
    const TText16 KSaraAm		= 0x0E33;
sl@0
    49
sl@0
    50
    
sl@0
    51
     TBool IsThaiGlyph(TUint code)
sl@0
    52
    	{
sl@0
    53
       	return ((code > 0x0E00 && code < 0x0E3B) ||
sl@0
    54
    			(code > 0x0E3E && code < 0x0E5C) ||
sl@0
    55
    			(code >= 0xF700 && code <= 0xF71A));
sl@0
    56
    	}
sl@0
    57
sl@0
    58
     TBool IsThaiConsonant(TUint code)
sl@0
    59
    	{
sl@0
    60
    	return (code >= 0x0E01 && code <= 0x0E2E);
sl@0
    61
    	}
sl@0
    62
sl@0
    63
     TBool IsThaiTallConsonant(TUint code)
sl@0
    64
    	{
sl@0
    65
    	return (//code == 0x0E0A ||	// CHO CHANG not tall at all
sl@0
    66
    			//code == 0x0E0B ||	// SO SO not tall at all
sl@0
    67
    			code == 0x0E1B ||	// PO PLA
sl@0
    68
    			code == 0x0E1D ||	// FO FA
sl@0
    69
    			code == 0x0E1F ||	// FO FAN
sl@0
    70
    			code == 0x0E2C);	// LO CHULA in some fonts, Unicode tables show it as tall
sl@0
    71
    	}
sl@0
    72
sl@0
    73
     TBool IsThaiShortConsonant(TUint code)
sl@0
    74
    	{
sl@0
    75
    	return (((code >= 0x0E01 && code <= 0x0E2E) || (code == KUnicodeDottedCircle)) &&
sl@0
    76
    			code != 0x0E1B &&	// PO PLA
sl@0
    77
    			code != 0x0E1D &&	// FO FA
sl@0
    78
    			code != 0x0E1F &&	// FO FAN
sl@0
    79
    			code != 0x0E2C);	// LO CHULA in some fonts, Unicode tables show it as tall
sl@0
    80
    	}
sl@0
    81
sl@0
    82
     TBool IsThaiConsonantWithDisjointDescender(TUint code)
sl@0
    83
    	{
sl@0
    84
    	return (code == ThaiGlyph::KYoYing || code == ThaiGlyph::KThoThan);
sl@0
    85
    	}
sl@0
    86
sl@0
    87
     TBool IsThaiConsonantWithJointDescender(TUint code)
sl@0
    88
    	{
sl@0
    89
    	return (code == 0x0E0E || // DO CHADA
sl@0
    90
    			code == 0x0E0F || // PO PATAK
sl@0
    91
    			code == 0x0E24 || // RU
sl@0
    92
       			code == 0x0E26);  // LU
sl@0
    93
    	}
sl@0
    94
sl@0
    95
     TBool IsThaiVowel(TUint code)
sl@0
    96
    	{
sl@0
    97
    	return ((code >= 0x0E30 && code <= 0x0E3A) ||
sl@0
    98
    			(code >= 0x0E40 && code <= 0x0E44) ||
sl@0
    99
    			code == 0x0E47);	// MAITAIKHU
sl@0
   100
    	}
sl@0
   101
sl@0
   102
     TBool IsThaiDepVowel(TUint code)
sl@0
   103
    	{
sl@0
   104
    	return (code == 0x0E31 ||	// MAI HAN-AKAT
sl@0
   105
    			(code >= 0x0E34 && code <= 0x0E3A) ||
sl@0
   106
    			code == 0x0E47);	// MAITAIKHU
sl@0
   107
    	}
sl@0
   108
sl@0
   109
     TBool IsThaiDepVowelAbove(TUint code)
sl@0
   110
    	{
sl@0
   111
    	return (code == 0x0E31 ||	// MAI HAN-AKAT
sl@0
   112
    			(code >= 0x0E34 && code <= 0x0E37) ||
sl@0
   113
    			code == 0x0E47);	// MAITAIKHU
sl@0
   114
    	}
sl@0
   115
sl@0
   116
     TBool IsThaiDepVowelAbovePUA(TUint code)
sl@0
   117
    	{
sl@0
   118
    	return (code == 0xF710 ||	// MAI HAN-AKAT
sl@0
   119
    			(code >= 0xF701 && code <= 0xF704) ||
sl@0
   120
    			code == 0xF712);	// MAITAIKHU
sl@0
   121
    	}
sl@0
   122
sl@0
   123
     TBool IsThaiDepVowelBelow(TUint code)
sl@0
   124
    	{
sl@0
   125
    	return (code >= 0x0E38 && code <= 0x0E3A);
sl@0
   126
    	}
sl@0
   127
sl@0
   128
     TBool IsThaiIndepVowel(TUint code)
sl@0
   129
    	{
sl@0
   130
    	return (code == 0x0E30 ||	// SARA A
sl@0
   131
      			code == 0x0E32 ||	// SARA AA
sl@0
   132
    			code == 0x0E33 ||	// SARA AM
sl@0
   133
    			(code >= 0x0E40 && code <= 0x0E44));
sl@0
   134
    	}
sl@0
   135
sl@0
   136
     TBool IsThaiToneMark(TUint code)
sl@0
   137
    	{
sl@0
   138
    	return (code >= 0x0E48 && code <= 0x0E4B);
sl@0
   139
    	}
sl@0
   140
    }
sl@0
   141
sl@0
   142
    
sl@0
   143
//
sl@0
   144
//
sl@0
   145
// ThaiCharRules Namespace definition
sl@0
   146
//
sl@0
   147
//
sl@0
   148
sl@0
   149
sl@0
   150
/**
sl@0
   151
 ThaiCharRules namespace holds the data and lookup methods
sl@0
   152
 implementing the WTT 2.0 input/output validation matrix.
sl@0
   153
@internalComponent
sl@0
   154
*/
sl@0
   155
namespace ThaiCharRules
sl@0
   156
	{
sl@0
   157
  	const TUint KThaiCodePageStart      = 0x0E00;
sl@0
   158
	const TUint KThaiCodePageEnd        = 0x0E5C;
sl@0
   159
	const TUint KNumThaiCharacters      = KThaiCodePageEnd-KThaiCodePageStart;
sl@0
   160
sl@0
   161
	enum Wtt2Rule
sl@0
   162
		{
sl@0
   163
		EUndefined,
sl@0
   164
		EAccept,
sl@0
   165
		EComposite,
sl@0
   166
		EReject,
sl@0
   167
		ERejectStrict,
sl@0
   168
		};
sl@0
   169
sl@0
   170
	/**
sl@0
   171
	This enumeration holds the set of classification values a Thai
sl@0
   172
	character can be categorised as in the WTT2.0 specification.
sl@0
   173
	*/
sl@0
   174
	enum CharClassification
sl@0
   175
		{
sl@0
   176
		ENull,
sl@0
   177
		EControl,
sl@0
   178
		ENonPrintable,
sl@0
   179
		EConsonant,
sl@0
   180
		ELeadingVowel,
sl@0
   181
		EOrdinaryFollowingVowel,
sl@0
   182
		EDependentFollowingVowel,
sl@0
   183
		ESpecialFollowingVowel,
sl@0
   184
		EShortBelowVowel,
sl@0
   185
		ELongBelowVowel,
sl@0
   186
		EBelowDiacritic,
sl@0
   187
		EToneMark,
sl@0
   188
		EAboveDiacritic0,
sl@0
   189
		EAboveDiacritic1,
sl@0
   190
		EAboveDiacritic2,
sl@0
   191
		EAboveDiacritic3,
sl@0
   192
		EAboveVowel1,
sl@0
   193
		EAboveVowel2,
sl@0
   194
		EAboveVowel3,
sl@0
   195
		// marker for end
sl@0
   196
		EMaxClassification
sl@0
   197
		};
sl@0
   198
sl@0
   199
sl@0
   200
	/**
sl@0
   201
	 Data table holding the classification of each character.
sl@0
   202
	*/
sl@0
   203
	static const TUint8 iCharClassifications[KNumThaiCharacters] = 
sl@0
   204
        {
sl@0
   205
    	ENull,			// No entry in code page
sl@0
   206
    	EConsonant,		// 0x0E01
sl@0
   207
    	EConsonant,		// 0x0E02
sl@0
   208
    	EConsonant,		// 0x0E03
sl@0
   209
    	EConsonant,		// 0x0E04
sl@0
   210
    	EConsonant,		// 0x0E05
sl@0
   211
    	EConsonant,		// 0x0E06
sl@0
   212
    	EConsonant,		// 0x0E07
sl@0
   213
    	EConsonant,		// 0x0E08
sl@0
   214
    	EConsonant,		// 0x0E09
sl@0
   215
    	EConsonant,		// 0x0E0A
sl@0
   216
    	EConsonant,		// 0x0E0B
sl@0
   217
    	EConsonant,		// 0x0E0C
sl@0
   218
    	EConsonant,		// 0x0E0D
sl@0
   219
    	EConsonant,		// 0x0E0E
sl@0
   220
    	EConsonant,		// 0x0E0F
sl@0
   221
sl@0
   222
    	EConsonant,		// 0x0E10
sl@0
   223
    	EConsonant,		// 0x0E11
sl@0
   224
    	EConsonant,		// 0x0E12
sl@0
   225
    	EConsonant,		// 0x0E13
sl@0
   226
    	EConsonant,		// 0x0E14
sl@0
   227
    	EConsonant,		// 0x0E15
sl@0
   228
    	EConsonant,		// 0x0E16
sl@0
   229
    	EConsonant,		// 0x0E17
sl@0
   230
    	EConsonant,		// 0x0E18
sl@0
   231
    	EConsonant,		// 0x0E19
sl@0
   232
    	EConsonant,		// 0x0E1A
sl@0
   233
    	EConsonant,		// 0x0E1B
sl@0
   234
    	EConsonant,		// 0x0E1C
sl@0
   235
    	EConsonant,		// 0x0E1D
sl@0
   236
    	EConsonant,		// 0x0E1E
sl@0
   237
    	EConsonant,		// 0x0E1F
sl@0
   238
sl@0
   239
    	EConsonant,		// 0x0E20
sl@0
   240
    	EConsonant,		// 0x0E21
sl@0
   241
    	EConsonant,		// 0x0E22
sl@0
   242
    	EConsonant,		// 0x0E23
sl@0
   243
    	EConsonant,		// 0x0E24
sl@0
   244
    	EConsonant,		// 0x0E25
sl@0
   245
    	EConsonant,		// 0x0E26
sl@0
   246
    	EConsonant,		// 0x0E27
sl@0
   247
    	EConsonant,		// 0x0E28
sl@0
   248
    	EConsonant,		// 0x0E29
sl@0
   249
    	EConsonant,		// 0x0E2A
sl@0
   250
    	EConsonant,		// 0x0E2B
sl@0
   251
    	EConsonant,		// 0x0E2C
sl@0
   252
    	EConsonant,		// 0x0E2D
sl@0
   253
    	EConsonant,		// 0x0E2E
sl@0
   254
    	ENonPrintable,	// 0x0E2F
sl@0
   255
sl@0
   256
    	EOrdinaryFollowingVowel,// 0x0E30
sl@0
   257
    	EAboveVowel2,			// 0x0E31
sl@0
   258
    	EOrdinaryFollowingVowel,// 0x0E32
sl@0
   259
    	EOrdinaryFollowingVowel,// 0x0E33
sl@0
   260
    	EAboveVowel1,			// 0x0E34
sl@0
   261
    	EAboveVowel3,			// 0x0E35
sl@0
   262
    	EAboveVowel2,			// 0x0E36
sl@0
   263
    	EAboveVowel3,			// 0x0E37
sl@0
   264
    	EShortBelowVowel,		// 0x0E38
sl@0
   265
    	ELongBelowVowel,		// 0x0E39
sl@0
   266
    	EBelowDiacritic,		// 0x0E3A
sl@0
   267
    	ENull,					// 0x0E3B
sl@0
   268
    	ENull,					// 0x0E3C
sl@0
   269
    	ENull,					// 0x0E3D
sl@0
   270
    	ENull,					// 0x0E3E
sl@0
   271
    	ENonPrintable,			// 0x0E3F
sl@0
   272
sl@0
   273
    	ELeadingVowel,			// 0x0E40
sl@0
   274
    	ELeadingVowel,			// 0x0E41
sl@0
   275
    	ELeadingVowel,			// 0x0E42
sl@0
   276
    	ELeadingVowel,			// 0x0E43
sl@0
   277
    	ELeadingVowel,			// 0x0E44
sl@0
   278
    	EDependentFollowingVowel,//0x0E45
sl@0
   279
    	ENonPrintable,			// 0x0E46
sl@0
   280
    	EAboveDiacritic2,		// 0x0E47
sl@0
   281
    	EToneMark,				// 0x0E48
sl@0
   282
    	EToneMark,				// 0x0E49
sl@0
   283
    	EToneMark,				// 0x0E4A
sl@0
   284
    	EToneMark,				// 0x0E4B
sl@0
   285
    	EAboveDiacritic1,		// 0x0E4C
sl@0
   286
    	EAboveDiacritic0,		// 0x0E4D
sl@0
   287
    	EAboveDiacritic3,		// 0x0E4E
sl@0
   288
    	ENonPrintable,			// 0x0E4F
sl@0
   289
sl@0
   290
    	ENonPrintable,			// 0x0E50
sl@0
   291
    	ENonPrintable,			// 0x0E51
sl@0
   292
    	ENonPrintable,			// 0x0E52
sl@0
   293
    	ENonPrintable,			// 0x0E53
sl@0
   294
    	ENonPrintable,			// 0x0E54
sl@0
   295
    	ENonPrintable,			// 0x0E55
sl@0
   296
    	ENonPrintable,			// 0x0E56
sl@0
   297
    	ENonPrintable,			// 0x0E57
sl@0
   298
    	ENonPrintable,			// 0x0E58
sl@0
   299
    	ENonPrintable,			// 0x0E59
sl@0
   300
    	ENonPrintable,			// 0x0E5A
sl@0
   301
    	ENonPrintable,			// 0x0E5B
sl@0
   302
sl@0
   303
    	// Value at last measurement was 92 bytes. 27/6/2003
sl@0
   304
        };
sl@0
   305
sl@0
   306
sl@0
   307
	/**
sl@0
   308
	 WTT 2.0 Rules data table of prev to next character
sl@0
   309
	*/
sl@0
   310
	static const TUint8 iInputRules[EMaxClassification][EMaxClassification] =
sl@0
   311
        {
sl@0
   312
    	/* Previous character ENull */
sl@0
   313
    	    {
sl@0
   314
    		EUndefined, EUndefined, EUndefined, EUndefined, EUndefined, 
sl@0
   315
    		EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
sl@0
   316
    		EUndefined, EUndefined, EUndefined, EUndefined, EUndefined,
sl@0
   317
    		EUndefined, EUndefined, EUndefined, EUndefined 
sl@0
   318
    	    },
sl@0
   319
sl@0
   320
    	/* Previous character EControl */
sl@0
   321
    	    {
sl@0
   322
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   323
    		EAccept, EAccept, EAccept, EReject, EReject,
sl@0
   324
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   325
    		EReject, EReject, EReject,
sl@0
   326
    	    },
sl@0
   327
sl@0
   328
    	/* Previous character ENonPrintable */
sl@0
   329
    	    {
sl@0
   330
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   331
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   332
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   333
    		EReject, EReject, EReject,
sl@0
   334
    	    },
sl@0
   335
sl@0
   336
    	/* Previous character EConsonant */
sl@0
   337
    	    {
sl@0
   338
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   339
    		EAccept, ERejectStrict, EAccept, EComposite, EComposite,
sl@0
   340
    		EComposite, EComposite, EComposite, EComposite, EComposite, EComposite,
sl@0
   341
    		EComposite, EComposite, EComposite,
sl@0
   342
    	    },
sl@0
   343
sl@0
   344
    	/* Previous character ELeadingVowel */
sl@0
   345
    	    {
sl@0
   346
    		EUndefined, EUndefined, ERejectStrict, EAccept, ERejectStrict, 
sl@0
   347
    		ERejectStrict, ERejectStrict, ERejectStrict, EReject, EReject,
sl@0
   348
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   349
    		EReject, EReject, EReject,
sl@0
   350
    	    },
sl@0
   351
sl@0
   352
    	/* Previous character EOrdinaryFollowingVowel */
sl@0
   353
    	    {
sl@0
   354
    		EUndefined, EUndefined, ERejectStrict, EAccept, ERejectStrict, 
sl@0
   355
    		EAccept, ERejectStrict, EAccept, EReject, EReject,
sl@0
   356
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   357
    		EReject, EReject, EReject,
sl@0
   358
    	    },
sl@0
   359
sl@0
   360
    	/* Previous character EDependentFollowingVowel */
sl@0
   361
    	    {
sl@0
   362
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   363
    		EAccept, ERejectStrict, EAccept, EReject, EReject,
sl@0
   364
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   365
    		EReject, EReject, EReject,
sl@0
   366
    	    },
sl@0
   367
sl@0
   368
    	/* Previous character ESpecialFollowingVowel */
sl@0
   369
    	    {
sl@0
   370
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   371
    		ERejectStrict, EAccept, ERejectStrict, EReject, EReject,
sl@0
   372
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   373
    		EReject, EReject, EReject,
sl@0
   374
    	    },
sl@0
   375
sl@0
   376
    	/* Previous character EShortBelowVowel */
sl@0
   377
    	    {
sl@0
   378
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   379
    		EAccept, ERejectStrict, EAccept, EReject, EReject,
sl@0
   380
    		EReject, EComposite, EComposite, EComposite, EReject, EReject,
sl@0
   381
    		EReject, EReject, EReject,
sl@0
   382
    	    },
sl@0
   383
    		
sl@0
   384
    	/* Previous character ELongBelowVowel */
sl@0
   385
    	    {
sl@0
   386
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   387
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   388
    		EReject, EComposite, EReject, EReject, EReject, EReject,
sl@0
   389
    		EReject, EReject, EReject,
sl@0
   390
    	    },
sl@0
   391
sl@0
   392
    	/* Previous character EBelowDiacritic */
sl@0
   393
    	    {
sl@0
   394
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   395
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   396
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   397
    		EReject, EReject, EReject,
sl@0
   398
    	    },
sl@0
   399
    	
sl@0
   400
    	/* Previous character EToneMark */
sl@0
   401
    	    {
sl@0
   402
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   403
    		EAccept, EAccept, EAccept, EReject, EReject,
sl@0
   404
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   405
    		EReject, EReject, EReject,
sl@0
   406
    	    },
sl@0
   407
    	
sl@0
   408
	   	/* Previous character EAboveDiacritic0 */
sl@0
   409
    	    {
sl@0
   410
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   411
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   412
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   413
    		EReject, EReject, EReject,
sl@0
   414
    	    },
sl@0
   415
    	
sl@0
   416
    	/* Previous character EAboveDiacritic1 */
sl@0
   417
    	    {
sl@0
   418
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   419
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   420
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   421
    		EReject, EReject, EReject,
sl@0
   422
    	    },
sl@0
   423
    	
sl@0
   424
    	/* Previous character EAboveDiacritic2 */
sl@0
   425
    	    {
sl@0
   426
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   427
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   428
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   429
    		EReject, EReject, EReject,
sl@0
   430
    	    },
sl@0
   431
    	
sl@0
   432
    	/* Previous character EAboveDiacritic3 */
sl@0
   433
    	    {
sl@0
   434
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   435
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   436
    		EReject, EReject, EReject, EReject, EReject, EReject,
sl@0
   437
    		EReject, EReject, EReject,
sl@0
   438
    	    },
sl@0
   439
    	
sl@0
   440
    	/* Previous character EAboveVowel1 */
sl@0
   441
    	    {
sl@0
   442
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   443
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   444
    		EReject, EComposite, EReject, EComposite, EReject, EReject,
sl@0
   445
//    		EReject, EComposite, EComposite, EComposite, EReject, EReject,
sl@0
   446
    		EReject, EReject, EReject,
sl@0
   447
    	    },
sl@0
   448
    	
sl@0
   449
    	/* Previous character EAboveVowel2 */
sl@0
   450
    	    {
sl@0
   451
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   452
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   453
    		EReject, EComposite, EReject, EReject, EReject, EReject,
sl@0
   454
    		EReject, EReject, EReject,
sl@0
   455
    	    },
sl@0
   456
    	
sl@0
   457
    	/* Previous character EAboveVowel3 */
sl@0
   458
    	    {
sl@0
   459
    		EUndefined, EUndefined, EAccept, EAccept, EAccept, 
sl@0
   460
    		ERejectStrict, ERejectStrict, EAccept, EReject, EReject,
sl@0
   461
    		EReject, EComposite, EReject, EReject, EReject, EReject,
sl@0
   462
//			EReject, EComposite, EReject, EComposite, EReject,
sl@0
   463
    		EReject, EReject, EReject,
sl@0
   464
    	    },
sl@0
   465
sl@0
   466
    	// Value at last measurement was 324 bytes. 27/6/2003
sl@0
   467
        };
sl@0
   468
sl@0
   469
sl@0
   470
    /**
sl@0
   471
     This routine looks up the WTT 2.0 rule for the given 
sl@0
   472
     Thai character codes provided in the WTT 2.0 data table.
sl@0
   473
    @param aPrevChar 
sl@0
   474
     Unicode character code preceding the assumed position.
sl@0
   475
    @param aChar
sl@0
   476
     Unicode character code proceeding the assumed position.
sl@0
   477
    @return Wtt2Rule
sl@0
   478
     The rule value found in data table.
sl@0
   479
    */
sl@0
   480
    Wtt2Rule LookupWtt2Rule(TUint aPrevChar, TUint aChar)
sl@0
   481
        {
sl@0
   482
    	const CharClassification prevCharClassification = 
sl@0
   483
    	    static_cast<CharClassification>(
sl@0
   484
    		(aPrevChar > KThaiCodePageStart && aPrevChar < KThaiCodePageEnd) ?
sl@0
   485
    			iCharClassifications[aPrevChar - KThaiCodePageStart] :
sl@0
   486
    			ENonPrintable);
sl@0
   487
    	const CharClassification charClassification = 
sl@0
   488
    	    static_cast<CharClassification>(
sl@0
   489
    		(aChar > KThaiCodePageStart && aChar < KThaiCodePageEnd) ?
sl@0
   490
    			iCharClassifications[aChar - KThaiCodePageStart] :
sl@0
   491
    			ENonPrintable);
sl@0
   492
sl@0
   493
    	return static_cast<Wtt2Rule>
sl@0
   494
    	    (iInputRules[prevCharClassification][charClassification]);
sl@0
   495
        }
sl@0
   496
sl@0
   497
    }
sl@0
   498
sl@0
   499
using namespace ThaiCharRules;
sl@0
   500
    
sl@0
   501
    
sl@0
   502
//
sl@0
   503
//
sl@0
   504
// ThaiGlyphPUASubstitution Namespace definition
sl@0
   505
//
sl@0
   506
//
sl@0
   507
sl@0
   508
sl@0
   509
/**
sl@0
   510
 This utility namespace holds the data and lookup mechanisms to support
sl@0
   511
 the GlyphSelector_Thai glyph selection class in choosing Private User
sl@0
   512
 Area (PUA) Thai character positional variant glyphs. Use of the PUA glyphs
sl@0
   513
 results in a satisfactory rendition of Thai writing in Symbian OS.
sl@0
   514
@internalComponent
sl@0
   515
*/
sl@0
   516
namespace ThaiGlyphPUASubstitution
sl@0
   517
	{
sl@0
   518
	
sl@0
   519
	typedef TBool (*UnicodeCharValidator)(const TGlyphSelectionState& aGss);
sl@0
   520
sl@0
   521
	struct PUASubstTableEntry
sl@0
   522
		{
sl@0
   523
		TUint	iOrigGlyph;
sl@0
   524
		TUint	iPUAGlyph;
sl@0
   525
		UnicodeCharValidator	iRuleFunc;
sl@0
   526
		};
sl@0
   527
sl@0
   528
sl@0
   529
    /**
sl@0
   530
     ThaiGlyphPUASubstitution rule method which checks the context for
sl@0
   531
     short consonant preceding char OR 
sl@0
   532
     short consonant & dependent vowel below preceding char.
sl@0
   533
    @param aGss
sl@0
   534
     Container object holds the glyph selection context for the method.
sl@0
   535
    @return TBool
sl@0
   536
     ETrue when the rule context is satisfied, EFalse if not. 
sl@0
   537
    */
sl@0
   538
     TBool RuleShortConsonant(const TGlyphSelectionState& aGss)
sl@0
   539
   	{
sl@0
   540
   		if (aGss.iParam.iOutputGlyphs == 1) {
sl@0
   541
   		//check the context for short consonant preceding char
sl@0
   542
    		TUint consonantGss = aGss.iParam.iOutput[0].iCode;
sl@0
   543
    		if (ThaiGlyph::IsThaiShortConsonant(consonantGss) ||
sl@0
   544
    			consonantGss == ThaiGlyph::KYoYingPua ||
sl@0
   545
    			consonantGss == ThaiGlyph::KThoThanPua)
sl@0
   546
    			return ETrue;
sl@0
   547
    		else 
sl@0
   548
    			return EFalse;
sl@0
   549
    	}
sl@0
   550
    	if (aGss.iParam.iOutputGlyphs == 2) {
sl@0
   551
    	//check the context for short consonant & dependent vowel below preceding char
sl@0
   552
    		TUint consonantGss = aGss.iParam.iOutput[0].iCode;
sl@0
   553
    		TUint depVowelGss = aGss.iParam.iOutput[1].iCode;
sl@0
   554
    		if ((ThaiGlyph::IsThaiShortConsonant(consonantGss) ||
sl@0
   555
    			consonantGss == ThaiGlyph::KYoYingPua ||
sl@0
   556
    			consonantGss == ThaiGlyph::KThoThanPua) && 
sl@0
   557
    		  (ThaiGlyph::IsThaiDepVowelBelow(depVowelGss) ||
sl@0
   558
    			(depVowelGss >= 0xF718 &&
sl@0
   559
    			 depVowelGss <= 0xF71A)))
sl@0
   560
    			return ETrue;
sl@0
   561
    		else
sl@0
   562
    			return EFalse;
sl@0
   563
    	}
sl@0
   564
    	return EFalse;
sl@0
   565
    }
sl@0
   566
sl@0
   567
    /**
sl@0
   568
     ThaiGlyphPUASubstitution rule method which checks the context for
sl@0
   569
     tall consonant preceding char.
sl@0
   570
    @param aGss
sl@0
   571
     Container object holds the glyph selection context for the method.
sl@0
   572
    @return TBool
sl@0
   573
     ETrue when the rule context is satisfied, EFalse if not. 
sl@0
   574
    */
sl@0
   575
    TBool RuleTallConsonant(const TGlyphSelectionState& aGss)
sl@0
   576
    	{
sl@0
   577
    	if ((aGss.iParam.iOutputGlyphs == 1) &&
sl@0
   578
    	 	ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode))
sl@0
   579
    		return ETrue;
sl@0
   580
    	else
sl@0
   581
    		return EFalse;
sl@0
   582
    	}
sl@0
   583
sl@0
   584
    /**
sl@0
   585
     ThaiGlyphPUASubstitution rule method which checks the context for a tall
sl@0
   586
     consonant which does not have a dependent vowel above or a nikhahit or a
sl@0
   587
     following sara am.
sl@0
   588
    @param aGss
sl@0
   589
     Container object holds the glyph selection context for the method.
sl@0
   590
    @return TBool
sl@0
   591
     ETrue when the rule context is satisfied, EFalse if not.
sl@0
   592
    */
sl@0
   593
    TBool RuleTallConsonantNoVowelAbove(const TGlyphSelectionState& aGss)
sl@0
   594
    	{
sl@0
   595
    	if (aGss.iParam.iOutputGlyphs == 0)
sl@0
   596
    		return EFalse;
sl@0
   597
    	if (!ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode))
sl@0
   598
    		return EFalse;
sl@0
   599
    	if (aGss.iParam.iOutputGlyphs == 1)
sl@0
   600
    		return ETrue;
sl@0
   601
    	if (aGss.iParam.iOutputGlyphs != 2)
sl@0
   602
    		return EFalse;
sl@0
   603
    	TUint wantDepVowel = aGss.iParam.iOutput[1].iCode;
sl@0
   604
    	if (ThaiGlyph::IsThaiDepVowelAbove(wantDepVowel)
sl@0
   605
    		|| ThaiGlyph::IsThaiDepVowelAbovePUA(wantDepVowel)
sl@0
   606
    		|| wantDepVowel == ThaiGlyph::KNikhahit
sl@0
   607
    		|| wantDepVowel == ThaiGlyph::KNikhahitPua)
sl@0
   608
    		return EFalse;
sl@0
   609
	return ETrue;
sl@0
   610
    	}
sl@0
   611
sl@0
   612
    /**
sl@0
   613
     ThaiGlyphPUASubstitution rule method which checks the context for tall
sl@0
   614
     consonant with either a dependent vowel above or nikhahit.
sl@0
   615
    @param aGss
sl@0
   616
     Container object holds the glyph selection context for the method.
sl@0
   617
    @return TBool
sl@0
   618
     ETrue when the rule context is satisfied, EFalse if not.
sl@0
   619
    */
sl@0
   620
    TBool RuleTallConsonantVowelAbove(const TGlyphSelectionState& aGss)
sl@0
   621
    	{
sl@0
   622
    	if ((aGss.iParam.iOutputGlyphs == 2) &&
sl@0
   623
    	 	ThaiGlyph::IsThaiTallConsonant(aGss.iParam.iOutput[0].iCode) &&
sl@0
   624
    		(ThaiGlyph::IsThaiDepVowelAbovePUA(aGss.iParam.iOutput[1].iCode))
sl@0
   625
    		|| aGss.iParam.iOutput[1].iCode == ThaiGlyph::KNikhahitPua)
sl@0
   626
    		return ETrue;
sl@0
   627
    	else
sl@0
   628
    		return EFalse;
sl@0
   629
    	}
sl@0
   630
sl@0
   631
    /**
sl@0
   632
     ThaiGlyphPUASubstitution rule method which checks the context for
sl@0
   633
     consonant with joined descender preceding char.
sl@0
   634
    @param aGss
sl@0
   635
     Container object holds the glyph selection context for the method.
sl@0
   636
    @return TBool
sl@0
   637
     ETrue when the rule context is satisfied, EFalse if not. 
sl@0
   638
    */
sl@0
   639
     TBool RuleConsonantWithJointDescender(const TGlyphSelectionState& aGss)
sl@0
   640
   	{
sl@0
   641
    	if ((aGss.iParam.iOutputGlyphs == 1) &&
sl@0
   642
    	 	ThaiGlyph::IsThaiConsonantWithJointDescender(aGss.iParam.iOutput[0].iCode))
sl@0
   643
    		return ETrue;
sl@0
   644
    	else
sl@0
   645
    		return EFalse;
sl@0
   646
    	}
sl@0
   647
sl@0
   648
sl@0
   649
    const PUASubstTableEntry RuleTable[] = {
sl@0
   650
    /**
sl@0
   651
     This data member of the ThaiGlyphPUASubstitution class holds rules
sl@0
   652
     on when a given PUA glyph should be substituted for the original
sl@0
   653
     0x0Exx glyph. Table lookup returns the first match found from the
sl@0
   654
     start of the table, therefore duplicate match situations must be 
sl@0
   655
     avoided in the rule set logic.
sl@0
   656
    */
sl@0
   657
    /*    iOrigGlyph, iPUAGlyph, iRuleFunc                                     */
sl@0
   658
sl@0
   659
    	// Substitutions for a tone or sign mark above a short consonant
sl@0
   660
    	{ 0x0E48,     0xF70A,    RuleShortConsonant },
sl@0
   661
    	{ 0x0E49,     0xF70B,    RuleShortConsonant },
sl@0
   662
    	{ 0x0E4A,     0xF70C,    RuleShortConsonant },
sl@0
   663
    	{ 0x0E4B,     0xF70D,    RuleShortConsonant },
sl@0
   664
    	{ 0x0E4C,     0xF70E,    RuleShortConsonant },
sl@0
   665
sl@0
   666
    	// Substitutions for a vowel or sign mark above a tall consonant
sl@0
   667
    	{ 0x0E34,	  0xF701,	 RuleTallConsonant },
sl@0
   668
    	{ 0x0E35,	  0xF702,	 RuleTallConsonant },
sl@0
   669
    	{ 0x0E36,	  0xF703,	 RuleTallConsonant },
sl@0
   670
    	{ 0x0E37,	  0xF704,	 RuleTallConsonant },
sl@0
   671
    	{ 0x0E31,	  0xF710,	 RuleTallConsonant },
sl@0
   672
    	{ 0x0E4D,	  0xF711,	 RuleTallConsonant },
sl@0
   673
    	{ 0x0E47,	  0xF712,	 RuleTallConsonant },
sl@0
   674
sl@0
   675
    	// Substitutions for a tone or sign mark above a tall consonant
sl@0
   676
    	{ 0x0E48,	  0xF705,	 RuleTallConsonantNoVowelAbove },
sl@0
   677
    	{ 0x0E49,	  0xF706,	 RuleTallConsonantNoVowelAbove },
sl@0
   678
    	{ 0x0E4A,	  0xF707,	 RuleTallConsonantNoVowelAbove },
sl@0
   679
    	{ 0x0E4B,	  0xF708,	 RuleTallConsonantNoVowelAbove },
sl@0
   680
    	{ 0x0E4C,	  0xF709, 	 RuleTallConsonantNoVowelAbove },	
sl@0
   681
sl@0
   682
    	// Substitutions for a tone or sign mark above a vowel which is 
sl@0
   683
    	// above a tall consonant
sl@0
   684
    	{ 0x0E48,	  0xF713,	 RuleTallConsonantVowelAbove },
sl@0
   685
    	{ 0x0E49,	  0xF714,	 RuleTallConsonantVowelAbove },
sl@0
   686
    	{ 0x0E4A,	  0xF715,	 RuleTallConsonantVowelAbove },
sl@0
   687
    	{ 0x0E4B,	  0xF716,	 RuleTallConsonantVowelAbove },
sl@0
   688
    	{ 0x0E4C,	  0xF717,	 RuleTallConsonantVowelAbove },	
sl@0
   689
sl@0
   690
    	// Substitutions for a vowel or sign mark below a consonant with a  
sl@0
   691
    	// joined descender
sl@0
   692
    	{ 0x0E38,	  0xF718,	 RuleConsonantWithJointDescender },
sl@0
   693
    	{ 0x0E39,	  0xF719,	 RuleConsonantWithJointDescender },
sl@0
   694
    	{ 0x0E3A,	  0xF71A,	 RuleConsonantWithJointDescender },
sl@0
   695
sl@0
   696
    	{ 0, 0, 0}
sl@0
   697
sl@0
   698
    	// Size of table at last measurement was 312 bytes. 27/6/2003
sl@0
   699
    	};
sl@0
   700
sl@0
   701
sl@0
   702
    /**
sl@0
   703
     This is the lookup method to determine if the current character being 
sl@0
   704
     processed needs to be substituted for a glyph in the PUA area given the 
sl@0
   705
     supplied context. It scans the rule table and returns when it finds it's
sl@0
   706
     first match. Therefore duplicate match situations must be avoided in
sl@0
   707
     the rule set logic.
sl@0
   708
    @param aCode
sl@0
   709
     On input it is the character to lookup, on exit it is either unchanged
sl@0
   710
     or a code in the PUA 0xF700..0xF71A.
sl@0
   711
    @param aGss
sl@0
   712
     Container object holds the glyph selection context for the method.
sl@0
   713
    @return TBool
sl@0
   714
     ETrue when a match is found and aCode has changed, EFalse otherwise.
sl@0
   715
    */
sl@0
   716
    TBool Lookup(TUint& aCode, const TGlyphSelectionState& aGss)
sl@0
   717
    	{
sl@0
   718
    	const PUASubstTableEntry* tablePtr = RuleTable;
sl@0
   719
    	while (tablePtr->iOrigGlyph)
sl@0
   720
    		{
sl@0
   721
    		if ((aCode == tablePtr->iOrigGlyph) && tablePtr->iRuleFunc(aGss))
sl@0
   722
    			{
sl@0
   723
    			aCode = tablePtr->iPUAGlyph;
sl@0
   724
    			return ETrue; // Rule match, substitute glyph code
sl@0
   725
    			}
sl@0
   726
    		tablePtr++;
sl@0
   727
    		}
sl@0
   728
    	return EFalse; // No match in table
sl@0
   729
    	}
sl@0
   730
    }
sl@0
   731
sl@0
   732
sl@0
   733
// 
sl@0
   734
//
sl@0
   735
// GlyphSelector_Thai Class definition
sl@0
   736
//
sl@0
   737
//
sl@0
   738
sl@0
   739
sl@0
   740
/**
sl@0
   741
 This is the default glyph processing method for the Thai characters in the
sl@0
   742
 range 0x0E00..0x0E7F and is invoked from the Glyph selection algorithm in 
sl@0
   743
 CFont::GetCharacterPosition() method. It is capable of processing base
sl@0
   744
 Thai characters as well as Thai combining vowels, signs a tone marks.
sl@0
   745
@param aGss
sl@0
   746
 Container object holds the input/output parameters of the method.
sl@0
   747
@return TBool
sl@0
   748
 ETrue when glyph cluster updated successfully, EFalse on error condition.
sl@0
   749
@see 
sl@0
   750
 The method GlyphSelector_Thai::Process() also handles it for other cases.
sl@0
   751
*/
sl@0
   752
TBool GlyphSelector_Thai::Process(TGlyphSelectionState& aGss, RShapeInfo&) 
sl@0
   753
	{
sl@0
   754
	// Get the Unicode character codes we need to process the current 
sl@0
   755
	// glyph and increment the iterator onto th next character.
sl@0
   756
	TUint prevCode = (aGss.iText.LengthToStart() > 0) ? aGss.iText.Get(-1) : 0xFFFF;
sl@0
   757
	TUint code = aGss.iText.GetThenNext(); // Inc to next char
sl@0
   758
	TUint nextCode = !aGss.iText.AtEnd() ? aGss.iText.Get(0) : 0xFFFF;
sl@0
   759
	
sl@0
   760
	// Is it a Thai base char or a mark (combining) char?
sl@0
   761
	if ((aGss.iCats & 0xF0) == TChar::EMarkGroup)
sl@0
   762
		{
sl@0
   763
    
sl@0
   764
		// Thai character is combining mark but first check to see if it
sl@0
   765
		// follows a Thai base character before processing it.
sl@0
   766
		if ((aGss.iParam.iOutputGlyphs > 0) && 
sl@0
   767
			!ThaiGlyph::IsThaiGlyph(prevCode))
sl@0
   768
			{
sl@0
   769
			(void) aGss.iText.Prev();
sl@0
   770
			aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
sl@0
   771
			return ETrue;
sl@0
   772
			}
sl@0
   773
		
sl@0
   774
		// Missing base glyph? Insert a dotted circle glyph if true.
sl@0
   775
		if (aGss.iParam.iOutputGlyphs == 0) 
sl@0
   776
			{
sl@0
   777
			if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
sl@0
   778
				return EFalse;
sl@0
   779
			aGss.iParam.iPen += aGss.iAdvance;
sl@0
   780
			}
sl@0
   781
sl@0
   782
		// Test if SARA AM follows this current Thai mark, since it is
sl@0
   783
		// a SPECIAL CASE. If present we need NIKHAHIT glyph before this 
sl@0
   784
		// current Thai mark char.
sl@0
   785
		if (nextCode == ThaiGlyph::KSaraAm &&
sl@0
   786
			(aGss.iParam.iOutputGlyphs == 1) && ThaiGlyph::IsThaiToneMark(code))
sl@0
   787
			{
sl@0
   788
			TUint nikhahit = ThaiGlyph::KNikhahit;
sl@0
   789
			// Check and do PUA glyph substitution on Nikhahit
sl@0
   790
			ThaiGlyphPUASubstitution::Lookup(nikhahit, aGss);
sl@0
   791
sl@0
   792
			if (!aGss.AppendGlyphToCluster(nikhahit))
sl@0
   793
				return EFalse;
sl@0
   794
	
sl@0
   795
			// Check and do PUA glyph substitution on combining mark
sl@0
   796
			ThaiGlyphPUASubstitution::Lookup(code, aGss);
sl@0
   797
sl@0
   798
			// Append the curernt Thai Mark to the output stack of glyphs.
sl@0
   799
			if (!aGss.AppendGlyphToCluster(code))
sl@0
   800
				return EFalse;
sl@0
   801
sl@0
   802
			// We now need to add SARA AA glyph after the current Thai mark char.
sl@0
   803
			aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
sl@0
   804
			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAa))
sl@0
   805
				return EFalse;
sl@0
   806
			
sl@0
   807
			// Skip the following SARA AM character since we've added
sl@0
   808
			// its glyphs to it's previous character's glyph cluster.
sl@0
   809
			// As we've added a base char to the end of the glyph cluster
sl@0
   810
			// make sure the pen is moved on by the caller.
sl@0
   811
			(void) aGss.iText.Next();
sl@0
   812
			aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
sl@0
   813
			}
sl@0
   814
		else
sl@0
   815
			{
sl@0
   816
			// Check and do PUA glyph substitution on combining mark
sl@0
   817
			ThaiGlyphPUASubstitution::Lookup(code, aGss);
sl@0
   818
sl@0
   819
			// Append the curernt Thai Mark to the output stack of glyphs.
sl@0
   820
			if (!aGss.AppendGlyphToCluster(code))
sl@0
   821
				return EFalse;
sl@0
   822
sl@0
   823
			aGss.iPen = TGlyphSelectionState::EPenAdvance_No;
sl@0
   824
			}
sl@0
   825
		}
sl@0
   826
	else
sl@0
   827
sl@0
   828
		{
sl@0
   829
		// Thai character is an independent consonant, digit or sign
sl@0
   830
sl@0
   831
		// Handle disjoint descender consonants followed by below vowel.
sl@0
   832
		// In these two cases we substitute consonant with PUA 
sl@0
   833
		// consonant that the descender removed. Check code not last one.
sl@0
   834
		if (code == ThaiGlyph::KYoYing && nextCode != 0xffff &&
sl@0
   835
			        ThaiGlyph::IsThaiDepVowelBelow(nextCode))
sl@0
   836
			code = ThaiGlyph::KYoYingPua;
sl@0
   837
		else if (code == ThaiGlyph::KThoThan &&  nextCode != 0xffff &&
sl@0
   838
			        ThaiGlyph::IsThaiDepVowelBelow(nextCode))
sl@0
   839
		  	code = ThaiGlyph::KThoThanPua;
sl@0
   840
			
sl@0
   841
		// Append the glyph details for the Thai character onto the output 
sl@0
   842
		// stack of glyphs.
sl@0
   843
		if (!aGss.AppendGlyphToCluster(code))
sl@0
   844
			return EFalse;
sl@0
   845
sl@0
   846
		// Make sure the caller advances the pen for a base char!
sl@0
   847
		aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
sl@0
   848
		}
sl@0
   849
sl@0
   850
	// Lookup in rule table to determine if the current glyph and cluster is 
sl@0
   851
	// now complete? 
sl@0
   852
	if (ThaiCharRules::LookupWtt2Rule(aGss.iCodePt, nextCode) == ThaiCharRules::EComposite)
sl@0
   853
		aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
sl@0
   854
	else
sl@0
   855
		aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
sl@0
   856
sl@0
   857
	return ETrue;
sl@0
   858
	}
sl@0
   859
sl@0
   860
sl@0
   861
// 
sl@0
   862
//
sl@0
   863
// GlyphSelector_ThaiSaraAm Class definition
sl@0
   864
//
sl@0
   865
//
sl@0
   866
sl@0
   867
sl@0
   868
/**
sl@0
   869
 This is the glyph processing method for the Thai SARA AM (U+0E33) character
sl@0
   870
 which is handled as a special case since it is decomposed into two glyphs 
sl@0
   871
 - the combining NIKHAHIT mark & SARA AA following vowel in some cases.
sl@0
   872
 It is invoked from the Glyph selection algorithm in 
sl@0
   873
 CFont::GetCharacterPosition() method for all cases where SARA AM is not 
sl@0
   874
 following a tone mark and thus be a glyph cluster of its own.
sl@0
   875
@param aGss
sl@0
   876
 Container object holds the input/output parameters of the method.
sl@0
   877
@return TBool
sl@0
   878
 ETrue when glyph cluster updated successfully, EFalse on error condition.
sl@0
   879
@see 
sl@0
   880
 The method GlyphSelector_Thai::Process() also handles it for other cases.
sl@0
   881
*/ 
sl@0
   882
TBool GlyphSelector_ThaiSaraAm::Process(TGlyphSelectionState& aGss, RShapeInfo&)
sl@0
   883
	{
sl@0
   884
	if (aGss.iCodePt != ThaiGlyph::KSaraAm) //could have got here via
sl@0
   885
		{                    //FindLocalisedProcessFunc in font.cpp
sl@0
   886
		RShapeInfo dummy;
sl@0
   887
		return GlyphSelector_Thai::Process(aGss, dummy);
sl@0
   888
		}
sl@0
   889
	
sl@0
   890
	// Pen advance accumulator local variable
sl@0
   891
	TSize compoundAdvance;
sl@0
   892
sl@0
   893
	if (aGss.iText.LengthToStart() == 0)
sl@0
   894
		{
sl@0
   895
		// If at the start of a line then render it with a preceding 
sl@0
   896
		// dotted circle as this is invalid positioning for SARA AM. 
sl@0
   897
		
sl@0
   898
		if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
sl@0
   899
			return EFalse;
sl@0
   900
		aGss.iParam.iPen += aGss.iAdvance;
sl@0
   901
sl@0
   902
		aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
sl@0
   903
		if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
sl@0
   904
			return EFalse;
sl@0
   905
		compoundAdvance += aGss.iAdvance;
sl@0
   906
		}
sl@0
   907
	else
sl@0
   908
		{
sl@0
   909
		// Normal condition - text iterator now some way into the text line
sl@0
   910
		// being processed.
sl@0
   911
		
sl@0
   912
		TUint prevChar = aGss.iText.Get(-1);
sl@0
   913
		if (ThaiGlyph::IsThaiShortConsonant(prevChar))
sl@0
   914
			{
sl@0
   915
			// SARA AM is following normal height consonant so we can output
sl@0
   916
			// non-decomposed SARA AM glyph.
sl@0
   917
sl@0
   918
			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
sl@0
   919
				return EFalse;
sl@0
   920
			compoundAdvance = aGss.iAdvance;
sl@0
   921
			}
sl@0
   922
		else if (ThaiGlyph::IsThaiTallConsonant(prevChar))
sl@0
   923
			{
sl@0
   924
			// SARA AM is following tall consonant so we output decomposed
sl@0
   925
			// version of SARA AM but with NIKHAHIT taken from the PUA.
sl@0
   926
sl@0
   927
			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KNikhahitPua))
sl@0
   928
				return EFalse;
sl@0
   929
			compoundAdvance = aGss.iAdvance;
sl@0
   930
			aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
sl@0
   931
			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAa))
sl@0
   932
				return EFalse;
sl@0
   933
			compoundAdvance += aGss.iAdvance;
sl@0
   934
			}
sl@0
   935
		else
sl@0
   936
			{
sl@0
   937
			// SARA AM is a following vowel but is not following a valid
sl@0
   938
			// consonant char and so default is to render with dotted circle.
sl@0
   939
			if (!aGss.AppendGlyphToCluster(KUnicodeDottedCircle))
sl@0
   940
				return EFalse;
sl@0
   941
			aGss.iParam.iPen += aGss.iAdvance;
sl@0
   942
sl@0
   943
			aGss.iAdvance.iWidth = aGss.iAdvance.iHeight = 0;
sl@0
   944
			if (!aGss.AppendGlyphToCluster(ThaiGlyph::KSaraAm))
sl@0
   945
				return EFalse;
sl@0
   946
			compoundAdvance += aGss.iAdvance;
sl@0
   947
			}
sl@0
   948
sl@0
   949
		}
sl@0
   950
sl@0
   951
	// Update output parameters resulting from above processing.
sl@0
   952
	// Move text iterator onto next character to process.
sl@0
   953
	aGss.iText.Next();
sl@0
   954
sl@0
   955
	// Advance pen just for the SARA AA char as advance for dotted 
sl@0
   956
	// circle is done above.
sl@0
   957
	aGss.iAdvance = compoundAdvance;
sl@0
   958
	aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
sl@0
   959
sl@0
   960
	if (!aGss.iText.AtEnd() &&
sl@0
   961
		(ThaiCharRules::LookupWtt2Rule(aGss.iCodePt, aGss.iText.Get()) == 
sl@0
   962
		 ThaiCharRules::EComposite))
sl@0
   963
		aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
sl@0
   964
	else
sl@0
   965
		aGss.iClusterState = TGlyphSelectionState::EGClusterComplete;
sl@0
   966
sl@0
   967
	return ETrue;
sl@0
   968
	}