os/graphics/graphicsdeviceinterface/gdi/sgdi/FontArabic.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 "FontArabic.h"
sl@0
    24
#include "GDIPANIC.h"
sl@0
    25
sl@0
    26
sl@0
    27
//
sl@0
    28
// Arabic Presentation Forms.
sl@0
    29
//
sl@0
    30
sl@0
    31
sl@0
    32
/**
sl@0
    33
 The contextual forms of each character in the range 0621 - 064A, in
sl@0
    34
 the order final, initial, medial; followed by the forms of
sl@0
    35
 the lam-alef ligatures (lam with 0622, 0623, 0625 and 0627);
sl@0
    36
 followed by the forms of the characters in the range 0671 - 06D3
sl@0
    37
*/
sl@0
    38
LOCAL_D const TUint16 TheArabicShapeTable[] =
sl@0
    39
	{
sl@0
    40
	// Contextual forms for standard Arabic letters
sl@0
    41
	0x621, 0x621, 0x621,			// 621
sl@0
    42
	0xfe82, 0x622, 0x622,			// 622
sl@0
    43
	0xfe84, 0x623, 0x623,			// 623
sl@0
    44
	0xfe86, 0x624, 0x624,			// 624
sl@0
    45
	0xfe88, 0x625, 0x625,			// 625
sl@0
    46
	0xfe8a, 0xfe8b, 0xfe8c,			// 626
sl@0
    47
	0xfe8e, 0x627,	0x627,			// 627
sl@0
    48
	0xfe90, 0xfe91, 0xfe92,			// 628
sl@0
    49
	0xfe94, 0x629, 0x629,			// 629
sl@0
    50
	0xfe96, 0xfe97, 0xfe98,			// 62a
sl@0
    51
	0xfe9a, 0xfe9b, 0xfe9c,			// 62b
sl@0
    52
	0xfe9e, 0xfe9f, 0xfea0,			// 62c
sl@0
    53
	0xfea2, 0xfea3, 0xfea4,			// 62d
sl@0
    54
	0xfea6, 0xfea7, 0xfea8,			// 62e
sl@0
    55
	0xfeaa, 0x62f, 0x62f,			// 62f
sl@0
    56
	0xfeac, 0x630, 0x630,			// 630
sl@0
    57
	0xfeae, 0x631, 0x631,			// 631
sl@0
    58
	0xfeb0, 0x632, 0x632,			// 632
sl@0
    59
	0xfeb2, 0xfeb3, 0xfeb4,			// 633
sl@0
    60
	0xfeb6, 0xfeb7, 0xfeb8,			// 634
sl@0
    61
	0xfeba, 0xfebb, 0xfebc,			// 635
sl@0
    62
	0xfebe, 0xfebf, 0xfec0,			// 636
sl@0
    63
	0xfec2, 0xfec3, 0xfec4,			// 637
sl@0
    64
	0xfec6, 0xfec7, 0xfec8,			// 638
sl@0
    65
	0xfeca, 0xfecb, 0xfecc,			// 639
sl@0
    66
	0xfece, 0xfecf, 0xfed0,			// 63a
sl@0
    67
	0x63b, 0x63b, 0x63b,			// placeholder
sl@0
    68
	0x63c, 0x63c, 0x63c,			// placeholder
sl@0
    69
	0x63d, 0x63d, 0x63d,			// placeholder
sl@0
    70
	0x63e, 0x63e, 0x63e,			// placeholder
sl@0
    71
	0x63f, 0x63f, 0x63f,			// placeholder
sl@0
    72
	0x640, 0x640, 0x640,			// 640
sl@0
    73
	0xfed2, 0xfed3, 0xfed4,			// 641
sl@0
    74
	0xfed6, 0xfed7, 0xfed8,			// 642
sl@0
    75
	0xfeda, 0xfedb, 0xfedc,			// 643
sl@0
    76
	0xfede, 0xfedf, 0xfee0,			// 644
sl@0
    77
	0xfee2, 0xfee3, 0xfee4,			// 645
sl@0
    78
	0xfee6, 0xfee7, 0xfee8,			// 646
sl@0
    79
	0xfeea, 0xfeeb, 0xfeec,			// 647
sl@0
    80
	0xfeee, 0x648, 0x648,			// 648
sl@0
    81
	0xfef0, 0xfbe8, 0xfbe9,			// 649
sl@0
    82
	0xfef2, 0xfef3, 0xfef4,			// 64A
sl@0
    83
sl@0
    84
	// Contextual forms for lam-alef ligatures
sl@0
    85
	0xfef6, 0xfef5, 0xfef5,			// 644 + 622
sl@0
    86
	0xfef8, 0xfef7, 0xfef7,			// 644 + 623
sl@0
    87
	0xfefa, 0xfef9, 0xfef9,			// 644 + 625
sl@0
    88
	0xfefc, 0xfefb, 0xfefb,			// 644 + 627
sl@0
    89
sl@0
    90
	// Contextual forms for extended Arabic letters for Persian, Urdu, Sindhi, etc.
sl@0
    91
	0xfb51, 0x0671, 0x0671,			// 671
sl@0
    92
	0x0672, 0x0672, 0x0672,			// placeholder
sl@0
    93
	0x0673, 0x0673, 0x0673,			// placeholder
sl@0
    94
	0x0674, 0x0674, 0x0674,			// placeholder
sl@0
    95
	0x0675, 0x0675, 0x0675,			// placeholder
sl@0
    96
	0x0676, 0x0676, 0x0676,			// placeholder
sl@0
    97
	0x0677, 0x0677, 0x0677,			// placeholder
sl@0
    98
	0x0678, 0x0678, 0x0678,			// placeholder
sl@0
    99
	0xfb67, 0xfb68, 0xfb69,			// 679
sl@0
   100
	0xfb5f, 0xfb60, 0xfb61,			// 67a
sl@0
   101
	0xfb53, 0xfb54, 0xfb55,			// 67b
sl@0
   102
	0x067c, 0x067c, 0x067c,			// placeholder
sl@0
   103
	0x067d, 0x067d, 0x067d,			// placeholder
sl@0
   104
	0xfb57, 0xfb58, 0xfb59,			// 67e
sl@0
   105
	0xfb63, 0xfb64, 0xfb65,			// 67f
sl@0
   106
sl@0
   107
	0xfb5b, 0xfb5c, 0xfb5d,			// 680
sl@0
   108
	0x0681, 0x0681, 0x0681,			// placeholder
sl@0
   109
	0x0682, 0x0682, 0x0682,			// placeholder
sl@0
   110
	0xfb77, 0xfb78, 0xfb79,			// 683
sl@0
   111
	0xfb73, 0xfb74, 0xfb75,			// 684
sl@0
   112
	0x0685, 0x0685, 0x0685,			// placeholder
sl@0
   113
	0xfb7b, 0xfb7c, 0xfb7d,			// 686
sl@0
   114
	0xfb7f, 0xfb80, 0xfb81,			// 687
sl@0
   115
	0xfb89, 0x0688, 0x0688,			// 688
sl@0
   116
	0x0689, 0x0689, 0x0689,			// placeholder
sl@0
   117
	0x068a, 0x068a, 0x068a,			// placeholder
sl@0
   118
	0x068b, 0x068b, 0x068b,			// placeholder
sl@0
   119
	0xfb85, 0x068c, 0x068c,			// 68c
sl@0
   120
	0xfb83, 0x068d, 0x068d,			// 68d
sl@0
   121
	0xfb87, 0x068e, 0x068e,			// 68e
sl@0
   122
	0x068f, 0x068f, 0x068f,			// placeholder
sl@0
   123
sl@0
   124
	0x0690, 0x0690, 0x0690,			// placeholder
sl@0
   125
	0xfb8d, 0x0691, 0x0691,			// 691
sl@0
   126
	0x0692, 0x0692, 0x0692,			// placeholder
sl@0
   127
	0x0693, 0x0693, 0x0693,			// placeholder
sl@0
   128
	0x0694, 0x0694, 0x0694,			// placeholder
sl@0
   129
	0x0695, 0x0695, 0x0695,			// placeholder
sl@0
   130
	0x0696, 0x0696, 0x0696,			// placeholder
sl@0
   131
	0x0697, 0x0697, 0x0697,			// placeholder
sl@0
   132
	0xfb8b, 0x0698, 0x0698,			// 698
sl@0
   133
	0x0699, 0x0699, 0x0699,			// placeholder
sl@0
   134
	0x069a, 0x069a, 0x069a,			// placeholder
sl@0
   135
	0x069b, 0x069b, 0x069b,			// placeholder
sl@0
   136
	0x069c, 0x069c, 0x069c,			// placeholder
sl@0
   137
	0x069d, 0x069d, 0x069d,			// placeholder
sl@0
   138
	0x069e, 0x069e, 0x069e,			// placeholder
sl@0
   139
	0x069f, 0x069f, 0x069f,			// placeholder
sl@0
   140
sl@0
   141
	0x06a0, 0x06a0, 0x06a0,			// placeholder
sl@0
   142
	0x06a1, 0x06a1, 0x06a1,			// placeholder
sl@0
   143
	0x06a2, 0x06a2, 0x06a2,			// placeholder
sl@0
   144
	0x06a3, 0x06a3, 0x06a3,			// placeholder
sl@0
   145
	0xfb6b, 0xfb6c, 0xfb6d,			// 6a4
sl@0
   146
	0x06a5, 0x06a5, 0x06a5,			// placeholder
sl@0
   147
	0xfb6f, 0xfb70, 0xfb71,			// 6a6
sl@0
   148
	0x06a7, 0x06a7, 0x06a7,			// placeholder
sl@0
   149
	0x06a8, 0x06a8, 0x06a8,			// placeholder
sl@0
   150
	0xfb8f, 0xfb90, 0xfb91,			// 6a9
sl@0
   151
	0x06aa, 0x06aa, 0x06aa,			// 6aa
sl@0
   152
	0x06ab, 0x06ab, 0x06ab,			// 6ab
sl@0
   153
	0x06ac, 0x06ac, 0x06ac,			// 6ac
sl@0
   154
	0xfbd4, 0xfbd5, 0xfbd6,			// 6ad
sl@0
   155
	0x06ae, 0x06ae, 0x06ae,			// 6ae
sl@0
   156
	0xfb93, 0xfb94, 0xfb95,			// 6af
sl@0
   157
sl@0
   158
	0x06b0, 0x06b0, 0x06b0,			// placeholder
sl@0
   159
	0xfb9b, 0xfb9c, 0xfb9d,			// 6b1
sl@0
   160
	0x06b2, 0x06b2, 0x06b2,			// 6b2
sl@0
   161
	0xfb97, 0xfb98, 0xfb99,			// 6b3
sl@0
   162
	0x06b4, 0x06b4, 0x06b4,			// placeholder
sl@0
   163
	0x06b5, 0x06b5, 0x06b5,			// placeholder
sl@0
   164
	0x06b6, 0x06b6, 0x06b6,			// placeholder
sl@0
   165
	0x06b7, 0x06b7, 0x06b7,			// placeholder
sl@0
   166
	0x06b8, 0x06b8, 0x06b8,			// placeholder
sl@0
   167
	0x06b9, 0x06b9, 0x06b9,			// placeholder
sl@0
   168
	0xfb9f, 0x06ba, 0x06ba,			// 6ba
sl@0
   169
	0xfba1, 0xfba2, 0xfba3,			// 6bb
sl@0
   170
	0x06bc, 0x06bc, 0x06bc,			// placeholder
sl@0
   171
	0x06bd, 0x06bd, 0x06bd,			// placeholder
sl@0
   172
	0xfbab, 0xfbac, 0xfbad,			// 6be
sl@0
   173
	0x06bf, 0x06bf, 0x06bf,			// placeholder
sl@0
   174
sl@0
   175
	0xfba5, 0x06c0, 0x06c0,			// 6c0
sl@0
   176
	0xfba7, 0xfba8, 0xfba9,			// 6c1
sl@0
   177
	0x06c2, 0x06c2, 0x06c2,			// placeholder
sl@0
   178
	0x06c3, 0x06c3, 0x06c3,			// placeholder
sl@0
   179
	0x06c4, 0x06c4, 0x06c4,			// placeholder
sl@0
   180
	0xfbe1, 0x06c5, 0x06c5,			// 6c5
sl@0
   181
	0xfbda, 0x06c6, 0x06c6,			// 6c6
sl@0
   182
	0xfbd8, 0x06c7, 0x06c7,			// 6c7
sl@0
   183
	0xfbdc, 0x06c8, 0x06c8,			// 6c8
sl@0
   184
	0xfbe3, 0x06c9, 0x06c9,			// 6c9
sl@0
   185
	0x06ca, 0x06ca, 0x06ca,			// placeholder
sl@0
   186
	0xfbdf, 0x06cb, 0x06cb,			// 6cb
sl@0
   187
	0xfbfd, 0xfbfe, 0xfbff,			// 6cc
sl@0
   188
	0x06cd, 0x06cd, 0x06cd,			// placeholder
sl@0
   189
	0x06ce, 0x06ce, 0x06ce,			// placeholder
sl@0
   190
	0x06cf, 0x06cf, 0x06cf,			// placeholder
sl@0
   191
sl@0
   192
	0xfbe5, 0xfbe6, 0xfbe7,			// 6d0
sl@0
   193
	0x06d1, 0x06d1, 0x06d1,			// placeholder
sl@0
   194
	0xfbaf, 0x06d2, 0x06d2,			// 6d2
sl@0
   195
	0xfbb1, 0x06d3, 0x06d3			// 6d3
sl@0
   196
	};
sl@0
   197
sl@0
   198
sl@0
   199
static const int KFinal = 0;
sl@0
   200
static const int KInitial = 1;
sl@0
   201
static const int KMedial = 2;
sl@0
   202
static const int KStandardShapeTableOffset = 0x621;
sl@0
   203
static const int KLamAlefShapeTableStart = 0x64B - 0x621;
sl@0
   204
static const int KExtendedShapeTableOffset = 0x671 - (0x64f - 0x621);
sl@0
   205
sl@0
   206
sl@0
   207
static inline TInt ArabicShapeTableIndex(TInt aCode)
sl@0
   208
	{
sl@0
   209
	if (aCode >= 0x621 && aCode <= 0x64a)
sl@0
   210
		return (aCode - KStandardShapeTableOffset) * 3;
sl@0
   211
	if (aCode >= 0x671 && aCode <= 0x6d3)
sl@0
   212
		return (aCode - KExtendedShapeTableOffset) * 3;
sl@0
   213
	return KErrNotFound;
sl@0
   214
	}
sl@0
   215
sl@0
   216
sl@0
   217
static inline TBool IsArabicPoint(TInt aCode)
sl@0
   218
	{
sl@0
   219
	return (aCode >= 0x64B && aCode <= 0x655) || aCode == 0x670;
sl@0
   220
	}
sl@0
   221
sl@0
   222
TInt ConsumeCharsAndDeterminePresentationForm(const TUtf32Iterator& aText,
sl@0
   223
	TUint aFlags, TInt& aLigaturePortionsRemaining)
sl@0
   224
/**
sl@0
   225
 Get the Arabic or other presentation form, consuming as many characters 
sl@0
   226
 as necessary. This function can cope with text that has already been 
sl@0
   227
 reversed.
sl@0
   228
@internalComponent
sl@0
   229
*/
sl@0
   230
	{
sl@0
   231
	TUint c = aText.Get();
sl@0
   232
	TInt index = ArabicShapeTableIndex(c);
sl@0
   233
	if (index != -1)
sl@0
   234
		{
sl@0
   235
		if (aLigaturePortionsRemaining != 0)
sl@0
   236
			{
sl@0
   237
			--aLigaturePortionsRemaining;
sl@0
   238
			GDI_ASSERT_DEBUG(!aText.AtEnd(), EGdiPanic_Invariant);
sl@0
   239
			return 0xFFFF;
sl@0
   240
			}
sl@0
   241
sl@0
   242
		int position = -1;
sl@0
   243
sl@0
   244
		// Find previous and next character, skipping Arabic points.
sl@0
   245
		TUtf32Iterator tmpText(aText);		
sl@0
   246
		tmpText.Prev();
sl@0
   247
        TUint prev = 0xFFFF;
sl@0
   248
        while (!tmpText.BeforeStart() && (prev == 0xFFFF || IsArabicPoint(prev)))
sl@0
   249
            prev = tmpText.GetThenPrev();		
sl@0
   250
sl@0
   251
		tmpText = aText;
sl@0
   252
		tmpText.Next();
sl@0
   253
        TUint next = 0xFFFF;
sl@0
   254
        while (!tmpText.AtEnd() && (next == 0xFFFF || IsArabicPoint(next)))
sl@0
   255
            next = tmpText.GetThenNext();		
sl@0
   256
		
sl@0
   257
		TInt possible_lam = (aFlags & CFont::TPositionParam::EFLogicalOrder)?
sl@0
   258
			c : next;
sl@0
   259
		TInt possible_alef = (aFlags & CFont::TPositionParam::EFLogicalOrder)?
sl@0
   260
			next : c;
sl@0
   261
sl@0
   262
		// Perform lam-alef ligation if necessary.
sl@0
   263
		if (possible_lam == 0x644 &&
sl@0
   264
			(possible_alef == 0x622 || possible_alef == 0x623 || possible_alef == 0x625 || possible_alef == 0x627))
sl@0
   265
			{
sl@0
   266
			switch(possible_alef)
sl@0
   267
				{
sl@0
   268
				case 0x622:
sl@0
   269
					{
sl@0
   270
					c = 0xfef5;
sl@0
   271
					index = KLamAlefShapeTableStart;
sl@0
   272
					break;
sl@0
   273
					}
sl@0
   274
				case 0x623:
sl@0
   275
					{
sl@0
   276
					c = 0xfef7;
sl@0
   277
					index = KLamAlefShapeTableStart + 1;
sl@0
   278
					break;
sl@0
   279
					}
sl@0
   280
				case 0x625:
sl@0
   281
					{
sl@0
   282
					c = 0xfef9;
sl@0
   283
					index = KLamAlefShapeTableStart + 2;
sl@0
   284
					break;
sl@0
   285
					}
sl@0
   286
				default:
sl@0
   287
					{
sl@0
   288
					c = 0xfefb;
sl@0
   289
					index = KLamAlefShapeTableStart + 3;
sl@0
   290
					}
sl@0
   291
				}
sl@0
   292
			index *= 3;
sl@0
   293
			aLigaturePortionsRemaining = 2;
sl@0
   294
sl@0
   295
			next = 0xFFFF;
sl@0
   296
			while (!tmpText.AtEnd() && (next == 0xFFFF || IsArabicPoint(next)))
sl@0
   297
				{
sl@0
   298
				next = tmpText.Get();
sl@0
   299
				tmpText.Next();
sl@0
   300
				}
sl@0
   301
			}
sl@0
   302
sl@0
   303
		TInt left = (aFlags & CFont::TPositionParam::EFLogicalOrder)? prev : next;
sl@0
   304
		TInt right = (aFlags & CFont::TPositionParam::EFLogicalOrder)? next : prev;
sl@0
   305
sl@0
   306
		TBool prefix = FALSE;
sl@0
   307
		if (left == 0x640 || left == 0x200D) // kashida or Zero-Width Joiner
sl@0
   308
			prefix = TRUE;
sl@0
   309
		else
sl@0
   310
			{
sl@0
   311
			TInt left_index = ArabicShapeTableIndex(left);
sl@0
   312
			if (left_index != -1)
sl@0
   313
				{
sl@0
   314
				if (static_cast<TInt>(TheArabicShapeTable[left_index + KInitial]) != left ||
sl@0
   315
					static_cast<TInt>(TheArabicShapeTable[left_index + KMedial]) != left)
sl@0
   316
					prefix = TRUE;
sl@0
   317
				}
sl@0
   318
			}
sl@0
   319
		TBool suffix = FALSE;
sl@0
   320
		if (right == 0x640 || right == 0x200D) // kashida or Zero-Width Joiner
sl@0
   321
			suffix = TRUE;
sl@0
   322
		else 
sl@0
   323
			{
sl@0
   324
			TInt right_index = ArabicShapeTableIndex(right);
sl@0
   325
			if (right_index != -1)
sl@0
   326
				{
sl@0
   327
				if (static_cast<TInt>(TheArabicShapeTable[right_index + KFinal]) != right ||
sl@0
   328
					static_cast<TInt>(TheArabicShapeTable[right_index + KMedial]) != right)
sl@0
   329
					suffix = TRUE;
sl@0
   330
				}
sl@0
   331
			}
sl@0
   332
		TBool medial = static_cast<TUint>(TheArabicShapeTable[index + KMedial]) != c;
sl@0
   333
		if (medial)
sl@0
   334
			{
sl@0
   335
			if (prefix && suffix)
sl@0
   336
				position = KMedial;
sl@0
   337
			else if (prefix)
sl@0
   338
				position = KFinal;
sl@0
   339
			else if (suffix)
sl@0
   340
				position = KInitial;
sl@0
   341
			}
sl@0
   342
		else
sl@0
   343
			{
sl@0
   344
			if (prefix)
sl@0
   345
				position = KFinal;
sl@0
   346
			else if (suffix)
sl@0
   347
				position = KInitial;
sl@0
   348
			}
sl@0
   349
		if (position >= 0)
sl@0
   350
			c = TheArabicShapeTable[index + position];
sl@0
   351
		}
sl@0
   352
sl@0
   353
	return c;
sl@0
   354
	}
sl@0
   355
sl@0
   356
sl@0
   357
// 
sl@0
   358
//
sl@0
   359
// GlyphSelector_Arabic Class definition
sl@0
   360
//
sl@0
   361
//
sl@0
   362
sl@0
   363
TBool GlyphSelector_Arabic::Process(TGlyphSelectionState& aGss, RShapeInfo&) 
sl@0
   364
	{
sl@0
   365
	// Select glyph - use presentation form if applicable.
sl@0
   366
	TInt ligaturePortions = aGss.iLigaturePortionsRemaining;
sl@0
   367
	TUint flags = aGss.iParam.iFlags;
sl@0
   368
	TUint code = ConsumeCharsAndDeterminePresentationForm(aGss.iText,
sl@0
   369
		flags, ligaturePortions);
sl@0
   370
sl@0
   371
	aGss.iText.Next();
sl@0
   372
	aGss.iClusterState = !aGss.iText.AtEnd() &&
sl@0
   373
		(aGss.iText.Get().GetCategory() & 0xF0) == TChar::EMarkGroup?
sl@0
   374
		TGlyphSelectionState::EGClusterNotComplete
sl@0
   375
		: TGlyphSelectionState::EGClusterComplete;
sl@0
   376
sl@0
   377
	// If we are beginning a new portion of a ligature, we must set the state.
sl@0
   378
	if (ligaturePortions != aGss.iLigaturePortionsRemaining)
sl@0
   379
		{
sl@0
   380
		if (ligaturePortions != 1)
sl@0
   381
			aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
sl@0
   382
		aGss.iLigaturePortionFirstMark = aGss.iParam.iOutputGlyphs;
sl@0
   383
		if (ligaturePortions < aGss.iLigaturePortionsRemaining)
sl@0
   384
			{
sl@0
   385
			aGss.iLigaturePortionsRemaining = ligaturePortions;
sl@0
   386
			// We have just swallowed a non-initial part of the ligature, which
sl@0
   387
			// must not be drawn.
sl@0
   388
			GDI_ASSERT_DEBUG(code == 0xFFFF, EGdiPanic_Invariant);
sl@0
   389
			return ETrue;
sl@0
   390
			}
sl@0
   391
		aGss.iLigaturePortionsRemaining = ligaturePortions;
sl@0
   392
		}
sl@0
   393
sl@0
   394
	// In this method we always output the glyph code calculate previously.
sl@0
   395
	if (!aGss.AppendGlyphToCluster(code))
sl@0
   396
		return EFalse;
sl@0
   397
sl@0
   398
	if (!aGss.IsCombiningClass())
sl@0
   399
		{
sl@0
   400
		aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
sl@0
   401
		return ETrue;
sl@0
   402
		}
sl@0
   403
sl@0
   404
	// Adjust glyph's bounds further to position this character.
sl@0
   405
	aGss.iPen = TGlyphSelectionState::EPenAdvance_No;
sl@0
   406
	TRect baseBounds = aGss.iParam.iOutput[0].iBounds;
sl@0
   407
	TInt firstMark = 1;
sl@0
   408
	if (aGss.iLigaturePortionsRemaining != 0)
sl@0
   409
		{
sl@0
   410
		TInt centre = (baseBounds.iBr.iX + baseBounds.iTl.iX) >> 1;
sl@0
   411
		TBool firstHalf = aGss.iLigaturePortionsRemaining == 2;
sl@0
   412
		TBool rightHandSide = flags & CFont::TPositionParam::EFLogicalOrder?
sl@0
   413
			firstHalf : !firstHalf;
sl@0
   414
		if (rightHandSide)
sl@0
   415
			baseBounds.iTl.iX = centre;
sl@0
   416
		else
sl@0
   417
			baseBounds.iBr.iX = centre;
sl@0
   418
		if (firstHalf)
sl@0
   419
			aGss.iClusterState = TGlyphSelectionState::EGClusterNotComplete;
sl@0
   420
		firstMark = aGss.iLigaturePortionFirstMark;
sl@0
   421
		}
sl@0
   422
	aGss.CombineLastGlyphToBase(baseBounds, firstMark);
sl@0
   423
sl@0
   424
	return ETrue;
sl@0
   425
	}
sl@0
   426
sl@0
   427
sl@0
   428
TBool GlyphSelector_Arabic::CharactersJoin(TInt aLeftCharacter, TInt aRightCharacter)
sl@0
   429
	{
sl@0
   430
	// All the characters join to the right, so we don't need to look them up.
sl@0
   431
	// as long as they are there at all, it is OK.
sl@0
   432
	TBool leftIsFixedJoiner = aLeftCharacter == 0x640 || aLeftCharacter == 0x200D;
sl@0
   433
	if (!leftIsFixedJoiner)
sl@0
   434
		{
sl@0
   435
		TInt leftIndex = ArabicShapeTableIndex(aLeftCharacter);
sl@0
   436
		if (leftIndex == -1)
sl@0
   437
			return EFalse;
sl@0
   438
		if (static_cast<TInt>(TheArabicShapeTable[leftIndex + KFinal])
sl@0
   439
			== aLeftCharacter)
sl@0
   440
			return EFalse;
sl@0
   441
		}
sl@0
   442
	if (aRightCharacter == 0x640 || aRightCharacter == 0x200D)
sl@0
   443
		return !leftIsFixedJoiner;
sl@0
   444
	TInt rightIndex = ArabicShapeTableIndex(aRightCharacter);
sl@0
   445
	return rightIndex != -1
sl@0
   446
		&& static_cast<TInt>(TheArabicShapeTable[rightIndex + KInitial])
sl@0
   447
			!= aRightCharacter;
sl@0
   448
	}
sl@0
   449