os/textandloc/fontservices/textshaperplugin/source/IcuLayoutEngine.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/textandloc/fontservices/textshaperplugin/source/IcuLayoutEngine.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,455 @@
     1.4 +/*
     1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +* Implementation of CIcuLayoutEngine
    1.19 +* This is a CShaper using the Icu Layout Engine.
    1.20 +*
    1.21 +*/
    1.22 +
    1.23 +// System includes
    1.24 +#include <e32base.h>
    1.25 +#include <gdi.h>
    1.26 +#include <e32math.h>
    1.27 +#include <openfont.h>
    1.28 +#include <fntstore.h>
    1.29 +
    1.30 +// ICU includes
    1.31 +#include "math.h"
    1.32 +#include "LETypes.h"
    1.33 +#include "LEScripts.h"
    1.34 +#include "LELanguages.h"
    1.35 +#include "LayoutEngine.h"
    1.36 +#include "SymbianFontInstance.h"
    1.37 +
    1.38 +#include "IcuLayoutEngine.h"
    1.39 +
    1.40 +// Icu namespace
    1.41 +U_NAMESPACE_USE
    1.42 +
    1.43 +// Convert from float to int rounding to the nearest integer
    1.44 +inline TInt FloatToInt(float a)
    1.45 +	{
    1.46 +	return a < 0? static_cast<TInt>(a - 0.5) : static_cast<TInt>(a + 0.5);
    1.47 +	}
    1.48 +
    1.49 +/** Array of Script Codes that need to be translated into LEScriptCodes for the 
    1.50 +construction of the LayoutEngine. */
    1.51 +const LETag scriptCodes[] = {
    1.52 +    zyyyScriptTag, /* 'zyyy' (COMMON) */
    1.53 +    qaaiScriptTag, /* 'qaai' (INHERITED) */
    1.54 +    arabScriptTag, /* 'arab' (ARABIC) */
    1.55 +    armnScriptTag, /* 'armn' (ARMENIAN) */
    1.56 +    bengScriptTag, /* 'beng' (BENGALI) */
    1.57 +    bopoScriptTag, /* 'bopo' (BOPOMOFO) */
    1.58 +    cherScriptTag, /* 'cher' (CHEROKEE) */
    1.59 +    qaacScriptTag, /* 'qaac' (COPTIC) */
    1.60 +    cyrlScriptTag, /* 'cyrl' (CYRILLIC) */
    1.61 +    dsrtScriptTag, /* 'dsrt' (DESERET) */
    1.62 +    devaScriptTag, /* 'deva' (DEVANAGARI) */
    1.63 +    ethiScriptTag, /* 'ethi' (ETHIOPIC) */
    1.64 +    georScriptTag, /* 'geor' (GEORGIAN) */
    1.65 +    gothScriptTag, /* 'goth' (GOTHIC) */
    1.66 +    grekScriptTag, /* 'grek' (GREEK) */
    1.67 +    gujrScriptTag, /* 'gujr' (GUJARATI) */
    1.68 +    guruScriptTag, /* 'guru' (GURMUKHI) */
    1.69 +    haniScriptTag, /* 'hani' (HAN) */
    1.70 +    hangScriptTag, /* 'hang' (HANGUL) */
    1.71 +    hebrScriptTag, /* 'hebr' (HEBREW) */
    1.72 +    hiraScriptTag, /* 'hira' (HIRAGANA) */
    1.73 +    kndaScriptTag, /* 'knda' (KANNADA) */
    1.74 +    kanaScriptTag, /* 'kana' (KATAKANA) */
    1.75 +    khmrScriptTag, /* 'khmr' (KHMER) */
    1.76 +    laooScriptTag, /* 'laoo' (LAO) */
    1.77 +    latnScriptTag, /* 'latn' (LATIN) */
    1.78 +    mlymScriptTag, /* 'mlym' (MALAYALAM) */
    1.79 +    mongScriptTag, /* 'mong' (MONGOLIAN) */
    1.80 +    mymrScriptTag, /* 'mymr' (MYANMAR) */
    1.81 +    ogamScriptTag, /* 'ogam' (OGHAM) */
    1.82 +    italScriptTag, /* 'ital' (OLD_ITALIC) */
    1.83 +    oryaScriptTag, /* 'orya' (ORIYA) */
    1.84 +    runrScriptTag, /* 'runr' (RUNIC) */
    1.85 +    sinhScriptTag, /* 'sinh' (SINHALA) */
    1.86 +    syrcScriptTag, /* 'syrc' (SYRIAC) */
    1.87 +    tamlScriptTag, /* 'taml' (TAMIL) */
    1.88 +    teluScriptTag, /* 'telu' (TELUGU) */
    1.89 +    thaaScriptTag, /* 'thaa' (THAANA) */
    1.90 +    thaiScriptTag, /* 'thai' (THAI) */
    1.91 +    tibtScriptTag, /* 'tibt' (TIBETAN) */
    1.92 +    cansScriptTag, /* 'cans' (CANADIAN_ABORIGINAL) */
    1.93 +    yiiiScriptTag, /* 'yiii' (YI) */
    1.94 +    tglgScriptTag, /* 'tglg' (TAGALOG) */
    1.95 +    hanoScriptTag, /* 'hano' (HANUNOO) */
    1.96 +    buhdScriptTag, /* 'buhd' (BUHID) */
    1.97 +    tagbScriptTag, /* 'tagb' (TAGBANWA) */
    1.98 +    braiScriptTag, /* 'brai' (BRAILLE) */
    1.99 +    cprtScriptTag, /* 'cprt' (CYPRIOT) */
   1.100 +    limbScriptTag, /* 'limb' (LIMBU) */
   1.101 +    linbScriptTag, /* 'linb' (LINEAR_B) */
   1.102 +    osmaScriptTag, /* 'osma' (OSMANYA) */
   1.103 +    shawScriptTag, /* 'shaw' (SHAVIAN) */
   1.104 +    taleScriptTag, /* 'tale' (TAI_LE) */
   1.105 +    ugarScriptTag, /* 'ugar' (UGARITIC) */
   1.106 +    hrktScriptTag  /* 'hrkt' (KATAKANA_OR_HIRAGANA) */
   1.107 +};
   1.108 +
   1.109 +/** Array of Language Codes that need to be translated into LELanguageCodes for the 
   1.110 +construction of the LayoutEngine. */
   1.111 +const LETag languageCodes[] = {
   1.112 +    nullLanguageTag, /* '' (null) */
   1.113 +    araLanguageTag, /* 'ARA' (Arabic) */
   1.114 +    asmLanguageTag, /* 'ASM' (Assamese) */
   1.115 +    benLanguageTag, /* 'BEN' (Bengali) */
   1.116 +    farLanguageTag, /* 'FAR' (Farsi) */
   1.117 +    gujLanguageTag, /* 'GUJ' (Gujarati) */
   1.118 +    hinLanguageTag, /* 'HIN' (Hindi) */
   1.119 +    iwrLanguageTag, /* 'IWR' (Hebrew) */
   1.120 +    jiiLanguageTag, /* 'JII' (Yiddish) */
   1.121 +    janLanguageTag, /* 'JAN' (Japanese) */
   1.122 +    kanLanguageTag, /* 'KAN' (Kannada) */
   1.123 +    kokLanguageTag, /* 'KOK' (Konkani) */
   1.124 +    korLanguageTag, /* 'KOR' (Korean) */
   1.125 +    kshLanguageTag, /* 'KSH' (Kashmiri) */
   1.126 +    malLanguageTag, /* 'MAL' (Malayalam (Traditional)) */
   1.127 +    marLanguageTag, /* 'MAR' (Marathi) */
   1.128 +    mlrLanguageTag, /* 'MLR' (Malayalam (Reformed)) */
   1.129 +    mniLanguageTag, /* 'MNI' (Manipuri) */
   1.130 +    oriLanguageTag, /* 'ORI' (Oriya) */
   1.131 +    sanLanguageTag, /* 'SAN' (Sanscrit) */
   1.132 +    sndLanguageTag, /* 'SND' (Sindhi) */
   1.133 +    snhLanguageTag, /* 'SNH' (Sinhalese) */
   1.134 +    syrLanguageTag, /* 'SYR' (Syriac) */
   1.135 +    tamLanguageTag, /* 'TAM' (Tamil) */
   1.136 +    telLanguageTag, /* 'TEL' (Telugu) */
   1.137 +    thaLanguageTag, /* 'THA' (Thai) */
   1.138 +    urdLanguageTag, /* 'URD' (Urdu) */
   1.139 +    zhpLanguageTag, /* 'ZHP' (Chinese (Phonetic)) */
   1.140 +    zhsLanguageTag, /* 'ZHS' (Chinese (Simplified)) */
   1.141 +    zhtLanguageTag  /* 'ZHT' (Chinese (Traditional)) */
   1.142 +};
   1.143 +
   1.144 +/**
   1.145 +Translate the script code passed in to a LEScriptCode
   1.146 +*/ 
   1.147 +TInt ScriptCode(TUint32 aScript)
   1.148 +	{
   1.149 +	TInt scriptCode = -1;
   1.150 +    for (TInt i= 0; i < scriptCodeCount; i++)
   1.151 +    	{
   1.152 +    	if (scriptCodes[i] == aScript)
   1.153 +    		{
   1.154 +    		scriptCode = i;
   1.155 +    		break;
   1.156 +    		}
   1.157 +    	}
   1.158 +    return scriptCode;
   1.159 +	}
   1.160 +	
   1.161 +/**
   1.162 +Translate the language code passed in to a LELanguageCode
   1.163 +*/
   1.164 +TInt LanguageCode(TUint32 aLanguage)
   1.165 +	{
   1.166 +	TInt languageCode = -1;
   1.167 +    for (TInt i= 0; i < languageCodeCount; i++)
   1.168 +    	{
   1.169 +    	if (languageCodes[i] == aLanguage)
   1.170 +    		{
   1.171 +    		languageCode = i;
   1.172 +    		break;
   1.173 +    		}
   1.174 +    	}
   1.175 +    return languageCode;
   1.176 +	}
   1.177 +
   1.178 +/**
   1.179 +Create a instance of CIcuLayoutEngine
   1.180 +@param aBitmapFont The required font.
   1.181 +@param aHeap The heap to be used for storage by the engine.
   1.182 +@return A pointer to the new CIcuLayoutEngine instance.
   1.183 +*/
   1.184 +CShaper * CIcuLayoutEngine::NewL(CBitmapFont* aBitmapFont, TInt aScript, TInt aLanguage, RHeap* aHeap)
   1.185 +	{
   1.186 +	CIcuLayoutEngine* newShaper = new(ELeave)CIcuLayoutEngine(aScript, aLanguage);
   1.187 +	CleanupStack::PushL(newShaper);
   1.188 +	newShaper->ConstructL(aBitmapFont, aScript, aLanguage, aHeap);
   1.189 +	CleanupStack::Pop(); // newShaper
   1.190 +	return newShaper;	
   1.191 +	} 
   1.192 +
   1.193 +
   1.194 +/**
   1.195 +Construct an instance of CIcuLayoutEngine 	
   1.196 +@param aBitMapFont The required font
   1.197 +@param aHeap The heap to be used for storage by the engine
   1.198 +@return incase of exceptions with an Error Code
   1.199 +@see CShaper
   1.200 + */
   1.201 +TInt  CIcuLayoutEngine::ConstructL(CBitmapFont* aBitMapFont, TInt aScript, TInt aLanguage, RHeap* aHeap )
   1.202 +	{
   1.203 +	// allocate a block of memory from aHeap for the layout engine 
   1.204 +	// which is accessed via the Umemory class
   1.205 +	iClientHeap = aHeap;
   1.206 +
   1.207 +	// this needs to be on the heap
   1.208 +	LEErrorCode fontStatus = LE_NO_ERROR;
   1.209 +	iFontInstance = new SymbianFontInstance(aBitMapFont, fontStatus, aScript == mlymScriptTag);
   1.210 +	if(NULL == iFontInstance)
   1.211 +		{
   1.212 +		User::Leave(KErrGeneral);
   1.213 +		}
   1.214 +	if (fontStatus == LE_MEMORY_ALLOCATION_ERROR)
   1.215 +   		{
   1.216 +   		User::Leave(KErrNoMemory);
   1.217 +   		} 	
   1.218 +   	else if (fontStatus != LE_NO_ERROR)
   1.219 +   		{
   1.220 +   		//note this leave may actually be caused by OOM situations, 
   1.221 +   		//due to the way errors codes are handled in the open source code
   1.222 +   		User::Leave(KErrGeneral);
   1.223 +   	 	}
   1.224 +   	 	
   1.225 +
   1.226 + 	// create and initialise a ICU layout Engine
   1.227 +	// Note the engine is created using the Umemory heap 
   1.228 +    LEErrorCode success = LE_NO_ERROR;
   1.229 +    
   1.230 +    // Translate the script code into an LEScriptCode
   1.231 +    TInt scriptCode = ScriptCode(aScript);
   1.232 +    
   1.233 +    // Translate the language code into an LELanguageCode
   1.234 +    TInt languageCode = LanguageCode(aLanguage);
   1.235 +    
   1.236 +    // Finally instantiate the LayoutEngine    
   1.237 +	iEngine = LayoutEngine::layoutEngineFactory(iFontInstance, scriptCode, languageCode, success); 
   1.238 +
   1.239 +	// For debugging - check the total memory used by construction
   1.240 +#ifdef SHAPER_MEMORY_DEBUG
   1.241 +	TInt totalAllocSize = 0;
   1.242 +	TInt used = iHeap->AllocSize(totalAllocSize);
   1.243 +	RDebug::Print(_L("shaper construction %d cells %d"), totalAllocSize, used);
   1.244 +#endif
   1.245 +
   1.246 +	if (success == LE_MEMORY_ALLOCATION_ERROR)
   1.247 +		{
   1.248 +		User::Leave(KErrNoMemory);	
   1.249 +		}
   1.250 +	else if (success != LE_NO_ERROR)
   1.251 +		{
   1.252 + 		//note this leave may actually be caused by OOM situations, 
   1.253 + 		//due to the way errors codes are handled in the open source code
   1.254 + 		User::Leave(KErrGeneral);
   1.255 +		}
   1.256 +	return KErrNone;
   1.257 +	}
   1.258 +
   1.259 +CIcuLayoutEngine::CIcuLayoutEngine(TUint32 aScript, TUint32 aLanguage):
   1.260 +	iScript(aScript),
   1.261 +	iLanguage(aLanguage)
   1.262 +	{
   1.263 +	}
   1.264 +
   1.265 +/** 
   1.266 + Frees all resources owned by ...
   1.267 + */
   1.268 + CIcuLayoutEngine::~CIcuLayoutEngine()
   1.269 +	{
   1.270 +	// delete the engine instance
   1.271 +	if ( iEngine )
   1.272 +		{
   1.273 +		delete( iEngine );
   1.274 +		}
   1.275 +		
   1.276 +	// delete the font instance from client heap
   1.277 +	delete( iFontInstance );
   1.278 +	}
   1.279 +
   1.280 +/**
   1.281 +Returns the script and the language this shaper has been instansiated with.
   1.282 +*/	
   1.283 +void* CIcuLayoutEngine::ExtendedInterface (TUid aInterfaceId)
   1.284 +	{
   1.285 +	if (aInterfaceId == KUidShaperGetScript)		
   1.286 +		return (TUint32*)iScript;
   1.287 +	else
   1.288 +		if (aInterfaceId == KUidShaperGetLang)
   1.289 +			return (TUint32*)iLanguage;
   1.290 +		else
   1.291 +			return CShaper::ExtendedInterface(aInterfaceId);			
   1.292 +	}
   1.293 +	
   1.294 +/** This is implementation of CShaper::ShapeText for the Icu layout Engine
   1.295 + The data is taken from TInput and pass to the shaper.
   1.296 + A memory buffer is allocated on aHeapForOutput starting with TShapeHeader is allocated.
   1.297 + The results of the shaping are copied into this buffer and passed back via aOutput. 
   1.298 + @param aOutput On success a new structure containing the results allocated on aHeapForOutput.  
   1.299 + @param aInput The input text and other parameters.
   1.300 + @param aHeapForOutput On success, aOutput should be allocated from this and nothing else. 
   1.301 + 		On failure, nothing should be allocated from it.
   1.302 + @return Error value from one of the system-wide error codes on	failure, KErrNone on success.
   1.303 + @see CShaper::ShapeText
   1.304 + */		
   1.305 +TInt CIcuLayoutEngine::ShapeText(TShapeHeader*& aOutput, const TInput& aInput, RHeap* aHeapForOutput)
   1.306 +	{
   1.307 +	// For debugging - the heap before shaping
   1.308 +	TInt totalAllocSize = 0;
   1.309 +	TInt used;
   1.310 +#ifdef SHAPER_MEMORY_DEBUG
   1.311 +	used = User::Heap().AllocSize(totalAllocSize);
   1.312 +	RDebug::Print(_L("before shaping %d cells %d bytes used"), used, totalAllocSize);
   1.313 +#endif
   1.314 +
   1.315 +	iFontInstance->SetSessionHandle(aInput.iSessionHandle);
   1.316 +	TRAPD( error, IcuShapeTextL(aOutput, aInput, aHeapForOutput));
   1.317 +	if (error == KErrNoMemory)
   1.318 +		{
   1.319 +		used = User::Heap().AllocSize(totalAllocSize);
   1.320 +		RDebug::Print(_L("shaper out of memory %d cells %d"), totalAllocSize, used);
   1.321 +		}
   1.322 +
   1.323 +#ifdef SHAPER_MEMORY_DEBUG
   1.324 +	used = User::Heap().AllocSize(totalAllocSize);
   1.325 +	RDebug::Print(_L("Shaped %d characters %d glyphs "), aOutput->iCharacterCount, aOutput->iGlyphCount );
   1.326 +	RDebug::Print(_L("after shaping %d cells %d bytes used"), used, totalAllocSize);
   1.327 +#endif
   1.328 +
   1.329 +	// hide the ICU error codes as KErrGeneral
   1.330 +	if ((error == KErrNoMemory) || (error == KErrNone))
   1.331 +		return error;
   1.332 +	else
   1.333 +		return KErrGeneral;		
   1.334 +	}
   1.335 +
   1.336 +/** This calls the ICU Layout engine to shape the text.  It allocates memory for the results
   1.337 +and then reads the results.  This memory is freed by the caller.
   1.338 +This function can leave if OOM.
   1.339 + @param aOutput On success a new structure containing the results allocated on aHeapForOutput.  
   1.340 + @param aInput The input text and other parameters.
   1.341 + @param aHeapForOutput On success, aOutput should be allocated from this and nothing else. 
   1.342 + 		On failure, nothing should be allocated from it.
   1.343 + @return Error value from one of the system-wide error codes on	failure, KErrNone on success.
   1.344 + @see CIcuLayoutEngine::ShapeText
   1.345 + */
   1.346 +void  CIcuLayoutEngine::IcuShapeTextL(TShapeHeader*& aOutput, const TInput& aInput, RHeap* aHeapForOutput)
   1.347 +	{
   1.348 +	LEErrorCode success = LE_NO_ERROR;
   1.349 +	const LEUnicode * p = (LEUnicode *)aInput.iText->Ptr();
   1.350 +	TInt noChars = aInput.iEnd - aInput.iStart;
   1.351 +
   1.352 +	// Call to layout  
   1.353 +	TInt noOfGlyphs = iEngine->layoutChars(
   1.354 +			p, 							// chars - the input character context
   1.355 +			aInput.iStart,				// the offset of the first character to process	
   1.356 +			noChars,					// count - the number of characters to process	// offset
   1.357 +			aInput.iText->Length(), 	// max - the number of characters in the input context	// size of text
   1.358 +			FALSE, 						// rightToLeft - TRUE if the characters are in a right to left directional run
   1.359 +			0, 							// start X
   1.360 +			0, 							// start Y
   1.361 +			success);					// result code
   1.362 +
   1.363 +	if (success == LE_MEMORY_ALLOCATION_ERROR)
   1.364 +		User::Leave(KErrNoMemory);
   1.365 +	else if (success != LE_NO_ERROR) 
   1.366 +		{
   1.367 +		User::Leave(KErrGeneral);
   1.368 +		}
   1.369 +	
   1.370 +
   1.371 +	// Get some memory to pass into the layout engine for the results
   1.372 +	TInt bufferSize = (sizeof(LEGlyphID) + sizeof(le_int32) + sizeof(float) * 2)
   1.373 +		* noOfGlyphs + sizeof(float) * 2;
   1.374 +	TUint8* buffer = reinterpret_cast<TUint8*>( User::AllocL(bufferSize) );
   1.375 +	CleanupStack::PushL(buffer);
   1.376 +	LEGlyphID* glyphBuffer = reinterpret_cast<LEGlyphID*>(buffer);
   1.377 +	le_int32* indexBuffer = reinterpret_cast<le_int32*>(glyphBuffer + noOfGlyphs);
   1.378 +	float* positionBuffer = reinterpret_cast<float*>(indexBuffer + noOfGlyphs);
   1.379 +	
   1.380 +	
   1.381 +	// now get results glyph codes, positions and indices
   1.382 +	// from the layout engine
   1.383 +	if (success == LE_NO_ERROR)
   1.384 +		iEngine->getGlyphs(glyphBuffer, success);
   1.385 +
   1.386 +	if (success == LE_NO_ERROR)
   1.387 +		iEngine->getGlyphPositions(positionBuffer, success);
   1.388 +
   1.389 +	if (success == LE_NO_ERROR)
   1.390 +		iEngine->getCharIndices(indexBuffer, aInput.iStart, success);
   1.391 +	if (success == LE_NO_ERROR)
   1.392 +		// Reset the memory used by the IcuLayoutEngine
   1.393 +		iEngine->reset();
   1.394 +	if (success == LE_MEMORY_ALLOCATION_ERROR)
   1.395 +		User::Leave(KErrNoMemory);
   1.396 +	else 
   1.397 +		if (success != LE_NO_ERROR)
   1.398 + 			{
   1.399 +			User::Leave(KErrGeneral);
   1.400 +			}
   1.401 +
   1.402 +	// Some of the glyph codes are 0xFFFF and 0x0001. 0xFFFF is a value used by ICU layout
   1.403 +	// engine to indicate no glyph, and 0x0001 is used to indicate a ZWJ or a ZWNJ.
   1.404 +	// These should be stripped out now. A ZWJ or a ZWNJ glyph has no meaning here. Their 
   1.405 +	// effects on the precedig and proceding characters have already been taken into 
   1.406 +	// consideration during shaping, so we don't need them anymore.
   1.407 +	// Also, their presence in the final glyph list was causing GDI to break with GDI:1
   1.408 +	// i.e. more than 8 glyphs in a glyph cluster.
   1.409 +	LEGlyphID gidOfZWJ = iFontInstance->mapCharToGlyph(0x200D); // Added by Symbian: 1922 mlyl
   1.410 +	TInt actualNoOfGlyphs = 0;
   1.411 +	for (LEGlyphID* p = glyphBuffer + noOfGlyphs; p != glyphBuffer;)
   1.412 +		{
   1.413 +		--p;
   1.414 +		if (*p != 0xFFFF && *p != 0x0001 && *p != gidOfZWJ) // Added by Symbian: 1922 mlyl
   1.415 +			++actualNoOfGlyphs;
   1.416 +		}
   1.417 +
   1.418 +	// get some memory to pass back the results,  
   1.419 +	// This needs to be big enough for a TShapeHeader
   1.420 +	// plus 10 bytes for every glyph returned (-1 for the 1 byte allocated in TShapeHeader for iBuffer)
   1.421 +	aOutput = reinterpret_cast<TShapeHeader*>( aHeapForOutput->AllocL(
   1.422 +		sizeof(TShapeHeader) + (actualNoOfGlyphs * 10) + 3) );
   1.423 +
   1.424 +	// get the results into the shaper structure aOutput 
   1.425 +	aOutput->iGlyphCount = actualNoOfGlyphs;
   1.426 +	aOutput->iCharacterCount = noChars;
   1.427 + 	aOutput->iReserved0 = 0;
   1.428 +	aOutput->iReserved1 = 0;
   1.429 +
   1.430 + 	// iBuffer contains 10 bytes for every glyph
   1.431 + 	// the glyph code (4 bytes), position X(2 bytes) Y(2 bytes) and indices(2 bytes)
   1.432 + 
   1.433 + 	// first is glyph count * 4 byte glyph codes
   1.434 + 	TUint32* glyphOut = reinterpret_cast<TUint32*>(aOutput->iBuffer);
   1.435 + 	TInt16* posOut = reinterpret_cast<TInt16*>(aOutput->iBuffer +
   1.436 + 		(4 * actualNoOfGlyphs));
   1.437 + 	TInt16* indicesOut = reinterpret_cast<TInt16*>(aOutput->iBuffer +
   1.438 + 		(8 * actualNoOfGlyphs) + 4);
   1.439 + 	for (TInt i=0; i < noOfGlyphs; i++)
   1.440 + 		{
   1.441 + 		if (*glyphBuffer != 0xFFFF && *glyphBuffer != 0x0001 && *glyphBuffer != gidOfZWJ) // Added by Symbian: 1922 mlyl
   1.442 + 			{
   1.443 +	  		*glyphOut++ = *glyphBuffer;
   1.444 +			*posOut++ = FloatToInt( positionBuffer[0] );
   1.445 +			*posOut++ = FloatToInt( positionBuffer[1] );
   1.446 +			*indicesOut++ = *indexBuffer;
   1.447 + 			}
   1.448 + 		++glyphBuffer;
   1.449 + 		positionBuffer += 2;
   1.450 + 		++indexBuffer;
   1.451 +		}
   1.452 +	// There is an extra pair of positions: this is the total advance
   1.453 +	posOut[0] = FloatToInt( positionBuffer[0] );
   1.454 +	posOut[1] = FloatToInt( positionBuffer[1] );
   1.455 +	
   1.456 +	CleanupStack::PopAndDestroy(buffer);	
   1.457 +	
   1.458 +	}