os/textandloc/fontservices/textshaperplugin/source/IcuLayoutEngine.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
* Implementation of CIcuLayoutEngine
sl@0
    16
* This is a CShaper using the Icu Layout Engine.
sl@0
    17
*
sl@0
    18
*/
sl@0
    19
sl@0
    20
// System includes
sl@0
    21
#include <e32base.h>
sl@0
    22
#include <gdi.h>
sl@0
    23
#include <e32math.h>
sl@0
    24
#include <openfont.h>
sl@0
    25
#include <fntstore.h>
sl@0
    26
sl@0
    27
// ICU includes
sl@0
    28
#include "math.h"
sl@0
    29
#include "LETypes.h"
sl@0
    30
#include "LEScripts.h"
sl@0
    31
#include "LELanguages.h"
sl@0
    32
#include "LayoutEngine.h"
sl@0
    33
#include "SymbianFontInstance.h"
sl@0
    34
sl@0
    35
#include "IcuLayoutEngine.h"
sl@0
    36
sl@0
    37
// Icu namespace
sl@0
    38
U_NAMESPACE_USE
sl@0
    39
sl@0
    40
// Convert from float to int rounding to the nearest integer
sl@0
    41
inline TInt FloatToInt(float a)
sl@0
    42
	{
sl@0
    43
	return a < 0? static_cast<TInt>(a - 0.5) : static_cast<TInt>(a + 0.5);
sl@0
    44
	}
sl@0
    45
sl@0
    46
/** Array of Script Codes that need to be translated into LEScriptCodes for the 
sl@0
    47
construction of the LayoutEngine. */
sl@0
    48
const LETag scriptCodes[] = {
sl@0
    49
    zyyyScriptTag, /* 'zyyy' (COMMON) */
sl@0
    50
    qaaiScriptTag, /* 'qaai' (INHERITED) */
sl@0
    51
    arabScriptTag, /* 'arab' (ARABIC) */
sl@0
    52
    armnScriptTag, /* 'armn' (ARMENIAN) */
sl@0
    53
    bengScriptTag, /* 'beng' (BENGALI) */
sl@0
    54
    bopoScriptTag, /* 'bopo' (BOPOMOFO) */
sl@0
    55
    cherScriptTag, /* 'cher' (CHEROKEE) */
sl@0
    56
    qaacScriptTag, /* 'qaac' (COPTIC) */
sl@0
    57
    cyrlScriptTag, /* 'cyrl' (CYRILLIC) */
sl@0
    58
    dsrtScriptTag, /* 'dsrt' (DESERET) */
sl@0
    59
    devaScriptTag, /* 'deva' (DEVANAGARI) */
sl@0
    60
    ethiScriptTag, /* 'ethi' (ETHIOPIC) */
sl@0
    61
    georScriptTag, /* 'geor' (GEORGIAN) */
sl@0
    62
    gothScriptTag, /* 'goth' (GOTHIC) */
sl@0
    63
    grekScriptTag, /* 'grek' (GREEK) */
sl@0
    64
    gujrScriptTag, /* 'gujr' (GUJARATI) */
sl@0
    65
    guruScriptTag, /* 'guru' (GURMUKHI) */
sl@0
    66
    haniScriptTag, /* 'hani' (HAN) */
sl@0
    67
    hangScriptTag, /* 'hang' (HANGUL) */
sl@0
    68
    hebrScriptTag, /* 'hebr' (HEBREW) */
sl@0
    69
    hiraScriptTag, /* 'hira' (HIRAGANA) */
sl@0
    70
    kndaScriptTag, /* 'knda' (KANNADA) */
sl@0
    71
    kanaScriptTag, /* 'kana' (KATAKANA) */
sl@0
    72
    khmrScriptTag, /* 'khmr' (KHMER) */
sl@0
    73
    laooScriptTag, /* 'laoo' (LAO) */
sl@0
    74
    latnScriptTag, /* 'latn' (LATIN) */
sl@0
    75
    mlymScriptTag, /* 'mlym' (MALAYALAM) */
sl@0
    76
    mongScriptTag, /* 'mong' (MONGOLIAN) */
sl@0
    77
    mymrScriptTag, /* 'mymr' (MYANMAR) */
sl@0
    78
    ogamScriptTag, /* 'ogam' (OGHAM) */
sl@0
    79
    italScriptTag, /* 'ital' (OLD_ITALIC) */
sl@0
    80
    oryaScriptTag, /* 'orya' (ORIYA) */
sl@0
    81
    runrScriptTag, /* 'runr' (RUNIC) */
sl@0
    82
    sinhScriptTag, /* 'sinh' (SINHALA) */
sl@0
    83
    syrcScriptTag, /* 'syrc' (SYRIAC) */
sl@0
    84
    tamlScriptTag, /* 'taml' (TAMIL) */
sl@0
    85
    teluScriptTag, /* 'telu' (TELUGU) */
sl@0
    86
    thaaScriptTag, /* 'thaa' (THAANA) */
sl@0
    87
    thaiScriptTag, /* 'thai' (THAI) */
sl@0
    88
    tibtScriptTag, /* 'tibt' (TIBETAN) */
sl@0
    89
    cansScriptTag, /* 'cans' (CANADIAN_ABORIGINAL) */
sl@0
    90
    yiiiScriptTag, /* 'yiii' (YI) */
sl@0
    91
    tglgScriptTag, /* 'tglg' (TAGALOG) */
sl@0
    92
    hanoScriptTag, /* 'hano' (HANUNOO) */
sl@0
    93
    buhdScriptTag, /* 'buhd' (BUHID) */
sl@0
    94
    tagbScriptTag, /* 'tagb' (TAGBANWA) */
sl@0
    95
    braiScriptTag, /* 'brai' (BRAILLE) */
sl@0
    96
    cprtScriptTag, /* 'cprt' (CYPRIOT) */
sl@0
    97
    limbScriptTag, /* 'limb' (LIMBU) */
sl@0
    98
    linbScriptTag, /* 'linb' (LINEAR_B) */
sl@0
    99
    osmaScriptTag, /* 'osma' (OSMANYA) */
sl@0
   100
    shawScriptTag, /* 'shaw' (SHAVIAN) */
sl@0
   101
    taleScriptTag, /* 'tale' (TAI_LE) */
sl@0
   102
    ugarScriptTag, /* 'ugar' (UGARITIC) */
sl@0
   103
    hrktScriptTag  /* 'hrkt' (KATAKANA_OR_HIRAGANA) */
sl@0
   104
};
sl@0
   105
sl@0
   106
/** Array of Language Codes that need to be translated into LELanguageCodes for the 
sl@0
   107
construction of the LayoutEngine. */
sl@0
   108
const LETag languageCodes[] = {
sl@0
   109
    nullLanguageTag, /* '' (null) */
sl@0
   110
    araLanguageTag, /* 'ARA' (Arabic) */
sl@0
   111
    asmLanguageTag, /* 'ASM' (Assamese) */
sl@0
   112
    benLanguageTag, /* 'BEN' (Bengali) */
sl@0
   113
    farLanguageTag, /* 'FAR' (Farsi) */
sl@0
   114
    gujLanguageTag, /* 'GUJ' (Gujarati) */
sl@0
   115
    hinLanguageTag, /* 'HIN' (Hindi) */
sl@0
   116
    iwrLanguageTag, /* 'IWR' (Hebrew) */
sl@0
   117
    jiiLanguageTag, /* 'JII' (Yiddish) */
sl@0
   118
    janLanguageTag, /* 'JAN' (Japanese) */
sl@0
   119
    kanLanguageTag, /* 'KAN' (Kannada) */
sl@0
   120
    kokLanguageTag, /* 'KOK' (Konkani) */
sl@0
   121
    korLanguageTag, /* 'KOR' (Korean) */
sl@0
   122
    kshLanguageTag, /* 'KSH' (Kashmiri) */
sl@0
   123
    malLanguageTag, /* 'MAL' (Malayalam (Traditional)) */
sl@0
   124
    marLanguageTag, /* 'MAR' (Marathi) */
sl@0
   125
    mlrLanguageTag, /* 'MLR' (Malayalam (Reformed)) */
sl@0
   126
    mniLanguageTag, /* 'MNI' (Manipuri) */
sl@0
   127
    oriLanguageTag, /* 'ORI' (Oriya) */
sl@0
   128
    sanLanguageTag, /* 'SAN' (Sanscrit) */
sl@0
   129
    sndLanguageTag, /* 'SND' (Sindhi) */
sl@0
   130
    snhLanguageTag, /* 'SNH' (Sinhalese) */
sl@0
   131
    syrLanguageTag, /* 'SYR' (Syriac) */
sl@0
   132
    tamLanguageTag, /* 'TAM' (Tamil) */
sl@0
   133
    telLanguageTag, /* 'TEL' (Telugu) */
sl@0
   134
    thaLanguageTag, /* 'THA' (Thai) */
sl@0
   135
    urdLanguageTag, /* 'URD' (Urdu) */
sl@0
   136
    zhpLanguageTag, /* 'ZHP' (Chinese (Phonetic)) */
sl@0
   137
    zhsLanguageTag, /* 'ZHS' (Chinese (Simplified)) */
sl@0
   138
    zhtLanguageTag  /* 'ZHT' (Chinese (Traditional)) */
sl@0
   139
};
sl@0
   140
sl@0
   141
/**
sl@0
   142
Translate the script code passed in to a LEScriptCode
sl@0
   143
*/ 
sl@0
   144
TInt ScriptCode(TUint32 aScript)
sl@0
   145
	{
sl@0
   146
	TInt scriptCode = -1;
sl@0
   147
    for (TInt i= 0; i < scriptCodeCount; i++)
sl@0
   148
    	{
sl@0
   149
    	if (scriptCodes[i] == aScript)
sl@0
   150
    		{
sl@0
   151
    		scriptCode = i;
sl@0
   152
    		break;
sl@0
   153
    		}
sl@0
   154
    	}
sl@0
   155
    return scriptCode;
sl@0
   156
	}
sl@0
   157
	
sl@0
   158
/**
sl@0
   159
Translate the language code passed in to a LELanguageCode
sl@0
   160
*/
sl@0
   161
TInt LanguageCode(TUint32 aLanguage)
sl@0
   162
	{
sl@0
   163
	TInt languageCode = -1;
sl@0
   164
    for (TInt i= 0; i < languageCodeCount; i++)
sl@0
   165
    	{
sl@0
   166
    	if (languageCodes[i] == aLanguage)
sl@0
   167
    		{
sl@0
   168
    		languageCode = i;
sl@0
   169
    		break;
sl@0
   170
    		}
sl@0
   171
    	}
sl@0
   172
    return languageCode;
sl@0
   173
	}
sl@0
   174
sl@0
   175
/**
sl@0
   176
Create a instance of CIcuLayoutEngine
sl@0
   177
@param aBitmapFont The required font.
sl@0
   178
@param aHeap The heap to be used for storage by the engine.
sl@0
   179
@return A pointer to the new CIcuLayoutEngine instance.
sl@0
   180
*/
sl@0
   181
CShaper * CIcuLayoutEngine::NewL(CBitmapFont* aBitmapFont, TInt aScript, TInt aLanguage, RHeap* aHeap)
sl@0
   182
	{
sl@0
   183
	CIcuLayoutEngine* newShaper = new(ELeave)CIcuLayoutEngine(aScript, aLanguage);
sl@0
   184
	CleanupStack::PushL(newShaper);
sl@0
   185
	newShaper->ConstructL(aBitmapFont, aScript, aLanguage, aHeap);
sl@0
   186
	CleanupStack::Pop(); // newShaper
sl@0
   187
	return newShaper;	
sl@0
   188
	} 
sl@0
   189
sl@0
   190
sl@0
   191
/**
sl@0
   192
Construct an instance of CIcuLayoutEngine 	
sl@0
   193
@param aBitMapFont The required font
sl@0
   194
@param aHeap The heap to be used for storage by the engine
sl@0
   195
@return incase of exceptions with an Error Code
sl@0
   196
@see CShaper
sl@0
   197
 */
sl@0
   198
TInt  CIcuLayoutEngine::ConstructL(CBitmapFont* aBitMapFont, TInt aScript, TInt aLanguage, RHeap* aHeap )
sl@0
   199
	{
sl@0
   200
	// allocate a block of memory from aHeap for the layout engine 
sl@0
   201
	// which is accessed via the Umemory class
sl@0
   202
	iClientHeap = aHeap;
sl@0
   203
sl@0
   204
	// this needs to be on the heap
sl@0
   205
	LEErrorCode fontStatus = LE_NO_ERROR;
sl@0
   206
	iFontInstance = new SymbianFontInstance(aBitMapFont, fontStatus, aScript == mlymScriptTag);
sl@0
   207
	if(NULL == iFontInstance)
sl@0
   208
		{
sl@0
   209
		User::Leave(KErrGeneral);
sl@0
   210
		}
sl@0
   211
	if (fontStatus == LE_MEMORY_ALLOCATION_ERROR)
sl@0
   212
   		{
sl@0
   213
   		User::Leave(KErrNoMemory);
sl@0
   214
   		} 	
sl@0
   215
   	else if (fontStatus != LE_NO_ERROR)
sl@0
   216
   		{
sl@0
   217
   		//note this leave may actually be caused by OOM situations, 
sl@0
   218
   		//due to the way errors codes are handled in the open source code
sl@0
   219
   		User::Leave(KErrGeneral);
sl@0
   220
   	 	}
sl@0
   221
   	 	
sl@0
   222
sl@0
   223
 	// create and initialise a ICU layout Engine
sl@0
   224
	// Note the engine is created using the Umemory heap 
sl@0
   225
    LEErrorCode success = LE_NO_ERROR;
sl@0
   226
    
sl@0
   227
    // Translate the script code into an LEScriptCode
sl@0
   228
    TInt scriptCode = ScriptCode(aScript);
sl@0
   229
    
sl@0
   230
    // Translate the language code into an LELanguageCode
sl@0
   231
    TInt languageCode = LanguageCode(aLanguage);
sl@0
   232
    
sl@0
   233
    // Finally instantiate the LayoutEngine    
sl@0
   234
	iEngine = LayoutEngine::layoutEngineFactory(iFontInstance, scriptCode, languageCode, success); 
sl@0
   235
sl@0
   236
	// For debugging - check the total memory used by construction
sl@0
   237
#ifdef SHAPER_MEMORY_DEBUG
sl@0
   238
	TInt totalAllocSize = 0;
sl@0
   239
	TInt used = iHeap->AllocSize(totalAllocSize);
sl@0
   240
	RDebug::Print(_L("shaper construction %d cells %d"), totalAllocSize, used);
sl@0
   241
#endif
sl@0
   242
sl@0
   243
	if (success == LE_MEMORY_ALLOCATION_ERROR)
sl@0
   244
		{
sl@0
   245
		User::Leave(KErrNoMemory);	
sl@0
   246
		}
sl@0
   247
	else if (success != LE_NO_ERROR)
sl@0
   248
		{
sl@0
   249
 		//note this leave may actually be caused by OOM situations, 
sl@0
   250
 		//due to the way errors codes are handled in the open source code
sl@0
   251
 		User::Leave(KErrGeneral);
sl@0
   252
		}
sl@0
   253
	return KErrNone;
sl@0
   254
	}
sl@0
   255
sl@0
   256
CIcuLayoutEngine::CIcuLayoutEngine(TUint32 aScript, TUint32 aLanguage):
sl@0
   257
	iScript(aScript),
sl@0
   258
	iLanguage(aLanguage)
sl@0
   259
	{
sl@0
   260
	}
sl@0
   261
sl@0
   262
/** 
sl@0
   263
 Frees all resources owned by ...
sl@0
   264
 */
sl@0
   265
 CIcuLayoutEngine::~CIcuLayoutEngine()
sl@0
   266
	{
sl@0
   267
	// delete the engine instance
sl@0
   268
	if ( iEngine )
sl@0
   269
		{
sl@0
   270
		delete( iEngine );
sl@0
   271
		}
sl@0
   272
		
sl@0
   273
	// delete the font instance from client heap
sl@0
   274
	delete( iFontInstance );
sl@0
   275
	}
sl@0
   276
sl@0
   277
/**
sl@0
   278
Returns the script and the language this shaper has been instansiated with.
sl@0
   279
*/	
sl@0
   280
void* CIcuLayoutEngine::ExtendedInterface (TUid aInterfaceId)
sl@0
   281
	{
sl@0
   282
	if (aInterfaceId == KUidShaperGetScript)		
sl@0
   283
		return (TUint32*)iScript;
sl@0
   284
	else
sl@0
   285
		if (aInterfaceId == KUidShaperGetLang)
sl@0
   286
			return (TUint32*)iLanguage;
sl@0
   287
		else
sl@0
   288
			return CShaper::ExtendedInterface(aInterfaceId);			
sl@0
   289
	}
sl@0
   290
	
sl@0
   291
/** This is implementation of CShaper::ShapeText for the Icu layout Engine
sl@0
   292
 The data is taken from TInput and pass to the shaper.
sl@0
   293
 A memory buffer is allocated on aHeapForOutput starting with TShapeHeader is allocated.
sl@0
   294
 The results of the shaping are copied into this buffer and passed back via aOutput. 
sl@0
   295
 @param aOutput On success a new structure containing the results allocated on aHeapForOutput.  
sl@0
   296
 @param aInput The input text and other parameters.
sl@0
   297
 @param aHeapForOutput On success, aOutput should be allocated from this and nothing else. 
sl@0
   298
 		On failure, nothing should be allocated from it.
sl@0
   299
 @return Error value from one of the system-wide error codes on	failure, KErrNone on success.
sl@0
   300
 @see CShaper::ShapeText
sl@0
   301
 */		
sl@0
   302
TInt CIcuLayoutEngine::ShapeText(TShapeHeader*& aOutput, const TInput& aInput, RHeap* aHeapForOutput)
sl@0
   303
	{
sl@0
   304
	// For debugging - the heap before shaping
sl@0
   305
	TInt totalAllocSize = 0;
sl@0
   306
	TInt used;
sl@0
   307
#ifdef SHAPER_MEMORY_DEBUG
sl@0
   308
	used = User::Heap().AllocSize(totalAllocSize);
sl@0
   309
	RDebug::Print(_L("before shaping %d cells %d bytes used"), used, totalAllocSize);
sl@0
   310
#endif
sl@0
   311
sl@0
   312
	iFontInstance->SetSessionHandle(aInput.iSessionHandle);
sl@0
   313
	TRAPD( error, IcuShapeTextL(aOutput, aInput, aHeapForOutput));
sl@0
   314
	if (error == KErrNoMemory)
sl@0
   315
		{
sl@0
   316
		used = User::Heap().AllocSize(totalAllocSize);
sl@0
   317
		RDebug::Print(_L("shaper out of memory %d cells %d"), totalAllocSize, used);
sl@0
   318
		}
sl@0
   319
sl@0
   320
#ifdef SHAPER_MEMORY_DEBUG
sl@0
   321
	used = User::Heap().AllocSize(totalAllocSize);
sl@0
   322
	RDebug::Print(_L("Shaped %d characters %d glyphs "), aOutput->iCharacterCount, aOutput->iGlyphCount );
sl@0
   323
	RDebug::Print(_L("after shaping %d cells %d bytes used"), used, totalAllocSize);
sl@0
   324
#endif
sl@0
   325
sl@0
   326
	// hide the ICU error codes as KErrGeneral
sl@0
   327
	if ((error == KErrNoMemory) || (error == KErrNone))
sl@0
   328
		return error;
sl@0
   329
	else
sl@0
   330
		return KErrGeneral;		
sl@0
   331
	}
sl@0
   332
sl@0
   333
/** This calls the ICU Layout engine to shape the text.  It allocates memory for the results
sl@0
   334
and then reads the results.  This memory is freed by the caller.
sl@0
   335
This function can leave if OOM.
sl@0
   336
 @param aOutput On success a new structure containing the results allocated on aHeapForOutput.  
sl@0
   337
 @param aInput The input text and other parameters.
sl@0
   338
 @param aHeapForOutput On success, aOutput should be allocated from this and nothing else. 
sl@0
   339
 		On failure, nothing should be allocated from it.
sl@0
   340
 @return Error value from one of the system-wide error codes on	failure, KErrNone on success.
sl@0
   341
 @see CIcuLayoutEngine::ShapeText
sl@0
   342
 */
sl@0
   343
void  CIcuLayoutEngine::IcuShapeTextL(TShapeHeader*& aOutput, const TInput& aInput, RHeap* aHeapForOutput)
sl@0
   344
	{
sl@0
   345
	LEErrorCode success = LE_NO_ERROR;
sl@0
   346
	const LEUnicode * p = (LEUnicode *)aInput.iText->Ptr();
sl@0
   347
	TInt noChars = aInput.iEnd - aInput.iStart;
sl@0
   348
sl@0
   349
	// Call to layout  
sl@0
   350
	TInt noOfGlyphs = iEngine->layoutChars(
sl@0
   351
			p, 							// chars - the input character context
sl@0
   352
			aInput.iStart,				// the offset of the first character to process	
sl@0
   353
			noChars,					// count - the number of characters to process	// offset
sl@0
   354
			aInput.iText->Length(), 	// max - the number of characters in the input context	// size of text
sl@0
   355
			FALSE, 						// rightToLeft - TRUE if the characters are in a right to left directional run
sl@0
   356
			0, 							// start X
sl@0
   357
			0, 							// start Y
sl@0
   358
			success);					// result code
sl@0
   359
sl@0
   360
	if (success == LE_MEMORY_ALLOCATION_ERROR)
sl@0
   361
		User::Leave(KErrNoMemory);
sl@0
   362
	else if (success != LE_NO_ERROR) 
sl@0
   363
		{
sl@0
   364
		User::Leave(KErrGeneral);
sl@0
   365
		}
sl@0
   366
	
sl@0
   367
sl@0
   368
	// Get some memory to pass into the layout engine for the results
sl@0
   369
	TInt bufferSize = (sizeof(LEGlyphID) + sizeof(le_int32) + sizeof(float) * 2)
sl@0
   370
		* noOfGlyphs + sizeof(float) * 2;
sl@0
   371
	TUint8* buffer = reinterpret_cast<TUint8*>( User::AllocL(bufferSize) );
sl@0
   372
	CleanupStack::PushL(buffer);
sl@0
   373
	LEGlyphID* glyphBuffer = reinterpret_cast<LEGlyphID*>(buffer);
sl@0
   374
	le_int32* indexBuffer = reinterpret_cast<le_int32*>(glyphBuffer + noOfGlyphs);
sl@0
   375
	float* positionBuffer = reinterpret_cast<float*>(indexBuffer + noOfGlyphs);
sl@0
   376
	
sl@0
   377
	
sl@0
   378
	// now get results glyph codes, positions and indices
sl@0
   379
	// from the layout engine
sl@0
   380
	if (success == LE_NO_ERROR)
sl@0
   381
		iEngine->getGlyphs(glyphBuffer, success);
sl@0
   382
sl@0
   383
	if (success == LE_NO_ERROR)
sl@0
   384
		iEngine->getGlyphPositions(positionBuffer, success);
sl@0
   385
sl@0
   386
	if (success == LE_NO_ERROR)
sl@0
   387
		iEngine->getCharIndices(indexBuffer, aInput.iStart, success);
sl@0
   388
	if (success == LE_NO_ERROR)
sl@0
   389
		// Reset the memory used by the IcuLayoutEngine
sl@0
   390
		iEngine->reset();
sl@0
   391
	if (success == LE_MEMORY_ALLOCATION_ERROR)
sl@0
   392
		User::Leave(KErrNoMemory);
sl@0
   393
	else 
sl@0
   394
		if (success != LE_NO_ERROR)
sl@0
   395
 			{
sl@0
   396
			User::Leave(KErrGeneral);
sl@0
   397
			}
sl@0
   398
sl@0
   399
	// Some of the glyph codes are 0xFFFF and 0x0001. 0xFFFF is a value used by ICU layout
sl@0
   400
	// engine to indicate no glyph, and 0x0001 is used to indicate a ZWJ or a ZWNJ.
sl@0
   401
	// These should be stripped out now. A ZWJ or a ZWNJ glyph has no meaning here. Their 
sl@0
   402
	// effects on the precedig and proceding characters have already been taken into 
sl@0
   403
	// consideration during shaping, so we don't need them anymore.
sl@0
   404
	// Also, their presence in the final glyph list was causing GDI to break with GDI:1
sl@0
   405
	// i.e. more than 8 glyphs in a glyph cluster.
sl@0
   406
	LEGlyphID gidOfZWJ = iFontInstance->mapCharToGlyph(0x200D); // Added by Symbian: 1922 mlyl
sl@0
   407
	TInt actualNoOfGlyphs = 0;
sl@0
   408
	for (LEGlyphID* p = glyphBuffer + noOfGlyphs; p != glyphBuffer;)
sl@0
   409
		{
sl@0
   410
		--p;
sl@0
   411
		if (*p != 0xFFFF && *p != 0x0001 && *p != gidOfZWJ) // Added by Symbian: 1922 mlyl
sl@0
   412
			++actualNoOfGlyphs;
sl@0
   413
		}
sl@0
   414
sl@0
   415
	// get some memory to pass back the results,  
sl@0
   416
	// This needs to be big enough for a TShapeHeader
sl@0
   417
	// plus 10 bytes for every glyph returned (-1 for the 1 byte allocated in TShapeHeader for iBuffer)
sl@0
   418
	aOutput = reinterpret_cast<TShapeHeader*>( aHeapForOutput->AllocL(
sl@0
   419
		sizeof(TShapeHeader) + (actualNoOfGlyphs * 10) + 3) );
sl@0
   420
sl@0
   421
	// get the results into the shaper structure aOutput 
sl@0
   422
	aOutput->iGlyphCount = actualNoOfGlyphs;
sl@0
   423
	aOutput->iCharacterCount = noChars;
sl@0
   424
 	aOutput->iReserved0 = 0;
sl@0
   425
	aOutput->iReserved1 = 0;
sl@0
   426
sl@0
   427
 	// iBuffer contains 10 bytes for every glyph
sl@0
   428
 	// the glyph code (4 bytes), position X(2 bytes) Y(2 bytes) and indices(2 bytes)
sl@0
   429
 
sl@0
   430
 	// first is glyph count * 4 byte glyph codes
sl@0
   431
 	TUint32* glyphOut = reinterpret_cast<TUint32*>(aOutput->iBuffer);
sl@0
   432
 	TInt16* posOut = reinterpret_cast<TInt16*>(aOutput->iBuffer +
sl@0
   433
 		(4 * actualNoOfGlyphs));
sl@0
   434
 	TInt16* indicesOut = reinterpret_cast<TInt16*>(aOutput->iBuffer +
sl@0
   435
 		(8 * actualNoOfGlyphs) + 4);
sl@0
   436
 	for (TInt i=0; i < noOfGlyphs; i++)
sl@0
   437
 		{
sl@0
   438
 		if (*glyphBuffer != 0xFFFF && *glyphBuffer != 0x0001 && *glyphBuffer != gidOfZWJ) // Added by Symbian: 1922 mlyl
sl@0
   439
 			{
sl@0
   440
	  		*glyphOut++ = *glyphBuffer;
sl@0
   441
			*posOut++ = FloatToInt( positionBuffer[0] );
sl@0
   442
			*posOut++ = FloatToInt( positionBuffer[1] );
sl@0
   443
			*indicesOut++ = *indexBuffer;
sl@0
   444
 			}
sl@0
   445
 		++glyphBuffer;
sl@0
   446
 		positionBuffer += 2;
sl@0
   447
 		++indexBuffer;
sl@0
   448
		}
sl@0
   449
	// There is an extra pair of positions: this is the total advance
sl@0
   450
	posOut[0] = FloatToInt( positionBuffer[0] );
sl@0
   451
	posOut[1] = FloatToInt( positionBuffer[1] );
sl@0
   452
	
sl@0
   453
	CleanupStack::PopAndDestroy(buffer);	
sl@0
   454
	
sl@0
   455
	}