os/graphics/fbs/fontandbitmapserver/tfbs/tfbsglyphdata.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/fbs/fontandbitmapserver/tfbs/tfbsglyphdata.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,3212 @@
     1.4 +// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +/**
    1.20 + @file
    1.21 + @internalComponent - Internal Symbian test code
    1.22 +*/
    1.23 +
    1.24 +#include <test/graphicsfontutils.h>
    1.25 +#include <EGL/egl.h>
    1.26 +#include <VG/openvg.h>
    1.27 +#include <graphics/fbsglyphmetricsarray.h> 
    1.28 +#include <graphics/fbsglyphdataiterator.h>
    1.29 +#include <sgresource/sgimage.h>
    1.30 +#include <sgresource/sgdriver_test.h>
    1.31 +#include <sgresource/sgdriver_profiling.h>
    1.32 +#include "FbsMessage.h"
    1.33 +#include "tfbsglyphdata.h"
    1.34 +
    1.35 +_LIT(KTypefaceName, "DejaVu Sans Condensed");
    1.36 +//_LIT(KMonoTypefaceName, "DejaVu Sans Mono");
    1.37 +const TInt KNumGlyphCodesLatin = 96;
    1.38 +const TUint KDejaVuInvalidGlyphCode = 0;
    1.39 +
    1.40 +// Currently only used in debug. When TestMultithreadStressAtlas() test is enabled, #ifdef to be removed. 
    1.41 +#ifdef _DEBUG
    1.42 +const TInt KTestThreadMinHeapSize = 0x20000;
    1.43 +const TInt KTestThreadMaxHeapSize = 0x20000;
    1.44 +#endif
    1.45 +
    1.46 +// 'most significant bit' flag to ensure value is interpreted as a glyph code rather than an ascii code
    1.47 +const TUint KGlyphCodeFlag = 0x80000000;      
    1.48 +
    1.49 +
    1.50 +// Please note the following macros which enable helper functions, and are declared in the header.
    1.51 +// SAVEGLYPHSTOMBMDURINGCOMPARISON and
    1.52 +// SAVEGLYPHSTOMBMDEBUGFUNCTION
    1.53 +
    1.54 +// Utility function declarations - utilities used by the tests
    1.55 +static TFontSpec GenerateDejaVuFontSpec(TInt aSeed);
    1.56 +static void CopyCharLine(TUint32*& aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth, TInt16 aRepeatCount);
    1.57 +static void DecodeBinaryData(const TSize& aDataSize, const TUint8* aData, TInt aStride,	TUint32* aBinaryData);
    1.58 +static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage);
    1.59 +static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage, TUint8* aBuffer1, TUint8* aBuffer2);
    1.60 +// Following functions commented out because the tests which use these functions 
    1.61 +// are currently commented out due to Broadcom defect 
    1.62 +// ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM
    1.63 +//static TInt FillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages);
    1.64 +//static TInt NearlyFillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages);
    1.65 +
    1.66 +#if defined (SAVEGLYPHSTOMBMDEBUGFUNCTION) || defined (SAVEGLYPHSTOMBMDURINGCOMPARISON)
    1.67 +/**
    1.68 +Static utility function. Converts an A8 RSgImage into a CFbsBitmap.
    1.69 +To do this, the RSgImage is converted to an EGLImage, then to a VGImage,
    1.70 +where the image memory is read into a CFbsBitmap.
    1.71 +
    1.72 +@param aEGL The EGL helper object that will read the SgImage into a memory buffer.
    1.73 +@param aSgImage The RSgImage to convert.
    1.74 +@param aRect A rectangular region of the RSgImage to convert.
    1.75 +@param aBitmap On success, holds a pointer to a CFbsBitmap which contains the image
    1.76 +	data of the RSgImage.
    1.77 +@return One of the system-wide error codes.
    1.78 +*/
    1.79 +static TInt CreateBitmapFromSgImage(CEGLHelper* aEGL, const RSgImage& aSgImage, const TRect& aRect, CFbsBitmap*& aBitmap)
    1.80 +	{
    1.81 +	TInt err = KErrNone;
    1.82 +	const TSize bufferSize = aRect.Size();
    1.83 +	const TInt dataStride = bufferSize.iWidth;
    1.84 +
    1.85 +	TUint8* imageBuffer = reinterpret_cast<TUint8*>(User::AllocZ(bufferSize.iHeight * dataStride));
    1.86 +	if (!imageBuffer)
    1.87 +		{
    1.88 +		return KErrNoMemory;
    1.89 +		}
    1.90 +	err = aEGL->GetSgImageData(aSgImage, aRect, imageBuffer);
    1.91 +	if (err != KErrNone)
    1.92 +		{
    1.93 +		User::Free(imageBuffer);
    1.94 +		return err;
    1.95 +		}
    1.96 +	aBitmap = new CFbsBitmap();
    1.97 +	if (!aBitmap)
    1.98 +		{
    1.99 +		User::Free(imageBuffer);
   1.100 +		return KErrNoMemory;
   1.101 +		}
   1.102 +
   1.103 +	err = aBitmap->Create(bufferSize, EGray256);
   1.104 +	if (KErrNone == err)
   1.105 +		{
   1.106 +		TUint8* buf = imageBuffer;
   1.107 +		aBitmap->BeginDataAccess();
   1.108 +		TUint8* dataAddress = reinterpret_cast<TUint8*>(aBitmap->DataAddress());
   1.109 +		const TInt dataStride = aBitmap->DataStride();	
   1.110 +		for (TInt scanline = 0; scanline < bufferSize.iHeight; scanline++)
   1.111 +			{
   1.112 +			Mem::Copy(dataAddress, buf, bufferSize.iWidth);
   1.113 +			dataAddress += dataStride;
   1.114 +			buf += bufferSize.iWidth;
   1.115 +			}
   1.116 +		aBitmap->EndDataAccess(EFalse);
   1.117 +		}
   1.118 +	else
   1.119 +		{
   1.120 +		delete aBitmap;
   1.121 +		aBitmap = NULL;
   1.122 +		}
   1.123 +
   1.124 +	User::Free(imageBuffer);
   1.125 +	return err;
   1.126 +	}
   1.127 +
   1.128 +/**
   1.129 +Utility function to aid with debugging.
   1.130 +Saves a bitmap to file.
   1.131 +
   1.132 +@param aBmp Bitmap to save
   1.133 +@param aMeta Optional. If specified, it is added to the name of the bitmap file.
   1.134 +@param aRef Flag to show whether bitmap is a reference bitmap (ETrue) or test bitmap (EFalse).
   1.135 +*/
   1.136 +static void SaveBmp(CFbsBitmap* aBmp, TPtrC* aMeta, TBool aRef)
   1.137 +	{
   1.138 +	if (!aBmp)
   1.139 +		{
   1.140 +		return;
   1.141 +		}
   1.142 +	
   1.143 +	TBuf<256> testFileName;
   1.144 +	if (aRef)
   1.145 +		{
   1.146 +		testFileName.Append(_L("Ref"));
   1.147 +		}
   1.148 +	else
   1.149 +		{
   1.150 +		testFileName.Append(_L("Test"));
   1.151 +		}
   1.152 +	if (aMeta)
   1.153 +		{
   1.154 +		testFileName.Append(*aMeta);
   1.155 +		}
   1.156 +
   1.157 +	TFileName mbmFile;
   1.158 +	TBuf<20> testPathName;
   1.159 +	#ifdef __WINS__
   1.160 +		testPathName.Append(_L("c:\\%S.mbm"));
   1.161 +	#else
   1.162 +		testPathName.Append(_L("e:\\%S.mbm"));
   1.163 +	#endif
   1.164 +	mbmFile.Format(testPathName, &testFileName);
   1.165 +
   1.166 +	// As this is for debugging purposes only, doesn't matter reporting whether
   1.167 +	// saving succeeded or not.
   1.168 +	aBmp->Save(mbmFile);
   1.169 +	}
   1.170 +#endif // SAVEGLYPHSTOMBMDEBUGFUNCTION OR SAVEGLYPHSTOMBMDURINGCOMPARISON
   1.171 +
   1.172 +
   1.173 +#ifdef SAVEGLYPHSTOMBMDEBUGFUNCTION
   1.174 +void CTFbsGlyphData::SaveRSgImagesAsMbms(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, const RSgImage& aImageB, const TRect& aRectB )
   1.175 +	{
   1.176 +	static TInt countToAppend = 0;
   1.177 +
   1.178 +	CFbsBitmap* bitmap = NULL;
   1.179 +	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageA, aRectA, bitmap))
   1.180 +		{
   1.181 +		TBuf<KMaxFileName> buf( _L("String") );
   1.182 +		buf.AppendNum( countToAppend );
   1.183 +		TPtrC nameAppend( buf );
   1.184 +
   1.185 +		SaveBmp(bitmap, &nameAppend, EFalse);
   1.186 +		}
   1.187 +	delete bitmap;  
   1.188 +	bitmap = NULL;
   1.189 +
   1.190 +	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageB, aRectB, bitmap))
   1.191 +		{
   1.192 +		TBuf<KMaxFileName> buf( _L("String") );
   1.193 +		buf.AppendNum( countToAppend );
   1.194 +		TPtrC nameAppend( buf );
   1.195 +
   1.196 +		SaveBmp(bitmap, &nameAppend, ETrue);
   1.197 +		}
   1.198 +	delete bitmap;
   1.199 +	bitmap = NULL;
   1.200 +
   1.201 +	countToAppend++;
   1.202 +	}
   1.203 +
   1.204 +/**
   1.205 +Static debug utility method that outputs the glyph images of the given glyph
   1.206 +codes for the given font to a file.
   1.207 + */
   1.208 +static void DumpFontGlyphs(CEGLHelper* aEGL, CFont* aFont, TInt aCodesCount)
   1.209 +	{
   1.210 +	TFontSpec fontSpec = aFont->FontSpecInTwips();
   1.211 +	TOpenFontCharMetrics charMetrics;
   1.212 +	TSize bitmapSize;
   1.213 +	const TUint8* bitmapData = NULL;
   1.214 +	
   1.215 +	for (TInt glyphCode = 0; glyphCode < aCodesCount; glyphCode++)
   1.216 +		{
   1.217 +		CFont::TCharacterDataAvailability availability = aFont->GetCharacterData(glyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
   1.218 +		if (availability == CFont::EAllCharacterData)
   1.219 +			{
   1.220 +			RSgImage characterDataImage;
   1.221 +			TInt err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
   1.222 +			if (err == KErrNone)
   1.223 +				{
   1.224 +				CFbsBitmap* bitmap = NULL;
   1.225 +				err = CreateBitmapFromSgImage(aEGL, characterDataImage, TRect(TPoint(0, 0), bitmapSize), bitmap);
   1.226 +				if (err == KErrNone)
   1.227 +					{
   1.228 +					TBuf<256> bitmapName;
   1.229 +					bitmapName.AppendFormat(_L("%S-%i"), &(fontSpec.iTypeface.Name()), glyphCode);
   1.230 +					TPtrC bitmapNamePtr(bitmapName);
   1.231 +					SaveBmp(bitmap, &bitmapNamePtr, EFalse);
   1.232 +					delete bitmap;
   1.233 +					}
   1.234 +				}
   1.235 +			characterDataImage.Close();
   1.236 +			}
   1.237 +		}
   1.238 +	}
   1.239 +#endif // SAVEGLYPHSTOMBMDEBUGFUNCTION
   1.240 +
   1.241 +
   1.242 +/**
   1.243 +Utility to return a fontspec such that the font created from it will
   1.244 +not match any other font generated by a different seed. The font
   1.245 +will be useable by RFbsGlyphDataIterator and RFbsGlyphMetricsArray.
   1.246 +It will always return a font based on the DejaVu fontspec, this is 
   1.247 +so that the glyphcodes in DejaVuASCIIToGlyphCode are guaranteed to
   1.248 +work.
   1.249 +
   1.250 +@param aSeed Specifies a variant of the fontspec to create. Passing the
   1.251 +	same seed will cause the same TFontSpec to be returned.
   1.252 +@return The generated fontspec. 
   1.253 + */
   1.254 +static TFontSpec GenerateDejaVuFontSpec(TInt aSeed)
   1.255 +	{
   1.256 +	const TInt KFontHeightStep = 4;
   1.257 +	const TInt KFontInitialHeight = 8;
   1.258 +	
   1.259 +	const TInt KNumFontTypefaces = 3;
   1.260 +	const TInt KNumFontBitmapTypes = 2;
   1.261 +	const TInt KNumFontStyles = 4;
   1.262 +	
   1.263 +	TInt fontBitmapTypeVariant = aSeed % KNumFontBitmapTypes;
   1.264 +	TInt fontStyleVariant = (aSeed / KNumFontBitmapTypes) % KNumFontStyles;
   1.265 +	TInt fontTypefaceVariant = (aSeed / ( KNumFontStyles * KNumFontBitmapTypes)) % KNumFontTypefaces;
   1.266 +	TInt fontHeightVariant = aSeed / (KNumFontStyles * KNumFontTypefaces * KNumFontBitmapTypes);
   1.267 +	
   1.268 +	TFontSpec fontSpec;	
   1.269 +	fontSpec.iHeight = KFontInitialHeight + (fontHeightVariant * KFontHeightStep);
   1.270 +	// Set the typeface name
   1.271 +	// Set the style.
   1.272 +	switch (fontStyleVariant)
   1.273 +		{
   1.274 +		case 1: // italic
   1.275 +			fontSpec.iFontStyle.SetPosture(EPostureItalic);
   1.276 +			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
   1.277 +			break;
   1.278 +		case 2: // bold
   1.279 +			fontSpec.iFontStyle.SetPosture(EPostureUpright);
   1.280 +			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
   1.281 +			break;
   1.282 +		case 3: // bold italic
   1.283 +			fontSpec.iFontStyle.SetPosture(EPostureItalic);
   1.284 +			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
   1.285 +			break;
   1.286 +		default: // normal 
   1.287 +			fontSpec.iFontStyle.SetPosture(EPostureUpright);
   1.288 +			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
   1.289 +			break;
   1.290 +		}
   1.291 +	switch (fontTypefaceVariant)
   1.292 +		{
   1.293 +		case 1:
   1.294 +			fontSpec.iTypeface.SetName(_L("DejaVu Sans Mono"));
   1.295 +			break;
   1.296 +		case 2:
   1.297 +			fontSpec.iTypeface.SetName(_L("DejaVu Serif Condensed"));
   1.298 +			break;
   1.299 +		case 3:
   1.300 +			fontSpec.iTypeface.SetName(_L("DejaVu Sans Condensed"));
   1.301 +			break;
   1.302 +		}
   1.303 +	switch(fontBitmapTypeVariant)
   1.304 +		{
   1.305 +		case 1:
   1.306 +			fontSpec.iFontStyle.SetBitmapType(EMonochromeGlyphBitmap);
   1.307 +			break;
   1.308 +		default:
   1.309 +			fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
   1.310 +			break;
   1.311 +		}
   1.312 +
   1.313 +	return fontSpec;
   1.314 +	}
   1.315 +
   1.316 +
   1.317 +/**
   1.318 + * 
   1.319 + EGL helper class to retrieve image data from an SgImage into a memory buffer.
   1.320 + */
   1.321 +CEGLHelper::CEGLHelper() :
   1.322 +	iDisplay(EGL_NO_DISPLAY),
   1.323 +	iContext(EGL_NO_CONTEXT),
   1.324 +	iSurface(EGL_NO_SURFACE)
   1.325 +	{
   1.326 +	}
   1.327 +CEGLHelper::~CEGLHelper()
   1.328 +	{
   1.329 +	iMutex.Close();
   1.330 +	eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   1.331 +	eglDestroyContext(iDisplay, iContext);
   1.332 +	eglDestroySurface(iDisplay, iSurface);
   1.333 +	eglTerminate(iDisplay);
   1.334 +	eglReleaseThread();
   1.335 +	iSgDriver.Close();
   1.336 +	}
   1.337 +
   1.338 +/**
   1.339 +Factory method to create CEGLHelper.
   1.340 +@return A pointer to an instance of CEGLHelper.
   1.341 + */
   1.342 +CEGLHelper* CEGLHelper::NewL()
   1.343 +	{
   1.344 +	CEGLHelper* self = new CEGLHelper();
   1.345 +	CleanupStack::PushL(self);
   1.346 +	self->ConstructL();
   1.347 +	CleanupStack::Pop(1); // self
   1.348 +	return self;
   1.349 +	}
   1.350 +
   1.351 +/**
   1.352 +Opens handle to the process-wide synchronisation semaphore,
   1.353 +loads EGL and VG extension function pointers,
   1.354 +sets up EGL resources so that EGLImages can be constructed. 
   1.355 + */
   1.356 +void CEGLHelper::ConstructL()
   1.357 +	{
   1.358 +	_LIT(KEGLMutex, "TFbsGlyphDataEGLMutex");
   1.359 +	User::LeaveIfError(iMutex.CreateGlobal(KEGLMutex, EOwnerProcess));
   1.360 +	User::LeaveIfError(iSgDriver.Open());
   1.361 +
   1.362 +	iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   1.363 +	if (iDisplay == EGL_NO_DISPLAY)
   1.364 +		{
   1.365 +		User::Leave(KErrNotSupported);
   1.366 +		}
   1.367 +	if (EGL_TRUE != eglInitialize(iDisplay, NULL, NULL))
   1.368 +		{
   1.369 +		User::Leave(KErrNotSupported);
   1.370 +		}
   1.371 +	eglBindAPI(EGL_OPENVG_API);
   1.372 +
   1.373 +	// Load the necessary EGL extensions...
   1.374 +	eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
   1.375 +	eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
   1.376 +	vgCreateImageTargetKHR = reinterpret_cast<TvgCreateEGLImageTargetKHRTypefPtr>(eglGetProcAddress("vgCreateEGLImageTargetKHR"));
   1.377 +	if (!eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateImageTargetKHR)
   1.378 +		{
   1.379 +		User::Leave(KErrExtensionNotSupported);
   1.380 +		}
   1.381 +
   1.382 +	// In order to create VGImages from EGLImages, a context must be current.
   1.383 +	// Therefore create an EGLContext and EGLSurface to make current, using
   1.384 +	// a dummy RSgImage.
   1.385 +
   1.386 +	RSgImage dummySurface;
   1.387 +	TSgImageInfo dummySurfaceInfo(TSize(1, 1), ESgPixelFormatRGB_565, ESgUsageBitOpenVgSurface);
   1.388 +	User::LeaveIfError(dummySurface.Create(dummySurfaceInfo, NULL, 0));
   1.389 +	CleanupClosePushL(dummySurface);
   1.390 +
   1.391 +	EGLint configAttribs[] = 
   1.392 +		{
   1.393 +		EGL_MATCH_NATIVE_PIXMAP, (EGLint)&dummySurface,
   1.394 +		EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
   1.395 +		EGL_NONE
   1.396 +		};
   1.397 +
   1.398 +	EGLint configId = 0;
   1.399 +	EGLint numConfigs = 0;
   1.400 +	if (EGL_FALSE == eglChooseConfig(iDisplay, configAttribs, &configId, 1, &numConfigs) || numConfigs == 0)
   1.401 +		{
   1.402 +		User::Leave(KErrGeneral);
   1.403 +		}
   1.404 +	iContext = eglCreateContext(iDisplay, configId, EGL_NO_CONTEXT, NULL);
   1.405 +	if (iContext == EGL_NO_CONTEXT)
   1.406 +		{
   1.407 +		User::Leave(KErrGeneral);
   1.408 +		}
   1.409 +	iSurface = eglCreatePixmapSurface(iDisplay, configId, &dummySurface, NULL);
   1.410 +	if (iSurface == EGL_NO_SURFACE)
   1.411 +		{
   1.412 +		User::Leave(KErrGeneral);
   1.413 +		}
   1.414 +	CleanupStack::PopAndDestroy(1); // dummySurface
   1.415 +	}
   1.416 +
   1.417 +/**
   1.418 +Retrieves the data from an A8 RSgImage into a buffer.
   1.419 +To do this, the RSgImage is converted to an EGLImage, then to a VGImage,
   1.420 +where the image memory is read into the given buffer.
   1.421 +The function can be called from multiple threads and synchronisation
   1.422 +with EGL is controlled via a mutex.
   1.423 +
   1.424 +@param aSgImage The RSgImage to convert.
   1.425 +@param aRect A rectangular region of the RSgImage to convert.
   1.426 +@param aBuf On success, contains the image data of the RSgImage.
   1.427 +@return One of the system-wide error codes.
   1.428 + */
   1.429 +TInt CEGLHelper::GetSgImageData(const RSgImage& aSgImage, const TRect& aRect, TUint8*& aBuf)
   1.430 +	{
   1.431 +	const TSize bufferSize = aRect.Size();
   1.432 +	const TInt dataStride = bufferSize.iWidth;
   1.433 +
   1.434 +	if (bufferSize == TSize(0,0))
   1.435 +		{
   1.436 +		return KErrNone;
   1.437 +		}
   1.438 +	iMutex.Wait();
   1.439 +
   1.440 +	TInt err = KErrNone;
   1.441 +	EGLImageKHR eglImage;
   1.442 +	if (EGL_FALSE == eglBindAPI(EGL_OPENVG_API))
   1.443 +		{
   1.444 +		err = KErrGeneral;
   1.445 +		}
   1.446 +	else if (EGL_FALSE == eglMakeCurrent(iDisplay, iSurface, iSurface, iContext))
   1.447 +		{
   1.448 +		err = KErrGeneral;
   1.449 +		}
   1.450 +	else
   1.451 +		{
   1.452 +		// Create EGLImages from the RSgImage.
   1.453 +		EGLint imageAttribs[] =
   1.454 +			{
   1.455 +			EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 
   1.456 +			EGL_NONE
   1.457 +			};
   1.458 +		eglImage = eglCreateImageKHR(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<EGLClientBuffer>(&aSgImage), imageAttribs);
   1.459 +		if (eglImage == EGL_NO_IMAGE_KHR)
   1.460 +			{
   1.461 +			err = KErrArgument;
   1.462 +			}
   1.463 +		}
   1.464 +	if (err == KErrNone)
   1.465 +		{
   1.466 +		// Create VGImages from the EGLImage.
   1.467 +		VGImage vgImage = vgCreateImageTargetKHR(eglImage);
   1.468 +		eglDestroyImageKHR(iDisplay, eglImage);
   1.469 +		if (vgImage == VG_INVALID_HANDLE)
   1.470 +			{
   1.471 +			err = KErrArgument;
   1.472 +			}
   1.473 +		else
   1.474 +			{
   1.475 +			// Get the image data in 8bpp format
   1.476 +			vgGetImageSubData(vgImage, aBuf, dataStride, VG_A_8, aRect.iTl.iX, aRect.iTl.iY, bufferSize.iWidth, bufferSize.iHeight);
   1.477 +			vgDestroyImage(vgImage);
   1.478 +			}
   1.479 +		}
   1.480 +	eglReleaseThread();
   1.481 +	iMutex.Signal();
   1.482 +	return err;
   1.483 +	}
   1.484 +
   1.485 +CTFbsGlyphData::CTFbsGlyphData(CTestStep* aStep):
   1.486 +	CTGraphicsBase(aStep)
   1.487 +	{
   1.488 +	}
   1.489 +
   1.490 +void CTFbsGlyphData::ConstructL()
   1.491 +	{
   1.492 +	User::LeaveIfError(Logger().ShareAuto());
   1.493 +	User::LeaveIfError(RFbsSession::Connect());
   1.494 +	iFbs = RFbsSession::GetSession();
   1.495 +	iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
   1.496 +	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTypefaceName, 15)));
   1.497 +	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont2, TFontSpec(KTypefaceName, 8)));
   1.498 +	
   1.499 +	CCharCodeConverter* converter = CCharCodeConverter::NewLC();
   1.500 +	converter->UseFontL(iFont);
   1.501 +	iGlyphCodesLatin = new(ELeave) TUint[KNumGlyphCodesLatin];
   1.502 +	for (TInt ii = 0; ii < KNumGlyphCodesLatin; ++ii)
   1.503 +		{
   1.504 +		TUint asciiCode = ii+0x20; // ASCII characters from 0020 to 007F
   1.505 +		iGlyphCodesLatin[ii] = converter->GlyphCodeL(asciiCode);
   1.506 +		}
   1.507 +	CleanupStack::PopAndDestroy(1); // converter
   1.508 +	
   1.509 +	User::LeaveIfError(iSgDriver.Open());
   1.510 +	iEGL = CEGLHelper::NewL();
   1.511 +	
   1.512 +	// Creating a CFbsBitmap will force the RFbsSession to allocate a scanline buffer
   1.513 +	// now rather than in the middle of a test, thus avoiding heap check failure. 
   1.514 +	CFbsBitmap* dummyBitmap = new (ELeave) CFbsBitmap;
   1.515 +	CleanupStack::PushL(dummyBitmap);
   1.516 +	User::LeaveIfError(dummyBitmap->Create(TSize(512, 1), EGray256));
   1.517 +	CleanupStack::PopAndDestroy(dummyBitmap);
   1.518 +
   1.519 +	INFO_PRINTF1(_L("FBSERV Glyph Data Testing"));
   1.520 +	}
   1.521 +
   1.522 +
   1.523 +
   1.524 +
   1.525 +CTFbsGlyphData::~CTFbsGlyphData()
   1.526 +	{
   1.527 +	delete iEGL;
   1.528 +	iSgDriver.Close();
   1.529 +	if (iTs)
   1.530 +		{
   1.531 +		iTs->ReleaseFont(iFont);
   1.532 +		iTs->ReleaseFont(iFont2);
   1.533 +		}
   1.534 +	delete iTs;
   1.535 +	delete[] iGlyphCodesLatin;
   1.536 +	User::Free(iTempBuf1);
   1.537 +	User::Free(iTempBuf2);
   1.538 +	RFbsSession::Disconnect();
   1.539 +	}
   1.540 +
   1.541 +void CTFbsGlyphData::RunTestCaseL(TInt aCurTestCase)
   1.542 +	{
   1.543 +	((CTFbsGlyphDataStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
   1.544 +	
   1.545 +	TRAPD(leave, 
   1.546 +
   1.547 +	switch(aCurTestCase)
   1.548 +		{
   1.549 +	case 1:
   1.550 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0624"));
   1.551 +		TestConsistencyWithGetCharacterData();
   1.552 +		break;
   1.553 +	case 2:
   1.554 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0625"));
   1.555 +		TestInvalidGlyphCode();
   1.556 +		break;
   1.557 +	case 3:
   1.558 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0626"));
   1.559 +		TestGlyphMetricsArrayParameters();
   1.560 +		break;
   1.561 +	case 4:
   1.562 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0627"));
   1.563 +		TestGlyphMetricsArrayReuse();
   1.564 +		break;
   1.565 +	case 5:
   1.566 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0628"));
   1.567 +		TestGlyphDataIteratorClose();
   1.568 +		break;
   1.569 +	case 6:
   1.570 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0629"));
   1.571 +		TestGlyphDataIteratorSequence();
   1.572 +		break;	
   1.573 +	case 7:
   1.574 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0632"));
   1.575 +		TestGlyphDataIteratorMultipleUsesOnMultipleFonts();
   1.576 +		break;
   1.577 +	case 8:
   1.578 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0633"));
   1.579 +		TestGlyphDataIteratorImageValidity();
   1.580 +		break;
   1.581 +	case 9:
   1.582 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0634"));
   1.583 +		TestGlyphDataIteratorOpenInvalidCode();
   1.584 +		break;
   1.585 +	case 10:
   1.586 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0636"));
   1.587 +		TestGlyphDataIteratorOpenTwice();
   1.588 +		break;
   1.589 +	case 11:
   1.590 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0637"));
   1.591 +		TestGlyphDataIteratorOpenTwiceWithDifferentFonts();
   1.592 +		break;
   1.593 +	case 12:
   1.594 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0638"));
   1.595 +		TestGlyphDataIteratorOpenTooBigFont();
   1.596 +		break;
   1.597 +	case 13:
   1.598 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0640"));
   1.599 +		TestGlyphDataIteratorOpenWithWrongArgument();
   1.600 +		break;
   1.601 +	case 14:
   1.602 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0641"));
   1.603 +		TestGlyphDataIteratorImageMemoryLeak();
   1.604 +		break;
   1.605 +	case 15:
   1.606 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0662"));
   1.607 +		TestGlyphDataIteratorNoGraphicsMemory();
   1.608 +		break;
   1.609 +	case 16: 
   1.610 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0659"));
   1.611 +		TestGlyphDataIteratorLargeFontStress();
   1.612 +		break;
   1.613 +	case 17: 
   1.614 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0660"));
   1.615 +		TestGlyphDataIteratorManyFontsStressL();
   1.616 +		break;
   1.617 +	case 18:
   1.618 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0666"));
   1.619 +		TestGlyphDataIteratorNextIsAtomic();
   1.620 +		break;
   1.621 +	case 19:
   1.622 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0665"));
   1.623 +		TestGlyphDataIteratorSameGlyphCodes();
   1.624 +		break;
   1.625 +	case 20:
   1.626 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0668"));
   1.627 +		TestGlyphDataIteratorManyArraySizes();
   1.628 +		break;
   1.629 +	case 21:
   1.630 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0669"));
   1.631 +		TestBitmapFontSupport();
   1.632 +		break;
   1.633 +	case 22:
   1.634 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0671"));
   1.635 +		TestMultithreadShareSingleFont();
   1.636 +		break;
   1.637 +	case 23:
   1.638 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0672"));
   1.639 +		TestMultithreadStressAtlas();
   1.640 +		break;
   1.641 +    case 24:
   1.642 +        ((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0673"));
   1.643 +        TestGlyphMetricsArrayHeapOOML();
   1.644 +        break;
   1.645 +    case 25:
   1.646 +        ((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0674"));
   1.647 +        TestGlyphDataIteratorHeapOOML();
   1.648 +        break;
   1.649 +	default:
   1.650 +		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
   1.651 +		((CTFbsGlyphDataStep*)iStep)->CloseTMSGraphicsStep();
   1.652 +		TestComplete();
   1.653 +		break;
   1.654 +		}
   1.655 +	
   1.656 +	); // TRAPD
   1.657 +
   1.658 +	if (leave != KErrNone)
   1.659 +		{
   1.660 +		ERR_PRINTF2(_L("Leave %d occurred during test"), leave);
   1.661 +		iStep->SetTestStepResult(EFail);
   1.662 +		}
   1.663 +
   1.664 +	((CTFbsGlyphDataStep*)iStep)->RecordTestResultL();
   1.665 +	}
   1.666 +
   1.667 +
   1.668 +/**
   1.669 +@SYMTestCaseID		GRAPHICS-FBSERV-0624
   1.670 +@SYMTestPriority	High
   1.671 +@SYMTestType		UT
   1.672 +@SYMTestStatus		Implemented
   1.673 +@SYMPREQ			PREQ2678
   1.674 +
   1.675 +@SYMTestCaseDesc
   1.676 +	Shows that RFbsGlyphMetricsArray::Get() and CFont::GetCharacterData() all 
   1.677 +	provide the same metrics for the same set of glyph codes when using a CFbsFont.
   1.678 +	Shows that RFbsGlyphDataIterator::Metrics() and CFont::GetCharacterData()
   1.679 +	provide the same metrics for the same set of glyph codes.
   1.680 +
   1.681 +@SYMTestActions
   1.682 +	i. Call RFbsGlyphMetricsArray::Get() for a set of glyph codes with 1 glyph code per call.
   1.683 +	ii. Call RFbsGlyphMetricsArray::Get() for a set of glyph codes all in 1 call.
   1.684 +	iii. Call RFbsGlyphDataIterator::Open() for a set of glyph codes.
   1.685 +	iv. Call CFont::GetCharacterData() for the same set of glyph codes.
   1.686 +	v. Compare the metrics for each glyph code from all calls.
   1.687 +
   1.688 +@SYMTestExpectedResults
   1.689 +	For each glyph code, metrics received from RFbsGlyphMetricsArray::Get() and
   1.690 +	CFont::GetCharacterData() and RFbsGlyphDataIterator are all the same.
   1.691 +*/
   1.692 +void CTFbsGlyphData::TestConsistencyWithGetCharacterData()
   1.693 +	{
   1.694 +	INFO_PRINTF1(_L("Test RFbsGlyphMetricsArray::Get() with GetCharacterData()"));
   1.695 +	
   1.696 +	__UHEAP_MARK;
   1.697 +
   1.698 +	RFbsGlyphDataIterator iter;
   1.699 +	RFbsGlyphMetricsArray glyphMetricsArray;
   1.700 +	RFbsGlyphMetricsArray glyphMetricsArraySingle;
   1.701 +	
   1.702 +	TInt numMismatches = 0;
   1.703 +	TOpenFontCharMetrics charMetrics;
   1.704 +	TSize bitmapSize;
   1.705 +	const TUint8* bitmapData = NULL;
   1.706 +	
   1.707 +	// Retrieve list of metrics for all glyph codes in one call
   1.708 +	TInt err = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
   1.709 +	TESTNOERROR(err);
   1.710 +	if (err == KErrNone)
   1.711 +		{
   1.712 +		TEST(KNumGlyphCodesLatin == glyphMetricsArray.Count());
   1.713 +		
   1.714 +		TInt index = 0;
   1.715 +		TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
   1.716 +		TESTNOERROR(iterErr);
   1.717 +		for (; iterErr == KErrNone; iterErr = iter.Next(), index++)
   1.718 +			{
   1.719 +			iFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
   1.720 +			
   1.721 +			// Retrieve the metrics for each glyph code, one at a time
   1.722 +			TESTNOERROR(err = glyphMetricsArraySingle.Get(*iFont, &iGlyphCodesLatin[index], 1));
   1.723 +			if (KErrNone == err)
   1.724 +				{
   1.725 +				// Compare GetCharacterData() metrics with single RFbsGlyphMetricsArray.
   1.726 +				TUint32 comparison1 = CompareMetrics(charMetrics, glyphMetricsArraySingle[0]); 
   1.727 +				// Compare GetCharacterData() metrics with large RFbsGlyphMetricsArray.
   1.728 +				TUint32 comparison2 = CompareMetrics(charMetrics, glyphMetricsArray[index]);
   1.729 +				// Compare GetCharacterData() metrics with RFbsGlyphDataIterator.
   1.730 +				TUint32 comparison3 = CompareMetrics(charMetrics, iter.Metrics());
   1.731 +				if (comparison1 != 0 || comparison2 != 0 || comparison3 != 0)
   1.732 +					{
   1.733 +					ERR_PRINTF5(_L("Glyphcode %i : Metrics mismatch: %d/%d/%d"), iGlyphCodesLatin[index], comparison1, comparison2, comparison3);
   1.734 +					++numMismatches;
   1.735 +					}
   1.736 +				}
   1.737 +			}
   1.738 +			iter.Close();
   1.739 +			glyphMetricsArray.Close();
   1.740 +			glyphMetricsArraySingle.Close();
   1.741 +			TESTE(iterErr == KErrNotFound, iterErr);
   1.742 +			TEST(numMismatches == 0);
   1.743 +			TEST(index == KNumGlyphCodesLatin);
   1.744 +		}		
   1.745 +	
   1.746 +	__UHEAP_MARKEND;
   1.747 +	}
   1.748 +
   1.749 +/**
   1.750 +@return A series of success/fail booleans as a bitmask. A return value of zero
   1.751 +	indicates all tests passed, a result of 1 indicates the first test case failed, 
   1.752 +	a return of 3 indicates the first and second test failed, and so on.
   1.753 +*/
   1.754 +TUint32 CTFbsGlyphData::CompareMetrics(const TOpenFontCharMetrics& aMetrics1, const TOpenFontCharMetrics& aMetrics2)
   1.755 +	{
   1.756 +	TUint32 result = 0;
   1.757 +	result |= (aMetrics1.Width() == aMetrics2.Width()) ? 0 : (1 << 0);
   1.758 +	result |= (aMetrics1.Height() == aMetrics2.Height()) ? 0 : (1 << 1);
   1.759 +	result |= (aMetrics1.HorizBearingX() == aMetrics2.HorizBearingX()) ? 0 : (1 << 2);
   1.760 +	result |= (aMetrics1.HorizBearingY() == aMetrics2.HorizBearingY()) ? 0 : (1 << 3);
   1.761 +	result |= (aMetrics1.HorizAdvance() == aMetrics2.HorizAdvance()) ? 0 : (1 << 4);
   1.762 +	result |= (aMetrics1.VertBearingX() == aMetrics2.VertBearingX()) ? 0 : (1 << 5);
   1.763 +	result |= (aMetrics1.VertBearingY() == aMetrics2.VertBearingY()) ? 0 : (1 << 6);
   1.764 +	result |= (aMetrics1.VertAdvance() == aMetrics2.VertAdvance()) ? 0 : (1 << 7);
   1.765 +	TRect rect1;
   1.766 +	aMetrics1.GetHorizBounds(rect1);
   1.767 +	TRect rect2;
   1.768 +	aMetrics2.GetHorizBounds(rect2);
   1.769 +	result |= (rect1 == rect2) ? 0 : (1 << 8);
   1.770 +	aMetrics1.GetVertBounds(rect1);
   1.771 +	aMetrics2.GetVertBounds(rect2);
   1.772 +	result |= (rect1 == rect2) ? 0 : (1 << 9);
   1.773 +	return result;
   1.774 +	}
   1.775 +
   1.776 +
   1.777 +/**
   1.778 +@SYMTestCaseID		GRAPHICS-FBSERV-0625
   1.779 +@SYMTestPriority	High
   1.780 +@SYMTestType		UT
   1.781 +@SYMTestStatus		Implemented
   1.782 +@SYMPREQ			PREQ2678
   1.783 +
   1.784 +@SYMTestCaseDesc
   1.785 +	Shows that RFbsGlyphMetricsArray::Get(), and CFont::GetCharacterData() show the same 
   1.786 +	behaviour when asked for metrics for an invalid glyph code when using a	CFbsFont. 
   1.787 +	An invalid glyph code is one for which there is no character equivalent, such as 
   1.788 +	0.
   1.789 +
   1.790 +@SYMTestActions
   1.791 +	i. Call CFont::GetCharacterData() for an invalid glyph code.
   1.792 +	ii. Call RFbsGlyphMetricsArray::Get() for the same invalid glyph code, and either 
   1.793 +		compare the metrics if i. was successful, or check an error code was returned
   1.794 +	
   1.795 +@SYMTestExpectedResults
   1.796 +	If GetCharacterData() is successful, the metrics received from
   1.797 +	RFbsGlyphMetricsArray::Get() and CFont::GetCharacterData()	are the same, otherwise
   1.798 +	RFbsGlyphMetricsArray::Get() should return an error code.
   1.799 +*/
   1.800 +
   1.801 +void CTFbsGlyphData::TestInvalidGlyphCode()
   1.802 +	{
   1.803 +	INFO_PRINTF1(_L("Test behaviour of RFbsGlyphMetricsArray::Get() with invalid glyph code is consistent with GetCharacterData"));
   1.804 +	
   1.805 +	__UHEAP_MARK;
   1.806 +	TInt arrayErr = KErrNone;
   1.807 +	RFbsGlyphMetricsArray glyphMetricsArray;
   1.808 +	TOpenFontCharMetrics charMetrics;
   1.809 +	TSize bitmapSize;
   1.810 +	const TUint8* bitmapData = NULL;
   1.811 +	
   1.812 +	CFont::TCharacterDataAvailability availability = iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
   1.813 +	if (availability == CFont::ENoCharacterData)
   1.814 +		{
   1.815 +		// Some rasterizers fail to return any data for KDejaVuInvalidGlyphCode, therefore
   1.816 +		// rather than compare metrics, make sure RFbsGlyphDataIterator returns an error code.
   1.817 +		WARN_PRINTF1(_L("Rasterizer failed to return data for invalid glyph code; not comparing glyph metrics"));
   1.818 +		arrayErr = glyphMetricsArray.Get(*iFont, &KDejaVuInvalidGlyphCode, 1);
   1.819 +		TESTE(arrayErr != KErrNone, arrayErr);
   1.820 +		}
   1.821 +	else
   1.822 +		{
   1.823 +		TESTNOERROR(arrayErr = glyphMetricsArray.Get(*iFont, &KDejaVuInvalidGlyphCode, 1));
   1.824 +		if (KErrNone == arrayErr)
   1.825 +			{
   1.826 +			iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
   1.827 +			TUint comparisonResult = CompareMetrics(charMetrics, glyphMetricsArray[0]);
   1.828 +			TESTNOERROR( comparisonResult );
   1.829 +			}
   1.830 +		}
   1.831 +	glyphMetricsArray.Close();
   1.832 +
   1.833 +	__UHEAP_MARKEND;
   1.834 +	}
   1.835 +
   1.836 +/**
   1.837 +@SYMTestCaseID		GRAPHICS-FBSERV-0626
   1.838 +@SYMTestPriority	High
   1.839 +@SYMTestType		UT
   1.840 +@SYMTestStatus		Implemented
   1.841 +@SYMPREQ			PREQ2678
   1.842 +
   1.843 +@SYMTestCaseDesc
   1.844 +	Shows that RFbsGlyphMetricsArray::Get() returns with the correct error code when passed
   1.845 +	various combinations of parameters, and preserves the state of the array.
   1.846 +
   1.847 +@SYMTestActions
   1.848 +	Populate the array with a single metrics entry.
   1.849 +	Call RFbsGlyphMetricsArray::Get with the following parameter combinations:
   1.850 +		1. A negative count
   1.851 +		2. A positive count and null glyph code array pointer
   1.852 +		3. A zero count and non-null glyph code array pointer
   1.853 +		4. A zero count and null glyph code array pointer
   1.854 +
   1.855 +@SYMTestExpectedResults
   1.856 +	The following return codes are expected for each call:
   1.857 +		1. KErrArgument
   1.858 +		2. KErrArgument
   1.859 +		3. KErrArgument
   1.860 +		4. KErrArgument	
   1.861 +	For each case the glyph metrics array remains unchanged.
   1.862 +*/
   1.863 +void CTFbsGlyphData::TestGlyphMetricsArrayParameters()
   1.864 +	{
   1.865 +	INFO_PRINTF1(_L("Test the return values of GetGlyphMetrics with different parameters"));
   1.866 +	__UHEAP_MARK;
   1.867 +	TInt arrayErr = KErrNone;
   1.868 +	TOpenFontCharMetrics dummyMetrics;
   1.869 +	
   1.870 +	RFbsGlyphMetricsArray glyphMetricsArray;
   1.871 +	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 1);
   1.872 +	TESTNOERROR(arrayErr);
   1.873 +	TEST(1 == glyphMetricsArray.Count());
   1.874 +	
   1.875 +	// 1. Negative Count
   1.876 +	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, -1);
   1.877 +	TESTE(KErrArgument == arrayErr, arrayErr);
   1.878 +	TEST(1 == glyphMetricsArray.Count());
   1.879 +	
   1.880 +	// 2. Positive Count and NULL Array Pointer
   1.881 +	arrayErr = glyphMetricsArray.Get(*iFont, NULL, 1);
   1.882 +	TESTE(KErrArgument == arrayErr, arrayErr);
   1.883 +	TEST(1 == glyphMetricsArray.Count());
   1.884 +
   1.885 +	// 3. Zero Count & Valid Array Pointer
   1.886 +	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 0);
   1.887 +	TESTE(KErrArgument == arrayErr, arrayErr);
   1.888 +
   1.889 +	// 4. Zero Count & NULL Array Pointer
   1.890 +	arrayErr = glyphMetricsArray.Get(*iFont, NULL, 0);
   1.891 +	TESTE(KErrArgument == arrayErr, arrayErr);
   1.892 +
   1.893 +	glyphMetricsArray.Close();
   1.894 +	__UHEAP_MARKEND;
   1.895 +	}
   1.896 +
   1.897 +/**
   1.898 +@SYMTestCaseID		GRAPHICS-FBSERV-0627
   1.899 +@SYMTestPriority	High
   1.900 +@SYMTestType		UT
   1.901 +@SYMTestStatus		Implemented
   1.902 +@SYMPREQ			PREQ2678
   1.903 +
   1.904 +@SYMTestCaseDesc
   1.905 +	Shows that reusing an RFbsGlyphMetricsArray works correctly.
   1.906 +	In particular when the array is reused and filled with fewer entries
   1.907 +	and when the array is reused and filled with more entries than previously.
   1.908 +	It also shows that when re-using an array that has been populated, memory 
   1.909 +	is not de-allocated if the new array of glyphs is smaller.
   1.910 +
   1.911 +@SYMTestActions
   1.912 +	i. Call RFbsGlyphMetricsArray::Get() for a set of 10 glyph codes.
   1.913 +	ii. Check that the RFbsGlyphMetricsArray has 10 entries.
   1.914 +	iii. Find the size of the heap-cell allocated to the array.
   1.915 +	iii. Call RFbsGlyphMetricsArray::Get() for a set of 5 glyph codes.
   1.916 +	iv. Check that the RFbsGlyphMetricsArray has 5 entries.
   1.917 +	v. Call RFbsGlyphMetricsArray::Get() for a set of 20 glyph codes.
   1.918 +	vi. Check that the RFbsGlyphMetricsArray has 20 entries.
   1.919 +	vii. Call RFbsGlyphMetricsArray::Get() for a set of 0 glyph codes.
   1.920 +	viii. Check that the RFbsGlyphMetricsArray has 0 entries.
   1.921 +	ix. Call RFbsGlyphMetricsArray::Get() for 1 glyph code.
   1.922 +	x. Check that the RFbsGlyphMetricsArray has 1 entries.
   1.923 +	xi. Close the RFbsGlyphMetricsArray.
   1.924 +	xii. Check that the RFbsGlyphMetricsArray has 0 entries.
   1.925 +	During the test check that the size of the heap cell allocated to the array
   1.926 +	does not shrink.
   1.927 +
   1.928 +@SYMTestExpectedResults
   1.929 +	After each call to RFbsGlyphMetricsArray::Get(), the array has the expected number of entries.
   1.930 +*/
   1.931 +void CTFbsGlyphData::TestGlyphMetricsArrayReuse()
   1.932 +	{
   1.933 +	INFO_PRINTF1(_L("Test reuse of array with RFbsGlyphMetricsArray"));
   1.934 +	__UHEAP_MARK;
   1.935 +	
   1.936 +	RFbsGlyphMetricsArray glyphMetricsArray;
   1.937 +
   1.938 +	// Retrieve list of metrics for 10 glyph codes
   1.939 +	TESTNOERROR(glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 10));
   1.940 +	TEST(10 == glyphMetricsArray.Count());
   1.941 +	
   1.942 +	// Find the size of the heap cell allocated for the array.
   1.943 +	TInt arrayHeapCellSize = User::Heap().AllocLen(&glyphMetricsArray[0]);
   1.944 +	
   1.945 +	// Retrieve list of metrics for 5 glyph codes.
   1.946 +	// To ensure that different metrics are returned, use different glyph codes
   1.947 +	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[10], 5));
   1.948 +	TEST(5 == glyphMetricsArray.Count());
   1.949 +	// Check that memory has not been de-allocated for a smaller array.
   1.950 +	TEST(User::Heap().AllocLen(&glyphMetricsArray[0]) == arrayHeapCellSize);
   1.951 +
   1.952 +	// Retrieve list of metrics for 20 glyph codes.
   1.953 +	// To ensure that different metrics are returned, use different glyph codes
   1.954 +	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[15], 20));
   1.955 +	TEST(20 == glyphMetricsArray.Count());
   1.956 +	arrayHeapCellSize = User::Heap().AllocLen(&glyphMetricsArray[0]);
   1.957 +		
   1.958 +	// Retrieve list of metrics for 0 glyph codes.
   1.959 +	TEST(KErrArgument == glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[35], 0));
   1.960 +	// We can't check whether memory has been de-allocated as glyphMetricsArray[0]
   1.961 +	// is null, therefore dereferencing it causes a panic.
   1.962 +
   1.963 +	// Retrieve list of metrics for 1 glyph code.
   1.964 +	// To ensure that different metrics are returned, use different glyph code
   1.965 +	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[35], 1));
   1.966 +	TEST(1 == glyphMetricsArray.Count());
   1.967 +	TEST(User::Heap().AllocLen(&glyphMetricsArray[0]) == arrayHeapCellSize);
   1.968 +	
   1.969 +	// Test that after closing a non-empty array, the array has 0 size.
   1.970 +	glyphMetricsArray.Close();
   1.971 +	TEST(0 == glyphMetricsArray.Count());
   1.972 +	
   1.973 +	__UHEAP_MARKEND;
   1.974 +	}
   1.975 +
   1.976 +/**
   1.977 +@SYMTestCaseID		GRAPHICS-FBSERV-0628
   1.978 +@SYMTestPriority	High
   1.979 +@SYMTestType		UT
   1.980 +@SYMTestStatus		Implemented
   1.981 +@SYMPREQ			PREQ2678
   1.982 +
   1.983 +@SYMTestCaseDesc
   1.984 +	Validates the behaviour of RFbsGlyphDataIterator::Close() in the following use cases:
   1.985 +		1. When called on an iterator instance which has not been opened, has no effect.
   1.986 +		2. When called on an open iterator closes the iterator 
   1.987 +
   1.988 +@SYMTestActions
   1.989 +	Use case 1:
   1.990 +		i. Create an RFbsGlyphDataIterator instance but do not open.
   1.991 +		ii. Call RFbsGlyphDataIterator::Close().
   1.992 +		
   1.993 +	Use case 2:
   1.994 +		i. Create an RFbsGlyphDataIterator instance and call RFbsGlyphDataIterator::Open().
   1.995 +		ii. Call RFbsGlyphDataIterator::Next() to prove the iterator is open.
   1.996 +		iii. Call RFbsGlyphDataIterator::Close().
   1.997 +		iv. Check that RFbsGlyphDataIterator::IsOpen() returns false.
   1.998 +	
   1.999 +@SYMTestExpectedResults
  1.1000 +	Each call to RFbsGlyphDataIterator::IsOpen() returns the expected value.
  1.1001 +*/
  1.1002 +void CTFbsGlyphData::TestGlyphDataIteratorClose()
  1.1003 +	{
  1.1004 +	INFO_PRINTF1(_L("Test closing an RFbsGlyphDataIterator"));
  1.1005 +	__UHEAP_MARK;
  1.1006 +
  1.1007 +	// Use case 1
  1.1008 +	RFbsGlyphDataIterator iter1;
  1.1009 +	iter1.Close();
  1.1010 +
  1.1011 +	// Use case 2
  1.1012 +	RFbsGlyphDataIterator iter2;
  1.1013 +	TESTNOERROR(iter2.Open(*iFont, iGlyphCodesLatin, 1));
  1.1014 +	TInt iterErr = iter2.Next();
  1.1015 +	TESTE(KErrNotFound == iterErr, iterErr);
  1.1016 +	iter2.Close();
  1.1017 +	
  1.1018 +	__UHEAP_MARKEND;
  1.1019 +	}
  1.1020 +
  1.1021 +/**
  1.1022 +@SYMTestCaseID		GRAPHICS-FBSERV-0629
  1.1023 +@SYMTestPriority	High
  1.1024 +@SYMTestType		UT
  1.1025 +@SYMTestStatus		Implemented
  1.1026 +@SYMPREQ			PREQ2678
  1.1027 +
  1.1028 +@SYMTestCaseDesc
  1.1029 +	Show that the sequence of iterations when calling RFbsGlyphDataIterator::Next()
  1.1030 +	matches the order of the array of glyph codes.
  1.1031 +
  1.1032 +@SYMTestActions
  1.1033 +	i. Create an RFbsGlyphDataIterator instance and call RFbsGlyphDataIterator::Open()
  1.1034 +		with an array of different glyph codes.
  1.1035 +	ii. Iterate through all the glyph data.
  1.1036 +		For each iteration check that the glyph code returned from 
  1.1037 +		RFbsGlyphDataIterator::GlyphCode() matches the corresponding glyph code
  1.1038 +		passed into Open().
  1.1039 +
  1.1040 +@SYMTestExpectedResults
  1.1041 +	Each comparison of glyph code should match.
  1.1042 +*/
  1.1043 +void CTFbsGlyphData::TestGlyphDataIteratorSequence()
  1.1044 +	{
  1.1045 +	INFO_PRINTF1(_L("Test the iterator sequence of RFbsGlyphDataIterator"));
  1.1046 +	__UHEAP_MARK;
  1.1047 +	
  1.1048 +	TBool matches = ETrue;
  1.1049 +	TInt index = 0;
  1.1050 +
  1.1051 +	RFbsGlyphDataIterator iter;
  1.1052 +	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1053 +	TESTNOERROR(iterErr);
  1.1054 +	for (; index < KNumGlyphCodesLatin && matches && (iterErr == KErrNone); iterErr = iter.Next(), index++)
  1.1055 +		{
  1.1056 +		if (iter.GlyphCode() != iGlyphCodesLatin[index])
  1.1057 +			{
  1.1058 +			ERR_PRINTF4(_L("Failed at iteration %d: wanted %d, got %d"), index, iGlyphCodesLatin[index], iter.GlyphCode());
  1.1059 +			matches = EFalse;
  1.1060 +			}
  1.1061 +		}
  1.1062 +	iter.Close();
  1.1063 +	TESTE(iterErr == KErrNotFound, iterErr);
  1.1064 +	TEST(matches);
  1.1065 +	TEST(index == KNumGlyphCodesLatin);
  1.1066 +	iter.Close();
  1.1067 +
  1.1068 +	__UHEAP_MARKEND;
  1.1069 +	}
  1.1070 +
  1.1071 +/**
  1.1072 +@SYMTestCaseID		GRAPHICS-FBSERV-0632
  1.1073 +@SYMTestPriority	High
  1.1074 +@SYMTestType		UT
  1.1075 +@SYMTestStatus		Implemented
  1.1076 +@SYMPREQ			PREQ2678
  1.1077 +
  1.1078 +@SYMTestCaseDesc
  1.1079 +	Ensure it is possible to reuse a closed iterator on another CFbsFont.
  1.1080 +	
  1.1081 +@SYMTestActions
  1.1082 +	i. Open an RFbsGlyphDataIterator with sample data.
  1.1083 +	ii. Iterate through until the end of the iterator has been reached by calling 
  1.1084 +		Next() on the final element.
  1.1085 +	iii. Re-open the same RFbsGlyphDataIterator with sample data on a different CFbsFont.
  1.1086 +	iv. Iterate through a second time until the end has been reached by calling Next()
  1.1087 +		on the final element.
  1.1088 +	v. Close the iterator.
  1.1089 +	vi. During both iterations the bitmap data returned and metrics are compared with
  1.1090 +		the equivalent from GetCharacterData().
  1.1091 +
  1.1092 +@SYMTestExpectedResults
  1.1093 +	The iterator should be opened successfully for both fonts and the data returned
  1.1094 +	should match the data from GetCharacterData().
  1.1095 +*/
  1.1096 +void CTFbsGlyphData::TestGlyphDataIteratorMultipleUsesOnMultipleFonts()
  1.1097 +	{
  1.1098 +	INFO_PRINTF1(_L("Reuse a closed iterator on a second CFbsFont"));
  1.1099 +	__UHEAP_MARK;
  1.1100 +	
  1.1101 +	const TUint8* bitmapData;
  1.1102 +	TSize bitmapSize;
  1.1103 +	TOpenFontCharMetrics charMetrics;
  1.1104 +	RFbsGlyphDataIterator iter;
  1.1105 +	
  1.1106 +	// Array of fonts to iterate through.
  1.1107 +	CFbsFont* font[2] = {iFont, iFont2};
  1.1108 +	
  1.1109 +	for (TInt fontId = 0; fontId < 2; fontId++)
  1.1110 +		{
  1.1111 +		// On the first iteration, open and use a font until all glyphs have been iterated through.
  1.1112 +		// On second iteration, use the same iterator on a different font and repeat.
  1.1113 +        CFbsFont* currentFont = font[fontId];
  1.1114 +
  1.1115 +		//Open the iterator on the first font and compare the returned bitmaps against GetCharacterData
  1.1116 +		TInt iterErr = iter.Open(*currentFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1117 +		TESTNOERROR(iterErr);
  1.1118 +		TFontSpec fontSpec = currentFont->FontSpecInTwips();
  1.1119 +		
  1.1120 +		TInt index = 0;
  1.1121 +		for (; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin); iterErr = iter.Next(), ++index)
  1.1122 +			{
  1.1123 +			currentFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
  1.1124 +			
  1.1125 +			TESTNOERROR(CompareMetrics(charMetrics, iter.Metrics()));
  1.1126 +			if (bitmapSize == TSize(0, 0))
  1.1127 +				{
  1.1128 +				TEST(bitmapSize == iter.Rect().Size());
  1.1129 +				}
  1.1130 +			else
  1.1131 +				{
  1.1132 +				// Compare images.
  1.1133 +				TBool match = EFalse;
  1.1134 +				RSgImage characterDataImage;
  1.1135 +				TInt err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
  1.1136 +				if (err == KErrNone)
  1.1137 +					{
  1.1138 +					err = CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), match);
  1.1139 +					}
  1.1140 +				characterDataImage.Close();
  1.1141 +				if (err != KErrNone)
  1.1142 +					{
  1.1143 +					TESTNOERROR(err);
  1.1144 +					break;
  1.1145 +					}
  1.1146 +				TEST(match);
  1.1147 +				}		
  1.1148 +			}
  1.1149 +		iter.Close();
  1.1150 +		TESTE(iterErr == KErrNotFound, iterErr);
  1.1151 +		TEST(index == KNumGlyphCodesLatin);
  1.1152 +		}
  1.1153 +	
  1.1154 +	__UHEAP_MARKEND;
  1.1155 +	}
  1.1156 +
  1.1157 +/**
  1.1158 +@SYMTestCaseID		GRAPHICS-FBSERV-0633
  1.1159 +@SYMTestPriority	High
  1.1160 +@SYMTestType		UT
  1.1161 +@SYMTestStatus		Implemented
  1.1162 +@SYMPREQ			PREQ2678
  1.1163 +
  1.1164 +@SYMTestCaseDesc
  1.1165 +	Check that for various Latin fonts, the images of the glyphs stored on the 
  1.1166 +	RSgImage matches those provided by GetCharacterData().
  1.1167 +
  1.1168 +@SYMTestActions
  1.1169 +	Create a selection of fonts, using various typefaces, sizes and bitmap types.
  1.1170 +	For each font:
  1.1171 +	i. Open the RFbsGlyphDataIterator and iterate each glyph.
  1.1172 +	ii. For each glyph, call GetCharacterData() with the expected glyph code.
  1.1173 +	iii. Convert the character data to an RSgImage.
  1.1174 +	iv. Perform a comparison between the character RSgImage and the iterator 
  1.1175 +		image. 
  1.1176 +	v. After all iterations, close the iterator and check all expected glyphs
  1.1177 +		were iterated through.
  1.1178 +
  1.1179 +@SYMTestExpectedResults
  1.1180 +	All glyph images should match.
  1.1181 +*/
  1.1182 +void CTFbsGlyphData::TestGlyphDataIteratorImageValidity()
  1.1183 +	{
  1.1184 +	INFO_PRINTF1(_L("Test the glyph images of the iterator match GetCharacterData()"));
  1.1185 +	__UHEAP_MARK;
  1.1186 +	
  1.1187 +	const TInt KNumFonts = 20;
  1.1188 +	
  1.1189 +	// Create a new typeface store for this test so that heap checking will not
  1.1190 +	// be affected by cached CFbsFonts.
  1.1191 +	CFbsTypefaceStore* typefaceStore = NULL;
  1.1192 +	TRAPD(err, typefaceStore = CFbsTypefaceStore::NewL(NULL));
  1.1193 +	if (err != KErrNone)
  1.1194 +		{
  1.1195 +		ERR_PRINTF1(_L("Failed to construct typeface store. Test aborted."));
  1.1196 +		__UHEAP_RESET;
  1.1197 +		iStep->SetTestStepResult(EFail);
  1.1198 +		return;
  1.1199 +		}
  1.1200 +	
  1.1201 +	for (TInt font = 0; font < KNumFonts; ++font)
  1.1202 +		{
  1.1203 +		// Use either a pre-created bitmap-font TFontSpec, or generate a Deja-vu one.
  1.1204 +		TFontSpec fontSpec = GenerateDejaVuFontSpec(font);
  1.1205 +		CFbsFont* latinFont = NULL;
  1.1206 +		TESTNOERROR(typefaceStore->GetNearestFontToDesignHeightInPixels((CFont*&)latinFont, fontSpec));	
  1.1207 +		
  1.1208 +		fontSpec = latinFont->FontSpecInTwips();
  1.1209 +		InfoPrintFontSpec(*latinFont);
  1.1210 +				
  1.1211 +		RFbsGlyphDataIterator iter;
  1.1212 +		TInt iterErr = iter.Open(*latinFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1213 +		TESTNOERROR(iterErr);
  1.1214 +
  1.1215 +		err = KErrNone;
  1.1216 +		TInt index = 0;
  1.1217 +		TInt numMismatches = 0;
  1.1218 +		// For each iteration, get the character data of the expected glyph.
  1.1219 +		// Create RSgImage from character data, and compare iter image with constructed image.
  1.1220 +		for (; (iterErr == KErrNone) && (err == KErrNone) && (index < KNumGlyphCodesLatin); (iterErr = iter.Next()), ++index)
  1.1221 +			{
  1.1222 +			TBool glyphMatches = ETrue;
  1.1223 +			const RSgImage& iteratorImage = iter.Image();
  1.1224 +
  1.1225 +			const TUint8* bitmapData = NULL;
  1.1226 +			TSize bitmapSize;
  1.1227 +			TOpenFontCharMetrics metrics;
  1.1228 +			TInt characterDataAvailability = latinFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
  1.1229 +			if (bitmapSize == TSize(0, 0))
  1.1230 +				{
  1.1231 +				glyphMatches = (bitmapSize == iter.Rect().Size());
  1.1232 +				}
  1.1233 +			else
  1.1234 +				{
  1.1235 +				RSgImage characterDataImage;
  1.1236 +				TESTNOERROR(CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage));
  1.1237 +				err = CompareSgImages(iEGL, iteratorImage, iter.Rect(), characterDataImage, TRect(bitmapSize), glyphMatches);
  1.1238 +				characterDataImage.Close();
  1.1239 +				}
  1.1240 +			if (err == KErrNone && !glyphMatches)
  1.1241 +				{
  1.1242 +				ERR_PRINTF2(_L("Glyphcode %i : Image mismatch"), iGlyphCodesLatin[index]);
  1.1243 +				++numMismatches;
  1.1244 +				}
  1.1245 +			}
  1.1246 +		iter.Close();
  1.1247 +		TESTNOERROR(err);
  1.1248 +		TESTE(iterErr == KErrNotFound, iterErr);
  1.1249 +		TEST(index == KNumGlyphCodesLatin);	
  1.1250 +		TEST(numMismatches == 0);
  1.1251 +		typefaceStore->ReleaseFont(latinFont);
  1.1252 +		}
  1.1253 +	delete typefaceStore;
  1.1254 +	__UHEAP_MARKEND;
  1.1255 +	}
  1.1256 +
  1.1257 +/**
  1.1258 +@SYMTestCaseID      GRAPHICS-FBSERV-0634
  1.1259 +@SYMTestPriority    High
  1.1260 +@SYMTestType        UT
  1.1261 +@SYMTestStatus      Implemented
  1.1262 +@SYMPREQ            PREQ2678
  1.1263 +
  1.1264 +@SYMTestCaseDesc
  1.1265 +	To ensure that if the glyph image iterator has a current invalid 
  1.1266 +	character code, the SgImage returned by the iterator will match 
  1.1267 +	to the image obtained from the GetCharacterData() function
  1.1268 +@SYMTestActions
  1.1269 +	i. Retrieve bitmap data and metrics by using GetCharacterData().
  1.1270 +	ii. Open a glyph data iterator passing an invalid character code.
  1.1271 +	iii. If i. was unsuccessful, check that opening the iterator returned
  1.1272 +		an error code and skip to ix.
  1.1273 +	iv. Create SgImage from bitmap data.
  1.1274 +	v. Get SgImage from the glyph data iterator.
  1.1275 +	vi. Compare SgImages obtained on iv and v steps.
  1.1276 +	vii. Get font metrics from the glyph data iterator.
  1.1277 +	viii. Compare metrics obtained on i and vii steps.
  1.1278 +	vii. Close the iterator.
  1.1279 +
  1.1280 +@SYMTestExpectedResults
  1.1281 +	If the request to get the character data failed, the return value of 
  1.1282 +	RFbsGlyphDataIterator::Open() must not be KErrNone.
  1.1283 +	Otherwise, images obtained from the iterator and GetCharacterData() should
  1.1284 +	match.
  1.1285 +*/
  1.1286 +void CTFbsGlyphData::TestGlyphDataIteratorOpenInvalidCode()
  1.1287 +	{
  1.1288 +	INFO_PRINTF1(_L("Ensure that the image returned by the iterator will \
  1.1289 +match to the image obtained from GetCharacterData() if character code is invalid"));
  1.1290 +	__UHEAP_MARK;
  1.1291 +
  1.1292 +	const TUint8* bitmapData = NULL;
  1.1293 +	TSize bitmapSize;
  1.1294 +	TOpenFontCharMetrics metrics;
  1.1295 +	const TFontSpec fontSpec = iFont->FontSpecInTwips();
  1.1296 +	CFont::TCharacterDataAvailability availability = iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
  1.1297 +
  1.1298 +	RFbsGlyphDataIterator iter;
  1.1299 +	TInt err = iter.Open(*iFont, &KDejaVuInvalidGlyphCode, 1);
  1.1300 +	if (availability == CFont::ENoCharacterData)
  1.1301 +		{
  1.1302 +		// Some rasterizers fail to return any data for KDejaVuInvalidGlyphCode, therefore
  1.1303 +		// rather than compare image contents, make sure RFbsGlyphDataIterator returns an error code.
  1.1304 +		WARN_PRINTF1(_L("Rasterizer failed to return data for invalid glyph code; not comparing image contents"));
  1.1305 +		TESTE(err != KErrNone, err);
  1.1306 +		}
  1.1307 +	else
  1.1308 +		{
  1.1309 +		TESTNOERROR(err);
  1.1310 +		if (err == KErrNone)
  1.1311 +			{
  1.1312 +			TBool glyphMatches = EFalse;
  1.1313 +			if (bitmapSize == TSize(0, 0))
  1.1314 +				{
  1.1315 +				glyphMatches = (bitmapSize == iter.Rect().Size());
  1.1316 +				}
  1.1317 +			else
  1.1318 +				{
  1.1319 +				RSgImage characterDataImage;
  1.1320 +				TESTNOERROR(CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage));
  1.1321 +				TESTNOERROR(CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), glyphMatches));
  1.1322 +				characterDataImage.Close();
  1.1323 +				}
  1.1324 +			TESTNOERROR(CompareMetrics(metrics, iter.Metrics()));
  1.1325 +			TEST(glyphMatches);
  1.1326 +			}
  1.1327 +		}
  1.1328 +	iter.Close();
  1.1329 +
  1.1330 +	__UHEAP_MARKEND;
  1.1331 +	}
  1.1332 +
  1.1333 +
  1.1334 +/**
  1.1335 +@SYMTestCaseID      GRAPHICS-FBSERV-0636
  1.1336 +@SYMTestPriority    High
  1.1337 +@SYMTestType        UT
  1.1338 +@SYMTestStatus      Implemented
  1.1339 +@SYMPREQ            PREQ2678
  1.1340 +
  1.1341 +@SYMTestCaseDesc
  1.1342 +	To ensure that opening the glyph data iterator which has already been opened with the same font
  1.1343 +	has no effect on the state of the iterator.
  1.1344 +@SYMTestActions
  1.1345 +	i. Open glyph data iterator on 2 glyph codes.
  1.1346 +	ii. Try to open the glyph data iterator again on the same font.
  1.1347 +	iii. Call RFbsGlyphDataIterator::Next() on the iterator and check error code, making the last
  1.1348 +		glyph code the current iteration.
  1.1349 +	iv. Call RFbsGlyphDataIterator::Next() again.
  1.1350 +@SYMTestExpectedResults
  1.1351 +	The second attempt to open the glyph data iterator will result an error with code KErrInUse.
  1.1352 +	The last two calls to RFbsGlyphDataIterator::Next() should return KErrNone and KErrNotFound
  1.1353 +	respectively, showing the iterator was not modified when the call to Open() failed.
  1.1354 +*/
  1.1355 +void CTFbsGlyphData::TestGlyphDataIteratorOpenTwice()
  1.1356 +	{
  1.1357 +	INFO_PRINTF1(_L("Ensure that opening the glyph data iterator which has already been opened with the same font has no effect"));
  1.1358 +	__UHEAP_MARK;
  1.1359 +
  1.1360 +	RFbsGlyphDataIterator iter;
  1.1361 +	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 2);
  1.1362 +	TESTNOERROR(iterErr);
  1.1363 +	
  1.1364 +	iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1365 +	TESTE(iterErr == KErrInUse, iterErr);
  1.1366 +	iterErr = iter.Next();
  1.1367 +	TESTNOERROR(iterErr);
  1.1368 +	iterErr = iter.Next();
  1.1369 +	TESTE(iterErr == KErrNotFound, iterErr);
  1.1370 +	iter.Close();
  1.1371 +
  1.1372 +	__UHEAP_MARKEND;
  1.1373 +	}
  1.1374 +
  1.1375 +/**
  1.1376 +@SYMTestCaseID      GRAPHICS-FBSERV-0637
  1.1377 +@SYMTestPriority    High
  1.1378 +@SYMTestType        UT
  1.1379 +@SYMTestStatus      Implemented
  1.1380 +@SYMPREQ            PREQ2678
  1.1381 +
  1.1382 +@SYMTestCaseDesc
  1.1383 +	To ensure that opening the glyph data iterator which has already been opened with different font
  1.1384 +	has no effect on the state of the iterator.
  1.1385 +@SYMTestActions
  1.1386 +	i. Open glyph data iterator on an 2 glyph codes
  1.1387 +	ii. Try to open the glyph data iterator again with a different font.
  1.1388 +	iii. Call RFbsGlyphDataIterator::Next() on the iterator and check error code, making the last
  1.1389 +		glyph code the current iteration.
  1.1390 +	iv. Call RFbsGlyphDataIterator::Next() again.
  1.1391 +@SYMTestExpectedResults
  1.1392 +	The second attempt to open the glyph data iterator will result an error with code KErrInUse.
  1.1393 +	The Next() call after this should return KErrNone, signifying the iterator is still open.
  1.1394 +	The last Next() call should return KErrNotFound, signifying the iterator has iterated 
  1.1395 +	through the two original glyph codes.
  1.1396 +*/
  1.1397 +void CTFbsGlyphData::TestGlyphDataIteratorOpenTwiceWithDifferentFonts()
  1.1398 +	{
  1.1399 +	INFO_PRINTF1(_L("Ensure that opening the glyph data iterator which has already been opened with different font has no effect"));
  1.1400 +	__UHEAP_MARK;
  1.1401 +
  1.1402 +	RFbsGlyphDataIterator iter;
  1.1403 +	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 2);
  1.1404 +	TESTNOERROR(iterErr);
  1.1405 +
  1.1406 +	iterErr = iter.Open(*iFont2, iGlyphCodesLatin, 2);
  1.1407 +	TESTE(iterErr == KErrInUse, iterErr);
  1.1408 +	iterErr = iter.Next();
  1.1409 +	TESTNOERROR(iterErr);
  1.1410 +	iterErr = iter.Next();
  1.1411 +	TESTE(iterErr == KErrNotFound, iterErr);
  1.1412 +	iter.Close();
  1.1413 +
  1.1414 +	__UHEAP_MARKEND;
  1.1415 +	}
  1.1416 +
  1.1417 +/**
  1.1418 +@SYMTestCaseID      GRAPHICS-FBSERV-0638
  1.1419 +@SYMTestPriority    High
  1.1420 +@SYMTestType        UT
  1.1421 +@SYMTestStatus      Implemented
  1.1422 +@SYMPREQ            PREQ2678
  1.1423 +
  1.1424 +@SYMTestCaseDesc
  1.1425 +	To ensure that opening of glyph data iterator with the font greater than 
  1.1426 +	2048 by 2048 will not be supported 
  1.1427 +@SYMTestActions
  1.1428 +	i. Create font with the height greater than 2048
  1.1429 +	ii. Try to open the glyph data iterator with the font created on previous step
  1.1430 +	iii Release the font
  1.1431 +@SYMTestExpectedResults
  1.1432 +	Must fail with error code KErrTooBig
  1.1433 +*/
  1.1434 +void CTFbsGlyphData::TestGlyphDataIteratorOpenTooBigFont()
  1.1435 +	{
  1.1436 +	INFO_PRINTF1(_L("To ensure that opening of glyph data iterator with the font greater than 2048X2048 will not be supported"));
  1.1437 +	__UHEAP_MARK;
  1.1438 +
  1.1439 +	CFbsFont* bigFont;
  1.1440 +	const TInt maxHeight = 2048;
  1.1441 +	const TInt maxHeightLimit = maxHeight + 20; //max size after we stop trying to create the font
  1.1442 +	// the loop below will guarantee that if the font with the size greater than 2048 is available it will be created
  1.1443 +	for(TInt height = maxHeight + 1; height < maxHeightLimit; height++)
  1.1444 +		{
  1.1445 +		TESTNOERROR(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)bigFont, TFontSpec(KTypefaceName, height)));
  1.1446 +		TInt realHeight = bigFont->FontMaxHeight();
  1.1447 +		if(realHeight > maxHeight)
  1.1448 +			{
  1.1449 +			break;
  1.1450 +			}
  1.1451 +		iTs->ReleaseFont(bigFont);
  1.1452 +		bigFont = NULL;
  1.1453 +		}
  1.1454 +
  1.1455 +	if (bigFont)
  1.1456 +		{
  1.1457 +		RFbsGlyphDataIterator iter;
  1.1458 +		TInt iterErr = iter.Open(*bigFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1459 +		TESTE(iterErr == KErrTooBig, iterErr);
  1.1460 +		iTs->ReleaseFont(bigFont); 
  1.1461 +		}
  1.1462 +	else
  1.1463 +		{
  1.1464 +		//It is legitimate to fail to create the font, as there are no requirements for the rasterizer here to support such big font. 
  1.1465 +		//In this case we will skip the test.
  1.1466 +		WARN_PRINTF1(_L("Failed to create font with height greater than 2048"));
  1.1467 +		}
  1.1468 +
  1.1469 +	__UHEAP_MARKEND;
  1.1470 +	}
  1.1471 +
  1.1472 +
  1.1473 +
  1.1474 +
  1.1475 +/**
  1.1476 +@SYMTestCaseID      GRAPHICS-FBSERV-0640
  1.1477 +@SYMTestPriority    High
  1.1478 +@SYMTestType        UT
  1.1479 +@SYMTestStatus      Implemented
  1.1480 +@SYMPREQ            PREQ2678
  1.1481 +
  1.1482 +@SYMTestCaseDesc
  1.1483 +	To ensure that the glyph data iterator processes wrong arguments correctly
  1.1484 +@SYMTestActions
  1.1485 +	i. Try to open the glyph data iterator with the negative count passed in
  1.1486 +	ii. Try to open the glyph data iterator with the positive count and NULL 
  1.1487 +	glyph code array pointer passed in
  1.1488 +	iii. Try to open the glyph data iterator with a valid glyph code array and 
  1.1489 +	count equal to zero
  1.1490 +@SYMTestExpectedResults
  1.1491 +	At all steps the returned value is set to KErrArgument.
  1.1492 +*/
  1.1493 +void CTFbsGlyphData::TestGlyphDataIteratorOpenWithWrongArgument()
  1.1494 +	{
  1.1495 +	INFO_PRINTF1(_L("To ensure that the glyph data iterator processes wrong arguments correctly"));
  1.1496 +	__UHEAP_MARK;
  1.1497 +
  1.1498 +	RFbsGlyphDataIterator iter;
  1.1499 +	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, -1);
  1.1500 +	TESTE(iterErr == KErrArgument, iterErr);
  1.1501 +	
  1.1502 +	iterErr = iter.Open(*iFont, NULL, 1);
  1.1503 +	TESTE(iterErr == KErrArgument, iterErr);
  1.1504 +	
  1.1505 +	iterErr = iter.Open(*iFont, iGlyphCodesLatin, 0);
  1.1506 +	TESTE(iterErr == KErrArgument, iterErr);
  1.1507 +	
  1.1508 +	__UHEAP_MARKEND;
  1.1509 +	}
  1.1510 +
  1.1511 +/**
  1.1512 +@SYMTestCaseID      GRAPHICS-FBSERV-0641
  1.1513 +@SYMTestPriority    High
  1.1514 +@SYMTestType        UT
  1.1515 +@SYMTestStatus      Implemented
  1.1516 +@SYMPREQ            PREQ2678
  1.1517 +
  1.1518 +@SYMTestCaseDesc
  1.1519 +	To ensure that all allocated RSgImages were released after the
  1.1520 +	glyph data iterator has been opened and closed multiple times.
  1.1521 +
  1.1522 +@SYMTestActions
  1.1523 +	i. Retrieve MSgDriver_Test interface from the SgDriver
  1.1524 +	ii. Mark alloc start and obtain resorce count from the interface
  1.1525 +	iii. Iterate through glyph data by calling RFbsGlyphDataIterator::Next() 
  1.1526 +	iv. Retrieve SgImage from the glyph data iterator instance
  1.1527 +	v. Repeate steps iii and iv multiple times
  1.1528 +	vi. Release font
  1.1529 +	vii.  Mark alloc end and obtain resorce count from the interface
  1.1530 +
  1.1531 +@SYMTestExpectedResults
  1.1532 +	Resorce count at the end matches resorce count at the beginning. 
  1.1533 +*/
  1.1534 +void CTFbsGlyphData::TestGlyphDataIteratorImageMemoryLeak()
  1.1535 +	{
  1.1536 +	__UHEAP_MARK;
  1.1537 +	
  1.1538 +	MSgDriver_Test* sgDriverTestInterface = NULL; 
  1.1539 +	TInt err = iSgDriver.GetInterface(sgDriverTestInterface);
  1.1540 +	if(err != KErrNone)
  1.1541 +		{
  1.1542 +		__UHEAP_MARKEND;
  1.1543 +		WARN_PRINTF2(_L("Failed to obtain MSgDriver_Test interface with error code: %d, the test will be skipped"), err);
  1.1544 +		return;
  1.1545 +		}
  1.1546 +
  1.1547 +	TEST(sgDriverTestInterface != NULL);
  1.1548 +	sgDriverTestInterface->AllocMarkStart();
  1.1549 +
  1.1550 +	MSgDriver_Profiling* sgDriverProfilInterface = NULL;
  1.1551 +	err = iSgDriver.GetInterface(sgDriverProfilInterface);
  1.1552 +	if(err != KErrNone)
  1.1553 +		{
  1.1554 +		sgDriverTestInterface->AllocMarkEnd(0);
  1.1555 +		__UHEAP_MARKEND;
  1.1556 +		WARN_PRINTF2(_L("Failed to obtain MSgDriver_Profiling interface with error code: %d, the test will be skipped"), err);
  1.1557 +		return;
  1.1558 +		}
  1.1559 +	const TInt resCount = sgDriverProfilInterface->LocalResourceCount();
  1.1560 +
  1.1561 +	CFbsFont* font = NULL;
  1.1562 +	err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KTypefaceName, 15));
  1.1563 +	TESTNOERROR(err);
  1.1564 +	if(err != KErrNone)
  1.1565 +		{
  1.1566 +		__UHEAP_MARKEND;
  1.1567 +		return;
  1.1568 +		}
  1.1569 +
  1.1570 +	for (TInt ii = 0; ii < 10; ii++)
  1.1571 +		{
  1.1572 +		TInt index = 0;
  1.1573 +		RFbsGlyphDataIterator iter;
  1.1574 +		TInt iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1575 +		TESTNOERROR(iterErr);
  1.1576 +		for (; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin); iterErr = iter.Next(), ++index)
  1.1577 +			{
  1.1578 +			const RSgImage& image = iter.Image();
  1.1579 +			}
  1.1580 +		iter.Close();
  1.1581 +		TEST(index == KNumGlyphCodesLatin);
  1.1582 +		TESTE(iterErr == KErrNotFound, iterErr);
  1.1583 +		}
  1.1584 +	iTs->ReleaseFont(font);
  1.1585 +	const TInt resCountEnd = sgDriverProfilInterface->LocalResourceCount();
  1.1586 +	TEST(resCountEnd == resCount);
  1.1587 +	sgDriverTestInterface->AllocMarkEnd(0);
  1.1588 +
  1.1589 +	__UHEAP_MARKEND;
  1.1590 +	}
  1.1591 +
  1.1592 +/**
  1.1593 +@SYMTestCaseID      GRAPHICS-FBSERV-0659
  1.1594 +@SYMTestPriority    Med
  1.1595 +@SYMTestType        UT
  1.1596 +@SYMTestStatus      Implemented
  1.1597 +@SYMPREQ            PREQ2678
  1.1598 +
  1.1599 +@SYMTestCaseDesc
  1.1600 +	Uses the RFbsGlyphDataIterator to render a large amount of unique glyphs, at a very large 
  1.1601 +	size, to ensure that if graphics memory runs out while the iterator is in use, eviction 
  1.1602 +	takes place and does not corrupt the glyph images in any way.
  1.1603 +
  1.1604 +@SYMTestActions
  1.1605 +	i. Create a large CFbsFont from the typeface store (size 100+)
  1.1606 +	ii. Simulate a low graphics-memory situation by creating enough RSgImages to fill the memory,
  1.1607 +		releasing one image in order to allow some small amount for the test.
  1.1608 +	iii. Open a RFbsGlyphDataIterator on the font, using a large array of unique glyph codes.
  1.1609 +	iv. Iterate through the glyphs, comparing each returned SgImage against the system-memory
  1.1610 +		representation of the glyph as returned by CFont::GetCharacterData().
  1.1611 +	v. Check for errors and mismatches, and release all images created by ii.
  1.1612 +	
  1.1613 +@SYMTestExpectedResults
  1.1614 +	At each iteration, each glyph should match in size and contents. 
  1.1615 +*/
  1.1616 +void CTFbsGlyphData::TestGlyphDataIteratorLargeFontStress()
  1.1617 +	{
  1.1618 +	INFO_PRINTF1(_L("Stress test using a RFbsGlyphDataIterator with a large font"));
  1.1619 +#ifdef __WINS__
  1.1620 +	// Cannot run test on emulator reliably - this is because on emulator
  1.1621 +	// system-memory is used for RSgImages, so using up RSgImage memory may 
  1.1622 +	// cause heap-allocation failures unrelated to the area being tested. 
  1.1623 +	// This test is specifically testing the behaviour when running out of
  1.1624 +	// RSgImage-based memory (i.e. graphics memory), but on emulator this 
  1.1625 +	// will cause a failed allocation anywhere.
  1.1626 +	INFO_PRINTF1(_L("Skipping test on emulator..."));
  1.1627 +#else
  1.1628 +	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM"));
  1.1629 +	TEST(EFalse);
  1.1630 +/*	__UHEAP_MARK;
  1.1631 +
  1.1632 +	const TInt KFontSize = 128;
  1.1633 +
  1.1634 +	CFbsFont* font;
  1.1635 +	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KMonoTypefaceName, KFontSize));
  1.1636 +	TESTNOERROR(err);
  1.1637 +	// Output the actual fontspec used in the test.
  1.1638 +	InfoPrintFontSpec(*font);
  1.1639 +	
  1.1640 +	// Create 2 buffers for use in comparing SgImages so that we don't run out 
  1.1641 +	// of system memory through allocating memory in the test
  1.1642 +	TInt maxFontWidth = font->MaxCharWidthInPixels();
  1.1643 +	TInt maxFontHeight = font->HeightInPixels();
  1.1644 +	iTempBuf1 = (TUint8*) User::AllocZ(maxFontWidth * maxFontHeight);
  1.1645 +	iTempBuf2 = (TUint8*) User::AllocZ(maxFontWidth * maxFontHeight);
  1.1646 +
  1.1647 +	// In order for the image comparisons to have enough memory to perform, keep 
  1.1648 +	// one large RSgImage which is created before the rest of the graphics memory 
  1.1649 +	// is filled.  This image can then be closed before doing the image comparison 
  1.1650 +	// and recreated after the image comparison to ensure that the graphics 
  1.1651 +	// memory is full.  Without this image, the image comparison could fail with 
  1.1652 +	// out of memory and the test would fail. 
  1.1653 +	RSgImage tempImage;
  1.1654 +	TESTNOERROR(tempImage.Create(TSgImageInfo(TSize(1000, 1000), ESgPixelFormatA_8, ESgUsageBitOpenVgImage)));
  1.1655 +
  1.1656 +	TFontSpec actualFontSpec;
  1.1657 +	actualFontSpec = font->FontSpecInTwips();
  1.1658 +	
  1.1659 +	// Create RSgImages from character data independently from using iterator.
  1.1660 +	// These will be used for comparing with RSgImages retrieved from iterator.
  1.1661 +	RArray <RSgImage> sgImageFromCharDataArray;
  1.1662 +	TInt index = 0;
  1.1663 +	for(; (index < KNumGlyphCodesLatin) && (err == KErrNone); ++index)
  1.1664 +		{
  1.1665 +		RSgImage characterDataSgImage;
  1.1666 +		TInt err = KErrNone;
  1.1667 +		const TUint8* bitmapData = NULL;
  1.1668 +		TSize bitmapSize;
  1.1669 +		TOpenFontCharMetrics metrics;
  1.1670 +		font->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
  1.1671 +
  1.1672 +		if (bitmapSize != TSize(0, 0))
  1.1673 +			{
  1.1674 +			err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, actualFontSpec.iFontStyle.BitmapType(), characterDataSgImage, iTempBuf1, iTempBuf2);
  1.1675 +			}
  1.1676 +		if (KErrNone == err)
  1.1677 +			{
  1.1678 +			err = sgImageFromCharDataArray.Append(characterDataSgImage);
  1.1679 +			}
  1.1680 +		}
  1.1681 +	TESTNOERROR(err);
  1.1682 +	TEST(index == KNumGlyphCodesLatin);
  1.1683 +
  1.1684 +	// Simulate low OOGM situation by creating many RSgImages until out of memory.
  1.1685 +	RArray <RSgImage> sgImageArray;
  1.1686 +	if (err == KErrNone)
  1.1687 +		{
  1.1688 +		TESTNOERROR(NearlyFillGraphicsMemoryWithImages(TSize(256, 256), sgImageArray));
  1.1689 +		}
  1.1690 +	
  1.1691 +	// Open Iterator on long string of data...
  1.1692 +	RFbsGlyphDataIterator iter;
  1.1693 +	TInt iterErr = KErrNone;
  1.1694 +	if (err == KErrNone)
  1.1695 +		{
  1.1696 +		iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1697 +		TESTNOERROR(iterErr);
  1.1698 +		}
  1.1699 +
  1.1700 +	// For each glyph, compare it to the system-memory version from GetCharacterData().
  1.1701 +	TInt numMismatches = 0;
  1.1702 +	for(index = 0; (iterErr == KErrNone) && (index < sgImageFromCharDataArray.Count()) && (err == KErrNone); iterErr = iter.Next(), ++index)
  1.1703 +		{
  1.1704 +		const TUint8* bitmapData = NULL;
  1.1705 +		TSize bitmapSize;
  1.1706 +		TOpenFontCharMetrics metrics;
  1.1707 +		font->GetCharacterData(iter.GlyphCode() | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
  1.1708 +
  1.1709 +		if (iter.Rect().Size() == TSize(0, 0))
  1.1710 +			{
  1.1711 +			numMismatches += (bitmapSize != TSize(0, 0)) ? 1 : 0;
  1.1712 +			}
  1.1713 +		else
  1.1714 +			{
  1.1715 +			// Free up memory so that the image compariso succeeds
  1.1716 +			// Release all the images used to simulate OOGM.
  1.1717 +			for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
  1.1718 +				{
  1.1719 +				sgImageArray[i].Close();
  1.1720 +				sgImageArray.Remove(i);
  1.1721 +				}
  1.1722 +			
  1.1723 +			TBool match = ETrue;
  1.1724 +			err = CompareSgImages(iEGL, sgImageFromCharDataArray[index], TRect(bitmapSize), iTempBuf1, iter.Image(), iter.Rect(), iTempBuf2, match);
  1.1725 +			if (err == KErrNone && !match)
  1.1726 +				{
  1.1727 +				++numMismatches;
  1.1728 +				}
  1.1729 +			TInt result = FillGraphicsMemoryWithImages(TSize(256, 256), sgImageArray);
  1.1730 +			TESTE(result == KErrNoMemory || result == KErrNoGraphicsMemory, result);
  1.1731 +			}
  1.1732 +		}
  1.1733 +	iter.Close();
  1.1734 +
  1.1735 +	// Release all images created from character data.
  1.1736 +	for (TInt i = sgImageFromCharDataArray.Count()-1; i >= 0; --i)
  1.1737 +		{
  1.1738 +		sgImageFromCharDataArray[i].Close();
  1.1739 +		}
  1.1740 +	sgImageFromCharDataArray.Close();
  1.1741 +
  1.1742 +	// Release all the images used to simulate OOGM.
  1.1743 +	for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
  1.1744 +		{
  1.1745 +		sgImageArray[i].Close();
  1.1746 +		}
  1.1747 +	sgImageArray.Close();
  1.1748 +	tempImage.Close();
  1.1749 +	iTs->ReleaseFont(font);
  1.1750 +	User::Free(iTempBuf1);
  1.1751 +	User::Free(iTempBuf2);
  1.1752 +	iTempBuf1 = NULL;
  1.1753 +	iTempBuf2 = NULL;
  1.1754 +
  1.1755 +	// Log any errors only after memory is freed - this ensures there is enough
  1.1756 +	// memory for the logger.
  1.1757 +	TESTNOERROR(err);
  1.1758 +	TESTE(iterErr == KErrNotFound, iterErr);
  1.1759 +	TEST(index == KNumGlyphCodesLatin);
  1.1760 +	TEST(numMismatches == 0);
  1.1761 +
  1.1762 +	__UHEAP_MARKEND;*/
  1.1763 +#endif
  1.1764 +	}
  1.1765 +
  1.1766 +/**
  1.1767 +@SYMTestCaseID      GRAPHICS-FBSERV-0660
  1.1768 +@SYMTestPriority    Med
  1.1769 +@SYMTestType        UT
  1.1770 +@SYMTestStatus      Implemented
  1.1771 +@SYMPREQ            PREQ2678
  1.1772 +
  1.1773 +@SYMTestCaseDesc
  1.1774 +	Opens an RFbsGlyphDataIterator on many different fonts of different sizes and typefaces
  1.1775 +	and uses many fonts, in order to test that the iterator can cope with being used on many
  1.1776 +	fonts with many glyphs.
  1.1777 +
  1.1778 +@SYMTestActions
  1.1779 +	i. Perform test of 100 iterations, where:
  1.1780 +		1. A new Latin font is created every iteration in order to force the Typeface Store
  1.1781 +			to create a brand-new server-side font at each iteration. 
  1.1782 +		2. For this font, open an RFbsGlyphDataIterator and cycle through all Latin glyphs.
  1.1783 +		3. For each glyph, compare against the glyph image returned by CFont::GetCharacterData().
  1.1784 +		4. Keep a record of the number of mismatches, and carry on to next font.
  1.1785 +	ii. Perform i. again, but using the existing fonts.
  1.1786 +	iii. Check that there are no mismatches, all glyphs and fonts were successfully checked, 
  1.1787 +		and no error codes returned during the test.
  1.1788 +	iv. Clean up all resources.
  1.1789 +	
  1.1790 +@SYMTestExpectedResults
  1.1791 +	The glyphs provided by the iterator should match that returned by GetCharacterData()
  1.1792 +	for every font and every iteration. 
  1.1793 +*/
  1.1794 +void CTFbsGlyphData::TestGlyphDataIteratorManyFontsStressL()
  1.1795 +	{
  1.1796 +	INFO_PRINTF1(_L("Stress test using a RFbsGlyphDataIterator with hundreds of fonts"));
  1.1797 +	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM"));
  1.1798 +	TEST(EFalse);
  1.1799 +	/*__UHEAP_MARK;
  1.1800 +
  1.1801 +	const TInt KNumFonts = 100;
  1.1802 +	const TInt KNumRepeatsPerFont = 2;
  1.1803 +	TInt err = KErrNone;
  1.1804 +	TInt numGlyphMismatches = 0;
  1.1805 +
  1.1806 +	CFbsFont** font = new (ELeave) CFbsFont*[KNumFonts];
  1.1807 +	Mem::FillZ(font, sizeof(CFbsFont*) * KNumFonts);
  1.1808 +
  1.1809 +	// Do the whole thing KNumRepeatsPerFont times. The second+ repeats will 
  1.1810 +	// re-use the fonts created in the first repeat, to ensure that fonts that 
  1.1811 +	// may have been evicted are able to be re-used with the iterator.
  1.1812 +	for (TInt rep = 0; (rep < KNumRepeatsPerFont) && (err == KErrNone); ++rep)
  1.1813 +		{
  1.1814 +		// Iterate through all the font variants:
  1.1815 +		// Iterate all font styles, for all latin typefaces, at increasing sizes.
  1.1816 +		TInt i = 0;
  1.1817 +		for (; (i < KNumFonts) && (err == KErrNone); ++i)
  1.1818 +			{
  1.1819 +			// Only create this font if this font isn't already valid (i.e. when this is the 
  1.1820 +			// first rep) otherwise re-use it.
  1.1821 +			if (!font[i])
  1.1822 +				{
  1.1823 +				TFontSpec requestedFontSpec = GenerateDejaVuFontSpec(i);
  1.1824 +				err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font[i], requestedFontSpec);
  1.1825 +				}
  1.1826 +			if (err == KErrNone)
  1.1827 +				{
  1.1828 +				RFbsGlyphDataIterator iter;
  1.1829 +				TInt iterErr = iter.Open(*(font[i]), iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1830 +				if (iterErr != KErrNone)
  1.1831 +					{
  1.1832 +					ERR_PRINTF2(_L("Failed to open RFbsGlyphDataIterator [err=%d]"), iterErr);
  1.1833 +					InfoPrintFontSpec(*(font[i]));
  1.1834 +					iStep->SetTestStepResult(EFail);
  1.1835 +					}
  1.1836 +				else
  1.1837 +					{
  1.1838 +					TInt index = 0;
  1.1839 +					for(; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin) && (err == KErrNone) ; iterErr = iter.Next(), index++)
  1.1840 +						{
  1.1841 +						const TUint8* bitmapData = NULL;
  1.1842 +						TSize bitmapSize;
  1.1843 +						TOpenFontCharMetrics metrics;
  1.1844 +						font[i]->GetCharacterData(iter.GlyphCode() | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
  1.1845 +						if (iter.Rect().Size() == TSize(0, 0))
  1.1846 +							{
  1.1847 +							numGlyphMismatches += (bitmapSize != TSize(0, 0)) ? 1 : 0;
  1.1848 +							}
  1.1849 +						else
  1.1850 +							{
  1.1851 +							TBool match = EFalse;
  1.1852 +							const TFontSpec fontSpec = font[i]->FontSpecInTwips();							
  1.1853 +							// Compare to system-memory version of glyph
  1.1854 +							RSgImage characterDataImage;
  1.1855 +							err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
  1.1856 +							if (err == KErrNone) 
  1.1857 +								{
  1.1858 +								err = CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), match);
  1.1859 +								}
  1.1860 +							if (err == KErrNone && !match)
  1.1861 +								{
  1.1862 +								++numGlyphMismatches;
  1.1863 +								}
  1.1864 +							characterDataImage.Close();
  1.1865 +							}					
  1.1866 +						}
  1.1867 +					iter.Close();
  1.1868 +					TESTE(iterErr == KErrNotFound, iterErr);
  1.1869 +					TEST(index == KNumGlyphCodesLatin);					
  1.1870 +					}
  1.1871 +				}
  1.1872 +			}
  1.1873 +		// Check all the fonts were iterated through.
  1.1874 +		TEST(i == KNumFonts);
  1.1875 +		}
  1.1876 +	TESTNOERROR(err);
  1.1877 +	TEST(numGlyphMismatches == 0);
  1.1878 +
  1.1879 +	// Cleanup
  1.1880 +	for (TInt ii = 0; ii < KNumFonts; ii++)
  1.1881 +		{
  1.1882 +		iTs->ReleaseFont(font[ii]);
  1.1883 +		}
  1.1884 +	delete [] font;
  1.1885 +	__UHEAP_MARKEND;*/
  1.1886 +	}
  1.1887 +
  1.1888 +/**
  1.1889 +@SYMTestCaseID      GRAPHICS-FBSERV-0662
  1.1890 +@SYMTestPriority    Low
  1.1891 +@SYMTestType        UT
  1.1892 +@SYMTestStatus      Implemented
  1.1893 +@SYMPREQ            PREQ2678
  1.1894 +
  1.1895 +@SYMTestCaseDesc
  1.1896 +	Uses a RFbsGlyphDataIterator when there is no graphics memory available in the system.
  1.1897 +	It shows that when under low graphics memory, Next() returns the correct error code
  1.1898 +	as per the API (either KErrNoMemory or KErrNoGraphicsMemory, depending on the implementation 
  1.1899 +	of Graphics Resource being used).
  1.1900 +
  1.1901 +@SYMTestActions
  1.1902 +	i. Create a CFbsFont from the typeface store.
  1.1903 +	ii. Simulate a low graphics-memory situation by creating enough RSgImages to fill the memory,
  1.1904 +	iii. Open a RFbsGlyphDataIterator on the font.
  1.1905 +	iv. Attempt to use the iterator, calling Next(), checking the returned code.
  1.1906 +	v. Close the iterator and release all graphics memory from ii.
  1.1907 +
  1.1908 +@SYMTestExpectedResults
  1.1909 +	Next() should return either KErrNoMemory or KErrNoGraphicsMemory depending on the implmentation
  1.1910 +	of Graphics Resource used. It should return the same error as is returned when filling
  1.1911 +	the graphics memory reaches the limit.
  1.1912 +*/
  1.1913 +void CTFbsGlyphData::TestGlyphDataIteratorNoGraphicsMemory()
  1.1914 +	{
  1.1915 +	INFO_PRINTF1(_L("Test that when there is no GPU memory available, Next() returns correct error"));
  1.1916 +	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM"));
  1.1917 +	TEST(EFalse);
  1.1918 +	/*__UHEAP_MARK;
  1.1919 +	
  1.1920 +	const TInt KFontSize = 128;
  1.1921 +	CFbsFont* font = NULL;
  1.1922 +	RFbsGlyphDataIterator iter;
  1.1923 +	
  1.1924 +	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KMonoTypefaceName, KFontSize));
  1.1925 +	TESTNOERROR(err);
  1.1926 +	
  1.1927 +	// Simulate low OOGM situation by creating many RSgImages until out of memory.
  1.1928 +	if (err == KErrNone)
  1.1929 +		{
  1.1930 +		InfoPrintFontSpec(*font);
  1.1931 +		RArray <RSgImage> sgImageArray;
  1.1932 +		TInt iterErr = KErrNone;
  1.1933 +		TInt gfxMemErr = FillGraphicsMemoryWithImages(TSize(KFontSize, KFontSize), sgImageArray);
  1.1934 +		TESTE(gfxMemErr == KErrNoMemory || gfxMemErr == KErrNoGraphicsMemory, gfxMemErr);
  1.1935 +		if (gfxMemErr == KErrNoMemory || gfxMemErr == KErrNoGraphicsMemory)
  1.1936 +			{
  1.1937 +			// Next() could either fail with KErrNoMemory or KErrNoGraphicsMemory, but should
  1.1938 +			// be the same error code as the last attempted creation of an SgImage, done in 
  1.1939 +			// FillGraphicsMemoryWithImages() so compare against that code.
  1.1940 +			iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.1941 +			for (; iterErr == KErrNone; iterErr = iter.Next())
  1.1942 +				{
  1.1943 +				// no operation
  1.1944 +				}
  1.1945 +			iter.Close();
  1.1946 +			}
  1.1947 +	
  1.1948 +		// Release all the images used to simulate OOGM.
  1.1949 +		for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
  1.1950 +			{
  1.1951 +			sgImageArray[i].Close();
  1.1952 +			}
  1.1953 +		sgImageArray.Close();
  1.1954 +		
  1.1955 +		// Log any errors only after memory is freed - this ensures there is enough
  1.1956 +		// memory for the logger.
  1.1957 +		TESTE(iterErr == gfxMemErr, iterErr);
  1.1958 +		}
  1.1959 +
  1.1960 +	iTs->ReleaseFont(font);
  1.1961 +	
  1.1962 +	__UHEAP_MARKEND;*/
  1.1963 +	}
  1.1964 +
  1.1965 +/**
  1.1966 +@SYMTestCaseID      GRAPHICS-FBSERV-0666
  1.1967 +@SYMTestPriority    Low
  1.1968 +@SYMTestType        UT
  1.1969 +@SYMTestStatus      Implemented
  1.1970 +@SYMPREQ            PREQ2678
  1.1971 +
  1.1972 +@SYMTestCaseDesc
  1.1973 +	Uses a RFbsGlyphDataIterator after Next() returns an error, in order to show that 
  1.1974 +	an error does not invalidate the state of the iterator and it is still usable. 
  1.1975 +
  1.1976 +@SYMTestActions
  1.1977 +	i. Open the RFbsGlyphDataIterator on 1 glyph code.
  1.1978 +	ii. Store the data of the iterator and call Next() to reach the end of the iterator
  1.1979 +	iii. Access the glyph data repeatedly and check that the iterator members
  1.1980 +		 still match those in ii.
  1.1981 +
  1.1982 +@SYMTestExpectedResults
  1.1983 +	The calls to Next() should cause KErrNotFound since it is past the final glyph.
  1.1984 +	The iterator data should match at all times since the iterator is never moved.
  1.1985 +*/
  1.1986 +void CTFbsGlyphData::TestGlyphDataIteratorNextIsAtomic()
  1.1987 +	{
  1.1988 +	INFO_PRINTF1(_L("To ensure that Next() is atomic, if it returns an error it is still useable"));
  1.1989 +	__UHEAP_MARK;
  1.1990 +
  1.1991 +	RFbsGlyphDataIterator iter;
  1.1992 +	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 1);
  1.1993 +	TESTNOERROR(iterErr);
  1.1994 +	
  1.1995 +	TSgDrawableId id = iter.Image().Id();
  1.1996 +	TOpenFontCharMetrics metrics = iter.Metrics();
  1.1997 +	TUint glyphCode = iter.GlyphCode();
  1.1998 +	TRect rect = iter.Rect();
  1.1999 +	
  1.2000 +	for (TInt i = 0; i < 2; i++)
  1.2001 +		{
  1.2002 +		iterErr = iter.Next();
  1.2003 +		TESTE(iterErr == KErrNotFound, iterErr);
  1.2004 +		
  1.2005 +		TEST(id == iter.Image().Id());
  1.2006 +		TEST(glyphCode == iter.GlyphCode());
  1.2007 +		TEST(rect == iter.Rect());
  1.2008 +		TEST(CompareMetrics(metrics, iter.Metrics()) == 0);
  1.2009 +		}
  1.2010 +	iter.Close();
  1.2011 +		
  1.2012 +	__UHEAP_MARKEND;
  1.2013 +	}
  1.2014 +
  1.2015 +/**
  1.2016 +@SYMTestCaseID      GRAPHICS-FBSERV-0665
  1.2017 +@SYMTestPriority    High
  1.2018 +@SYMTestType        UT
  1.2019 +@SYMTestStatus      Implemented
  1.2020 +@SYMPREQ            PREQ2678
  1.2021 +
  1.2022 +@SYMTestCaseDesc
  1.2023 +	Glyph Atlas white-box test.
  1.2024 +	To ensure that the same RSgImage is used for repeated requests for the 
  1.2025 +	same glyph in the same call to RFbsGlyphDataIterator:Open().
  1.2026 +@SYMTestActions
  1.2027 +	i Open the glyph data iterator with a list of glyph codes which are all the same
  1.2028 +	ii Retrieve the drawable id of each iteration 
  1.2029 +	iii Check that the same drawable id is retrieved in each iteration  
  1.2030 +@SYMTestExpectedResults
  1.2031 +	Each iteration returns the same drawable id. 
  1.2032 +*/
  1.2033 +void CTFbsGlyphData::TestGlyphDataIteratorSameGlyphCodes()
  1.2034 +	{
  1.2035 +	INFO_PRINTF1(_L("White box test - Ensure that the same RSgImage is used for repeated requests for the same glyph in the same call to Open()"));
  1.2036 +	__UHEAP_MARK;
  1.2037 +
  1.2038 +	const TUint KSameRepeatedGlyphCode = iGlyphCodesLatin['A' - 0x20];
  1.2039 +	const TInt KNumGlyphs = 10;
  1.2040 +	TUint* sameRepeatedGlyphCodes = new TUint[KNumGlyphs];
  1.2041 +	for (TInt ii = 0; ii < KNumGlyphs; ++ii)
  1.2042 +		{
  1.2043 +		sameRepeatedGlyphCodes[ii] = KSameRepeatedGlyphCode;
  1.2044 +		}
  1.2045 +	RFbsGlyphDataIterator iter;
  1.2046 +	TInt err = iter.Open(*iFont, sameRepeatedGlyphCodes, KNumGlyphs);
  1.2047 +	
  1.2048 +	TESTNOERROR(err);
  1.2049 +	if (KErrNone == err)
  1.2050 +		{
  1.2051 +		// get the drawable id of the first glyph and check that the id is valid
  1.2052 +		TSgDrawableId referenceId = iter.Image().Id();
  1.2053 +		RSgImage image;
  1.2054 +		TESTNOERROR(image.Open(referenceId));
  1.2055 +		image.Close();
  1.2056 +		TESTNOERROR(iter.Next());
  1.2057 +
  1.2058 +		for (;KErrNone == err; err = iter.Next())
  1.2059 +			{
  1.2060 +			TEST(referenceId == iter.Image().Id());
  1.2061 +			}
  1.2062 +		TESTE(KErrNotFound == err, err);
  1.2063 +		}
  1.2064 +
  1.2065 +	iter.Close();
  1.2066 +	delete[] sameRepeatedGlyphCodes;
  1.2067 +
  1.2068 +	__UHEAP_MARKEND;
  1.2069 +	}
  1.2070 +
  1.2071 +/**
  1.2072 +@SYMTestCaseID      GRAPHICS-FBSERV-0668
  1.2073 +@SYMTestPriority    High
  1.2074 +@SYMTestType        UT
  1.2075 +@SYMTestStatus      Implemented
  1.2076 +@SYMPREQ            PREQ2678
  1.2077 +
  1.2078 +@SYMTestCaseDesc
  1.2079 +	To ensure that the iterator can successfully be opened on an array
  1.2080 +	of glyph codes of various array sizes. 
  1.2081 +@SYMTestActions
  1.2082 +	Perform many iterations of opening an array and cycling through the glyphs,
  1.2083 +	increasing the size of the array after each iteration. Some simple sanity-checking
  1.2084 +	of the glyphs is performed.
  1.2085 +@SYMTestExpectedResults
  1.2086 +	KErrNone should be returned at all times. 
  1.2087 +*/
  1.2088 +void CTFbsGlyphData::TestGlyphDataIteratorManyArraySizes()
  1.2089 +	{
  1.2090 +	INFO_PRINTF1(_L("Ensure that the RFbsGlyphDataIterator successfully opens glyph code arrays of many sizes"));
  1.2091 +	__UHEAP_MARK;
  1.2092 +	
  1.2093 +	RFbsGlyphMetricsArray glyphMetricsArray;
  1.2094 +	
  1.2095 +	TESTNOERROR(glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin));
  1.2096 +	TInt iterErr = KErrNone;
  1.2097 +	
  1.2098 +	for (TInt arraySize = 1; (arraySize < KNumGlyphCodesLatin) && (iterErr == KErrNone); ++arraySize)
  1.2099 +		{
  1.2100 +		RFbsGlyphDataIterator iter;
  1.2101 +		TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, arraySize);
  1.2102 +		TESTNOERROR(iterErr);
  1.2103 +		
  1.2104 +		for (TInt index = 0; iterErr == KErrNone; iterErr = iter.Next(), ++index)
  1.2105 +			{
  1.2106 +			// sanity checking...
  1.2107 +			if (iter.GlyphCode() != iGlyphCodesLatin[index])
  1.2108 +				{
  1.2109 +				ERR_PRINTF4(_L("Test failed at array size %d - Wanted glyphcode %d, got %d"), arraySize, iGlyphCodesLatin[index], iter.GlyphCode());
  1.2110 +				iStep->SetTestStepResult(EFail);
  1.2111 +				}
  1.2112 +			if (CompareMetrics(iter.Metrics(), glyphMetricsArray[index]) != 0)
  1.2113 +				{
  1.2114 +				ERR_PRINTF3(_L("Test failed at array size %d, metrics check failed at glyphcode %d"), arraySize, iGlyphCodesLatin[index]);
  1.2115 +				iStep->SetTestStepResult(EFail);
  1.2116 +				}			
  1.2117 +			}
  1.2118 +		iter.Close();
  1.2119 +		}
  1.2120 +
  1.2121 +	glyphMetricsArray.Close();
  1.2122 +	TESTNOERROR(iterErr);
  1.2123 +
  1.2124 +	__UHEAP_MARKEND;
  1.2125 +	}
  1.2126 +
  1.2127 +/**
  1.2128 +@SYMTestCaseID      GRAPHICS-FBSERV-0669
  1.2129 +@SYMTestPriority    Low
  1.2130 +@SYMTestType        UT
  1.2131 +@SYMTestStatus      Implemented
  1.2132 +@SYMPREQ            PREQ2678
  1.2133 +
  1.2134 +@SYMTestCaseDesc
  1.2135 +	Negative test case to show that RFbsGlyphDataIterator and RFbsGlyphMetricsArray
  1.2136 +	do not support bitmap fonts.
  1.2137 +@SYMTestActions
  1.2138 +	i. Load a bitmap font.
  1.2139 +	ii. Attempt to open an RFbsGlyphDataIterator and RFbsGlyphMetricsArray with the font.
  1.2140 +@SYMTestExpectedResults
  1.2141 +	KErrNotSupported should be returned in both instances. 
  1.2142 +*/
  1.2143 + void CTFbsGlyphData::TestBitmapFontSupport()
  1.2144 +	{
  1.2145 +	INFO_PRINTF1(_L("Test bitmap font not supported"));
  1.2146 +	__UHEAP_MARK;
  1.2147 +	
  1.2148 +	CFbsFont* bitmapFont = NULL;
  1.2149 +	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)bitmapFont, TFontSpec(_L("Digital"), 14));
  1.2150 +	TESTNOERROR(err);
  1.2151 +	TEST(!bitmapFont->IsOpenFont());
  1.2152 +	
  1.2153 +	RFbsGlyphDataIterator iter;
  1.2154 +	err = iter.Open(*bitmapFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.2155 +	TEST(err == KErrNotSupported);
  1.2156 +	iter.Close();
  1.2157 +	
  1.2158 +	RFbsGlyphMetricsArray array;
  1.2159 +	err = array.Get(*bitmapFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.2160 +	TEST(err == KErrNotSupported);
  1.2161 +	array.Close();
  1.2162 +	
  1.2163 +	iTs->ReleaseFont(bitmapFont);
  1.2164 +	__UHEAP_MARKEND;
  1.2165 +	}
  1.2166 + 
  1.2167 +/**
  1.2168 +@SYMTestCaseID		GRAPHICS-FBSERV-0671
  1.2169 +@SYMTestPriority	High
  1.2170 +@SYMTestType		UT
  1.2171 +@SYMTestStatus		Implemented
  1.2172 +@SYMPREQ			PREQ2678
  1.2173 +
  1.2174 +@SYMTestCaseDesc
  1.2175 +	Shows that different threads (and therefore RFbsSessions) using fonts with the same
  1.2176 +	TFontSpec share the same glyphs	in the atlas and do not create duplicate entries
  1.2177 +	in the Glyph Atlas, and that releasing a font clears all associated glyphs in the
  1.2178 +	atlas.
  1.2179 +
  1.2180 +@SYMTestActions
  1.2181 +	i. Create a handle to a test font in the current process.
  1.2182 +	ii. Spawn a test thread and wait for it to complete. Within the thread :
  1.2183 +		1. Create a font with the same fontspec as the parent process.
  1.2184 +		2. Use the RFbsGlyphDataIterator API to force rasterization into the glyph atlas.
  1.2185 +		3. Release the iterator.
  1.2186 +	iii. Check there were no leaves from the thread.
  1.2187 +	iv. Repeat ii. and iii. several times. Before using RFbsGlyphDataIterator,
  1.2188 +		the thread checks that the glyphs are still in the atlas from the first thread.
  1.2189 +	v. Check that the number of fonts in the atlas has increased by one only.
  1.2190 +	vi. Check that the number of glyphs in the atlas has increased by the size of the 
  1.2191 +		glyph code array.
  1.2192 +	vii. Release the font in the parent process, thereby releasing the font and glyphs
  1.2193 +		in the glyph atlas, and check that the state of the atlas is the same as before
  1.2194 +		the test is run.
  1.2195 +
  1.2196 +@SYMTestExpectedResults
  1.2197 +	All threads should return no errors or leaves or panics.
  1.2198 +	After all threads have finished:
  1.2199 +		The glyph count should have increased by the size of the glyph code array used
  1.2200 +		in the RFbsGlyphDataIterator, showing that	glyphs are only being added to the atlas
  1.2201 +		once. The number of fonts in the atlas should have increased by one, showing
  1.2202 +		that only the single underlying font object is being added to the atlas, despite
  1.2203 +		different RFbsSessions and CFbsFont instances used.
  1.2204 +	After the test font is released in the main process:
  1.2205 +		The glyph count and font count return to the pre-test value, showing that when
  1.2206 +		the last handle to a TFontSpec is released, the atlas frees its associated data.
  1.2207 +*/
  1.2208 +void CTFbsGlyphData::TestMultithreadShareSingleFont()
  1.2209 +	{
  1.2210 +	INFO_PRINTF1(_L("Test glyphs shared between RFbsSessions/threads/processes"));
  1.2211 +#ifndef _DEBUG
  1.2212 +	// Test relies on debug-only FBS messages EFbsMessAtlasGlyphCount and EFbsMessAtlasFontCount
  1.2213 +	INFO_PRINTF1(_L("Skipping test in release mode"));
  1.2214 +#else	
  1.2215 +	__UHEAP_MARK;
  1.2216 +
  1.2217 +	_LIT(KThreadName, "GlyphDataTestThread");
  1.2218 +	const TInt KNumTestThreads = 5;
  1.2219 +	const TFontSpec KTestFontSpec(KTypefaceName, 50);	
  1.2220 +	const TInt atlasFontCountStart = iFbs->SendCommand(EFbsMessAtlasFontCount);
  1.2221 +	const TInt atlasGlyphCountStart = iFbs->SendCommand(EFbsMessAtlasGlyphCount);
  1.2222 +
  1.2223 +	CFbsFont* testFont;
  1.2224 +	TInt err = iTs->GetNearestFontToDesignHeightInPixels( (CFont*&)testFont, KTestFontSpec);
  1.2225 +	if (err != KErrNone)
  1.2226 +		{
  1.2227 +		ERR_PRINTF2(_L("Could not load font, err = %d"), err);
  1.2228 +		iStep->SetTestStepResult(EFail);
  1.2229 +		return;
  1.2230 +		}
  1.2231 +	
  1.2232 +	// Check there are no glyphs belonging to the test font before the test starts.
  1.2233 +	TInt atlasFontGlyphCount = iFbs->SendCommand(EFbsMessAtlasGlyphCount, testFont->Handle());
  1.2234 +	TEST(atlasFontGlyphCount == 0);
  1.2235 +
  1.2236 +	TGlyphDataMultithreadParams params = {KTestFontSpec, iGlyphCodesLatin, KNumGlyphCodesLatin, NULL};
  1.2237 +
  1.2238 +	// Run the test threads sequentially, and check its exit status.
  1.2239 +	RThread testThread;
  1.2240 +	TInt numThreadsPassed = 0;
  1.2241 +	for (TInt i = 0; i < KNumTestThreads; i++)
  1.2242 +		{
  1.2243 +		TBool threadPassed = ETrue;
  1.2244 +		TGlyphDataThreadInfo info = {EGlyphDataMultiSessionTestShareGlyphs, params, i, iStep};
  1.2245 +		err = testThread.Create(KThreadName, CTFbsGlyphData::ThreadFunction, KDefaultStackSize, KTestThreadMinHeapSize, KTestThreadMaxHeapSize, &info);
  1.2246 +		TESTNOERROR(err);
  1.2247 +
  1.2248 +		TRequestStatus statusThread;
  1.2249 +		testThread.Logon(statusThread);
  1.2250 +		testThread.Resume();
  1.2251 +		
  1.2252 +		User::WaitForRequest(statusThread);
  1.2253 +		TInt threadResult = testThread.ExitReason();
  1.2254 +		if (threadResult != KErrNone)
  1.2255 +			{
  1.2256 +			ERR_PRINTF3(_L("Thread %i: Terminated with reason %d"), i, threadResult);
  1.2257 +			threadPassed = EFalse; 
  1.2258 +			}
  1.2259 +		TExitCategoryName exitCategory = testThread.ExitCategory();
  1.2260 +		if (exitCategory.Compare(_L("Kill")) != 0)
  1.2261 +			{
  1.2262 +			ERR_PRINTF3(_L("Thread %i: Terminated with reason category '%S'"), i, &exitCategory);
  1.2263 +			threadPassed = EFalse;
  1.2264 +			}
  1.2265 +		testThread.Close();
  1.2266 +		numThreadsPassed += (threadPassed) ? 1 : 0;
  1.2267 +		}
  1.2268 +	TEST(numThreadsPassed == KNumTestThreads);
  1.2269 +
  1.2270 +	// Check that the atlas still contains the glyphs and the font created by the threads
  1.2271 +	// after they have died, since the font is still open in this process.
  1.2272 +	atlasFontGlyphCount = iFbs->SendCommand(EFbsMessAtlasGlyphCount, testFont->Handle());
  1.2273 +	TEST(atlasFontGlyphCount == params.iGlyphCodesCount);
  1.2274 +	TInt atlasFontCount = iFbs->SendCommand(EFbsMessAtlasFontCount);
  1.2275 +	TEST(atlasFontCount == (atlasFontCountStart + 1));
  1.2276 +
  1.2277 +	iTs->ReleaseFont(testFont);
  1.2278 +	testFont = NULL;
  1.2279 +
  1.2280 +	// Check the atlas state is now the same as it was before the test started,
  1.2281 +	// now that the last remaining handle to the font used in the threads is released.
  1.2282 +	TInt atlasGlyphCountEnd = iFbs->SendCommand(EFbsMessAtlasGlyphCount);
  1.2283 +	TEST(atlasGlyphCountStart == atlasGlyphCountEnd);
  1.2284 +	TInt atlasFontCountEnd = iFbs->SendCommand(EFbsMessAtlasFontCount);
  1.2285 +	TEST(atlasFontCountStart == atlasFontCountEnd);
  1.2286 +	__UHEAP_MARKEND;
  1.2287 +#endif
  1.2288 +	}
  1.2289 +
  1.2290 +/**
  1.2291 +Worker thread for TestMultithreadShareSingleFont().
  1.2292 +The thread uses RFbsGlyphDataIterator on a CFbsFont of the given TFontSpec.
  1.2293 +Once complete the atlas is queried for the number of associated glyphs.
  1.2294 + */
  1.2295 +void CTFbsGlyphData::ThreadShareGlyphsL(TInt aThreadNum, TGlyphDataMultithreadParams& aParam, CTestStep* aStep)
  1.2296 +	{
  1.2297 +	User::LeaveIfError(RFbsSession::Connect());
  1.2298 +	CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
  1.2299 +	CleanupStack::PushL(ts);
  1.2300 +	RFbsSession* fbs = RFbsSession::GetSession();
  1.2301 +
  1.2302 +	CFbsFont* font;
  1.2303 +	TInt err = ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, aParam.iFontSpec);
  1.2304 +	User::LeaveIfError(err);
  1.2305 +
  1.2306 +	if (aThreadNum > 0)
  1.2307 +		{
  1.2308 +		// If this is not the first thread, it means the first thread has already executed and 
  1.2309 +		// populated the glyph atlas with the glyphs. The font created by this thread 
  1.2310 +		// should already have its glyphs in the atlas.
  1.2311 +		TInt fontGlyphCount = fbs->SendCommand(EFbsMessAtlasGlyphCount, font->Handle());
  1.2312 +		if (fontGlyphCount != aParam.iGlyphCodesCount)
  1.2313 +			{
  1.2314 +			aStep->ERR_PRINTF4(_L("Thread %d: Only %d glyphs in atlas before first iteration, expected %d"), aThreadNum, fontGlyphCount, aParam.iGlyphCodesCount);
  1.2315 +			aStep->SetTestStepResult(EFail);
  1.2316 +			}
  1.2317 +		}
  1.2318 +
  1.2319 +	RFbsGlyphDataIterator iter;
  1.2320 +	for (err = iter.Open(*font, aParam.iGlyphCodes, aParam.iGlyphCodesCount); err == KErrNone; err = iter.Next())
  1.2321 +		{
  1.2322 +		// no-op
  1.2323 +		}
  1.2324 +	iter.Close();
  1.2325 +
  1.2326 +	// Check that the glyphs of this font have been added to the atlas
  1.2327 +	TInt fontGlyphCount = fbs->SendCommand(EFbsMessAtlasGlyphCount, font->Handle());
  1.2328 +	if (fontGlyphCount != aParam.iGlyphCodesCount)
  1.2329 +		{
  1.2330 +		aStep->ERR_PRINTF5(_L("Thread %d: Only %d glyphs in atlas after last iteration, expected %d (err=%d)"), aThreadNum, fontGlyphCount, aParam.iGlyphCodesCount, err);
  1.2331 +		aStep->SetTestStepResult(EFail);
  1.2332 +		}
  1.2333 +	if (err != KErrNotFound)
  1.2334 +		{
  1.2335 +		aStep->ERR_PRINTF3(_L("Thread %d: Error during test = %d"), aThreadNum, err);
  1.2336 +		aStep->SetTestStepResult(EFail);
  1.2337 +		}
  1.2338 +
  1.2339 +	ts->ReleaseFont(font);
  1.2340 +	CleanupStack::PopAndDestroy(1); // ts
  1.2341 +	RFbsSession::Disconnect();
  1.2342 +	}
  1.2343 +
  1.2344 +
  1.2345 +/**
  1.2346 +@SYMTestCaseID		GRAPHICS-FBSERV-0672
  1.2347 +@SYMTestPriority	Medium
  1.2348 +@SYMTestType		UT
  1.2349 +@SYMTestStatus		Implemented
  1.2350 +@SYMPREQ			PREQ2678
  1.2351 +
  1.2352 +@SYMTestCaseDesc
  1.2353 +	Tests that with many concurrent sessions connected to Fbserv, the atlas successfully
  1.2354 +	returns the correct glyph images even if the atlas becomes full and has to evict glyphs.
  1.2355 +
  1.2356 +@SYMTestActions
  1.2357 +	i. Create 25 threads, each a unique session with Fbserv.
  1.2358 +	ii. Launch the threads simultaneously. In each thread:
  1.2359 +		1. Create a FBS typeface store and create a font which is unique in the process.
  1.2360 +		2. Use RFbsGlyphDataIterator to iterate through the latin glyph codes.
  1.2361 +		3. Check the image is correct for each glyph against the image returned by 
  1.2362 +			CFont::GetCharacterData().
  1.2363 +		4. Close the iterator.
  1.2364 +		5. Release the font and close the typeface store. 
  1.2365 +	iii. Once all threads have finished, check the exit status of each thread
  1.2366 +
  1.2367 +@SYMTestExpectedResults
  1.2368 +	Every glyph for every thread should match the image returned by GetCharacterData()
  1.2369 +	All threads should exit normally with no Leave code.
  1.2370 +*/
  1.2371 +_LIT(KTestMultithreadStressFinishSemaphore, "TestMultithreadStressAtlasFinish");
  1.2372 +
  1.2373 +void CTFbsGlyphData::TestMultithreadStressAtlas()
  1.2374 +	{
  1.2375 +	INFO_PRINTF1(_L("Stress test glyph atlas with multiple RFbsSessions"));
  1.2376 +	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85NEFT - TB10.1 eglCreateImageKHR hangs during multithreading"));
  1.2377 +	TEST(EFalse);
  1.2378 +	/*__UHEAP_MARK;
  1.2379 +
  1.2380 +	TInt err = KErrNone;
  1.2381 +	const TInt KNumTestThreads = 25;
  1.2382 +	_LIT(KThreadNameFormat, "GlyphDataTestThread%i");
  1.2383 +
  1.2384 +	// Create a semaphore that is signalled by each test thread when it has finished.
  1.2385 +	RSemaphore threadFinishSemaphore;
  1.2386 +	err = threadFinishSemaphore.CreateGlobal(KTestMultithreadStressFinishSemaphore, 0, EOwnerThread);
  1.2387 +	TESTNOERROR(err);
  1.2388 +
  1.2389 +	// Prepare the testdata for the threads
  1.2390 +	// Each thread will have a TFontSpec which will cause unique CFbsFonts
  1.2391 +	// to be created in the server, and therefore the atlas.
  1.2392 +	RThread testThread[KNumTestThreads];
  1.2393 +	TGlyphDataThreadInfo testInfo[KNumTestThreads];	
  1.2394 +	for (TInt i = 0; i < KNumTestThreads; ++i)
  1.2395 +		{
  1.2396 +		testInfo[i].iStep = iStep;
  1.2397 +		testInfo[i].iTest = EGlyphDataMultiSessionTestStressAtlas;
  1.2398 +		testInfo[i].iParams.iFontSpec = GenerateDejaVuFontSpec(i);
  1.2399 +		testInfo[i].iParams.iGlyphCodes = iGlyphCodesLatin;
  1.2400 +		testInfo[i].iParams.iGlyphCodesCount = KNumGlyphCodesLatin;
  1.2401 +		testInfo[i].iParams.iEGL = iEGL;
  1.2402 +		testInfo[i].iThreadNum = i;	
  1.2403 +		TBuf<128> threadName;
  1.2404 +		threadName.AppendFormat(KThreadNameFormat, i);
  1.2405 +		err = testThread[i].Create(threadName, CTFbsGlyphData::ThreadFunction, KDefaultStackSize, KTestThreadMinHeapSize, KTestThreadMaxHeapSize, &testInfo[i]);
  1.2406 +		TESTNOERROR(err);
  1.2407 +		}
  1.2408 +
  1.2409 +	// All threads are created, start them simultaneously.
  1.2410 +	for (TInt i = 0; i < KNumTestThreads; ++i)
  1.2411 +		{
  1.2412 +		testThread[i].Resume();
  1.2413 +		}
  1.2414 +	// Wait for all threads to finish.
  1.2415 +	for (TInt i = 0; i < KNumTestThreads; ++i)
  1.2416 +		{
  1.2417 +		threadFinishSemaphore.Wait();
  1.2418 +		}
  1.2419 +	// Allow some time for remaining threads to finish tidy-up.
  1.2420 +	User::After(100000);
  1.2421 +	threadFinishSemaphore.Close();
  1.2422 +
  1.2423 +	TInt numThreadsPassed = 0;
  1.2424 +	for (TInt i = 0; i < KNumTestThreads; ++i)
  1.2425 +		{
  1.2426 +		TBool threadPassed = ETrue;
  1.2427 +		TInt threadResult = testThread[i].ExitReason();
  1.2428 +		if (threadResult != KErrNone)
  1.2429 +			{
  1.2430 +			ERR_PRINTF3(_L("Thread %i: Terminated with reason %d"), i, threadResult);
  1.2431 +			threadPassed = EFalse; 
  1.2432 +			}
  1.2433 +		TExitCategoryName exitCategory = testThread[i].ExitCategory();
  1.2434 +		if (exitCategory.Compare(_L("Kill")) != 0)
  1.2435 +			{
  1.2436 +			ERR_PRINTF3(_L("Thread %i: Terminated with reason category '%S'"), i, &exitCategory);
  1.2437 +			threadPassed = EFalse;
  1.2438 +			}
  1.2439 +		testThread[i].Close();
  1.2440 +		numThreadsPassed += (threadPassed) ? 1 : 0;
  1.2441 +		}
  1.2442 +	TEST(numThreadsPassed == KNumTestThreads);
  1.2443 +
  1.2444 +	__UHEAP_MARKEND;*/
  1.2445 +	}
  1.2446 +/**
  1.2447 +Worker thread for TestMultithreadStressAtlas().
  1.2448 +The thread uses RFbsGlyphDataIterator on a CFbsFont of the given TFontSpec.
  1.2449 +For each glyph, the image returned by the iterator is compared to the image 
  1.2450 +returned from CFont::GetCharacterData().
  1.2451 +Once complete, the semaphore is signalled to tell the parent process it has
  1.2452 +finished.
  1.2453 + */
  1.2454 +void CleanupFinishSemaphore(TAny* aItem)
  1.2455 +    {
  1.2456 +    RSemaphore* semaphore = reinterpret_cast<RSemaphore*>(aItem);
  1.2457 +    semaphore->Signal();
  1.2458 +    semaphore->Close();
  1.2459 +    }
  1.2460 +void CTFbsGlyphData::ThreadStressAtlasL(TInt aThreadNum, TGlyphDataMultithreadParams& aParam, CTestStep* aStep)
  1.2461 +	{
  1.2462 +	TOpenFontCharMetrics charMetrics;
  1.2463 +	const TUint8* bitmapData;
  1.2464 +	TSize bitmapSize;
  1.2465 +	RSgImage charDataImage;
  1.2466 +
  1.2467 +	RSemaphore threadFinishSemaphore;
  1.2468 +	User::LeaveIfError(threadFinishSemaphore.OpenGlobal(KTestMultithreadStressFinishSemaphore));
  1.2469 +	CleanupStack::PushL(TCleanupItem(CleanupFinishSemaphore, &threadFinishSemaphore));
  1.2470 +
  1.2471 +	User::LeaveIfError(RFbsSession::Connect());
  1.2472 +	CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
  1.2473 +	CleanupStack::PushL(ts);
  1.2474 +	
  1.2475 +	CFbsFont* font;
  1.2476 +	User::LeaveIfError(ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, aParam.iFontSpec));
  1.2477 +
  1.2478 +	TInt numGlyphMatches = 0;
  1.2479 +	TInt index = 0;
  1.2480 +	TInt err = KErrNone;
  1.2481 +	RFbsGlyphDataIterator iter;
  1.2482 +	for (err = iter.Open(*font, aParam.iGlyphCodes, aParam.iGlyphCodesCount); err == KErrNone; err = iter.Next(), ++index)
  1.2483 +		{
  1.2484 +		TBool glyphMatch = EFalse;
  1.2485 +		font->GetCharacterData(aParam.iGlyphCodes[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
  1.2486 +		if (bitmapSize == TSize(0, 0))
  1.2487 +			{
  1.2488 +			glyphMatch = (bitmapSize == iter.Rect().Size());
  1.2489 +			}
  1.2490 +		else
  1.2491 +			{
  1.2492 +			err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, font->FontSpecInTwips().iFontStyle.BitmapType(), charDataImage);
  1.2493 +			if (err == KErrNone)
  1.2494 +				{
  1.2495 +				err = CompareSgImages(aParam.iEGL, iter.Image(), iter.Rect(), charDataImage, TRect(bitmapSize), glyphMatch);
  1.2496 +				}
  1.2497 +			charDataImage.Close();
  1.2498 +			}
  1.2499 +		if (err != KErrNone)
  1.2500 +			{
  1.2501 +			break;
  1.2502 +			}
  1.2503 +		numGlyphMatches += (glyphMatch) ? 1 : 0;
  1.2504 +		}
  1.2505 +	iter.Close();
  1.2506 +	
  1.2507 +	if (index != aParam.iGlyphCodesCount)
  1.2508 +		{
  1.2509 +		aStep->ERR_PRINTF5(_L("Thread %d: Iterator terminated early - %d out of %d glyphs (err=%d)"), aThreadNum, index, aParam.iGlyphCodesCount, err);
  1.2510 +		aStep->SetTestStepResult(EFail);
  1.2511 +		}
  1.2512 +	if (index != numGlyphMatches)
  1.2513 +		{
  1.2514 +		aStep->ERR_PRINTF4(_L("Thread %d: Matched %d out of %d glyphs"), aThreadNum, numGlyphMatches, aParam.iGlyphCodesCount);
  1.2515 +		aStep->SetTestStepResult(EFail);
  1.2516 +		}
  1.2517 +
  1.2518 +	ts->ReleaseFont(font);
  1.2519 +	CleanupStack::PopAndDestroy(2); // ts, threadFinishSemaphore
  1.2520 +	RFbsSession::Disconnect();
  1.2521 +	}
  1.2522 +
  1.2523 +/**
  1.2524 +@SYMTestCaseID      GRAPHICS-FBSERV-0673
  1.2525 +@SYMTestPriority    Medium
  1.2526 +@SYMTestType        UT
  1.2527 +@SYMTestStatus      Implemented
  1.2528 +@SYMPREQ            PREQ2678
  1.2529 +
  1.2530 +@SYMTestCaseDesc
  1.2531 +    Tests the robustness of using RFbsGlyphMetricsArray when the client heap and the
  1.2532 +    FbServ private heap experience failures allocating memory, causing no panics 
  1.2533 +    or leaves.
  1.2534 +
  1.2535 +@SYMTestActions
  1.2536 +    i. Set the default heap failure for the next heap allocation.
  1.2537 +    ii. Create a new CFbsFont using a TFontSpec not already in the glyph atlas.
  1.2538 +    iii. Call RFbsGlyphMetricsArray::Get(), and close the array.
  1.2539 +    iv. Release the font so that nothing is left in the cache as a result of
  1.2540 +        attempting to use it, and reset the heap failure state.
  1.2541 +    v. While iii returns KErrNoMemory, increment the failure count and repeat
  1.2542 +        step ii.
  1.2543 +    vi. Using a separate font so that the test is not affected by the earlier
  1.2544 +        run, repeat ii. to v., but rather than setting the default heap to 
  1.2545 +        fail, the FbServ private heap is set to fail, via IPC messages to Fbs.
  1.2546 +
  1.2547 +@SYMTestExpectedResults
  1.2548 +    If no errors occur, KErrNone should be returned after a certain number of
  1.2549 +    repetitions. Any other error code denotes a problem handling low-memory 
  1.2550 +    situtations.
  1.2551 +*/
  1.2552 +void CTFbsGlyphData::TestGlyphMetricsArrayHeapOOML()
  1.2553 +    {
  1.2554 +    INFO_PRINTF1(_L("Test RFbsGlyphMetricsArray during heap alloc failure"));
  1.2555 +    __UHEAP_MARK;
  1.2556 +
  1.2557 +    // Create a font that wont be in the cache already...
  1.2558 +    TInt rep = 0;
  1.2559 +    TInt err = KErrNoMemory;
  1.2560 +    CFbsFont* font = NULL;
  1.2561 +    
  1.2562 +    while (err == KErrNoMemory)
  1.2563 +        {
  1.2564 +        User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(10)));
  1.2565 +        __UHEAP_FAILNEXT(rep);
  1.2566 +        RFbsGlyphMetricsArray array;
  1.2567 +        err = array.Get(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.2568 +        array.Close();
  1.2569 +        __UHEAP_RESET;
  1.2570 +        iTs->ReleaseFont(font);
  1.2571 +        font = NULL;
  1.2572 +        ++rep;
  1.2573 +        }
  1.2574 +
  1.2575 +	TESTE(err == KErrNone, err);
  1.2576 +    if (err == KErrNone)
  1.2577 +        {
  1.2578 +        INFO_PRINTF2(_L("Client Heap OOM : Test passed after rep %d"), rep);
  1.2579 +        }
  1.2580 +    else
  1.2581 +        {
  1.2582 +        ERR_PRINTF3(_L("Client Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
  1.2583 +        }
  1.2584 +
  1.2585 +    // Now test when the server-side FbServ heap fails...
  1.2586 +    rep = 0;
  1.2587 +    err = KErrNoMemory;
  1.2588 +    
  1.2589 +    while (err == KErrNoMemory)
  1.2590 +        {
  1.2591 +        User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(11)));
  1.2592 +        iFbs->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeServerMemory, rep);
  1.2593 +        RFbsGlyphMetricsArray array;
  1.2594 +        err = array.Get(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.2595 +        array.Close();
  1.2596 +        iFbs->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeServerMemory);
  1.2597 +        iTs->ReleaseFont(font);
  1.2598 +        font = NULL;
  1.2599 +        ++rep;
  1.2600 +        }
  1.2601 +
  1.2602 +	TESTE(err == KErrNone, err);
  1.2603 +    if (err == KErrNone)
  1.2604 +        {
  1.2605 +        INFO_PRINTF2(_L("FBServ Heap OOM : Test passed after rep %d"), rep);
  1.2606 +        }
  1.2607 +    else
  1.2608 +        {
  1.2609 +        ERR_PRINTF3(_L("FBServ Heap OOM : Test failed with err=%d, after rep %d"), err, rep);      
  1.2610 +        }
  1.2611 +    __UHEAP_MARKEND;
  1.2612 +    }
  1.2613 +
  1.2614 +/**
  1.2615 +@SYMTestCaseID      GRAPHICS-FBSERV-0674
  1.2616 +@SYMTestPriority    Medium
  1.2617 +@SYMTestType        UT
  1.2618 +@SYMTestStatus      Implemented
  1.2619 +@SYMPREQ            PREQ2678
  1.2620 +
  1.2621 +@SYMTestCaseDesc
  1.2622 +    Tests the robustness of using RFbsGlyphDataIterator when the client heap and the
  1.2623 +    FbServ private heap experience failures allocating memory, causing no panics 
  1.2624 +    or leaves.
  1.2625 +
  1.2626 +@SYMTestActions
  1.2627 +    i. Set the default heap failure for the next heap allocation.
  1.2628 +    ii. Create a new CFbsFont using a TFontSpec not already in the glyph atlas.
  1.2629 +    iii. Call RFbsGlyphDataIterator::Open(), and close the array.
  1.2630 +    iv. Release the font so that nothing is left in the cache as a result of
  1.2631 +        attempting to use it, and reset the heap failure state.
  1.2632 +    v. While iii returns KErrNoMemory, increment the failure count and repeat
  1.2633 +        step ii.
  1.2634 +    vi. Using a separate font so that the test is not affected by the earlier
  1.2635 +        run, repeat ii. to v., but rather than setting the default heap to 
  1.2636 +        fail, the FbServ private heap is set to fail, via IPC messages to Fbs.
  1.2637 +
  1.2638 +@SYMTestExpectedResults
  1.2639 +    If no errors occur, KErrNone should be returned after a certain number of
  1.2640 +    repetitions. Any other error code denotes a problem handling low-memory 
  1.2641 +    situtations.
  1.2642 +*/
  1.2643 +void CTFbsGlyphData::TestGlyphDataIteratorHeapOOML()
  1.2644 +    {
  1.2645 +    INFO_PRINTF1(_L("Test RFbsGlyphDataIterator during heap alloc failure"));    
  1.2646 +    __UHEAP_MARK;
  1.2647 +
  1.2648 +    // Create a font that wont be in the cache already...
  1.2649 +    TInt rep = 0;
  1.2650 +    TInt err = KErrNoMemory;
  1.2651 +    CFbsFont* font = NULL;
  1.2652 +    
  1.2653 +    while (err == KErrNoMemory)
  1.2654 +        {
  1.2655 +        User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(10)));
  1.2656 +        __UHEAP_FAILNEXT(rep);
  1.2657 +        RFbsGlyphDataIterator iter;
  1.2658 +        err = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.2659 +        if (err == KErrNone)
  1.2660 +            {
  1.2661 +            while (err == KErrNone) 
  1.2662 +               {
  1.2663 +               err = iter.Next();
  1.2664 +               }
  1.2665 +            err = (err == KErrNotFound) ? KErrNone : err;
  1.2666 +            }
  1.2667 +        iter.Close();
  1.2668 +        __UHEAP_RESET;
  1.2669 +        iTs->ReleaseFont(font);
  1.2670 +        font = NULL;
  1.2671 +        ++rep;
  1.2672 +        }
  1.2673 +
  1.2674 +	TESTE(err == KErrNone, err);
  1.2675 +    if (err == KErrNone)
  1.2676 +        {
  1.2677 +        INFO_PRINTF2(_L("Client Heap OOM : Test passed after rep %d"), rep);
  1.2678 +        }
  1.2679 +    else
  1.2680 +        {
  1.2681 +        ERR_PRINTF3(_L("Client Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
  1.2682 +        }
  1.2683 +
  1.2684 +    // Now test when the server-side FbServ heap fails...
  1.2685 +    rep = 0;
  1.2686 +    err = KErrNoMemory;
  1.2687 +    
  1.2688 +    while (err == KErrNoMemory)
  1.2689 +        {
  1.2690 +        User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(11)));
  1.2691 +        iFbs->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeServerMemory, rep);
  1.2692 +        RFbsGlyphDataIterator iter;
  1.2693 +        err = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
  1.2694 +        if (err == KErrNone)
  1.2695 +            {
  1.2696 +            while (err == KErrNone) 
  1.2697 +               {
  1.2698 +               err = iter.Next();
  1.2699 +               }
  1.2700 +            err = (err == KErrNotFound) ? KErrNone : err;
  1.2701 +            }
  1.2702 +        iter.Close();
  1.2703 +        iFbs->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeServerMemory);
  1.2704 +        iTs->ReleaseFont(font);
  1.2705 +        font = NULL;
  1.2706 +        ++rep;
  1.2707 +        }
  1.2708 +
  1.2709 +	TESTE(err == KErrNone, err);
  1.2710 +    if (err == KErrNone)
  1.2711 +        {
  1.2712 +        INFO_PRINTF2(_L("FBServ Heap OOM : Test passed after rep %d"), rep);
  1.2713 +        }
  1.2714 +    else
  1.2715 +        {
  1.2716 +        ERR_PRINTF3(_L("FBServ Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
  1.2717 +        }
  1.2718 +    __UHEAP_MARKEND;
  1.2719 +    }
  1.2720 +
  1.2721 +/**
  1.2722 +Utility function. Prints out a description of the font's fontspec to the log.
  1.2723 + */
  1.2724 +void CTFbsGlyphData::InfoPrintFontSpec(const CFont& aFont)
  1.2725 +	{
  1.2726 +	_LIT(KMonochromeBitmap, "Mono");
  1.2727 +	_LIT(KAntiAliasedBitmap, "AA");
  1.2728 +	_LIT(KStyleItalic, "Italic");
  1.2729 +	_LIT(KStyleBold, "Bold");
  1.2730 +	_LIT(KStyleNormal, "Normal");
  1.2731 +	_LIT(KUnknown, "Unknown");
  1.2732 +	TBufC<9> bitmapType;
  1.2733 +	TBuf<12> fontStyle;
  1.2734 +	TFontSpec fontSpec = aFont.FontSpecInTwips();
  1.2735 +	switch(fontSpec.iFontStyle.BitmapType())
  1.2736 +		{
  1.2737 +		case EMonochromeGlyphBitmap:
  1.2738 +			bitmapType = KMonochromeBitmap;
  1.2739 +			break;
  1.2740 +		case EAntiAliasedGlyphBitmap:
  1.2741 +			bitmapType = KAntiAliasedBitmap;
  1.2742 +			break;
  1.2743 +		default:
  1.2744 +			bitmapType = KUnknown;
  1.2745 +		}
  1.2746 +
  1.2747 +	if (fontSpec.iFontStyle.StrokeWeight() == EStrokeWeightBold)
  1.2748 +		{
  1.2749 +		fontStyle.Append(KStyleBold);
  1.2750 +		}
  1.2751 +	if (fontSpec.iFontStyle.Posture() == EPostureItalic)
  1.2752 +		{
  1.2753 +		fontStyle.Append(KStyleItalic);
  1.2754 +		}
  1.2755 +	if (fontStyle.Length() == 0)
  1.2756 +		{
  1.2757 +		fontStyle = KStyleNormal;
  1.2758 +		}
  1.2759 +
  1.2760 +	INFO_PRINTF5(_L("Font: name=%S size=%dtw type=%S style=%S"), &(fontSpec.iTypeface.iName), fontSpec.iHeight, &bitmapType, &fontStyle);
  1.2761 +	}
  1.2762 +
  1.2763 +
  1.2764 +/**
  1.2765 +Static utility function. Performs a per-pixel comparison of two open RSgImages.
  1.2766 +To do this requires access to the binary data of the images, only accessable
  1.2767 +via EGL and Khronos APIs. This function will bind the RSgImages to VGImages 
  1.2768 +and uses OpenVG to retrieve the image data in 8bpp.
  1.2769 +@param aEGL An EGL Helper to read the SgImages into system memory.
  1.2770 +@param aImageA The first image to compare.
  1.2771 +@param aRectA A rectangular portion in pixels of the first image to compare.
  1.2772 +@param aImageB The second image to compare.
  1.2773 +@param aRectB A rectangular portion in pixels fo the second image to compare.
  1.2774 +@param aMatch A boolean value, which on return tells the caller whether the two
  1.2775 +	images were deemed to match.
  1.2776 +@return KErrNone, if the comparison took place, otherwise one of the system-wide
  1.2777 +	error codes.
  1.2778 +*/
  1.2779 +TInt CTFbsGlyphData::CompareSgImages(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, const RSgImage& aImageB, const TRect& aRectB, TBool& aMatch)
  1.2780 +	{
  1.2781 +	return CTFbsGlyphData::CompareSgImages(aEGL, aImageA, aRectA, NULL, aImageB, aRectB, NULL, aMatch);
  1.2782 +	}
  1.2783 +
  1.2784 +/**
  1.2785 +Static utility function. Performs a per-pixel comparison of two open RSgImages.
  1.2786 +To do this requires access to the binary data of the images, only accessable
  1.2787 +via EGL and Khronos APIs. This function will bind the RSgImages to VGImages 
  1.2788 +and uses OpenVG to retrieve the image data in 8bpp.
  1.2789 +This version allows pre-created memory to be used in the comparison, to avoid
  1.2790 +allocation failure in low memory testing.
  1.2791 +@param aEGL An EGL Helper to read the SgImages into system memory buffers.
  1.2792 +@param aImageA The first image to compare.
  1.2793 +@param aRectA A rectangular portion in pixels of the first image to compare.
  1.2794 +@param aBufferA If non-NULL, specifies a memory buffer to read the data of
  1.2795 +	aImageA into, otherwise a buffer is dynamically allocated.
  1.2796 +@param aImageB The second image to compare.
  1.2797 +@param aRectB A rectangular portion in pixels fo the second image to compare.
  1.2798 +@param aBufferB If non-NULL, specifies a memory buffer to read the data of
  1.2799 +	aImageB into, otherwise a buffer is dynamically allocated.
  1.2800 +@param aMatch A boolean value, which on return tells the caller whether the two
  1.2801 +	images were deemed to match.
  1.2802 +@return KErrNone, if the comparison took place, otherwise one of the system-wide
  1.2803 +	error codes.
  1.2804 +*/
  1.2805 +TInt CTFbsGlyphData::CompareSgImages(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, TUint8* aBufferA, const RSgImage& aImageB, const TRect& aRectB, TUint8* aBufferB, TBool& aMatch)
  1.2806 +	{
  1.2807 +	// By default, assume they do not match.
  1.2808 +	aMatch = EFalse;
  1.2809 +	
  1.2810 +#ifdef SAVEGLYPHSTOMBMDURINGCOMPARISON
  1.2811 +	
  1.2812 +	static TInt countToAppend = 0;
  1.2813 +	
  1.2814 +	CFbsBitmap* bitmap = NULL;
  1.2815 +	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageA, aRectA, bitmap))
  1.2816 +		{
  1.2817 +		TBuf<KMaxFileName> buf;
  1.2818 +		buf.AppendNum( countToAppend );
  1.2819 +		TPtrC nameAppend( buf );
  1.2820 +		
  1.2821 +		SaveBmp(bitmap, &nameAppend, EFalse);
  1.2822 +		}
  1.2823 +	delete bitmap;	
  1.2824 +	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageB, aRectB, bitmap))
  1.2825 +		{
  1.2826 +		TBuf<KMaxFileName> buf;
  1.2827 +		buf.AppendNum( countToAppend );
  1.2828 +		TPtrC nameAppend( buf );
  1.2829 +	
  1.2830 +		SaveBmp(bitmap, &nameAppend, ETrue);
  1.2831 +		}
  1.2832 +	delete bitmap;
  1.2833 +	
  1.2834 +	countToAppend++;
  1.2835 +	
  1.2836 +#endif // SAVEGLYPHSTOMBMDURINGCOMPARISON
  1.2837 +	
  1.2838 +	TSgImageInfo imageInfoA;
  1.2839 +	TSgImageInfo imageInfoB;
  1.2840 +	if (aImageA.GetInfo(imageInfoA) != KErrNone ||
  1.2841 +		aImageB.GetInfo(imageInfoB) != KErrNone)
  1.2842 +		{
  1.2843 +		return KErrBadHandle;
  1.2844 +		}
  1.2845 +		
  1.2846 +	// Check the sizes of the images match, and the rects reside on the images.
  1.2847 +	if (aRectA.Size() != aRectB.Size() ||
  1.2848 +		!TRect(imageInfoA.iSizeInPixels).Intersects(aRectA) ||
  1.2849 +		!TRect(imageInfoB.iSizeInPixels).Intersects(aRectB))
  1.2850 +		{
  1.2851 +		return KErrNone;		
  1.2852 +		}
  1.2853 +	const TSize KBufferSize = aRectA.Size();
  1.2854 +	const TInt KDataStride = KBufferSize.iWidth;
  1.2855 +
  1.2856 +	TBool freeTempBufA = EFalse;
  1.2857 +	TBool freeTempBufB = EFalse;
  1.2858 +	if (!aBufferA)
  1.2859 +		{
  1.2860 +		aBufferA = (TUint8*) User::AllocZ(KDataStride * KBufferSize.iHeight);
  1.2861 +		freeTempBufA = ETrue;
  1.2862 +		}
  1.2863 +	if (!aBufferA)
  1.2864 +		{
  1.2865 +		return KErrNoMemory;
  1.2866 +		}
  1.2867 +	TInt err = aEGL->GetSgImageData(aImageA, aRectA, aBufferA);
  1.2868 +	if (err != KErrNone)
  1.2869 +		{
  1.2870 +		if (freeTempBufA)
  1.2871 +			{
  1.2872 +			User::Free(aBufferA);
  1.2873 +			aBufferA = NULL;
  1.2874 +			}
  1.2875 +		return err;
  1.2876 +		}
  1.2877 +	if (!aBufferB)
  1.2878 +		{
  1.2879 +		aBufferB = (TUint8*) User::AllocZ(KDataStride * KBufferSize.iHeight);
  1.2880 +		freeTempBufB = ETrue;
  1.2881 +		}
  1.2882 +	if (!aBufferB)
  1.2883 +		{
  1.2884 +		if (freeTempBufA)
  1.2885 +			{
  1.2886 +			User::Free(aBufferA);
  1.2887 +			aBufferA = NULL;
  1.2888 +			}
  1.2889 +		return KErrNoMemory;
  1.2890 +		}
  1.2891 +	err = aEGL->GetSgImageData(aImageB, aRectB, aBufferB);
  1.2892 +	if (err != KErrNone)
  1.2893 +		{
  1.2894 +		if (freeTempBufA)
  1.2895 +			{
  1.2896 +			User::Free(aBufferA);
  1.2897 +			aBufferA = NULL;
  1.2898 +			}
  1.2899 +		if (freeTempBufB)
  1.2900 +			{
  1.2901 +			User::Free(aBufferB);
  1.2902 +			aBufferB = NULL;
  1.2903 +			}
  1.2904 +		return err;
  1.2905 +		}	
  1.2906 +
  1.2907 +	// Perform a per-pixel comparison, scanline by scanline.
  1.2908 +	// The loop will break as soon as a mismatch is detected.
  1.2909 +	aMatch = ETrue;
  1.2910 +	for (TInt scanline = 0; (scanline < KBufferSize.iHeight) && aMatch; ++scanline)
  1.2911 +		{
  1.2912 +		TUint8* scanlineImageA = aBufferA + (scanline * KDataStride);
  1.2913 +		TUint8* scanlineImageB = aBufferB + (scanline * KDataStride);
  1.2914 +		aMatch = (Mem::Compare(scanlineImageA, KBufferSize.iWidth, scanlineImageB, KBufferSize.iWidth) == 0);
  1.2915 +		}
  1.2916 +
  1.2917 +	if (freeTempBufA)
  1.2918 +		{
  1.2919 +		User::Free(aBufferA);
  1.2920 +		aBufferA = NULL;
  1.2921 +		}
  1.2922 +	if (freeTempBufB)
  1.2923 +		{
  1.2924 +		User::Free(aBufferB);
  1.2925 +		aBufferB = NULL;
  1.2926 +		}
  1.2927 +	
  1.2928 +	return KErrNone;
  1.2929 +	}
  1.2930 +
  1.2931 +/**
  1.2932 +Second thread entry function for multi-threaded tests.
  1.2933 +*/
  1.2934 +TInt CTFbsGlyphData::ThreadFunction(TAny* aParam)
  1.2935 +	{
  1.2936 +	__UHEAP_MARK;
  1.2937 +	CTrapCleanup* cleanupStack = CTrapCleanup::New();
  1.2938 +	if (!cleanupStack)
  1.2939 +		{
  1.2940 +		return KErrNoMemory;
  1.2941 +		}
  1.2942 +
  1.2943 +	TGlyphDataThreadInfo* info = static_cast<TGlyphDataThreadInfo*>(aParam);
  1.2944 +	TRAPD(result,
  1.2945 +	switch(info->iTest)
  1.2946 +		{
  1.2947 +		case EGlyphDataMultiSessionTestShareGlyphs:
  1.2948 +			CTFbsGlyphData::ThreadShareGlyphsL(info->iThreadNum, info->iParams, info->iStep);
  1.2949 +			break;
  1.2950 +		case EGlyphDataMultiSessionTestStressAtlas:
  1.2951 +			CTFbsGlyphData::ThreadStressAtlasL(info->iThreadNum, info->iParams, info->iStep);
  1.2952 +			break;
  1.2953 +		default:
  1.2954 +			User::Leave(KErrArgument);
  1.2955 +		}
  1.2956 +	);
  1.2957 +
  1.2958 +	delete cleanupStack;
  1.2959 +	__UHEAP_MARKEND;
  1.2960 +	return result;
  1.2961 +	}
  1.2962 +
  1.2963 +
  1.2964 +
  1.2965 +/*
  1.2966 +	-----------------------------------------
  1.2967 +	Static utility Methods used by the tests.
  1.2968 +	-----------------------------------------
  1.2969 +*/
  1.2970 +
  1.2971 +
  1.2972 +
  1.2973 +/**
  1.2974 +Utility method that fills the RSgImage memory with RSgImages until either KErrNoMemory
  1.2975 +or KErrNoGraphicsMemory is returned.
  1.2976 +
  1.2977 +@param aSize The size of the image used to fill the graphics memory - a form of granularity
  1.2978 +@param aImages Returns the array of the images used to fill the graphics memory.
  1.2979 +@return KErrNoGraphicsMemory or KErrNoMemory if successful, otherwise one of the system
  1.2980 +	wide error codes.
  1.2981 + */
  1.2982 +/*static TInt FillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages)
  1.2983 +	{
  1.2984 +	TInt err = KErrNone;
  1.2985 +	while (KErrNone == err)
  1.2986 +		{
  1.2987 +		RSgImage sgImage;
  1.2988 +		err = sgImage.Create(TSgImageInfo(aSize, ESgPixelFormatA_8, ESgUsageBitOpenVgImage));
  1.2989 +		if (KErrNone == err)
  1.2990 +			{
  1.2991 +			err = aImages.Append(sgImage);
  1.2992 +			}
  1.2993 +		}
  1.2994 +	return err;
  1.2995 +	}*/
  1.2996 +
  1.2997 +/**
  1.2998 +Utility method that fills the RSgImage memory with RSgImages until either KErrNoMemory
  1.2999 +or KErrNoGraphicsMemory is returned and then closes one RSgImage to free up some memory.
  1.3000 +
  1.3001 +@param aSize The size of the image used to fill the graphics memory - a form of granularity
  1.3002 +@param aImages Returns the array of the images used to fill the graphics memory.
  1.3003 +@return KErrNone if successful, otherwise one of the system	wide error codes.
  1.3004 + */
  1.3005 +/*static TInt NearlyFillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages)
  1.3006 +	{
  1.3007 +	TInt err = FillGraphicsMemoryWithImages(aSize, aImages);
  1.3008 +	if (err == KErrNoMemory || err == KErrNoGraphicsMemory)
  1.3009 +		{
  1.3010 +		if (aImages.Count() > 0)
  1.3011 +			{
  1.3012 +			// Remove an image to free up some memory.
  1.3013 +			TInt lastIndex = aImages.Count() - 1;
  1.3014 +			aImages[lastIndex].Close();
  1.3015 +			aImages.Remove(lastIndex);
  1.3016 +			}
  1.3017 +		err = KErrNone;
  1.3018 +		}
  1.3019 +	return err;
  1.3020 +	}*/
  1.3021 +
  1.3022 +/**
  1.3023 +Static utility function. Creates an 8bpp RSgImage from 1bpp or 8bpp character
  1.3024 +data, with VGImage usage flag set.
  1.3025 +@param aData The character image data. Either in 8bpp or 1bpp RLE format.
  1.3026 +@param aSize The size of the character image in pixels.
  1.3027 +@param aType The type of glyph - Monochrome or Antialiased. 
  1.3028 +@param aSgImage A closed image which will be populated with 8bpp image data.
  1.3029 +*/
  1.3030 +static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage)
  1.3031 +	{
  1.3032 +	return CreateSgImageFromCharacterData(aData, aSize, aType, aImage, NULL, NULL);
  1.3033 +	}
  1.3034 +
  1.3035 +/**
  1.3036 +Static utility function. Creates an 8bpp RSgImage from 1bpp or 8bpp character
  1.3037 +data, with VGImage usage flag set. 
  1.3038 +This overload allows the memory for the buffers to be pre-created to avoid
  1.3039 +memory allocation failure during low-memory testing.
  1.3040 +@param aData The character image data. Either in 8bpp or 1bpp RLE format.
  1.3041 +@param aSize The size of the character image in pixels.
  1.3042 +@param aType The type of glyph - Monochrome or Antialiased. 
  1.3043 +@param aSgImage A closed image which will be populated with 8bpp image data.
  1.3044 +@param aBuffer1 If non-NULL, used as a memory buffer for reading the decoded 
  1.3045 +	image data into for monochrome images.
  1.3046 +@param aBuffer2 If non-NULL, used as a memory buffer for the decoded image
  1.3047 +	data for monochrome images.
  1.3048 +*/
  1.3049 +static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage, TUint8* aBuffer1, TUint8* aBuffer2)
  1.3050 +	{
  1.3051 +	TInt err = KErrNone;	
  1.3052 +	if (aSize == TSize(0, 0))
  1.3053 +		{
  1.3054 +		return KErrArgument;
  1.3055 +		}
  1.3056 +	TUint8* dataBuf = NULL;
  1.3057 +	TInt dataStride = 0;
  1.3058 +	TBool freeDataBuf = EFalse;
  1.3059 +	if (aType == EAntiAliasedGlyphBitmap)
  1.3060 +		{
  1.3061 +		dataBuf = const_cast<TUint8*>(aData);
  1.3062 +		dataStride = aSize.iWidth;
  1.3063 +		}
  1.3064 +	else if (aType == EMonochromeGlyphBitmap)
  1.3065 +		{
  1.3066 +		TUint8* binaryData = NULL;
  1.3067 +		TUint8* tempBuf = NULL;
  1.3068 +		TInt binaryDataStride = ((aSize.iWidth + 31) / 32) << 2;
  1.3069 +		TInt binaryDataSize = binaryDataStride * aSize.iHeight;
  1.3070 +		if (aBuffer1 && User::AllocLen(aBuffer1) >= binaryDataSize)
  1.3071 +			{
  1.3072 +			binaryData = aBuffer1;
  1.3073 +			}
  1.3074 +		else
  1.3075 +			{
  1.3076 +			tempBuf = (TUint8*) User::AllocZ(binaryDataSize);
  1.3077 +			if (!tempBuf)
  1.3078 +				{
  1.3079 +				return KErrNoMemory;
  1.3080 +				}
  1.3081 +			binaryData = tempBuf;
  1.3082 +			}
  1.3083 +		// Unpack the run length encoded data into 1bpp
  1.3084 +		DecodeBinaryData(aSize, aData, binaryDataStride, reinterpret_cast<TUint32*&>(binaryData));
  1.3085 +		dataStride = aSize.iWidth;
  1.3086 +		TInt byteDataSize = dataStride * aSize.iHeight;
  1.3087 +		TUint8* byteData = NULL;
  1.3088 +		// If aByteBuf supplied, use that instead of allocating a new buffer here.
  1.3089 +		if (aBuffer2 && User::AllocLen(aBuffer2) >= byteDataSize)
  1.3090 +			{
  1.3091 +			byteData = aBuffer2;
  1.3092 +			}
  1.3093 +		else
  1.3094 +			{
  1.3095 +			byteData = (TUint8*) User::AllocZ(byteDataSize);
  1.3096 +			if (!byteData)
  1.3097 +				{
  1.3098 +				User::Free(tempBuf);
  1.3099 +				return KErrNoMemory;
  1.3100 +				}
  1.3101 +			freeDataBuf = ETrue;
  1.3102 +			}
  1.3103 +		dataBuf = byteData;
  1.3104 +		for (TInt scanline = 0; scanline < aSize.iHeight; ++scanline)
  1.3105 +			{
  1.3106 +			TUint8* srcByte = binaryData;
  1.3107 +			for (TInt pixel = 0; pixel < aSize.iWidth; pixel++)
  1.3108 +				{
  1.3109 +				*(byteData+pixel) = ((*srcByte & (1 << (pixel % 8))) == 0) ? 0 : 0xFF;
  1.3110 +				if (((pixel + 1) % 8) == 0) srcByte++;
  1.3111 +				}
  1.3112 +			byteData += dataStride;
  1.3113 +			binaryData += binaryDataStride;
  1.3114 +			}
  1.3115 +		User::Free(tempBuf);
  1.3116 +		}
  1.3117 +	else
  1.3118 +		{
  1.3119 +		return KErrArgument;
  1.3120 +		}
  1.3121 +
  1.3122 +	// Create RSgImage from CFbsBitmap.
  1.3123 +	TSgImageInfo sgImageInfo(aSize, ESgPixelFormatA_8, ESgUsageBitOpenVgImage);
  1.3124 +	err = aImage.Create(sgImageInfo, dataBuf, dataStride);
  1.3125 +	if (freeDataBuf)
  1.3126 +		{
  1.3127 +		User::Free(dataBuf);
  1.3128 +		}
  1.3129 +	return err;
  1.3130 +	}
  1.3131 +
  1.3132 +
  1.3133 +/**
  1.3134 +Static utility function, Copies image data line(s) to a destination.
  1.3135 +@param aBinaryDataPtr pointer to a destination buffer.
  1.3136 +@param aBufferWords Stride of the image.
  1.3137 +@param aData Pointer to a source buffer.
  1.3138 +@param aBitShift Number of bits, binary data will be shifted. 
  1.3139 +@param aCharWidth Width of the image.
  1.3140 +@param aRepeatCount Number of lines to copy.
  1.3141 +*/
  1.3142 +static void CopyCharLine(TUint32*& aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth, TInt16 aRepeatCount)
  1.3143 +	{
  1.3144 +	aBitShift&=7;
  1.3145 +	TInt wordstocopy=(aCharWidth+31)>>5;
  1.3146 +	if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
  1.3147 +	TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
  1.3148 +	TUint32* dataword=(TUint32*)(TInt(aData)&~3);
  1.3149 +	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
  1.3150 +	
  1.3151 +	TUint32* startBinaryDataPtr = aBinaryDataPtr;
  1.3152 +	while(aBinaryDataPtr<ptrlimit)
  1.3153 +		{
  1.3154 +		*aBinaryDataPtr=*dataword++;
  1.3155 +		*aBinaryDataPtr>>=aBitShift;
  1.3156 +		if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
  1.3157 +		aBinaryDataPtr++;
  1.3158 +		}
  1.3159 +	
  1.3160 +	TUint32* curStartBinaryDataPtr = aBinaryDataPtr;
  1.3161 +	TInt byteToCopy = wordstocopy << 2;
  1.3162 +	while(aRepeatCount > 1)
  1.3163 +		{
  1.3164 +		Mem::Copy(curStartBinaryDataPtr, startBinaryDataPtr, byteToCopy);
  1.3165 +		curStartBinaryDataPtr += wordstocopy;
  1.3166 +		
  1.3167 +		aRepeatCount--;
  1.3168 +		}
  1.3169 +	aBinaryDataPtr = curStartBinaryDataPtr;
  1.3170 +	}
  1.3171 +
  1.3172 +/**
  1.3173 +Static utility function. Decodes a monochrome glyph whose data is run length encoded, 
  1.3174 +into a 1bpp bitmap.
  1.3175 +@param aDataSize Image size in pixels.
  1.3176 +@param aData Pointer to a source buffer.
  1.3177 +@param aStride Image data stride.
  1.3178 +@param aBinaryData Pointer to a destination buffer. This buffer must be allocated 
  1.3179 +	by the caller.
  1.3180 +*/
  1.3181 +static void DecodeBinaryData(const TSize& aDataSize, const TUint8* aData, TInt aStride,
  1.3182 +											TUint32* aBinaryData)
  1.3183 +	{
  1.3184 +	const TInt datalength = aDataSize.iWidth;
  1.3185 +	const TInt dataheight = aDataSize.iHeight;
  1.3186 +	TInt bitindex=0;
  1.3187 +	TInt16 repeatcount=0;
  1.3188 +	TUint32* slbuffer=aBinaryData;
  1.3189 +	const TInt slwords=aStride;
  1.3190 +
  1.3191 +	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
  1.3192 +		{
  1.3193 +		repeatcount=CFbsBitGc::Load16(aData+(bitindex>>3));
  1.3194 +		repeatcount>>=bitindex&7;
  1.3195 +		const TInt multilineflag=repeatcount&1;
  1.3196 +		repeatcount>>=1;
  1.3197 +		repeatcount&=0xf;
  1.3198 +		bitindex+=5;
  1.3199 +		if(multilineflag)
  1.3200 +			{
  1.3201 +			for(TInt currentline=0;currentline<repeatcount;currentline++)
  1.3202 +				{
  1.3203 +				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength, 1);
  1.3204 +				bitindex+=datalength;
  1.3205 +				}
  1.3206 +			}
  1.3207 +		else
  1.3208 +			{
  1.3209 +			CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength, repeatcount);
  1.3210 +			bitindex+=datalength;
  1.3211 +			}
  1.3212 +		}
  1.3213 +	}
  1.3214 +//--------------
  1.3215 +__CONSTRUCT_STEP__(FbsGlyphData)