fbs/fontandbitmapserver/tfbs/tfbsglyphdata.cpp
changeset 187 9f66f99ee56f
child 136 62bb7c97884c
equal deleted inserted replaced
103:2717213c588a 187:9f66f99ee56f
       
     1 // Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent - Internal Symbian test code
       
    19 */
       
    20 
       
    21 #include <EGL/egl.h>
       
    22 #include <VG/openvg.h>
       
    23 #include <graphics/fbsglyphmetricsarray.h> 
       
    24 #include <graphics/fbsglyphdataiterator.h>
       
    25 #include <sgresource/sgimage.h>
       
    26 #include <sgresource/sgdriver_test.h>
       
    27 #include <sgresource/sgdriver_profiling.h>
       
    28 #include "FbsMessage.h"
       
    29 #include "tfbsglyphdata.h"
       
    30 
       
    31 _LIT(KTypefaceName, "DejaVu Sans Condensed");
       
    32 //_LIT(KMonoTypefaceName, "DejaVu Sans Mono");
       
    33 const TInt KNumGlyphCodesLatin = 96;
       
    34 const TUint KDejaVuInvalidGlyphCode = 0;
       
    35 
       
    36 // Currently only used in debug. When TestMultithreadStressAtlas() test is enabled, #ifdef to be removed. 
       
    37 #ifdef _DEBUG
       
    38 const TInt KTestThreadMinHeapSize = 0x20000;
       
    39 const TInt KTestThreadMaxHeapSize = 0x20000;
       
    40 #endif
       
    41 
       
    42 // 'most significant bit' flag to ensure value is interpreted as a glyph code rather than an ascii code
       
    43 const TUint KGlyphCodeFlag = 0x80000000;      
       
    44 
       
    45 
       
    46 // Please note the following macros which enable helper functions, and are declared in the header.
       
    47 // SAVEGLYPHSTOMBMDURINGCOMPARISON and
       
    48 // SAVEGLYPHSTOMBMDEBUGFUNCTION
       
    49 
       
    50 /*
       
    51 Lookup table to convert from ascii code to
       
    52 glyph code for the Deja Vu family of fonts.
       
    53  */
       
    54 const TUint DejaVuASCIIToGlyphCode[] = 
       
    55 	{
       
    56 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
    57 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
    58 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       
    59 	0, 0, 3, 4, 5, 6, 7, 8, 9, 10,
       
    60 	11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
       
    61 	21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
       
    62 	31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
       
    63 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
       
    64 	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
       
    65 	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
       
    66 	71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
       
    67 	81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
       
    68 	91, 92, 93, 94, 95, 96, 97, 98,
       
    69 	};
       
    70 
       
    71 // Utility function declations - utilities used by the tests
       
    72 static TFontSpec GenerateDejaVuFontSpec(TInt aSeed);
       
    73 static void CopyCharLine(TUint32*& aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth, TInt16 aRepeatCount);
       
    74 static void DecodeBinaryData(const TSize& aDataSize, const TUint8* aData, TInt aStride,	TUint32* aBinaryData);
       
    75 static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage);
       
    76 static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage, TUint8* aBuffer1, TUint8* aBuffer2);
       
    77 // Following functions commented out because the tests which use these functions 
       
    78 // are currently commented out due to Broadcom defect 
       
    79 // ESLM-85LDV7 - TB10.1 Closing of RSgImage with duplicate handle used in same thread does not release GPU RAM
       
    80 //static TInt FillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages);
       
    81 //static TInt NearlyFillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages);
       
    82 
       
    83 #if defined (SAVEGLYPHSTOMBMDEBUGFUNCTION) || defined (SAVEGLYPHSTOMBMDURINGCOMPARISON)
       
    84 /**
       
    85 Static utility function. Converts an A8 RSgImage into a CFbsBitmap.
       
    86 To do this, the RSgImage is converted to an EGLImage, then to a VGImage,
       
    87 where the image memory is read into a CFbsBitmap.
       
    88 
       
    89 @param aEGL The EGL helper object that will read the SgImage into a memory buffer.
       
    90 @param aSgImage The RSgImage to convert.
       
    91 @param aRect A rectangular region of the RSgImage to convert.
       
    92 @param aBitmap On success, holds a pointer to a CFbsBitmap which contains the image
       
    93 	data of the RSgImage.
       
    94 @return One of the system-wide error codes.
       
    95 */
       
    96 static TInt CreateBitmapFromSgImage(CEGLHelper* aEGL, const RSgImage& aSgImage, const TRect& aRect, CFbsBitmap*& aBitmap)
       
    97 	{
       
    98 	TInt err = KErrNone;
       
    99 	const TSize bufferSize = aRect.Size();
       
   100 	const TInt dataStride = bufferSize.iWidth;
       
   101 
       
   102 	TUint8* imageBuffer = reinterpret_cast<TUint8*>(User::AllocZ(bufferSize.iHeight * dataStride));
       
   103 	if (!imageBuffer)
       
   104 		{
       
   105 		return KErrNoMemory;
       
   106 		}
       
   107 	err = aEGL->GetSgImageData(aSgImage, aRect, imageBuffer);
       
   108 	if (err != KErrNone)
       
   109 		{
       
   110 		User::Free(imageBuffer);
       
   111 		return err;
       
   112 		}
       
   113 	aBitmap = new CFbsBitmap();
       
   114 	if (!aBitmap)
       
   115 		{
       
   116 		User::Free(imageBuffer);
       
   117 		return KErrNoMemory;
       
   118 		}
       
   119 
       
   120 	err = aBitmap->Create(bufferSize, EGray256);
       
   121 	if (KErrNone == err)
       
   122 		{
       
   123 		TUint8* buf = imageBuffer;
       
   124 		aBitmap->BeginDataAccess();
       
   125 		TUint8* dataAddress = reinterpret_cast<TUint8*>(aBitmap->DataAddress());
       
   126 		const TInt dataStride = aBitmap->DataStride();	
       
   127 		for (TInt scanline = 0; scanline < bufferSize.iHeight; scanline++)
       
   128 			{
       
   129 			Mem::Copy(dataAddress, buf, bufferSize.iWidth);
       
   130 			dataAddress += dataStride;
       
   131 			buf += bufferSize.iWidth;
       
   132 			}
       
   133 		aBitmap->EndDataAccess(EFalse);
       
   134 		}
       
   135 	else
       
   136 		{
       
   137 		delete aBitmap;
       
   138 		aBitmap = NULL;
       
   139 		}
       
   140 
       
   141 	User::Free(imageBuffer);
       
   142 	return err;
       
   143 	}
       
   144 
       
   145 /**
       
   146 Utility function to aid with debugging.
       
   147 Saves a bitmap to file.
       
   148 
       
   149 @param aBmp Bitmap to save
       
   150 @param aMeta Optional. If specified, it is added to the name of the bitmap file.
       
   151 @param aRef Flag to show whether bitmap is a reference bitmap (ETrue) or test bitmap (EFalse).
       
   152 */
       
   153 static void SaveBmp(CFbsBitmap* aBmp, TPtrC* aMeta, TBool aRef)
       
   154 	{
       
   155 	if (!aBmp)
       
   156 		{
       
   157 		return;
       
   158 		}
       
   159 	
       
   160 	TBuf<256> testFileName;
       
   161 	if (aRef)
       
   162 		{
       
   163 		testFileName.Append(_L("Ref"));
       
   164 		}
       
   165 	else
       
   166 		{
       
   167 		testFileName.Append(_L("Test"));
       
   168 		}
       
   169 	if (aMeta)
       
   170 		{
       
   171 		testFileName.Append(*aMeta);
       
   172 		}
       
   173 
       
   174 	TFileName mbmFile;
       
   175 	TBuf<20> testPathName;
       
   176 	#ifdef __WINS__
       
   177 		testPathName.Append(_L("c:\\%S.mbm"));
       
   178 	#else
       
   179 		testPathName.Append(_L("e:\\%S.mbm"));
       
   180 	#endif
       
   181 	mbmFile.Format(testPathName, &testFileName);
       
   182 
       
   183 	// As this is for debugging purposes only, doesn't matter reporting whether
       
   184 	// saving succeeded or not.
       
   185 	aBmp->Save(mbmFile);
       
   186 	}
       
   187 #endif // SAVEGLYPHSTOMBMDEBUGFUNCTION OR SAVEGLYPHSTOMBMDURINGCOMPARISON
       
   188 
       
   189 
       
   190 #ifdef SAVEGLYPHSTOMBMDEBUGFUNCTION
       
   191 void CTFbsGlyphData::SaveRSgImagesAsMbms(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, const RSgImage& aImageB, const TRect& aRectB )
       
   192 	{
       
   193 	static TInt countToAppend = 0;
       
   194 
       
   195 	CFbsBitmap* bitmap = NULL;
       
   196 	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageA, aRectA, bitmap))
       
   197 		{
       
   198 		TBuf<KMaxFileName> buf( _L("String") );
       
   199 		buf.AppendNum( countToAppend );
       
   200 		TPtrC nameAppend( buf );
       
   201 
       
   202 		SaveBmp(bitmap, &nameAppend, EFalse);
       
   203 		}
       
   204 	delete bitmap;  
       
   205 	bitmap = NULL;
       
   206 
       
   207 	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageB, aRectB, bitmap))
       
   208 		{
       
   209 		TBuf<KMaxFileName> buf( _L("String") );
       
   210 		buf.AppendNum( countToAppend );
       
   211 		TPtrC nameAppend( buf );
       
   212 
       
   213 		SaveBmp(bitmap, &nameAppend, ETrue);
       
   214 		}
       
   215 	delete bitmap;
       
   216 	bitmap = NULL;
       
   217 
       
   218 	countToAppend++;
       
   219 	}
       
   220 
       
   221 /**
       
   222 Static debug utility method that outputs the glyph images of the given glyph
       
   223 codes for the given font to a file.
       
   224  */
       
   225 static void DumpFontGlyphs(CEGLHelper* aEGL, CFont* aFont, TInt aCodesCount)
       
   226 	{
       
   227 	TFontSpec fontSpec = aFont->FontSpecInTwips();
       
   228 	TOpenFontCharMetrics charMetrics;
       
   229 	TSize bitmapSize;
       
   230 	const TUint8* bitmapData = NULL;
       
   231 	
       
   232 	for (TInt glyphCode = 0; glyphCode < aCodesCount; glyphCode++)
       
   233 		{
       
   234 		CFont::TCharacterDataAvailability availability = aFont->GetCharacterData(glyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
       
   235 		if (availability == CFont::EAllCharacterData)
       
   236 			{
       
   237 			RSgImage characterDataImage;
       
   238 			TInt err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
       
   239 			if (err == KErrNone)
       
   240 				{
       
   241 				CFbsBitmap* bitmap = NULL;
       
   242 				err = CreateBitmapFromSgImage(aEGL, characterDataImage, TRect(TPoint(0, 0), bitmapSize), bitmap);
       
   243 				if (err == KErrNone)
       
   244 					{
       
   245 					TBuf<256> bitmapName;
       
   246 					bitmapName.AppendFormat(_L("%S-%i"), &(fontSpec.iTypeface.Name()), glyphCode);
       
   247 					TPtrC bitmapNamePtr(bitmapName);
       
   248 					SaveBmp(bitmap, &bitmapNamePtr, EFalse);
       
   249 					delete bitmap;
       
   250 					}
       
   251 				}
       
   252 			characterDataImage.Close();
       
   253 			}
       
   254 		}
       
   255 	}
       
   256 #endif // SAVEGLYPHSTOMBMDEBUGFUNCTION
       
   257 
       
   258 
       
   259 /**
       
   260 Utility to return a fontspec such that the font created from it will
       
   261 not match any other font generated by a different seed. The font
       
   262 will be useable by RFbsGlyphDataIterator and RFbsGlyphMetricsArray.
       
   263 It will always return a font based on the DejaVu fontspec, this is 
       
   264 so that the glyphcodes in DejaVuASCIIToGlyphCode are guaranteed to
       
   265 work.
       
   266 
       
   267 @param aSeed Specifies a variant of the fontspec to create. Passing the
       
   268 	same seed will cause the same TFontSpec to be returned.
       
   269 @return The generated fontspec. 
       
   270  */
       
   271 static TFontSpec GenerateDejaVuFontSpec(TInt aSeed)
       
   272 	{
       
   273 	const TInt KFontHeightStep = 4;
       
   274 	const TInt KFontInitialHeight = 8;
       
   275 	
       
   276 	const TInt KNumFontTypefaces = 3;
       
   277 	const TInt KNumFontBitmapTypes = 2;
       
   278 	const TInt KNumFontStyles = 4;
       
   279 	
       
   280 	TInt fontBitmapTypeVariant = aSeed % KNumFontBitmapTypes;
       
   281 	TInt fontStyleVariant = (aSeed / KNumFontBitmapTypes) % KNumFontStyles;
       
   282 	TInt fontTypefaceVariant = (aSeed / ( KNumFontStyles * KNumFontBitmapTypes)) % KNumFontTypefaces;
       
   283 	TInt fontHeightVariant = aSeed / (KNumFontStyles * KNumFontTypefaces * KNumFontBitmapTypes);
       
   284 	
       
   285 	TFontSpec fontSpec;	
       
   286 	fontSpec.iHeight = KFontInitialHeight + (fontHeightVariant * KFontHeightStep);
       
   287 	// Set the typeface name
       
   288 	// Set the style.
       
   289 	switch (fontStyleVariant)
       
   290 		{
       
   291 		case 1: // italic
       
   292 			fontSpec.iFontStyle.SetPosture(EPostureItalic);
       
   293 			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
       
   294 			break;
       
   295 		case 2: // bold
       
   296 			fontSpec.iFontStyle.SetPosture(EPostureUpright);
       
   297 			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
       
   298 			break;
       
   299 		case 3: // bold italic
       
   300 			fontSpec.iFontStyle.SetPosture(EPostureItalic);
       
   301 			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
       
   302 			break;
       
   303 		default: // normal 
       
   304 			fontSpec.iFontStyle.SetPosture(EPostureUpright);
       
   305 			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
       
   306 			break;
       
   307 		}
       
   308 	switch (fontTypefaceVariant)
       
   309 		{
       
   310 		case 1:
       
   311 			fontSpec.iTypeface.SetName(_L("DejaVu Sans Mono"));
       
   312 			break;
       
   313 		case 2:
       
   314 			fontSpec.iTypeface.SetName(_L("DejaVu Serif Condensed"));
       
   315 			break;
       
   316 		case 3:
       
   317 			fontSpec.iTypeface.SetName(_L("DejaVu Sans Condensed"));
       
   318 			break;
       
   319 		}
       
   320 	switch(fontBitmapTypeVariant)
       
   321 		{
       
   322 		case 1:
       
   323 			fontSpec.iFontStyle.SetBitmapType(EMonochromeGlyphBitmap);
       
   324 			break;
       
   325 		default:
       
   326 			fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
       
   327 			break;
       
   328 		}
       
   329 
       
   330 	return fontSpec;
       
   331 	}
       
   332 
       
   333 
       
   334 /**
       
   335  * 
       
   336  EGL helper class to retrieve image data from an SgImage into a memory buffer.
       
   337  */
       
   338 CEGLHelper::CEGLHelper() :
       
   339 	iDisplay(EGL_NO_DISPLAY),
       
   340 	iContext(EGL_NO_CONTEXT),
       
   341 	iSurface(EGL_NO_SURFACE)
       
   342 	{
       
   343 	}
       
   344 CEGLHelper::~CEGLHelper()
       
   345 	{
       
   346 	iMutex.Close();
       
   347 	eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
       
   348 	eglDestroyContext(iDisplay, iContext);
       
   349 	eglDestroySurface(iDisplay, iSurface);
       
   350 	eglTerminate(iDisplay);
       
   351 	eglReleaseThread();
       
   352 	iSgDriver.Close();
       
   353 	}
       
   354 
       
   355 /**
       
   356 Factory method to create CEGLHelper.
       
   357 @return A pointer to an instance of CEGLHelper.
       
   358  */
       
   359 CEGLHelper* CEGLHelper::NewL()
       
   360 	{
       
   361 	CEGLHelper* self = new CEGLHelper();
       
   362 	CleanupStack::PushL(self);
       
   363 	self->ConstructL();
       
   364 	CleanupStack::Pop(1); // self
       
   365 	return self;
       
   366 	}
       
   367 
       
   368 /**
       
   369 Opens handle to the process-wide synchronisation semaphore,
       
   370 loads EGL and VG extension function pointers,
       
   371 sets up EGL resources so that EGLImages can be constructed. 
       
   372  */
       
   373 void CEGLHelper::ConstructL()
       
   374 	{
       
   375 	_LIT(KEGLMutex, "TFbsGlyphDataEGLMutex");
       
   376 	User::LeaveIfError(iMutex.CreateGlobal(KEGLMutex, EOwnerProcess));
       
   377 	User::LeaveIfError(iSgDriver.Open());
       
   378 
       
   379 	iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
       
   380 	if (iDisplay == EGL_NO_DISPLAY)
       
   381 		{
       
   382 		User::Leave(KErrNotSupported);
       
   383 		}
       
   384 	if (EGL_TRUE != eglInitialize(iDisplay, NULL, NULL))
       
   385 		{
       
   386 		User::Leave(KErrNotSupported);
       
   387 		}
       
   388 	eglBindAPI(EGL_OPENVG_API);
       
   389 
       
   390 	// Load the necessary EGL extensions...
       
   391 	eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
       
   392 	eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
       
   393 	vgCreateImageTargetKHR = reinterpret_cast<TvgCreateEGLImageTargetKHRTypefPtr>(eglGetProcAddress("vgCreateEGLImageTargetKHR"));
       
   394 	if (!eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateImageTargetKHR)
       
   395 		{
       
   396 		User::Leave(KErrExtensionNotSupported);
       
   397 		}
       
   398 
       
   399 	// In order to create VGImages from EGLImages, a context must be current.
       
   400 	// Therefore create an EGLContext and EGLSurface to make current, using
       
   401 	// a dummy RSgImage.
       
   402 
       
   403 	RSgImage dummySurface;
       
   404 	TSgImageInfo dummySurfaceInfo(TSize(1, 1), ESgPixelFormatRGB_565, ESgUsageBitOpenVgSurface);
       
   405 	User::LeaveIfError(dummySurface.Create(dummySurfaceInfo, NULL, 0));
       
   406 	CleanupClosePushL(dummySurface);
       
   407 
       
   408 	EGLint configAttribs[] = 
       
   409 		{
       
   410 		EGL_MATCH_NATIVE_PIXMAP, (EGLint)&dummySurface,
       
   411 		EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
       
   412 		EGL_NONE
       
   413 		};
       
   414 
       
   415 	EGLint configId = 0;
       
   416 	EGLint numConfigs = 0;
       
   417 	if (EGL_FALSE == eglChooseConfig(iDisplay, configAttribs, &configId, 1, &numConfigs) || numConfigs == 0)
       
   418 		{
       
   419 		User::Leave(KErrGeneral);
       
   420 		}
       
   421 	iContext = eglCreateContext(iDisplay, configId, EGL_NO_CONTEXT, NULL);
       
   422 	if (iContext == EGL_NO_CONTEXT)
       
   423 		{
       
   424 		User::Leave(KErrGeneral);
       
   425 		}
       
   426 	iSurface = eglCreatePixmapSurface(iDisplay, configId, &dummySurface, NULL);
       
   427 	if (iSurface == EGL_NO_SURFACE)
       
   428 		{
       
   429 		User::Leave(KErrGeneral);
       
   430 		}
       
   431 	CleanupStack::PopAndDestroy(1); // dummySurface
       
   432 	}
       
   433 
       
   434 /**
       
   435 Retrieves the data from an A8 RSgImage into a buffer.
       
   436 To do this, the RSgImage is converted to an EGLImage, then to a VGImage,
       
   437 where the image memory is read into the given buffer.
       
   438 The function can be called from multiple threads and synchronisation
       
   439 with EGL is controlled via a mutex.
       
   440 
       
   441 @param aSgImage The RSgImage to convert.
       
   442 @param aRect A rectangular region of the RSgImage to convert.
       
   443 @param aBuf On success, contains the image data of the RSgImage.
       
   444 @return One of the system-wide error codes.
       
   445  */
       
   446 TInt CEGLHelper::GetSgImageData(const RSgImage& aSgImage, const TRect& aRect, TUint8*& aBuf)
       
   447 	{
       
   448 	const TSize bufferSize = aRect.Size();
       
   449 	const TInt dataStride = bufferSize.iWidth;
       
   450 
       
   451 	if (bufferSize == TSize(0,0))
       
   452 		{
       
   453 		return KErrNone;
       
   454 		}
       
   455 	iMutex.Wait();
       
   456 
       
   457 	TInt err = KErrNone;
       
   458 	EGLImageKHR eglImage;
       
   459 	if (EGL_FALSE == eglBindAPI(EGL_OPENVG_API))
       
   460 		{
       
   461 		err = KErrGeneral;
       
   462 		}
       
   463 	else if (EGL_FALSE == eglMakeCurrent(iDisplay, iSurface, iSurface, iContext))
       
   464 		{
       
   465 		err = KErrGeneral;
       
   466 		}
       
   467 	else
       
   468 		{
       
   469 		// Create EGLImages from the RSgImage.
       
   470 		EGLint imageAttribs[] =
       
   471 			{
       
   472 			EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 
       
   473 			EGL_NONE
       
   474 			};
       
   475 		eglImage = eglCreateImageKHR(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<EGLClientBuffer>(&aSgImage), imageAttribs);
       
   476 		if (eglImage == EGL_NO_IMAGE_KHR)
       
   477 			{
       
   478 			err = KErrArgument;
       
   479 			}
       
   480 		}
       
   481 	if (err == KErrNone)
       
   482 		{
       
   483 		// Create VGImages from the EGLImage.
       
   484 		VGImage vgImage = vgCreateImageTargetKHR(eglImage);
       
   485 		eglDestroyImageKHR(iDisplay, eglImage);
       
   486 		if (vgImage == VG_INVALID_HANDLE)
       
   487 			{
       
   488 			err = KErrArgument;
       
   489 			}
       
   490 		else
       
   491 			{
       
   492 			// Get the image data in 8bpp format
       
   493 			vgGetImageSubData(vgImage, aBuf, dataStride, VG_A_8, aRect.iTl.iX, aRect.iTl.iY, bufferSize.iWidth, bufferSize.iHeight);
       
   494 			vgDestroyImage(vgImage);
       
   495 			}
       
   496 		}
       
   497 	eglReleaseThread();
       
   498 	iMutex.Signal();
       
   499 	return err;
       
   500 	}
       
   501 
       
   502 CTFbsGlyphData::CTFbsGlyphData(CTestStep* aStep):
       
   503 	CTGraphicsBase(aStep)
       
   504 	{
       
   505 	}
       
   506 
       
   507 void CTFbsGlyphData::ConstructL()
       
   508 	{
       
   509 	User::LeaveIfError(Logger().ShareAuto());
       
   510 	User::LeaveIfError(RFbsSession::Connect());
       
   511 	iFbs = RFbsSession::GetSession();
       
   512 	iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
       
   513 	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTypefaceName, 15)));
       
   514 	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont2, TFontSpec(KTypefaceName, 8)));
       
   515 	
       
   516 	iGlyphCodesLatin = new(ELeave) TUint[KNumGlyphCodesLatin];
       
   517 	for (TInt ii = 0; ii < KNumGlyphCodesLatin; ++ii)
       
   518 		{
       
   519 		TUint asciiCode = ii+0x20; // ASCII characters from 0020 to 007F
       
   520 		iGlyphCodesLatin[ii] = DejaVuASCIIToGlyphCode[asciiCode];
       
   521 		}
       
   522 	
       
   523 	User::LeaveIfError(iSgDriver.Open());
       
   524 	iEGL = CEGLHelper::NewL();
       
   525 	
       
   526 	// Creating a CFbsBitmap will force the RFbsSession to allocate a scanline buffer
       
   527 	// now rather than in the middle of a test, thus avoiding heap check failure. 
       
   528 	CFbsBitmap* dummyBitmap = new (ELeave) CFbsBitmap;
       
   529 	CleanupStack::PushL(dummyBitmap);
       
   530 	User::LeaveIfError(dummyBitmap->Create(TSize(512, 1), EGray256));
       
   531 	CleanupStack::PopAndDestroy(dummyBitmap);
       
   532 
       
   533 	INFO_PRINTF1(_L("FBSERV Glyph Data Testing"));
       
   534 	}
       
   535 
       
   536 
       
   537 
       
   538 
       
   539 CTFbsGlyphData::~CTFbsGlyphData()
       
   540 	{
       
   541 	delete iEGL;
       
   542 	iSgDriver.Close();
       
   543 	if (iTs)
       
   544 		{
       
   545 		iTs->ReleaseFont(iFont);
       
   546 		iTs->ReleaseFont(iFont2);
       
   547 		}
       
   548 	delete iTs;
       
   549 	delete[] iGlyphCodesLatin;
       
   550 	User::Free(iTempBuf1);
       
   551 	User::Free(iTempBuf2);
       
   552 	RFbsSession::Disconnect();
       
   553 	}
       
   554 
       
   555 void CTFbsGlyphData::RunTestCaseL(TInt aCurTestCase)
       
   556 	{
       
   557 	((CTFbsGlyphDataStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
       
   558 	
       
   559 	TRAPD(leave, 
       
   560 
       
   561 	switch(aCurTestCase)
       
   562 		{
       
   563 	case 1:
       
   564 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0624"));
       
   565 		TestConsistencyWithGetCharacterData();
       
   566 		break;
       
   567 	case 2:
       
   568 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0625"));
       
   569 		TestInvalidGlyphCode();
       
   570 		break;
       
   571 	case 3:
       
   572 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0626"));
       
   573 		TestGlyphMetricsArrayParameters();
       
   574 		break;
       
   575 	case 4:
       
   576 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0627"));
       
   577 		TestGlyphMetricsArrayReuse();
       
   578 		break;
       
   579 	case 5:
       
   580 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0628"));
       
   581 		TestGlyphDataIteratorClose();
       
   582 		break;
       
   583 	case 6:
       
   584 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0629"));
       
   585 		TestGlyphDataIteratorSequence();
       
   586 		break;	
       
   587 	case 7:
       
   588 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0632"));
       
   589 		TestGlyphDataIteratorMultipleUsesOnMultipleFonts();
       
   590 		break;
       
   591 	case 8:
       
   592 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0633"));
       
   593 		TestGlyphDataIteratorImageValidity();
       
   594 		break;
       
   595 	case 9:
       
   596 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0634"));
       
   597 		TestGlyphDataIteratorOpenInvalidCode();
       
   598 		break;
       
   599 	case 10:
       
   600 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0636"));
       
   601 		TestGlyphDataIteratorOpenTwice();
       
   602 		break;
       
   603 	case 11:
       
   604 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0637"));
       
   605 		TestGlyphDataIteratorOpenTwiceWithDifferentFonts();
       
   606 		break;
       
   607 	case 12:
       
   608 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0638"));
       
   609 		TestGlyphDataIteratorOpenTooBigFont();
       
   610 		break;
       
   611 	case 13:
       
   612 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0640"));
       
   613 		TestGlyphDataIteratorOpenWithWrongArgument();
       
   614 		break;
       
   615 	case 14:
       
   616 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0641"));
       
   617 		TestGlyphDataIteratorImageMemoryLeak();
       
   618 		break;
       
   619 	case 15:
       
   620 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0662"));
       
   621 		TestGlyphDataIteratorNoGraphicsMemory();
       
   622 		break;
       
   623 	case 16: 
       
   624 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0659"));
       
   625 		TestGlyphDataIteratorLargeFontStress();
       
   626 		break;
       
   627 	case 17: 
       
   628 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0660"));
       
   629 		TestGlyphDataIteratorManyFontsStressL();
       
   630 		break;
       
   631 	case 18:
       
   632 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0666"));
       
   633 		TestGlyphDataIteratorNextIsAtomic();
       
   634 		break;
       
   635 	case 19:
       
   636 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0665"));
       
   637 		TestGlyphDataIteratorSameGlyphCodes();
       
   638 		break;
       
   639 	case 20:
       
   640 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0668"));
       
   641 		TestGlyphDataIteratorManyArraySizes();
       
   642 		break;
       
   643 	case 21:
       
   644 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0669"));
       
   645 		TestBitmapFontSupport();
       
   646 		break;
       
   647 	case 22:
       
   648 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0671"));
       
   649 		TestMultithreadShareSingleFont();
       
   650 		break;
       
   651 	case 23:
       
   652 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0672"));
       
   653 		TestMultithreadStressAtlas();
       
   654 		break;
       
   655     case 24:
       
   656         ((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0673"));
       
   657         TestGlyphMetricsArrayHeapOOML();
       
   658         break;
       
   659     case 25:
       
   660         ((CTFbsGlyphDataStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0674"));
       
   661         TestGlyphDataIteratorHeapOOML();
       
   662         break;
       
   663 	default:
       
   664 		((CTFbsGlyphDataStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
       
   665 		((CTFbsGlyphDataStep*)iStep)->CloseTMSGraphicsStep();
       
   666 		TestComplete();
       
   667 		break;
       
   668 		}
       
   669 	
       
   670 	); // TRAPD
       
   671 
       
   672 	if (leave != KErrNone)
       
   673 		{
       
   674 		ERR_PRINTF2(_L("Leave %d occurred during test"), leave);
       
   675 		iStep->SetTestStepResult(EFail);
       
   676 		}
       
   677 
       
   678 	((CTFbsGlyphDataStep*)iStep)->RecordTestResultL();
       
   679 	}
       
   680 
       
   681 
       
   682 /**
       
   683 @SYMTestCaseID		GRAPHICS-FBSERV-0624
       
   684 @SYMTestPriority	High
       
   685 @SYMTestType		UT
       
   686 @SYMTestStatus		Implemented
       
   687 @SYMPREQ			PREQ2678
       
   688 
       
   689 @SYMTestCaseDesc
       
   690 	Shows that RFbsGlyphMetricsArray::Get() and CFont::GetCharacterData() all 
       
   691 	provide the same metrics for the same set of glyph codes when using a CFbsFont.
       
   692 	Shows that RFbsGlyphDataIterator::Metrics() and CFont::GetCharacterData()
       
   693 	provide the same metrics for the same set of glyph codes.
       
   694 
       
   695 @SYMTestActions
       
   696 	i. Call RFbsGlyphMetricsArray::Get() for a set of glyph codes with 1 glyph code per call.
       
   697 	ii. Call RFbsGlyphMetricsArray::Get() for a set of glyph codes all in 1 call.
       
   698 	iii. Call RFbsGlyphDataIterator::Open() for a set of glyph codes.
       
   699 	iv. Call CFont::GetCharacterData() for the same set of glyph codes.
       
   700 	v. Compare the metrics for each glyph code from all calls.
       
   701 
       
   702 @SYMTestExpectedResults
       
   703 	For each glyph code, metrics received from RFbsGlyphMetricsArray::Get() and
       
   704 	CFont::GetCharacterData() and RFbsGlyphDataIterator are all the same.
       
   705 */
       
   706 void CTFbsGlyphData::TestConsistencyWithGetCharacterData()
       
   707 	{
       
   708 	INFO_PRINTF1(_L("Test RFbsGlyphMetricsArray::Get() with GetCharacterData()"));
       
   709 	
       
   710 	__UHEAP_MARK;
       
   711 
       
   712 	RFbsGlyphDataIterator iter;
       
   713 	RFbsGlyphMetricsArray glyphMetricsArray;
       
   714 	RFbsGlyphMetricsArray glyphMetricsArraySingle;
       
   715 	
       
   716 	TInt numMismatches = 0;
       
   717 	TOpenFontCharMetrics charMetrics;
       
   718 	TSize bitmapSize;
       
   719 	const TUint8* bitmapData = NULL;
       
   720 	
       
   721 	// Retrieve list of metrics for all glyph codes in one call
       
   722 	TInt err = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
   723 	TESTNOERROR(err);
       
   724 	if (err == KErrNone)
       
   725 		{
       
   726 		TEST(KNumGlyphCodesLatin == glyphMetricsArray.Count());
       
   727 		
       
   728 		TInt index = 0;
       
   729 		TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
   730 		TESTNOERROR(iterErr);
       
   731 		for (; iterErr == KErrNone; iterErr = iter.Next(), index++)
       
   732 			{
       
   733 			iFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
       
   734 			
       
   735 			// Retrieve the metrics for each glyph code, one at a time
       
   736 			TESTNOERROR(err = glyphMetricsArraySingle.Get(*iFont, &iGlyphCodesLatin[index], 1));
       
   737 			if (KErrNone == err)
       
   738 				{
       
   739 				// Compare GetCharacterData() metrics with single RFbsGlyphMetricsArray.
       
   740 				TUint32 comparison1 = CompareMetrics(charMetrics, glyphMetricsArraySingle[0]); 
       
   741 				// Compare GetCharacterData() metrics with large RFbsGlyphMetricsArray.
       
   742 				TUint32 comparison2 = CompareMetrics(charMetrics, glyphMetricsArray[index]);
       
   743 				// Compare GetCharacterData() metrics with RFbsGlyphDataIterator.
       
   744 				TUint32 comparison3 = CompareMetrics(charMetrics, iter.Metrics());
       
   745 				if (comparison1 != 0 || comparison2 != 0 || comparison3 != 0)
       
   746 					{
       
   747 					ERR_PRINTF5(_L("Glyphcode %i : Metrics mismatch: %d/%d/%d"), iGlyphCodesLatin[index], comparison1, comparison2, comparison3);
       
   748 					++numMismatches;
       
   749 					}
       
   750 				}
       
   751 			}
       
   752 			iter.Close();
       
   753 			glyphMetricsArray.Close();
       
   754 			glyphMetricsArraySingle.Close();
       
   755 			TESTE(iterErr == KErrNotFound, iterErr);
       
   756 			TEST(numMismatches == 0);
       
   757 			TEST(index == KNumGlyphCodesLatin);
       
   758 		}		
       
   759 	
       
   760 	__UHEAP_MARKEND;
       
   761 	}
       
   762 
       
   763 /**
       
   764 @return A series of success/fail booleans as a bitmask. A return value of zero
       
   765 	indicates all tests passed, a result of 1 indicates the first test case failed, 
       
   766 	a return of 3 indicates the first and second test failed, and so on.
       
   767 */
       
   768 TUint32 CTFbsGlyphData::CompareMetrics(const TOpenFontCharMetrics& aMetrics1, const TOpenFontCharMetrics& aMetrics2)
       
   769 	{
       
   770 	TUint32 result = 0;
       
   771 	result |= (aMetrics1.Width() == aMetrics2.Width()) ? 0 : (1 << 0);
       
   772 	result |= (aMetrics1.Height() == aMetrics2.Height()) ? 0 : (1 << 1);
       
   773 	result |= (aMetrics1.HorizBearingX() == aMetrics2.HorizBearingX()) ? 0 : (1 << 2);
       
   774 	result |= (aMetrics1.HorizBearingY() == aMetrics2.HorizBearingY()) ? 0 : (1 << 3);
       
   775 	result |= (aMetrics1.HorizAdvance() == aMetrics2.HorizAdvance()) ? 0 : (1 << 4);
       
   776 	result |= (aMetrics1.VertBearingX() == aMetrics2.VertBearingX()) ? 0 : (1 << 5);
       
   777 	result |= (aMetrics1.VertBearingY() == aMetrics2.VertBearingY()) ? 0 : (1 << 6);
       
   778 	result |= (aMetrics1.VertAdvance() == aMetrics2.VertAdvance()) ? 0 : (1 << 7);
       
   779 	TRect rect1;
       
   780 	aMetrics1.GetHorizBounds(rect1);
       
   781 	TRect rect2;
       
   782 	aMetrics2.GetHorizBounds(rect2);
       
   783 	result |= (rect1 == rect2) ? 0 : (1 << 8);
       
   784 	aMetrics1.GetVertBounds(rect1);
       
   785 	aMetrics2.GetVertBounds(rect2);
       
   786 	result |= (rect1 == rect2) ? 0 : (1 << 9);
       
   787 	return result;
       
   788 	}
       
   789 
       
   790 
       
   791 /**
       
   792 @SYMTestCaseID		GRAPHICS-FBSERV-0625
       
   793 @SYMTestPriority	High
       
   794 @SYMTestType		UT
       
   795 @SYMTestStatus		Implemented
       
   796 @SYMPREQ			PREQ2678
       
   797 
       
   798 @SYMTestCaseDesc
       
   799 	Shows that RFbsGlyphMetricsArray::Get(), and CFont::GetCharacterData() show the same 
       
   800 	behaviour when asked for metrics for an invalid glyph code when using a	CFbsFont. 
       
   801 	An invalid glyph code is one for which there is no character equivalent, such as 
       
   802 	0.
       
   803 
       
   804 @SYMTestActions
       
   805 	i. Call CFont::GetCharacterData() for an invalid glyph code.
       
   806 	ii. Call RFbsGlyphMetricsArray::Get() for the same invalid glyph code, and either 
       
   807 		compare the metrics if i. was successful, or check an error code was returned
       
   808 	
       
   809 @SYMTestExpectedResults
       
   810 	If GetCharacterData() is successful, the metrics received from
       
   811 	RFbsGlyphMetricsArray::Get() and CFont::GetCharacterData()	are the same, otherwise
       
   812 	RFbsGlyphMetricsArray::Get() should return an error code.
       
   813 */
       
   814 
       
   815 void CTFbsGlyphData::TestInvalidGlyphCode()
       
   816 	{
       
   817 	INFO_PRINTF1(_L("Test behaviour of RFbsGlyphMetricsArray::Get() with invalid glyph code is consistent with GetCharacterData"));
       
   818 	
       
   819 	__UHEAP_MARK;
       
   820 	TInt arrayErr = KErrNone;
       
   821 	RFbsGlyphMetricsArray glyphMetricsArray;
       
   822 	TOpenFontCharMetrics charMetrics;
       
   823 	TSize bitmapSize;
       
   824 	const TUint8* bitmapData = NULL;
       
   825 	
       
   826 	CFont::TCharacterDataAvailability availability = iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
       
   827 	if (availability == CFont::ENoCharacterData)
       
   828 		{
       
   829 		// Some rasterizers fail to return any data for KDejaVuInvalidGlyphCode, therefore
       
   830 		// rather than compare metrics, make sure RFbsGlyphDataIterator returns an error code.
       
   831 		WARN_PRINTF1(_L("Rasterizer failed to return data for invalid glyph code; not comparing glyph metrics"));
       
   832 		arrayErr = glyphMetricsArray.Get(*iFont, &KDejaVuInvalidGlyphCode, 1);
       
   833 		TESTE(arrayErr != KErrNone, arrayErr);
       
   834 		}
       
   835 	else
       
   836 		{
       
   837 		TESTNOERROR(arrayErr = glyphMetricsArray.Get(*iFont, &KDejaVuInvalidGlyphCode, 1));
       
   838 		if (KErrNone == arrayErr)
       
   839 			{
       
   840 			iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
       
   841 			TUint comparisonResult = CompareMetrics(charMetrics, glyphMetricsArray[0]);
       
   842 			TESTNOERROR( comparisonResult );
       
   843 			}
       
   844 		}
       
   845 	glyphMetricsArray.Close();
       
   846 
       
   847 	__UHEAP_MARKEND;
       
   848 	}
       
   849 
       
   850 /**
       
   851 @SYMTestCaseID		GRAPHICS-FBSERV-0626
       
   852 @SYMTestPriority	High
       
   853 @SYMTestType		UT
       
   854 @SYMTestStatus		Implemented
       
   855 @SYMPREQ			PREQ2678
       
   856 
       
   857 @SYMTestCaseDesc
       
   858 	Shows that RFbsGlyphMetricsArray::Get() returns with the correct error code when passed
       
   859 	various combinations of parameters, and preserves the state of the array.
       
   860 
       
   861 @SYMTestActions
       
   862 	Populate the array with a single metrics entry.
       
   863 	Call RFbsGlyphMetricsArray::Get with the following parameter combinations:
       
   864 		1. A negative count
       
   865 		2. A positive count and null glyph code array pointer
       
   866 		3. A zero count and non-null glyph code array pointer
       
   867 		4. A zero count and null glyph code array pointer
       
   868 
       
   869 @SYMTestExpectedResults
       
   870 	The following return codes are expected for each call:
       
   871 		1. KErrArgument
       
   872 		2. KErrArgument
       
   873 		3. KErrArgument
       
   874 		4. KErrArgument	
       
   875 	For each case the glyph metrics array remains unchanged.
       
   876 */
       
   877 void CTFbsGlyphData::TestGlyphMetricsArrayParameters()
       
   878 	{
       
   879 	INFO_PRINTF1(_L("Test the return values of GetGlyphMetrics with different parameters"));
       
   880 	__UHEAP_MARK;
       
   881 	TInt arrayErr = KErrNone;
       
   882 	TOpenFontCharMetrics dummyMetrics;
       
   883 	
       
   884 	RFbsGlyphMetricsArray glyphMetricsArray;
       
   885 	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 1);
       
   886 	TESTNOERROR(arrayErr);
       
   887 	TEST(1 == glyphMetricsArray.Count());
       
   888 	
       
   889 	// 1. Negative Count
       
   890 	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, -1);
       
   891 	TESTE(KErrArgument == arrayErr, arrayErr);
       
   892 	TEST(1 == glyphMetricsArray.Count());
       
   893 	
       
   894 	// 2. Positive Count and NULL Array Pointer
       
   895 	arrayErr = glyphMetricsArray.Get(*iFont, NULL, 1);
       
   896 	TESTE(KErrArgument == arrayErr, arrayErr);
       
   897 	TEST(1 == glyphMetricsArray.Count());
       
   898 
       
   899 	// 3. Zero Count & Valid Array Pointer
       
   900 	arrayErr = glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 0);
       
   901 	TESTE(KErrArgument == arrayErr, arrayErr);
       
   902 
       
   903 	// 4. Zero Count & NULL Array Pointer
       
   904 	arrayErr = glyphMetricsArray.Get(*iFont, NULL, 0);
       
   905 	TESTE(KErrArgument == arrayErr, arrayErr);
       
   906 
       
   907 	glyphMetricsArray.Close();
       
   908 	__UHEAP_MARKEND;
       
   909 	}
       
   910 
       
   911 /**
       
   912 @SYMTestCaseID		GRAPHICS-FBSERV-0627
       
   913 @SYMTestPriority	High
       
   914 @SYMTestType		UT
       
   915 @SYMTestStatus		Implemented
       
   916 @SYMPREQ			PREQ2678
       
   917 
       
   918 @SYMTestCaseDesc
       
   919 	Shows that reusing an RFbsGlyphMetricsArray works correctly.
       
   920 	In particular when the array is reused and filled with fewer entries
       
   921 	and when the array is reused and filled with more entries than previously.
       
   922 	It also shows that when re-using an array that has been populated, memory 
       
   923 	is not de-allocated if the new array of glyphs is smaller.
       
   924 
       
   925 @SYMTestActions
       
   926 	i. Call RFbsGlyphMetricsArray::Get() for a set of 10 glyph codes.
       
   927 	ii. Check that the RFbsGlyphMetricsArray has 10 entries.
       
   928 	iii. Find the size of the heap-cell allocated to the array.
       
   929 	iii. Call RFbsGlyphMetricsArray::Get() for a set of 5 glyph codes.
       
   930 	iv. Check that the RFbsGlyphMetricsArray has 5 entries.
       
   931 	v. Call RFbsGlyphMetricsArray::Get() for a set of 20 glyph codes.
       
   932 	vi. Check that the RFbsGlyphMetricsArray has 20 entries.
       
   933 	vii. Call RFbsGlyphMetricsArray::Get() for a set of 0 glyph codes.
       
   934 	viii. Check that the RFbsGlyphMetricsArray has 0 entries.
       
   935 	ix. Call RFbsGlyphMetricsArray::Get() for 1 glyph code.
       
   936 	x. Check that the RFbsGlyphMetricsArray has 1 entries.
       
   937 	xi. Close the RFbsGlyphMetricsArray.
       
   938 	xii. Check that the RFbsGlyphMetricsArray has 0 entries.
       
   939 	During the test check that the size of the heap cell allocated to the array
       
   940 	does not shrink.
       
   941 
       
   942 @SYMTestExpectedResults
       
   943 	After each call to RFbsGlyphMetricsArray::Get(), the array has the expected number of entries.
       
   944 */
       
   945 void CTFbsGlyphData::TestGlyphMetricsArrayReuse()
       
   946 	{
       
   947 	INFO_PRINTF1(_L("Test reuse of array with RFbsGlyphMetricsArray"));
       
   948 	__UHEAP_MARK;
       
   949 	
       
   950 	RFbsGlyphMetricsArray glyphMetricsArray;
       
   951 
       
   952 	// Retrieve list of metrics for 10 glyph codes
       
   953 	TESTNOERROR(glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, 10));
       
   954 	TEST(10 == glyphMetricsArray.Count());
       
   955 	
       
   956 	// Find the size of the heap cell allocated for the array.
       
   957 	TInt arrayHeapCellSize = User::Heap().AllocLen(&glyphMetricsArray[0]);
       
   958 	
       
   959 	// Retrieve list of metrics for 5 glyph codes.
       
   960 	// To ensure that different metrics are returned, use different glyph codes
       
   961 	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[10], 5));
       
   962 	TEST(5 == glyphMetricsArray.Count());
       
   963 	// Check that memory has not been de-allocated for a smaller array.
       
   964 	TEST(User::Heap().AllocLen(&glyphMetricsArray[0]) == arrayHeapCellSize);
       
   965 
       
   966 	// Retrieve list of metrics for 20 glyph codes.
       
   967 	// To ensure that different metrics are returned, use different glyph codes
       
   968 	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[15], 20));
       
   969 	TEST(20 == glyphMetricsArray.Count());
       
   970 	arrayHeapCellSize = User::Heap().AllocLen(&glyphMetricsArray[0]);
       
   971 		
       
   972 	// Retrieve list of metrics for 0 glyph codes.
       
   973 	TEST(KErrArgument == glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[35], 0));
       
   974 	// We can't check whether memory has been de-allocated as glyphMetricsArray[0]
       
   975 	// is null, therefore dereferencing it causes a panic.
       
   976 
       
   977 	// Retrieve list of metrics for 1 glyph code.
       
   978 	// To ensure that different metrics are returned, use different glyph code
       
   979 	TESTNOERROR(glyphMetricsArray.Get(*iFont, &iGlyphCodesLatin[35], 1));
       
   980 	TEST(1 == glyphMetricsArray.Count());
       
   981 	TEST(User::Heap().AllocLen(&glyphMetricsArray[0]) == arrayHeapCellSize);
       
   982 	
       
   983 	// Test that after closing a non-empty array, the array has 0 size.
       
   984 	glyphMetricsArray.Close();
       
   985 	TEST(0 == glyphMetricsArray.Count());
       
   986 	
       
   987 	__UHEAP_MARKEND;
       
   988 	}
       
   989 
       
   990 /**
       
   991 @SYMTestCaseID		GRAPHICS-FBSERV-0628
       
   992 @SYMTestPriority	High
       
   993 @SYMTestType		UT
       
   994 @SYMTestStatus		Implemented
       
   995 @SYMPREQ			PREQ2678
       
   996 
       
   997 @SYMTestCaseDesc
       
   998 	Validates the behaviour of RFbsGlyphDataIterator::Close() in the following use cases:
       
   999 		1. When called on an iterator instance which has not been opened, has no effect.
       
  1000 		2. When called on an open iterator closes the iterator 
       
  1001 
       
  1002 @SYMTestActions
       
  1003 	Use case 1:
       
  1004 		i. Create an RFbsGlyphDataIterator instance but do not open.
       
  1005 		ii. Call RFbsGlyphDataIterator::Close().
       
  1006 		
       
  1007 	Use case 2:
       
  1008 		i. Create an RFbsGlyphDataIterator instance and call RFbsGlyphDataIterator::Open().
       
  1009 		ii. Call RFbsGlyphDataIterator::Next() to prove the iterator is open.
       
  1010 		iii. Call RFbsGlyphDataIterator::Close().
       
  1011 		iv. Check that RFbsGlyphDataIterator::IsOpen() returns false.
       
  1012 	
       
  1013 @SYMTestExpectedResults
       
  1014 	Each call to RFbsGlyphDataIterator::IsOpen() returns the expected value.
       
  1015 */
       
  1016 void CTFbsGlyphData::TestGlyphDataIteratorClose()
       
  1017 	{
       
  1018 	INFO_PRINTF1(_L("Test closing an RFbsGlyphDataIterator"));
       
  1019 	__UHEAP_MARK;
       
  1020 
       
  1021 	// Use case 1
       
  1022 	RFbsGlyphDataIterator iter1;
       
  1023 	iter1.Close();
       
  1024 
       
  1025 	// Use case 2
       
  1026 	RFbsGlyphDataIterator iter2;
       
  1027 	TESTNOERROR(iter2.Open(*iFont, iGlyphCodesLatin, 1));
       
  1028 	TInt iterErr = iter2.Next();
       
  1029 	TESTE(KErrNotFound == iterErr, iterErr);
       
  1030 	iter2.Close();
       
  1031 	
       
  1032 	__UHEAP_MARKEND;
       
  1033 	}
       
  1034 
       
  1035 /**
       
  1036 @SYMTestCaseID		GRAPHICS-FBSERV-0629
       
  1037 @SYMTestPriority	High
       
  1038 @SYMTestType		UT
       
  1039 @SYMTestStatus		Implemented
       
  1040 @SYMPREQ			PREQ2678
       
  1041 
       
  1042 @SYMTestCaseDesc
       
  1043 	Show that the sequence of iterations when calling RFbsGlyphDataIterator::Next()
       
  1044 	matches the order of the array of glyph codes.
       
  1045 
       
  1046 @SYMTestActions
       
  1047 	i. Create an RFbsGlyphDataIterator instance and call RFbsGlyphDataIterator::Open()
       
  1048 		with an array of different glyph codes.
       
  1049 	ii. Iterate through all the glyph data.
       
  1050 		For each iteration check that the glyph code returned from 
       
  1051 		RFbsGlyphDataIterator::GlyphCode() matches the corresponding glyph code
       
  1052 		passed into Open().
       
  1053 
       
  1054 @SYMTestExpectedResults
       
  1055 	Each comparison of glyph code should match.
       
  1056 */
       
  1057 void CTFbsGlyphData::TestGlyphDataIteratorSequence()
       
  1058 	{
       
  1059 	INFO_PRINTF1(_L("Test the iterator sequence of RFbsGlyphDataIterator"));
       
  1060 	__UHEAP_MARK;
       
  1061 	
       
  1062 	TBool matches = ETrue;
       
  1063 	TInt index = 0;
       
  1064 
       
  1065 	RFbsGlyphDataIterator iter;
       
  1066 	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1067 	TESTNOERROR(iterErr);
       
  1068 	for (; index < KNumGlyphCodesLatin && matches && (iterErr == KErrNone); iterErr = iter.Next(), index++)
       
  1069 		{
       
  1070 		if (iter.GlyphCode() != iGlyphCodesLatin[index])
       
  1071 			{
       
  1072 			ERR_PRINTF4(_L("Failed at iteration %d: wanted %d, got %d"), index, iGlyphCodesLatin[index], iter.GlyphCode());
       
  1073 			matches = EFalse;
       
  1074 			}
       
  1075 		}
       
  1076 	iter.Close();
       
  1077 	TESTE(iterErr == KErrNotFound, iterErr);
       
  1078 	TEST(matches);
       
  1079 	TEST(index == KNumGlyphCodesLatin);
       
  1080 	iter.Close();
       
  1081 
       
  1082 	__UHEAP_MARKEND;
       
  1083 	}
       
  1084 
       
  1085 /**
       
  1086 @SYMTestCaseID		GRAPHICS-FBSERV-0632
       
  1087 @SYMTestPriority	High
       
  1088 @SYMTestType		UT
       
  1089 @SYMTestStatus		Implemented
       
  1090 @SYMPREQ			PREQ2678
       
  1091 
       
  1092 @SYMTestCaseDesc
       
  1093 	Ensure it is possible to reuse a closed iterator on another CFbsFont.
       
  1094 	
       
  1095 @SYMTestActions
       
  1096 	i. Open an RFbsGlyphDataIterator with sample data.
       
  1097 	ii. Iterate through until the end of the iterator has been reached by calling 
       
  1098 		Next() on the final element.
       
  1099 	iii. Re-open the same RFbsGlyphDataIterator with sample data on a different CFbsFont.
       
  1100 	iv. Iterate through a second time until the end has been reached by calling Next()
       
  1101 		on the final element.
       
  1102 	v. Close the iterator.
       
  1103 	vi. During both iterations the bitmap data returned and metrics are compared with
       
  1104 		the equivalent from GetCharacterData().
       
  1105 
       
  1106 @SYMTestExpectedResults
       
  1107 	The iterator should be opened successfully for both fonts and the data returned
       
  1108 	should match the data from GetCharacterData().
       
  1109 */
       
  1110 void CTFbsGlyphData::TestGlyphDataIteratorMultipleUsesOnMultipleFonts()
       
  1111 	{
       
  1112 	INFO_PRINTF1(_L("Reuse a closed iterator on a second CFbsFont"));
       
  1113 	__UHEAP_MARK;
       
  1114 	
       
  1115 	const TUint8* bitmapData;
       
  1116 	TSize bitmapSize;
       
  1117 	TOpenFontCharMetrics charMetrics;
       
  1118 	RFbsGlyphDataIterator iter;
       
  1119 	
       
  1120 	// Array of fonts to iterate through.
       
  1121 	CFbsFont* font[2] = {iFont, iFont2};
       
  1122 	
       
  1123 	for (TInt fontId = 0; fontId < 2; fontId++)
       
  1124 		{
       
  1125 		// On the first iteration, open and use a font until all glyphs have been iterated through.
       
  1126 		// On second iteration, use the same iterator on a different font and repeat.
       
  1127         CFbsFont* currentFont = font[fontId];
       
  1128 
       
  1129 		//Open the iterator on the first font and compare the returned bitmaps against GetCharacterData
       
  1130 		TInt iterErr = iter.Open(*currentFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1131 		TESTNOERROR(iterErr);
       
  1132 		TFontSpec fontSpec = currentFont->FontSpecInTwips();
       
  1133 		
       
  1134 		TInt index = 0;
       
  1135 		for (; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin); iterErr = iter.Next(), ++index)
       
  1136 			{
       
  1137 			currentFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
       
  1138 			
       
  1139 			TESTNOERROR(CompareMetrics(charMetrics, iter.Metrics()));
       
  1140 			if (bitmapSize == TSize(0, 0))
       
  1141 				{
       
  1142 				TEST(bitmapSize == iter.Rect().Size());
       
  1143 				}
       
  1144 			else
       
  1145 				{
       
  1146 				// Compare images.
       
  1147 				TBool match = EFalse;
       
  1148 				RSgImage characterDataImage;
       
  1149 				TInt err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
       
  1150 				if (err == KErrNone)
       
  1151 					{
       
  1152 					err = CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), match);
       
  1153 					}
       
  1154 				characterDataImage.Close();
       
  1155 				if (err != KErrNone)
       
  1156 					{
       
  1157 					TESTNOERROR(err);
       
  1158 					break;
       
  1159 					}
       
  1160 				TEST(match);
       
  1161 				}		
       
  1162 			}
       
  1163 		iter.Close();
       
  1164 		TESTE(iterErr == KErrNotFound, iterErr);
       
  1165 		TEST(index == KNumGlyphCodesLatin);
       
  1166 		}
       
  1167 	
       
  1168 	__UHEAP_MARKEND;
       
  1169 	}
       
  1170 
       
  1171 /**
       
  1172 @SYMTestCaseID		GRAPHICS-FBSERV-0633
       
  1173 @SYMTestPriority	High
       
  1174 @SYMTestType		UT
       
  1175 @SYMTestStatus		Implemented
       
  1176 @SYMPREQ			PREQ2678
       
  1177 
       
  1178 @SYMTestCaseDesc
       
  1179 	Check that for various Latin fonts, the images of the glyphs stored on the 
       
  1180 	RSgImage matches those provided by GetCharacterData().
       
  1181 
       
  1182 @SYMTestActions
       
  1183 	Create a selection of fonts, using various typefaces, sizes and bitmap types.
       
  1184 	For each font:
       
  1185 	i. Open the RFbsGlyphDataIterator and iterate each glyph.
       
  1186 	ii. For each glyph, call GetCharacterData() with the expected glyph code.
       
  1187 	iii. Convert the character data to an RSgImage.
       
  1188 	iv. Perform a comparison between the character RSgImage and the iterator 
       
  1189 		image. 
       
  1190 	v. After all iterations, close the iterator and check all expected glyphs
       
  1191 		were iterated through.
       
  1192 
       
  1193 @SYMTestExpectedResults
       
  1194 	All glyph images should match.
       
  1195 */
       
  1196 void CTFbsGlyphData::TestGlyphDataIteratorImageValidity()
       
  1197 	{
       
  1198 	INFO_PRINTF1(_L("Test the glyph images of the iterator match GetCharacterData()"));
       
  1199 	__UHEAP_MARK;
       
  1200 	
       
  1201 	const TInt KNumFonts = 20;
       
  1202 	
       
  1203 	// Create a new typeface store for this test so that heap checking will not
       
  1204 	// be affected by cached CFbsFonts.
       
  1205 	CFbsTypefaceStore* typefaceStore = NULL;
       
  1206 	TRAPD(err, typefaceStore = CFbsTypefaceStore::NewL(NULL));
       
  1207 	if (err != KErrNone)
       
  1208 		{
       
  1209 		ERR_PRINTF1(_L("Failed to construct typeface store. Test aborted."));
       
  1210 		__UHEAP_RESET;
       
  1211 		iStep->SetTestStepResult(EFail);
       
  1212 		return;
       
  1213 		}
       
  1214 	
       
  1215 	for (TInt font = 0; font < KNumFonts; ++font)
       
  1216 		{
       
  1217 		// Use either a pre-created bitmap-font TFontSpec, or generate a Deja-vu one.
       
  1218 		TFontSpec fontSpec = GenerateDejaVuFontSpec(font);
       
  1219 		CFbsFont* latinFont = NULL;
       
  1220 		TESTNOERROR(typefaceStore->GetNearestFontToDesignHeightInPixels((CFont*&)latinFont, fontSpec));	
       
  1221 		
       
  1222 		fontSpec = latinFont->FontSpecInTwips();
       
  1223 		InfoPrintFontSpec(*latinFont);
       
  1224 				
       
  1225 		RFbsGlyphDataIterator iter;
       
  1226 		TInt iterErr = iter.Open(*latinFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1227 		TESTNOERROR(iterErr);
       
  1228 
       
  1229 		err = KErrNone;
       
  1230 		TInt index = 0;
       
  1231 		TInt numMismatches = 0;
       
  1232 		// For each iteration, get the character data of the expected glyph.
       
  1233 		// Create RSgImage from character data, and compare iter image with constructed image.
       
  1234 		for (; (iterErr == KErrNone) && (err == KErrNone) && (index < KNumGlyphCodesLatin); (iterErr = iter.Next()), ++index)
       
  1235 			{
       
  1236 			TBool glyphMatches = ETrue;
       
  1237 			const RSgImage& iteratorImage = iter.Image();
       
  1238 
       
  1239 			const TUint8* bitmapData = NULL;
       
  1240 			TSize bitmapSize;
       
  1241 			TOpenFontCharMetrics metrics;
       
  1242 			TInt characterDataAvailability = latinFont->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
       
  1243 			if (bitmapSize == TSize(0, 0))
       
  1244 				{
       
  1245 				glyphMatches = (bitmapSize == iter.Rect().Size());
       
  1246 				}
       
  1247 			else
       
  1248 				{
       
  1249 				RSgImage characterDataImage;
       
  1250 				TESTNOERROR(CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage));
       
  1251 				err = CompareSgImages(iEGL, iteratorImage, iter.Rect(), characterDataImage, TRect(bitmapSize), glyphMatches);
       
  1252 				characterDataImage.Close();
       
  1253 				}
       
  1254 			if (err == KErrNone && !glyphMatches)
       
  1255 				{
       
  1256 				ERR_PRINTF2(_L("Glyphcode %i : Image mismatch"), iGlyphCodesLatin[index]);
       
  1257 				++numMismatches;
       
  1258 				}
       
  1259 			}
       
  1260 		iter.Close();
       
  1261 		TESTNOERROR(err);
       
  1262 		TESTE(iterErr == KErrNotFound, iterErr);
       
  1263 		TEST(index == KNumGlyphCodesLatin);	
       
  1264 		TEST(numMismatches == 0);
       
  1265 		typefaceStore->ReleaseFont(latinFont);
       
  1266 		}
       
  1267 	delete typefaceStore;
       
  1268 	__UHEAP_MARKEND;
       
  1269 	}
       
  1270 
       
  1271 /**
       
  1272 @SYMTestCaseID      GRAPHICS-FBSERV-0634
       
  1273 @SYMTestPriority    High
       
  1274 @SYMTestType        UT
       
  1275 @SYMTestStatus      Implemented
       
  1276 @SYMPREQ            PREQ2678
       
  1277 
       
  1278 @SYMTestCaseDesc
       
  1279 	To ensure that if the glyph image iterator has a current invalid 
       
  1280 	character code, the SgImage returned by the iterator will match 
       
  1281 	to the image obtained from the GetCharacterData() function
       
  1282 @SYMTestActions
       
  1283 	i. Retrieve bitmap data and metrics by using GetCharacterData().
       
  1284 	ii. Open a glyph data iterator passing an invalid character code.
       
  1285 	iii. If i. was unsuccessful, check that opening the iterator returned
       
  1286 		an error code and skip to ix.
       
  1287 	iv. Create SgImage from bitmap data.
       
  1288 	v. Get SgImage from the glyph data iterator.
       
  1289 	vi. Compare SgImages obtained on iv and v steps.
       
  1290 	vii. Get font metrics from the glyph data iterator.
       
  1291 	viii. Compare metrics obtained on i and vii steps.
       
  1292 	vii. Close the iterator.
       
  1293 
       
  1294 @SYMTestExpectedResults
       
  1295 	If the request to get the character data failed, the return value of 
       
  1296 	RFbsGlyphDataIterator::Open() must not be KErrNone.
       
  1297 	Otherwise, images obtained from the iterator and GetCharacterData() should
       
  1298 	match.
       
  1299 */
       
  1300 void CTFbsGlyphData::TestGlyphDataIteratorOpenInvalidCode()
       
  1301 	{
       
  1302 	INFO_PRINTF1(_L("Ensure that the image returned by the iterator will \
       
  1303 match to the image obtained from GetCharacterData() if character code is invalid"));
       
  1304 	__UHEAP_MARK;
       
  1305 
       
  1306 	const TUint8* bitmapData = NULL;
       
  1307 	TSize bitmapSize;
       
  1308 	TOpenFontCharMetrics metrics;
       
  1309 	const TFontSpec fontSpec = iFont->FontSpecInTwips();
       
  1310 	CFont::TCharacterDataAvailability availability = iFont->GetCharacterData(KDejaVuInvalidGlyphCode | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
       
  1311 
       
  1312 	RFbsGlyphDataIterator iter;
       
  1313 	TInt err = iter.Open(*iFont, &KDejaVuInvalidGlyphCode, 1);
       
  1314 	if (availability == CFont::ENoCharacterData)
       
  1315 		{
       
  1316 		// Some rasterizers fail to return any data for KDejaVuInvalidGlyphCode, therefore
       
  1317 		// rather than compare image contents, make sure RFbsGlyphDataIterator returns an error code.
       
  1318 		WARN_PRINTF1(_L("Rasterizer failed to return data for invalid glyph code; not comparing image contents"));
       
  1319 		TESTE(err != KErrNone, err);
       
  1320 		}
       
  1321 	else
       
  1322 		{
       
  1323 		TESTNOERROR(err);
       
  1324 		if (err == KErrNone)
       
  1325 			{
       
  1326 			TBool glyphMatches = EFalse;
       
  1327 			if (bitmapSize == TSize(0, 0))
       
  1328 				{
       
  1329 				glyphMatches = (bitmapSize == iter.Rect().Size());
       
  1330 				}
       
  1331 			else
       
  1332 				{
       
  1333 				RSgImage characterDataImage;
       
  1334 				TESTNOERROR(CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage));
       
  1335 				TESTNOERROR(CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), glyphMatches));
       
  1336 				characterDataImage.Close();
       
  1337 				}
       
  1338 			TESTNOERROR(CompareMetrics(metrics, iter.Metrics()));
       
  1339 			TEST(glyphMatches);
       
  1340 			}
       
  1341 		}
       
  1342 	iter.Close();
       
  1343 
       
  1344 	__UHEAP_MARKEND;
       
  1345 	}
       
  1346 
       
  1347 
       
  1348 /**
       
  1349 @SYMTestCaseID      GRAPHICS-FBSERV-0636
       
  1350 @SYMTestPriority    High
       
  1351 @SYMTestType        UT
       
  1352 @SYMTestStatus      Implemented
       
  1353 @SYMPREQ            PREQ2678
       
  1354 
       
  1355 @SYMTestCaseDesc
       
  1356 	To ensure that opening the glyph data iterator which has already been opened with the same font
       
  1357 	has no effect on the state of the iterator.
       
  1358 @SYMTestActions
       
  1359 	i. Open glyph data iterator on 2 glyph codes.
       
  1360 	ii. Try to open the glyph data iterator again on the same font.
       
  1361 	iii. Call RFbsGlyphDataIterator::Next() on the iterator and check error code, making the last
       
  1362 		glyph code the current iteration.
       
  1363 	iv. Call RFbsGlyphDataIterator::Next() again.
       
  1364 @SYMTestExpectedResults
       
  1365 	The second attempt to open the glyph data iterator will result an error with code KErrInUse.
       
  1366 	The last two calls to RFbsGlyphDataIterator::Next() should return KErrNone and KErrNotFound
       
  1367 	respectively, showing the iterator was not modified when the call to Open() failed.
       
  1368 */
       
  1369 void CTFbsGlyphData::TestGlyphDataIteratorOpenTwice()
       
  1370 	{
       
  1371 	INFO_PRINTF1(_L("Ensure that opening the glyph data iterator which has already been opened with the same font has no effect"));
       
  1372 	__UHEAP_MARK;
       
  1373 
       
  1374 	RFbsGlyphDataIterator iter;
       
  1375 	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 2);
       
  1376 	TESTNOERROR(iterErr);
       
  1377 	
       
  1378 	iterErr = iter.Open(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1379 	TESTE(iterErr == KErrInUse, iterErr);
       
  1380 	iterErr = iter.Next();
       
  1381 	TESTNOERROR(iterErr);
       
  1382 	iterErr = iter.Next();
       
  1383 	TESTE(iterErr == KErrNotFound, iterErr);
       
  1384 	iter.Close();
       
  1385 
       
  1386 	__UHEAP_MARKEND;
       
  1387 	}
       
  1388 
       
  1389 /**
       
  1390 @SYMTestCaseID      GRAPHICS-FBSERV-0637
       
  1391 @SYMTestPriority    High
       
  1392 @SYMTestType        UT
       
  1393 @SYMTestStatus      Implemented
       
  1394 @SYMPREQ            PREQ2678
       
  1395 
       
  1396 @SYMTestCaseDesc
       
  1397 	To ensure that opening the glyph data iterator which has already been opened with different font
       
  1398 	has no effect on the state of the iterator.
       
  1399 @SYMTestActions
       
  1400 	i. Open glyph data iterator on an 2 glyph codes
       
  1401 	ii. Try to open the glyph data iterator again with a different font.
       
  1402 	iii. Call RFbsGlyphDataIterator::Next() on the iterator and check error code, making the last
       
  1403 		glyph code the current iteration.
       
  1404 	iv. Call RFbsGlyphDataIterator::Next() again.
       
  1405 @SYMTestExpectedResults
       
  1406 	The second attempt to open the glyph data iterator will result an error with code KErrInUse.
       
  1407 	The Next() call after this should return KErrNone, signifying the iterator is still open.
       
  1408 	The last Next() call should return KErrNotFound, signifying the iterator has iterated 
       
  1409 	through the two original glyph codes.
       
  1410 */
       
  1411 void CTFbsGlyphData::TestGlyphDataIteratorOpenTwiceWithDifferentFonts()
       
  1412 	{
       
  1413 	INFO_PRINTF1(_L("Ensure that opening the glyph data iterator which has already been opened with different font has no effect"));
       
  1414 	__UHEAP_MARK;
       
  1415 
       
  1416 	RFbsGlyphDataIterator iter;
       
  1417 	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 2);
       
  1418 	TESTNOERROR(iterErr);
       
  1419 
       
  1420 	iterErr = iter.Open(*iFont2, iGlyphCodesLatin, 2);
       
  1421 	TESTE(iterErr == KErrInUse, iterErr);
       
  1422 	iterErr = iter.Next();
       
  1423 	TESTNOERROR(iterErr);
       
  1424 	iterErr = iter.Next();
       
  1425 	TESTE(iterErr == KErrNotFound, iterErr);
       
  1426 	iter.Close();
       
  1427 
       
  1428 	__UHEAP_MARKEND;
       
  1429 	}
       
  1430 
       
  1431 /**
       
  1432 @SYMTestCaseID      GRAPHICS-FBSERV-0638
       
  1433 @SYMTestPriority    High
       
  1434 @SYMTestType        UT
       
  1435 @SYMTestStatus      Implemented
       
  1436 @SYMPREQ            PREQ2678
       
  1437 
       
  1438 @SYMTestCaseDesc
       
  1439 	To ensure that opening of glyph data iterator with the font greater than 
       
  1440 	2048 by 2048 will not be supported 
       
  1441 @SYMTestActions
       
  1442 	i. Create font with the height greater than 2048
       
  1443 	ii. Try to open the glyph data iterator with the font created on previous step
       
  1444 	iii Release the font
       
  1445 @SYMTestExpectedResults
       
  1446 	Must fail with error code KErrTooBig
       
  1447 */
       
  1448 void CTFbsGlyphData::TestGlyphDataIteratorOpenTooBigFont()
       
  1449 	{
       
  1450 	INFO_PRINTF1(_L("To ensure that opening of glyph data iterator with the font greater than 2048X2048 will not be supported"));
       
  1451 	__UHEAP_MARK;
       
  1452 
       
  1453 	CFbsFont* bigFont;
       
  1454 	const TInt maxHeight = 2048;
       
  1455 	const TInt maxHeightLimit = maxHeight + 20; //max size after we stop trying to create the font
       
  1456 	// the loop below will guarantee that if the font with the size greater than 2048 is available it will be created
       
  1457 	for(TInt height = maxHeight + 1; height < maxHeightLimit; height++)
       
  1458 		{
       
  1459 		TESTNOERROR(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)bigFont, TFontSpec(KTypefaceName, height)));
       
  1460 		TInt realHeight = bigFont->FontMaxHeight();
       
  1461 		if(realHeight > maxHeight)
       
  1462 			{
       
  1463 			break;
       
  1464 			}
       
  1465 		iTs->ReleaseFont(bigFont);
       
  1466 		bigFont = NULL;
       
  1467 		}
       
  1468 
       
  1469 	if (bigFont)
       
  1470 		{
       
  1471 		RFbsGlyphDataIterator iter;
       
  1472 		TInt iterErr = iter.Open(*bigFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1473 		TESTE(iterErr == KErrTooBig, iterErr);
       
  1474 		iTs->ReleaseFont(bigFont); 
       
  1475 		}
       
  1476 	else
       
  1477 		{
       
  1478 		//It is legitimate to fail to create the font, as there are no requirements for the rasterizer here to support such big font. 
       
  1479 		//In this case we will skip the test.
       
  1480 		WARN_PRINTF1(_L("Failed to create font with height greater than 2048"));
       
  1481 		}
       
  1482 
       
  1483 	__UHEAP_MARKEND;
       
  1484 	}
       
  1485 
       
  1486 
       
  1487 
       
  1488 
       
  1489 /**
       
  1490 @SYMTestCaseID      GRAPHICS-FBSERV-0640
       
  1491 @SYMTestPriority    High
       
  1492 @SYMTestType        UT
       
  1493 @SYMTestStatus      Implemented
       
  1494 @SYMPREQ            PREQ2678
       
  1495 
       
  1496 @SYMTestCaseDesc
       
  1497 	To ensure that the glyph data iterator processes wrong arguments correctly
       
  1498 @SYMTestActions
       
  1499 	i. Try to open the glyph data iterator with the negative count passed in
       
  1500 	ii. Try to open the glyph data iterator with the positive count and NULL 
       
  1501 	glyph code array pointer passed in
       
  1502 	iii. Try to open the glyph data iterator with a valid glyph code array and 
       
  1503 	count equal to zero
       
  1504 @SYMTestExpectedResults
       
  1505 	At all steps the returned value is set to KErrArgument.
       
  1506 */
       
  1507 void CTFbsGlyphData::TestGlyphDataIteratorOpenWithWrongArgument()
       
  1508 	{
       
  1509 	INFO_PRINTF1(_L("To ensure that the glyph data iterator processes wrong arguments correctly"));
       
  1510 	__UHEAP_MARK;
       
  1511 
       
  1512 	RFbsGlyphDataIterator iter;
       
  1513 	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, -1);
       
  1514 	TESTE(iterErr == KErrArgument, iterErr);
       
  1515 	
       
  1516 	iterErr = iter.Open(*iFont, NULL, 1);
       
  1517 	TESTE(iterErr == KErrArgument, iterErr);
       
  1518 	
       
  1519 	iterErr = iter.Open(*iFont, iGlyphCodesLatin, 0);
       
  1520 	TESTE(iterErr == KErrArgument, iterErr);
       
  1521 	
       
  1522 	__UHEAP_MARKEND;
       
  1523 	}
       
  1524 
       
  1525 /**
       
  1526 @SYMTestCaseID      GRAPHICS-FBSERV-0641
       
  1527 @SYMTestPriority    High
       
  1528 @SYMTestType        UT
       
  1529 @SYMTestStatus      Implemented
       
  1530 @SYMPREQ            PREQ2678
       
  1531 
       
  1532 @SYMTestCaseDesc
       
  1533 	To ensure that all allocated RSgImages were released after the
       
  1534 	glyph data iterator has been opened and closed multiple times.
       
  1535 
       
  1536 @SYMTestActions
       
  1537 	i. Retrieve MSgDriver_Test interface from the SgDriver
       
  1538 	ii. Mark alloc start and obtain resorce count from the interface
       
  1539 	iii. Iterate through glyph data by calling RFbsGlyphDataIterator::Next() 
       
  1540 	iv. Retrieve SgImage from the glyph data iterator instance
       
  1541 	v. Repeate steps iii and iv multiple times
       
  1542 	vi. Release font
       
  1543 	vii.  Mark alloc end and obtain resorce count from the interface
       
  1544 
       
  1545 @SYMTestExpectedResults
       
  1546 	Resorce count at the end matches resorce count at the beginning. 
       
  1547 */
       
  1548 void CTFbsGlyphData::TestGlyphDataIteratorImageMemoryLeak()
       
  1549 	{
       
  1550 	__UHEAP_MARK;
       
  1551 	
       
  1552 	MSgDriver_Test* sgDriverTestInterface = NULL; 
       
  1553 	TInt err = iSgDriver.GetInterface(sgDriverTestInterface);
       
  1554 	if(err != KErrNone)
       
  1555 		{
       
  1556 		__UHEAP_MARKEND;
       
  1557 		WARN_PRINTF2(_L("Failed to obtain MSgDriver_Test interface with error code: %d, the test will be skipped"), err);
       
  1558 		return;
       
  1559 		}
       
  1560 
       
  1561 	TEST(sgDriverTestInterface != NULL);
       
  1562 	sgDriverTestInterface->AllocMarkStart();
       
  1563 
       
  1564 	MSgDriver_Profiling* sgDriverProfilInterface = NULL;
       
  1565 	err = iSgDriver.GetInterface(sgDriverProfilInterface);
       
  1566 	if(err != KErrNone)
       
  1567 		{
       
  1568 		sgDriverTestInterface->AllocMarkEnd(0);
       
  1569 		__UHEAP_MARKEND;
       
  1570 		WARN_PRINTF2(_L("Failed to obtain MSgDriver_Profiling interface with error code: %d, the test will be skipped"), err);
       
  1571 		return;
       
  1572 		}
       
  1573 	const TInt resCount = sgDriverProfilInterface->LocalResourceCount();
       
  1574 
       
  1575 	CFbsFont* font = NULL;
       
  1576 	err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KTypefaceName, 15));
       
  1577 	TESTNOERROR(err);
       
  1578 	if(err != KErrNone)
       
  1579 		{
       
  1580 		__UHEAP_MARKEND;
       
  1581 		return;
       
  1582 		}
       
  1583 
       
  1584 	for (TInt ii = 0; ii < 10; ii++)
       
  1585 		{
       
  1586 		TInt index = 0;
       
  1587 		RFbsGlyphDataIterator iter;
       
  1588 		TInt iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1589 		TESTNOERROR(iterErr);
       
  1590 		for (; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin); iterErr = iter.Next(), ++index)
       
  1591 			{
       
  1592 			const RSgImage& image = iter.Image();
       
  1593 			}
       
  1594 		iter.Close();
       
  1595 		TEST(index == KNumGlyphCodesLatin);
       
  1596 		TESTE(iterErr == KErrNotFound, iterErr);
       
  1597 		}
       
  1598 	iTs->ReleaseFont(font);
       
  1599 	const TInt resCountEnd = sgDriverProfilInterface->LocalResourceCount();
       
  1600 	TEST(resCountEnd == resCount);
       
  1601 	sgDriverTestInterface->AllocMarkEnd(0);
       
  1602 
       
  1603 	__UHEAP_MARKEND;
       
  1604 	}
       
  1605 
       
  1606 /**
       
  1607 @SYMTestCaseID      GRAPHICS-FBSERV-0659
       
  1608 @SYMTestPriority    Med
       
  1609 @SYMTestType        UT
       
  1610 @SYMTestStatus      Implemented
       
  1611 @SYMPREQ            PREQ2678
       
  1612 
       
  1613 @SYMTestCaseDesc
       
  1614 	Uses the RFbsGlyphDataIterator to render a large amount of unique glyphs, at a very large 
       
  1615 	size, to ensure that if graphics memory runs out while the iterator is in use, eviction 
       
  1616 	takes place and does not corrupt the glyph images in any way.
       
  1617 
       
  1618 @SYMTestActions
       
  1619 	i. Create a large CFbsFont from the typeface store (size 100+)
       
  1620 	ii. Simulate a low graphics-memory situation by creating enough RSgImages to fill the memory,
       
  1621 		releasing one image in order to allow some small amount for the test.
       
  1622 	iii. Open a RFbsGlyphDataIterator on the font, using a large array of unique glyph codes.
       
  1623 	iv. Iterate through the glyphs, comparing each returned SgImage against the system-memory
       
  1624 		representation of the glyph as returned by CFont::GetCharacterData().
       
  1625 	v. Check for errors and mismatches, and release all images created by ii.
       
  1626 	
       
  1627 @SYMTestExpectedResults
       
  1628 	At each iteration, each glyph should match in size and contents. 
       
  1629 */
       
  1630 void CTFbsGlyphData::TestGlyphDataIteratorLargeFontStress()
       
  1631 	{
       
  1632 	INFO_PRINTF1(_L("Stress test using a RFbsGlyphDataIterator with a large font"));
       
  1633 #ifdef __WINS__
       
  1634 	// Cannot run test on emulator reliably - this is because on emulator
       
  1635 	// system-memory is used for RSgImages, so using up RSgImage memory may 
       
  1636 	// cause heap-allocation failures unrelated to the area being tested. 
       
  1637 	// This test is specifically testing the behaviour when running out of
       
  1638 	// RSgImage-based memory (i.e. graphics memory), but on emulator this 
       
  1639 	// will cause a failed allocation anywhere.
       
  1640 	INFO_PRINTF1(_L("Skipping test on emulator..."));
       
  1641 #else
       
  1642 	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"));
       
  1643 	TEST(EFalse);
       
  1644 /*	__UHEAP_MARK;
       
  1645 
       
  1646 	const TInt KFontSize = 128;
       
  1647 
       
  1648 	CFbsFont* font;
       
  1649 	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KMonoTypefaceName, KFontSize));
       
  1650 	TESTNOERROR(err);
       
  1651 	// Output the actual fontspec used in the test.
       
  1652 	InfoPrintFontSpec(*font);
       
  1653 	
       
  1654 	// Create 2 buffers for use in comparing SgImages so that we don't run out 
       
  1655 	// of system memory through allocating memory in the test
       
  1656 	TInt maxFontWidth = font->MaxCharWidthInPixels();
       
  1657 	TInt maxFontHeight = font->HeightInPixels();
       
  1658 	iTempBuf1 = (TUint8*) User::AllocZ(maxFontWidth * maxFontHeight);
       
  1659 	iTempBuf2 = (TUint8*) User::AllocZ(maxFontWidth * maxFontHeight);
       
  1660 
       
  1661 	// In order for the image comparisons to have enough memory to perform, keep 
       
  1662 	// one large RSgImage which is created before the rest of the graphics memory 
       
  1663 	// is filled.  This image can then be closed before doing the image comparison 
       
  1664 	// and recreated after the image comparison to ensure that the graphics 
       
  1665 	// memory is full.  Without this image, the image comparison could fail with 
       
  1666 	// out of memory and the test would fail. 
       
  1667 	RSgImage tempImage;
       
  1668 	TESTNOERROR(tempImage.Create(TSgImageInfo(TSize(1000, 1000), ESgPixelFormatA_8, ESgUsageBitOpenVgImage)));
       
  1669 
       
  1670 	TFontSpec actualFontSpec;
       
  1671 	actualFontSpec = font->FontSpecInTwips();
       
  1672 	
       
  1673 	// Create RSgImages from character data independently from using iterator.
       
  1674 	// These will be used for comparing with RSgImages retrieved from iterator.
       
  1675 	RArray <RSgImage> sgImageFromCharDataArray;
       
  1676 	TInt index = 0;
       
  1677 	for(; (index < KNumGlyphCodesLatin) && (err == KErrNone); ++index)
       
  1678 		{
       
  1679 		RSgImage characterDataSgImage;
       
  1680 		TInt err = KErrNone;
       
  1681 		const TUint8* bitmapData = NULL;
       
  1682 		TSize bitmapSize;
       
  1683 		TOpenFontCharMetrics metrics;
       
  1684 		font->GetCharacterData(iGlyphCodesLatin[index] | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
       
  1685 
       
  1686 		if (bitmapSize != TSize(0, 0))
       
  1687 			{
       
  1688 			err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, actualFontSpec.iFontStyle.BitmapType(), characterDataSgImage, iTempBuf1, iTempBuf2);
       
  1689 			}
       
  1690 		if (KErrNone == err)
       
  1691 			{
       
  1692 			err = sgImageFromCharDataArray.Append(characterDataSgImage);
       
  1693 			}
       
  1694 		}
       
  1695 	TESTNOERROR(err);
       
  1696 	TEST(index == KNumGlyphCodesLatin);
       
  1697 
       
  1698 	// Simulate low OOGM situation by creating many RSgImages until out of memory.
       
  1699 	RArray <RSgImage> sgImageArray;
       
  1700 	if (err == KErrNone)
       
  1701 		{
       
  1702 		TESTNOERROR(NearlyFillGraphicsMemoryWithImages(TSize(256, 256), sgImageArray));
       
  1703 		}
       
  1704 	
       
  1705 	// Open Iterator on long string of data...
       
  1706 	RFbsGlyphDataIterator iter;
       
  1707 	TInt iterErr = KErrNone;
       
  1708 	if (err == KErrNone)
       
  1709 		{
       
  1710 		iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1711 		TESTNOERROR(iterErr);
       
  1712 		}
       
  1713 
       
  1714 	// For each glyph, compare it to the system-memory version from GetCharacterData().
       
  1715 	TInt numMismatches = 0;
       
  1716 	for(index = 0; (iterErr == KErrNone) && (index < sgImageFromCharDataArray.Count()) && (err == KErrNone); iterErr = iter.Next(), ++index)
       
  1717 		{
       
  1718 		const TUint8* bitmapData = NULL;
       
  1719 		TSize bitmapSize;
       
  1720 		TOpenFontCharMetrics metrics;
       
  1721 		font->GetCharacterData(iter.GlyphCode() | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
       
  1722 
       
  1723 		if (iter.Rect().Size() == TSize(0, 0))
       
  1724 			{
       
  1725 			numMismatches += (bitmapSize != TSize(0, 0)) ? 1 : 0;
       
  1726 			}
       
  1727 		else
       
  1728 			{
       
  1729 			// Free up memory so that the image compariso succeeds
       
  1730 			// Release all the images used to simulate OOGM.
       
  1731 			for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
       
  1732 				{
       
  1733 				sgImageArray[i].Close();
       
  1734 				sgImageArray.Remove(i);
       
  1735 				}
       
  1736 			
       
  1737 			TBool match = ETrue;
       
  1738 			err = CompareSgImages(iEGL, sgImageFromCharDataArray[index], TRect(bitmapSize), iTempBuf1, iter.Image(), iter.Rect(), iTempBuf2, match);
       
  1739 			if (err == KErrNone && !match)
       
  1740 				{
       
  1741 				++numMismatches;
       
  1742 				}
       
  1743 			TInt result = FillGraphicsMemoryWithImages(TSize(256, 256), sgImageArray);
       
  1744 			TESTE(result == KErrNoMemory || result == KErrNoGraphicsMemory, result);
       
  1745 			}
       
  1746 		}
       
  1747 	iter.Close();
       
  1748 
       
  1749 	// Release all images created from character data.
       
  1750 	for (TInt i = sgImageFromCharDataArray.Count()-1; i >= 0; --i)
       
  1751 		{
       
  1752 		sgImageFromCharDataArray[i].Close();
       
  1753 		}
       
  1754 	sgImageFromCharDataArray.Close();
       
  1755 
       
  1756 	// Release all the images used to simulate OOGM.
       
  1757 	for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
       
  1758 		{
       
  1759 		sgImageArray[i].Close();
       
  1760 		}
       
  1761 	sgImageArray.Close();
       
  1762 	tempImage.Close();
       
  1763 	iTs->ReleaseFont(font);
       
  1764 	User::Free(iTempBuf1);
       
  1765 	User::Free(iTempBuf2);
       
  1766 	iTempBuf1 = NULL;
       
  1767 	iTempBuf2 = NULL;
       
  1768 
       
  1769 	// Log any errors only after memory is freed - this ensures there is enough
       
  1770 	// memory for the logger.
       
  1771 	TESTNOERROR(err);
       
  1772 	TESTE(iterErr == KErrNotFound, iterErr);
       
  1773 	TEST(index == KNumGlyphCodesLatin);
       
  1774 	TEST(numMismatches == 0);
       
  1775 
       
  1776 	__UHEAP_MARKEND;*/
       
  1777 #endif
       
  1778 	}
       
  1779 
       
  1780 /**
       
  1781 @SYMTestCaseID      GRAPHICS-FBSERV-0660
       
  1782 @SYMTestPriority    Med
       
  1783 @SYMTestType        UT
       
  1784 @SYMTestStatus      Implemented
       
  1785 @SYMPREQ            PREQ2678
       
  1786 
       
  1787 @SYMTestCaseDesc
       
  1788 	Opens an RFbsGlyphDataIterator on many different fonts of different sizes and typefaces
       
  1789 	and uses many fonts, in order to test that the iterator can cope with being used on many
       
  1790 	fonts with many glyphs.
       
  1791 
       
  1792 @SYMTestActions
       
  1793 	i. Perform test of 100 iterations, where:
       
  1794 		1. A new Latin font is created every iteration in order to force the Typeface Store
       
  1795 			to create a brand-new server-side font at each iteration. 
       
  1796 		2. For this font, open an RFbsGlyphDataIterator and cycle through all Latin glyphs.
       
  1797 		3. For each glyph, compare against the glyph image returned by CFont::GetCharacterData().
       
  1798 		4. Keep a record of the number of mismatches, and carry on to next font.
       
  1799 	ii. Perform i. again, but using the existing fonts.
       
  1800 	iii. Check that there are no mismatches, all glyphs and fonts were successfully checked, 
       
  1801 		and no error codes returned during the test.
       
  1802 	iv. Clean up all resources.
       
  1803 	
       
  1804 @SYMTestExpectedResults
       
  1805 	The glyphs provided by the iterator should match that returned by GetCharacterData()
       
  1806 	for every font and every iteration. 
       
  1807 */
       
  1808 void CTFbsGlyphData::TestGlyphDataIteratorManyFontsStressL()
       
  1809 	{
       
  1810 	INFO_PRINTF1(_L("Stress test using a RFbsGlyphDataIterator with hundreds of fonts"));
       
  1811 	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"));
       
  1812 	TEST(EFalse);
       
  1813 	/*__UHEAP_MARK;
       
  1814 
       
  1815 	const TInt KNumFonts = 100;
       
  1816 	const TInt KNumRepeatsPerFont = 2;
       
  1817 	TInt err = KErrNone;
       
  1818 	TInt numGlyphMismatches = 0;
       
  1819 
       
  1820 	CFbsFont** font = new (ELeave) CFbsFont*[KNumFonts];
       
  1821 	Mem::FillZ(font, sizeof(CFbsFont*) * KNumFonts);
       
  1822 
       
  1823 	// Do the whole thing KNumRepeatsPerFont times. The second+ repeats will 
       
  1824 	// re-use the fonts created in the first repeat, to ensure that fonts that 
       
  1825 	// may have been evicted are able to be re-used with the iterator.
       
  1826 	for (TInt rep = 0; (rep < KNumRepeatsPerFont) && (err == KErrNone); ++rep)
       
  1827 		{
       
  1828 		// Iterate through all the font variants:
       
  1829 		// Iterate all font styles, for all latin typefaces, at increasing sizes.
       
  1830 		TInt i = 0;
       
  1831 		for (; (i < KNumFonts) && (err == KErrNone); ++i)
       
  1832 			{
       
  1833 			// Only create this font if this font isn't already valid (i.e. when this is the 
       
  1834 			// first rep) otherwise re-use it.
       
  1835 			if (!font[i])
       
  1836 				{
       
  1837 				TFontSpec requestedFontSpec = GenerateDejaVuFontSpec(i);
       
  1838 				err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font[i], requestedFontSpec);
       
  1839 				}
       
  1840 			if (err == KErrNone)
       
  1841 				{
       
  1842 				RFbsGlyphDataIterator iter;
       
  1843 				TInt iterErr = iter.Open(*(font[i]), iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1844 				if (iterErr != KErrNone)
       
  1845 					{
       
  1846 					ERR_PRINTF2(_L("Failed to open RFbsGlyphDataIterator [err=%d]"), iterErr);
       
  1847 					InfoPrintFontSpec(*(font[i]));
       
  1848 					iStep->SetTestStepResult(EFail);
       
  1849 					}
       
  1850 				else
       
  1851 					{
       
  1852 					TInt index = 0;
       
  1853 					for(; (iterErr == KErrNone) && (index < KNumGlyphCodesLatin) && (err == KErrNone) ; iterErr = iter.Next(), index++)
       
  1854 						{
       
  1855 						const TUint8* bitmapData = NULL;
       
  1856 						TSize bitmapSize;
       
  1857 						TOpenFontCharMetrics metrics;
       
  1858 						font[i]->GetCharacterData(iter.GlyphCode() | KGlyphCodeFlag, metrics, bitmapData, bitmapSize);
       
  1859 						if (iter.Rect().Size() == TSize(0, 0))
       
  1860 							{
       
  1861 							numGlyphMismatches += (bitmapSize != TSize(0, 0)) ? 1 : 0;
       
  1862 							}
       
  1863 						else
       
  1864 							{
       
  1865 							TBool match = EFalse;
       
  1866 							const TFontSpec fontSpec = font[i]->FontSpecInTwips();							
       
  1867 							// Compare to system-memory version of glyph
       
  1868 							RSgImage characterDataImage;
       
  1869 							err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, fontSpec.iFontStyle.BitmapType(), characterDataImage);
       
  1870 							if (err == KErrNone) 
       
  1871 								{
       
  1872 								err = CompareSgImages(iEGL, iter.Image(), iter.Rect(), characterDataImage, TRect(bitmapSize), match);
       
  1873 								}
       
  1874 							if (err == KErrNone && !match)
       
  1875 								{
       
  1876 								++numGlyphMismatches;
       
  1877 								}
       
  1878 							characterDataImage.Close();
       
  1879 							}					
       
  1880 						}
       
  1881 					iter.Close();
       
  1882 					TESTE(iterErr == KErrNotFound, iterErr);
       
  1883 					TEST(index == KNumGlyphCodesLatin);					
       
  1884 					}
       
  1885 				}
       
  1886 			}
       
  1887 		// Check all the fonts were iterated through.
       
  1888 		TEST(i == KNumFonts);
       
  1889 		}
       
  1890 	TESTNOERROR(err);
       
  1891 	TEST(numGlyphMismatches == 0);
       
  1892 
       
  1893 	// Cleanup
       
  1894 	for (TInt ii = 0; ii < KNumFonts; ii++)
       
  1895 		{
       
  1896 		iTs->ReleaseFont(font[ii]);
       
  1897 		}
       
  1898 	delete [] font;
       
  1899 	__UHEAP_MARKEND;*/
       
  1900 	}
       
  1901 
       
  1902 /**
       
  1903 @SYMTestCaseID      GRAPHICS-FBSERV-0662
       
  1904 @SYMTestPriority    Low
       
  1905 @SYMTestType        UT
       
  1906 @SYMTestStatus      Implemented
       
  1907 @SYMPREQ            PREQ2678
       
  1908 
       
  1909 @SYMTestCaseDesc
       
  1910 	Uses a RFbsGlyphDataIterator when there is no graphics memory available in the system.
       
  1911 	It shows that when under low graphics memory, Next() returns the correct error code
       
  1912 	as per the API (either KErrNoMemory or KErrNoGraphicsMemory, depending on the implementation 
       
  1913 	of Graphics Resource being used).
       
  1914 
       
  1915 @SYMTestActions
       
  1916 	i. Create a CFbsFont from the typeface store.
       
  1917 	ii. Simulate a low graphics-memory situation by creating enough RSgImages to fill the memory,
       
  1918 	iii. Open a RFbsGlyphDataIterator on the font.
       
  1919 	iv. Attempt to use the iterator, calling Next(), checking the returned code.
       
  1920 	v. Close the iterator and release all graphics memory from ii.
       
  1921 
       
  1922 @SYMTestExpectedResults
       
  1923 	Next() should return either KErrNoMemory or KErrNoGraphicsMemory depending on the implmentation
       
  1924 	of Graphics Resource used. It should return the same error as is returned when filling
       
  1925 	the graphics memory reaches the limit.
       
  1926 */
       
  1927 void CTFbsGlyphData::TestGlyphDataIteratorNoGraphicsMemory()
       
  1928 	{
       
  1929 	INFO_PRINTF1(_L("Test that when there is no GPU memory available, Next() returns correct error"));
       
  1930 	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"));
       
  1931 	TEST(EFalse);
       
  1932 	/*__UHEAP_MARK;
       
  1933 	
       
  1934 	const TInt KFontSize = 128;
       
  1935 	CFbsFont* font = NULL;
       
  1936 	RFbsGlyphDataIterator iter;
       
  1937 	
       
  1938 	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KMonoTypefaceName, KFontSize));
       
  1939 	TESTNOERROR(err);
       
  1940 	
       
  1941 	// Simulate low OOGM situation by creating many RSgImages until out of memory.
       
  1942 	if (err == KErrNone)
       
  1943 		{
       
  1944 		InfoPrintFontSpec(*font);
       
  1945 		RArray <RSgImage> sgImageArray;
       
  1946 		TInt iterErr = KErrNone;
       
  1947 		TInt gfxMemErr = FillGraphicsMemoryWithImages(TSize(KFontSize, KFontSize), sgImageArray);
       
  1948 		TESTE(gfxMemErr == KErrNoMemory || gfxMemErr == KErrNoGraphicsMemory, gfxMemErr);
       
  1949 		if (gfxMemErr == KErrNoMemory || gfxMemErr == KErrNoGraphicsMemory)
       
  1950 			{
       
  1951 			// Next() could either fail with KErrNoMemory or KErrNoGraphicsMemory, but should
       
  1952 			// be the same error code as the last attempted creation of an SgImage, done in 
       
  1953 			// FillGraphicsMemoryWithImages() so compare against that code.
       
  1954 			iterErr = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  1955 			for (; iterErr == KErrNone; iterErr = iter.Next())
       
  1956 				{
       
  1957 				// no operation
       
  1958 				}
       
  1959 			iter.Close();
       
  1960 			}
       
  1961 	
       
  1962 		// Release all the images used to simulate OOGM.
       
  1963 		for (TInt i = sgImageArray.Count() - 1; i >= 0; --i)
       
  1964 			{
       
  1965 			sgImageArray[i].Close();
       
  1966 			}
       
  1967 		sgImageArray.Close();
       
  1968 		
       
  1969 		// Log any errors only after memory is freed - this ensures there is enough
       
  1970 		// memory for the logger.
       
  1971 		TESTE(iterErr == gfxMemErr, iterErr);
       
  1972 		}
       
  1973 
       
  1974 	iTs->ReleaseFont(font);
       
  1975 	
       
  1976 	__UHEAP_MARKEND;*/
       
  1977 	}
       
  1978 
       
  1979 /**
       
  1980 @SYMTestCaseID      GRAPHICS-FBSERV-0666
       
  1981 @SYMTestPriority    Low
       
  1982 @SYMTestType        UT
       
  1983 @SYMTestStatus      Implemented
       
  1984 @SYMPREQ            PREQ2678
       
  1985 
       
  1986 @SYMTestCaseDesc
       
  1987 	Uses a RFbsGlyphDataIterator after Next() returns an error, in order to show that 
       
  1988 	an error does not invalidate the state of the iterator and it is still usable. 
       
  1989 
       
  1990 @SYMTestActions
       
  1991 	i. Open the RFbsGlyphDataIterator on 1 glyph code.
       
  1992 	ii. Store the data of the iterator and call Next() to reach the end of the iterator
       
  1993 	iii. Access the glyph data repeatedly and check that the iterator members
       
  1994 		 still match those in ii.
       
  1995 
       
  1996 @SYMTestExpectedResults
       
  1997 	The calls to Next() should cause KErrNotFound since it is past the final glyph.
       
  1998 	The iterator data should match at all times since the iterator is never moved.
       
  1999 */
       
  2000 void CTFbsGlyphData::TestGlyphDataIteratorNextIsAtomic()
       
  2001 	{
       
  2002 	INFO_PRINTF1(_L("To ensure that Next() is atomic, if it returns an error it is still useable"));
       
  2003 	__UHEAP_MARK;
       
  2004 
       
  2005 	RFbsGlyphDataIterator iter;
       
  2006 	TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, 1);
       
  2007 	TESTNOERROR(iterErr);
       
  2008 	
       
  2009 	TSgDrawableId id = iter.Image().Id();
       
  2010 	TOpenFontCharMetrics metrics = iter.Metrics();
       
  2011 	TUint glyphCode = iter.GlyphCode();
       
  2012 	TRect rect = iter.Rect();
       
  2013 	
       
  2014 	for (TInt i = 0; i < 2; i++)
       
  2015 		{
       
  2016 		iterErr = iter.Next();
       
  2017 		TESTE(iterErr == KErrNotFound, iterErr);
       
  2018 		
       
  2019 		TEST(id == iter.Image().Id());
       
  2020 		TEST(glyphCode == iter.GlyphCode());
       
  2021 		TEST(rect == iter.Rect());
       
  2022 		TEST(CompareMetrics(metrics, iter.Metrics()) == 0);
       
  2023 		}
       
  2024 	iter.Close();
       
  2025 		
       
  2026 	__UHEAP_MARKEND;
       
  2027 	}
       
  2028 
       
  2029 /**
       
  2030 @SYMTestCaseID      GRAPHICS-FBSERV-0665
       
  2031 @SYMTestPriority    High
       
  2032 @SYMTestType        UT
       
  2033 @SYMTestStatus      Implemented
       
  2034 @SYMPREQ            PREQ2678
       
  2035 
       
  2036 @SYMTestCaseDesc
       
  2037 	Glyph Atlas white-box test.
       
  2038 	To ensure that the same RSgImage is used for repeated requests for the 
       
  2039 	same glyph in the same call to RFbsGlyphDataIterator:Open().
       
  2040 @SYMTestActions
       
  2041 	i Open the glyph data iterator with a list of glyph codes which are all the same
       
  2042 	ii Retrieve the drawable id of each iteration 
       
  2043 	iii Check that the same drawable id is retrieved in each iteration  
       
  2044 @SYMTestExpectedResults
       
  2045 	Each iteration returns the same drawable id. 
       
  2046 */
       
  2047 void CTFbsGlyphData::TestGlyphDataIteratorSameGlyphCodes()
       
  2048 	{
       
  2049 	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()"));
       
  2050 	__UHEAP_MARK;
       
  2051 
       
  2052 	const TUint KSameRepeatedGlyphCode = DejaVuASCIIToGlyphCode[0x004B]; // 'K'
       
  2053 	const TInt KNumGlyphs = 10;
       
  2054 	TUint* sameRepeatedGlyphCodes = new TUint[KNumGlyphs];
       
  2055 	for (TInt ii = 0; ii < KNumGlyphs; ++ii)
       
  2056 		{
       
  2057 		sameRepeatedGlyphCodes[ii] = KSameRepeatedGlyphCode;
       
  2058 		}
       
  2059 	RFbsGlyphDataIterator iter;
       
  2060 	TInt err = iter.Open(*iFont, sameRepeatedGlyphCodes, KNumGlyphs);
       
  2061 	
       
  2062 	TESTNOERROR(err);
       
  2063 	if (KErrNone == err)
       
  2064 		{
       
  2065 		// get the drawable id of the first glyph and check that the id is valid
       
  2066 		TSgDrawableId referenceId = iter.Image().Id();
       
  2067 		RSgImage image;
       
  2068 		TESTNOERROR(image.Open(referenceId));
       
  2069 		image.Close();
       
  2070 		TESTNOERROR(iter.Next());
       
  2071 
       
  2072 		for (;KErrNone == err; err = iter.Next())
       
  2073 			{
       
  2074 			TEST(referenceId == iter.Image().Id());
       
  2075 			}
       
  2076 		TESTE(KErrNotFound == err, err);
       
  2077 		}
       
  2078 
       
  2079 	iter.Close();
       
  2080 	delete[] sameRepeatedGlyphCodes;
       
  2081 
       
  2082 	__UHEAP_MARKEND;
       
  2083 	}
       
  2084 
       
  2085 /**
       
  2086 @SYMTestCaseID      GRAPHICS-FBSERV-0668
       
  2087 @SYMTestPriority    High
       
  2088 @SYMTestType        UT
       
  2089 @SYMTestStatus      Implemented
       
  2090 @SYMPREQ            PREQ2678
       
  2091 
       
  2092 @SYMTestCaseDesc
       
  2093 	To ensure that the iterator can successfully be opened on an array
       
  2094 	of glyph codes of various array sizes. 
       
  2095 @SYMTestActions
       
  2096 	Perform many iterations of opening an array and cycling through the glyphs,
       
  2097 	increasing the size of the array after each iteration. Some simple sanity-checking
       
  2098 	of the glyphs is performed.
       
  2099 @SYMTestExpectedResults
       
  2100 	KErrNone should be returned at all times. 
       
  2101 */
       
  2102 void CTFbsGlyphData::TestGlyphDataIteratorManyArraySizes()
       
  2103 	{
       
  2104 	INFO_PRINTF1(_L("Ensure that the RFbsGlyphDataIterator successfully opens glyph code arrays of many sizes"));
       
  2105 	__UHEAP_MARK;
       
  2106 	
       
  2107 	RFbsGlyphMetricsArray glyphMetricsArray;
       
  2108 	
       
  2109 	TESTNOERROR(glyphMetricsArray.Get(*iFont, iGlyphCodesLatin, KNumGlyphCodesLatin));
       
  2110 	TInt iterErr = KErrNone;
       
  2111 	
       
  2112 	for (TInt arraySize = 1; (arraySize < KNumGlyphCodesLatin) && (iterErr == KErrNone); ++arraySize)
       
  2113 		{
       
  2114 		RFbsGlyphDataIterator iter;
       
  2115 		TInt iterErr = iter.Open(*iFont, iGlyphCodesLatin, arraySize);
       
  2116 		TESTNOERROR(iterErr);
       
  2117 		
       
  2118 		for (TInt index = 0; iterErr == KErrNone; iterErr = iter.Next(), ++index)
       
  2119 			{
       
  2120 			// sanity checking...
       
  2121 			if (iter.GlyphCode() != iGlyphCodesLatin[index])
       
  2122 				{
       
  2123 				ERR_PRINTF4(_L("Test failed at array size %d - Wanted glyphcode %d, got %d"), arraySize, iGlyphCodesLatin[index], iter.GlyphCode());
       
  2124 				iStep->SetTestStepResult(EFail);
       
  2125 				}
       
  2126 			if (CompareMetrics(iter.Metrics(), glyphMetricsArray[index]) != 0)
       
  2127 				{
       
  2128 				ERR_PRINTF3(_L("Test failed at array size %d, metrics check failed at glyphcode %d"), arraySize, iGlyphCodesLatin[index]);
       
  2129 				iStep->SetTestStepResult(EFail);
       
  2130 				}			
       
  2131 			}
       
  2132 		iter.Close();
       
  2133 		}
       
  2134 
       
  2135 	glyphMetricsArray.Close();
       
  2136 	TESTNOERROR(iterErr);
       
  2137 
       
  2138 	__UHEAP_MARKEND;
       
  2139 	}
       
  2140 
       
  2141 /**
       
  2142 @SYMTestCaseID      GRAPHICS-FBSERV-0669
       
  2143 @SYMTestPriority    Low
       
  2144 @SYMTestType        UT
       
  2145 @SYMTestStatus      Implemented
       
  2146 @SYMPREQ            PREQ2678
       
  2147 
       
  2148 @SYMTestCaseDesc
       
  2149 	Negative test case to show that RFbsGlyphDataIterator and RFbsGlyphMetricsArray
       
  2150 	do not support bitmap fonts.
       
  2151 @SYMTestActions
       
  2152 	i. Load a bitmap font.
       
  2153 	ii. Attempt to open an RFbsGlyphDataIterator and RFbsGlyphMetricsArray with the font.
       
  2154 @SYMTestExpectedResults
       
  2155 	KErrNotSupported should be returned in both instances. 
       
  2156 */
       
  2157  void CTFbsGlyphData::TestBitmapFontSupport()
       
  2158 	{
       
  2159 	INFO_PRINTF1(_L("Test bitmap font not supported"));
       
  2160 	__UHEAP_MARK;
       
  2161 	
       
  2162 	CFbsFont* bitmapFont = NULL;
       
  2163 	TInt err = iTs->GetNearestFontToDesignHeightInPixels((CFont*&)bitmapFont, TFontSpec(_L("Digital"), 14));
       
  2164 	TESTNOERROR(err);
       
  2165 	TEST(!bitmapFont->IsOpenFont());
       
  2166 	
       
  2167 	RFbsGlyphDataIterator iter;
       
  2168 	err = iter.Open(*bitmapFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  2169 	TEST(err == KErrNotSupported);
       
  2170 	iter.Close();
       
  2171 	
       
  2172 	RFbsGlyphMetricsArray array;
       
  2173 	err = array.Get(*bitmapFont, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  2174 	TEST(err == KErrNotSupported);
       
  2175 	array.Close();
       
  2176 	
       
  2177 	iTs->ReleaseFont(bitmapFont);
       
  2178 	__UHEAP_MARKEND;
       
  2179 	}
       
  2180  
       
  2181 /**
       
  2182 @SYMTestCaseID		GRAPHICS-FBSERV-0671
       
  2183 @SYMTestPriority	High
       
  2184 @SYMTestType		UT
       
  2185 @SYMTestStatus		Implemented
       
  2186 @SYMPREQ			PREQ2678
       
  2187 
       
  2188 @SYMTestCaseDesc
       
  2189 	Shows that different threads (and therefore RFbsSessions) using fonts with the same
       
  2190 	TFontSpec share the same glyphs	in the atlas and do not create duplicate entries
       
  2191 	in the Glyph Atlas, and that releasing a font clears all associated glyphs in the
       
  2192 	atlas.
       
  2193 
       
  2194 @SYMTestActions
       
  2195 	i. Create a handle to a test font in the current process.
       
  2196 	ii. Spawn a test thread and wait for it to complete. Within the thread :
       
  2197 		1. Create a font with the same fontspec as the parent process.
       
  2198 		2. Use the RFbsGlyphDataIterator API to force rasterization into the glyph atlas.
       
  2199 		3. Release the iterator.
       
  2200 	iii. Check there were no leaves from the thread.
       
  2201 	iv. Repeat ii. and iii. several times. Before using RFbsGlyphDataIterator,
       
  2202 		the thread checks that the glyphs are still in the atlas from the first thread.
       
  2203 	v. Check that the number of fonts in the atlas has increased by one only.
       
  2204 	vi. Check that the number of glyphs in the atlas has increased by the size of the 
       
  2205 		glyph code array.
       
  2206 	vii. Release the font in the parent process, thereby releasing the font and glyphs
       
  2207 		in the glyph atlas, and check that the state of the atlas is the same as before
       
  2208 		the test is run.
       
  2209 
       
  2210 @SYMTestExpectedResults
       
  2211 	All threads should return no errors or leaves or panics.
       
  2212 	After all threads have finished:
       
  2213 		The glyph count should have increased by the size of the glyph code array used
       
  2214 		in the RFbsGlyphDataIterator, showing that	glyphs are only being added to the atlas
       
  2215 		once. The number of fonts in the atlas should have increased by one, showing
       
  2216 		that only the single underlying font object is being added to the atlas, despite
       
  2217 		different RFbsSessions and CFbsFont instances used.
       
  2218 	After the test font is released in the main process:
       
  2219 		The glyph count and font count return to the pre-test value, showing that when
       
  2220 		the last handle to a TFontSpec is released, the atlas frees its associated data.
       
  2221 */
       
  2222 void CTFbsGlyphData::TestMultithreadShareSingleFont()
       
  2223 	{
       
  2224 	INFO_PRINTF1(_L("Test glyphs shared between RFbsSessions/threads/processes"));
       
  2225 #ifndef _DEBUG
       
  2226 	// Test relies on debug-only FBS messages EFbsMessAtlasGlyphCount and EFbsMessAtlasFontCount
       
  2227 	INFO_PRINTF1(_L("Skipping test in release mode"));
       
  2228 #else	
       
  2229 	__UHEAP_MARK;
       
  2230 
       
  2231 	_LIT(KThreadName, "GlyphDataTestThread");
       
  2232 	const TInt KNumTestThreads = 5;
       
  2233 	const TFontSpec KTestFontSpec(KTypefaceName, 50);	
       
  2234 	const TInt atlasFontCountStart = iFbs->SendCommand(EFbsMessAtlasFontCount);
       
  2235 	const TInt atlasGlyphCountStart = iFbs->SendCommand(EFbsMessAtlasGlyphCount);
       
  2236 
       
  2237 	CFbsFont* testFont;
       
  2238 	TInt err = iTs->GetNearestFontToDesignHeightInPixels( (CFont*&)testFont, KTestFontSpec);
       
  2239 	if (err != KErrNone)
       
  2240 		{
       
  2241 		ERR_PRINTF2(_L("Could not load font, err = %d"), err);
       
  2242 		iStep->SetTestStepResult(EFail);
       
  2243 		return;
       
  2244 		}
       
  2245 	
       
  2246 	// Check there are no glyphs belonging to the test font before the test starts.
       
  2247 	TInt atlasFontGlyphCount = iFbs->SendCommand(EFbsMessAtlasGlyphCount, testFont->Handle());
       
  2248 	TEST(atlasFontGlyphCount == 0);
       
  2249 
       
  2250 	TGlyphDataMultithreadParams params = {KTestFontSpec, iGlyphCodesLatin, KNumGlyphCodesLatin, NULL};
       
  2251 
       
  2252 	// Run the test threads sequentially, and check its exit status.
       
  2253 	RThread testThread;
       
  2254 	TInt numThreadsPassed = 0;
       
  2255 	for (TInt i = 0; i < KNumTestThreads; i++)
       
  2256 		{
       
  2257 		TBool threadPassed = ETrue;
       
  2258 		TGlyphDataThreadInfo info = {EGlyphDataMultiSessionTestShareGlyphs, params, i, iStep};
       
  2259 		err = testThread.Create(KThreadName, CTFbsGlyphData::ThreadFunction, KDefaultStackSize, KTestThreadMinHeapSize, KTestThreadMaxHeapSize, &info);
       
  2260 		TESTNOERROR(err);
       
  2261 
       
  2262 		TRequestStatus statusThread;
       
  2263 		testThread.Logon(statusThread);
       
  2264 		testThread.Resume();
       
  2265 		
       
  2266 		User::WaitForRequest(statusThread);
       
  2267 		TInt threadResult = testThread.ExitReason();
       
  2268 		if (threadResult != KErrNone)
       
  2269 			{
       
  2270 			ERR_PRINTF3(_L("Thread %i: Terminated with reason %d"), i, threadResult);
       
  2271 			threadPassed = EFalse; 
       
  2272 			}
       
  2273 		TExitCategoryName exitCategory = testThread.ExitCategory();
       
  2274 		if (exitCategory.Compare(_L("Kill")) != 0)
       
  2275 			{
       
  2276 			ERR_PRINTF3(_L("Thread %i: Terminated with reason category '%S'"), i, &exitCategory);
       
  2277 			threadPassed = EFalse;
       
  2278 			}
       
  2279 		testThread.Close();
       
  2280 		numThreadsPassed += (threadPassed) ? 1 : 0;
       
  2281 		}
       
  2282 	TEST(numThreadsPassed == KNumTestThreads);
       
  2283 
       
  2284 	// Check that the atlas still contains the glyphs and the font created by the threads
       
  2285 	// after they have died, since the font is still open in this process.
       
  2286 	atlasFontGlyphCount = iFbs->SendCommand(EFbsMessAtlasGlyphCount, testFont->Handle());
       
  2287 	TEST(atlasFontGlyphCount == params.iGlyphCodesCount);
       
  2288 	TInt atlasFontCount = iFbs->SendCommand(EFbsMessAtlasFontCount);
       
  2289 	TEST(atlasFontCount == (atlasFontCountStart + 1));
       
  2290 
       
  2291 	iTs->ReleaseFont(testFont);
       
  2292 	testFont = NULL;
       
  2293 
       
  2294 	// Check the atlas state is now the same as it was before the test started,
       
  2295 	// now that the last remaining handle to the font used in the threads is released.
       
  2296 	TInt atlasGlyphCountEnd = iFbs->SendCommand(EFbsMessAtlasGlyphCount);
       
  2297 	TEST(atlasGlyphCountStart == atlasGlyphCountEnd);
       
  2298 	TInt atlasFontCountEnd = iFbs->SendCommand(EFbsMessAtlasFontCount);
       
  2299 	TEST(atlasFontCountStart == atlasFontCountEnd);
       
  2300 	__UHEAP_MARKEND;
       
  2301 #endif
       
  2302 	}
       
  2303 
       
  2304 /**
       
  2305 Worker thread for TestMultithreadShareSingleFont().
       
  2306 The thread uses RFbsGlyphDataIterator on a CFbsFont of the given TFontSpec.
       
  2307 Once complete the atlas is queried for the number of associated glyphs.
       
  2308  */
       
  2309 void CTFbsGlyphData::ThreadShareGlyphsL(TInt aThreadNum, TGlyphDataMultithreadParams& aParam, CTestStep* aStep)
       
  2310 	{
       
  2311 	User::LeaveIfError(RFbsSession::Connect());
       
  2312 	CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
       
  2313 	CleanupStack::PushL(ts);
       
  2314 	RFbsSession* fbs = RFbsSession::GetSession();
       
  2315 
       
  2316 	CFbsFont* font;
       
  2317 	TInt err = ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, aParam.iFontSpec);
       
  2318 	User::LeaveIfError(err);
       
  2319 
       
  2320 	if (aThreadNum > 0)
       
  2321 		{
       
  2322 		// If this is not the first thread, it means the first thread has already executed and 
       
  2323 		// populated the glyph atlas with the glyphs. The font created by this thread 
       
  2324 		// should already have its glyphs in the atlas.
       
  2325 		TInt fontGlyphCount = fbs->SendCommand(EFbsMessAtlasGlyphCount, font->Handle());
       
  2326 		if (fontGlyphCount != aParam.iGlyphCodesCount)
       
  2327 			{
       
  2328 			aStep->ERR_PRINTF4(_L("Thread %d: Only %d glyphs in atlas before first iteration, expected %d"), aThreadNum, fontGlyphCount, aParam.iGlyphCodesCount);
       
  2329 			aStep->SetTestStepResult(EFail);
       
  2330 			}
       
  2331 		}
       
  2332 
       
  2333 	RFbsGlyphDataIterator iter;
       
  2334 	for (err = iter.Open(*font, aParam.iGlyphCodes, aParam.iGlyphCodesCount); err == KErrNone; err = iter.Next())
       
  2335 		{
       
  2336 		// no-op
       
  2337 		}
       
  2338 	iter.Close();
       
  2339 
       
  2340 	// Check that the glyphs of this font have been added to the atlas
       
  2341 	TInt fontGlyphCount = fbs->SendCommand(EFbsMessAtlasGlyphCount, font->Handle());
       
  2342 	if (fontGlyphCount != aParam.iGlyphCodesCount)
       
  2343 		{
       
  2344 		aStep->ERR_PRINTF5(_L("Thread %d: Only %d glyphs in atlas after last iteration, expected %d (err=%d)"), aThreadNum, fontGlyphCount, aParam.iGlyphCodesCount, err);
       
  2345 		aStep->SetTestStepResult(EFail);
       
  2346 		}
       
  2347 	if (err != KErrNotFound)
       
  2348 		{
       
  2349 		aStep->ERR_PRINTF3(_L("Thread %d: Error during test = %d"), aThreadNum, err);
       
  2350 		aStep->SetTestStepResult(EFail);
       
  2351 		}
       
  2352 
       
  2353 	ts->ReleaseFont(font);
       
  2354 	CleanupStack::PopAndDestroy(1); // ts
       
  2355 	RFbsSession::Disconnect();
       
  2356 	}
       
  2357 
       
  2358 
       
  2359 /**
       
  2360 @SYMTestCaseID		GRAPHICS-FBSERV-0672
       
  2361 @SYMTestPriority	Medium
       
  2362 @SYMTestType		UT
       
  2363 @SYMTestStatus		Implemented
       
  2364 @SYMPREQ			PREQ2678
       
  2365 
       
  2366 @SYMTestCaseDesc
       
  2367 	Tests that with many concurrent sessions connected to Fbserv, the atlas successfully
       
  2368 	returns the correct glyph images even if the atlas becomes full and has to evict glyphs.
       
  2369 
       
  2370 @SYMTestActions
       
  2371 	i. Create 25 threads, each a unique session with Fbserv.
       
  2372 	ii. Launch the threads simultaneously. In each thread:
       
  2373 		1. Create a FBS typeface store and create a font which is unique in the process.
       
  2374 		2. Use RFbsGlyphDataIterator to iterate through the latin glyph codes.
       
  2375 		3. Check the image is correct for each glyph against the image returned by 
       
  2376 			CFont::GetCharacterData().
       
  2377 		4. Close the iterator.
       
  2378 		5. Release the font and close the typeface store. 
       
  2379 	iii. Once all threads have finished, check the exit status of each thread
       
  2380 
       
  2381 @SYMTestExpectedResults
       
  2382 	Every glyph for every thread should match the image returned by GetCharacterData()
       
  2383 	All threads should exit normally with no Leave code.
       
  2384 */
       
  2385 _LIT(KTestMultithreadStressFinishSemaphore, "TestMultithreadStressAtlasFinish");
       
  2386 
       
  2387 void CTFbsGlyphData::TestMultithreadStressAtlas()
       
  2388 	{
       
  2389 	INFO_PRINTF1(_L("Stress test glyph atlas with multiple RFbsSessions"));
       
  2390 	WARN_PRINTF1(_L("---Stress test TO BE REVISITED due to Broadcom defect ESLM-85NEFT - TB10.1 eglCreateImageKHR hangs during multithreading"));
       
  2391 	TEST(EFalse);
       
  2392 	/*__UHEAP_MARK;
       
  2393 
       
  2394 	TInt err = KErrNone;
       
  2395 	const TInt KNumTestThreads = 25;
       
  2396 	_LIT(KThreadNameFormat, "GlyphDataTestThread%i");
       
  2397 
       
  2398 	// Create a semaphore that is signalled by each test thread when it has finished.
       
  2399 	RSemaphore threadFinishSemaphore;
       
  2400 	err = threadFinishSemaphore.CreateGlobal(KTestMultithreadStressFinishSemaphore, 0, EOwnerThread);
       
  2401 	TESTNOERROR(err);
       
  2402 
       
  2403 	// Prepare the testdata for the threads
       
  2404 	// Each thread will have a TFontSpec which will cause unique CFbsFonts
       
  2405 	// to be created in the server, and therefore the atlas.
       
  2406 	RThread testThread[KNumTestThreads];
       
  2407 	TGlyphDataThreadInfo testInfo[KNumTestThreads];	
       
  2408 	for (TInt i = 0; i < KNumTestThreads; ++i)
       
  2409 		{
       
  2410 		testInfo[i].iStep = iStep;
       
  2411 		testInfo[i].iTest = EGlyphDataMultiSessionTestStressAtlas;
       
  2412 		testInfo[i].iParams.iFontSpec = GenerateDejaVuFontSpec(i);
       
  2413 		testInfo[i].iParams.iGlyphCodes = iGlyphCodesLatin;
       
  2414 		testInfo[i].iParams.iGlyphCodesCount = KNumGlyphCodesLatin;
       
  2415 		testInfo[i].iParams.iEGL = iEGL;
       
  2416 		testInfo[i].iThreadNum = i;	
       
  2417 		TBuf<128> threadName;
       
  2418 		threadName.AppendFormat(KThreadNameFormat, i);
       
  2419 		err = testThread[i].Create(threadName, CTFbsGlyphData::ThreadFunction, KDefaultStackSize, KTestThreadMinHeapSize, KTestThreadMaxHeapSize, &testInfo[i]);
       
  2420 		TESTNOERROR(err);
       
  2421 		}
       
  2422 
       
  2423 	// All threads are created, start them simultaneously.
       
  2424 	for (TInt i = 0; i < KNumTestThreads; ++i)
       
  2425 		{
       
  2426 		testThread[i].Resume();
       
  2427 		}
       
  2428 	// Wait for all threads to finish.
       
  2429 	for (TInt i = 0; i < KNumTestThreads; ++i)
       
  2430 		{
       
  2431 		threadFinishSemaphore.Wait();
       
  2432 		}
       
  2433 	// Allow some time for remaining threads to finish tidy-up.
       
  2434 	User::After(100000);
       
  2435 	threadFinishSemaphore.Close();
       
  2436 
       
  2437 	TInt numThreadsPassed = 0;
       
  2438 	for (TInt i = 0; i < KNumTestThreads; ++i)
       
  2439 		{
       
  2440 		TBool threadPassed = ETrue;
       
  2441 		TInt threadResult = testThread[i].ExitReason();
       
  2442 		if (threadResult != KErrNone)
       
  2443 			{
       
  2444 			ERR_PRINTF3(_L("Thread %i: Terminated with reason %d"), i, threadResult);
       
  2445 			threadPassed = EFalse; 
       
  2446 			}
       
  2447 		TExitCategoryName exitCategory = testThread[i].ExitCategory();
       
  2448 		if (exitCategory.Compare(_L("Kill")) != 0)
       
  2449 			{
       
  2450 			ERR_PRINTF3(_L("Thread %i: Terminated with reason category '%S'"), i, &exitCategory);
       
  2451 			threadPassed = EFalse;
       
  2452 			}
       
  2453 		testThread[i].Close();
       
  2454 		numThreadsPassed += (threadPassed) ? 1 : 0;
       
  2455 		}
       
  2456 	TEST(numThreadsPassed == KNumTestThreads);
       
  2457 
       
  2458 	__UHEAP_MARKEND;*/
       
  2459 	}
       
  2460 /**
       
  2461 Worker thread for TestMultithreadStressAtlas().
       
  2462 The thread uses RFbsGlyphDataIterator on a CFbsFont of the given TFontSpec.
       
  2463 For each glyph, the image returned by the iterator is compared to the image 
       
  2464 returned from CFont::GetCharacterData().
       
  2465 Once complete, the semaphore is signalled to tell the parent process it has
       
  2466 finished.
       
  2467  */
       
  2468 void CleanupFinishSemaphore(TAny* aItem)
       
  2469     {
       
  2470     RSemaphore* semaphore = reinterpret_cast<RSemaphore*>(aItem);
       
  2471     semaphore->Signal();
       
  2472     semaphore->Close();
       
  2473     }
       
  2474 void CTFbsGlyphData::ThreadStressAtlasL(TInt aThreadNum, TGlyphDataMultithreadParams& aParam, CTestStep* aStep)
       
  2475 	{
       
  2476 	TOpenFontCharMetrics charMetrics;
       
  2477 	const TUint8* bitmapData;
       
  2478 	TSize bitmapSize;
       
  2479 	RSgImage charDataImage;
       
  2480 
       
  2481 	RSemaphore threadFinishSemaphore;
       
  2482 	User::LeaveIfError(threadFinishSemaphore.OpenGlobal(KTestMultithreadStressFinishSemaphore));
       
  2483 	CleanupStack::PushL(TCleanupItem(CleanupFinishSemaphore, &threadFinishSemaphore));
       
  2484 
       
  2485 	User::LeaveIfError(RFbsSession::Connect());
       
  2486 	CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
       
  2487 	CleanupStack::PushL(ts);
       
  2488 	
       
  2489 	CFbsFont* font;
       
  2490 	User::LeaveIfError(ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, aParam.iFontSpec));
       
  2491 
       
  2492 	TInt numGlyphMatches = 0;
       
  2493 	TInt index = 0;
       
  2494 	TInt err = KErrNone;
       
  2495 	RFbsGlyphDataIterator iter;
       
  2496 	for (err = iter.Open(*font, aParam.iGlyphCodes, aParam.iGlyphCodesCount); err == KErrNone; err = iter.Next(), ++index)
       
  2497 		{
       
  2498 		TBool glyphMatch = EFalse;
       
  2499 		font->GetCharacterData(aParam.iGlyphCodes[index] | KGlyphCodeFlag, charMetrics, bitmapData, bitmapSize);
       
  2500 		if (bitmapSize == TSize(0, 0))
       
  2501 			{
       
  2502 			glyphMatch = (bitmapSize == iter.Rect().Size());
       
  2503 			}
       
  2504 		else
       
  2505 			{
       
  2506 			err = CreateSgImageFromCharacterData(bitmapData, bitmapSize, font->FontSpecInTwips().iFontStyle.BitmapType(), charDataImage);
       
  2507 			if (err == KErrNone)
       
  2508 				{
       
  2509 				err = CompareSgImages(aParam.iEGL, iter.Image(), iter.Rect(), charDataImage, TRect(bitmapSize), glyphMatch);
       
  2510 				}
       
  2511 			charDataImage.Close();
       
  2512 			}
       
  2513 		if (err != KErrNone)
       
  2514 			{
       
  2515 			break;
       
  2516 			}
       
  2517 		numGlyphMatches += (glyphMatch) ? 1 : 0;
       
  2518 		}
       
  2519 	iter.Close();
       
  2520 	
       
  2521 	if (index != aParam.iGlyphCodesCount)
       
  2522 		{
       
  2523 		aStep->ERR_PRINTF5(_L("Thread %d: Iterator terminated early - %d out of %d glyphs (err=%d)"), aThreadNum, index, aParam.iGlyphCodesCount, err);
       
  2524 		aStep->SetTestStepResult(EFail);
       
  2525 		}
       
  2526 	if (index != numGlyphMatches)
       
  2527 		{
       
  2528 		aStep->ERR_PRINTF4(_L("Thread %d: Matched %d out of %d glyphs"), aThreadNum, numGlyphMatches, aParam.iGlyphCodesCount);
       
  2529 		aStep->SetTestStepResult(EFail);
       
  2530 		}
       
  2531 
       
  2532 	ts->ReleaseFont(font);
       
  2533 	CleanupStack::PopAndDestroy(2); // ts, threadFinishSemaphore
       
  2534 	RFbsSession::Disconnect();
       
  2535 	}
       
  2536 
       
  2537 /**
       
  2538 @SYMTestCaseID      GRAPHICS-FBSERV-0673
       
  2539 @SYMTestPriority    Medium
       
  2540 @SYMTestType        UT
       
  2541 @SYMTestStatus      Implemented
       
  2542 @SYMPREQ            PREQ2678
       
  2543 
       
  2544 @SYMTestCaseDesc
       
  2545     Tests the robustness of using RFbsGlyphMetricsArray when the client heap and the
       
  2546     FbServ private heap experience failures allocating memory, causing no panics 
       
  2547     or leaves.
       
  2548 
       
  2549 @SYMTestActions
       
  2550     i. Set the default heap failure for the next heap allocation.
       
  2551     ii. Create a new CFbsFont using a TFontSpec not already in the glyph atlas.
       
  2552     iii. Call RFbsGlyphMetricsArray::Get(), and close the array.
       
  2553     iv. Release the font so that nothing is left in the cache as a result of
       
  2554         attempting to use it, and reset the heap failure state.
       
  2555     v. While iii returns KErrNoMemory, increment the failure count and repeat
       
  2556         step ii.
       
  2557     vi. Using a separate font so that the test is not affected by the earlier
       
  2558         run, repeat ii. to v., but rather than setting the default heap to 
       
  2559         fail, the FbServ private heap is set to fail, via IPC messages to Fbs.
       
  2560 
       
  2561 @SYMTestExpectedResults
       
  2562     If no errors occur, KErrNone should be returned after a certain number of
       
  2563     repetitions. Any other error code denotes a problem handling low-memory 
       
  2564     situtations.
       
  2565 */
       
  2566 void CTFbsGlyphData::TestGlyphMetricsArrayHeapOOML()
       
  2567     {
       
  2568     INFO_PRINTF1(_L("Test RFbsGlyphMetricsArray during heap alloc failure"));
       
  2569     __UHEAP_MARK;
       
  2570 
       
  2571     // Create a font that wont be in the cache already...
       
  2572     TInt rep = 0;
       
  2573     TInt err = KErrNoMemory;
       
  2574     CFbsFont* font = NULL;
       
  2575     
       
  2576     while (err == KErrNoMemory)
       
  2577         {
       
  2578         User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(10)));
       
  2579         __UHEAP_FAILNEXT(rep);
       
  2580         RFbsGlyphMetricsArray array;
       
  2581         err = array.Get(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  2582         array.Close();
       
  2583         __UHEAP_RESET;
       
  2584         iTs->ReleaseFont(font);
       
  2585         font = NULL;
       
  2586         ++rep;
       
  2587         }
       
  2588 
       
  2589 	TESTE(err == KErrNone, err);
       
  2590     if (err == KErrNone)
       
  2591         {
       
  2592         INFO_PRINTF2(_L("Client Heap OOM : Test passed after rep %d"), rep);
       
  2593         }
       
  2594     else
       
  2595         {
       
  2596         ERR_PRINTF3(_L("Client Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
       
  2597         }
       
  2598 
       
  2599     // Now test when the server-side FbServ heap fails...
       
  2600     rep = 0;
       
  2601     err = KErrNoMemory;
       
  2602     
       
  2603     while (err == KErrNoMemory)
       
  2604         {
       
  2605         User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(11)));
       
  2606         iFbs->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeServerMemory, rep);
       
  2607         RFbsGlyphMetricsArray array;
       
  2608         err = array.Get(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  2609         array.Close();
       
  2610         iFbs->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeServerMemory);
       
  2611         iTs->ReleaseFont(font);
       
  2612         font = NULL;
       
  2613         ++rep;
       
  2614         }
       
  2615 
       
  2616 	TESTE(err == KErrNone, err);
       
  2617     if (err == KErrNone)
       
  2618         {
       
  2619         INFO_PRINTF2(_L("FBServ Heap OOM : Test passed after rep %d"), rep);
       
  2620         }
       
  2621     else
       
  2622         {
       
  2623         ERR_PRINTF3(_L("FBServ Heap OOM : Test failed with err=%d, after rep %d"), err, rep);      
       
  2624         }
       
  2625     __UHEAP_MARKEND;
       
  2626     }
       
  2627 
       
  2628 /**
       
  2629 @SYMTestCaseID      GRAPHICS-FBSERV-0674
       
  2630 @SYMTestPriority    Medium
       
  2631 @SYMTestType        UT
       
  2632 @SYMTestStatus      Implemented
       
  2633 @SYMPREQ            PREQ2678
       
  2634 
       
  2635 @SYMTestCaseDesc
       
  2636     Tests the robustness of using RFbsGlyphDataIterator when the client heap and the
       
  2637     FbServ private heap experience failures allocating memory, causing no panics 
       
  2638     or leaves.
       
  2639 
       
  2640 @SYMTestActions
       
  2641     i. Set the default heap failure for the next heap allocation.
       
  2642     ii. Create a new CFbsFont using a TFontSpec not already in the glyph atlas.
       
  2643     iii. Call RFbsGlyphDataIterator::Open(), and close the array.
       
  2644     iv. Release the font so that nothing is left in the cache as a result of
       
  2645         attempting to use it, and reset the heap failure state.
       
  2646     v. While iii returns KErrNoMemory, increment the failure count and repeat
       
  2647         step ii.
       
  2648     vi. Using a separate font so that the test is not affected by the earlier
       
  2649         run, repeat ii. to v., but rather than setting the default heap to 
       
  2650         fail, the FbServ private heap is set to fail, via IPC messages to Fbs.
       
  2651 
       
  2652 @SYMTestExpectedResults
       
  2653     If no errors occur, KErrNone should be returned after a certain number of
       
  2654     repetitions. Any other error code denotes a problem handling low-memory 
       
  2655     situtations.
       
  2656 */
       
  2657 void CTFbsGlyphData::TestGlyphDataIteratorHeapOOML()
       
  2658     {
       
  2659     INFO_PRINTF1(_L("Test RFbsGlyphDataIterator during heap alloc failure"));    
       
  2660     __UHEAP_MARK;
       
  2661 
       
  2662     // Create a font that wont be in the cache already...
       
  2663     TInt rep = 0;
       
  2664     TInt err = KErrNoMemory;
       
  2665     CFbsFont* font = NULL;
       
  2666     
       
  2667     while (err == KErrNoMemory)
       
  2668         {
       
  2669         User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(10)));
       
  2670         __UHEAP_FAILNEXT(rep);
       
  2671         RFbsGlyphDataIterator iter;
       
  2672         err = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  2673         if (err == KErrNone)
       
  2674             {
       
  2675             while (err == KErrNone) 
       
  2676                {
       
  2677                err = iter.Next();
       
  2678                }
       
  2679             err = (err == KErrNotFound) ? KErrNone : err;
       
  2680             }
       
  2681         iter.Close();
       
  2682         __UHEAP_RESET;
       
  2683         iTs->ReleaseFont(font);
       
  2684         font = NULL;
       
  2685         ++rep;
       
  2686         }
       
  2687 
       
  2688 	TESTE(err == KErrNone, err);
       
  2689     if (err == KErrNone)
       
  2690         {
       
  2691         INFO_PRINTF2(_L("Client Heap OOM : Test passed after rep %d"), rep);
       
  2692         }
       
  2693     else
       
  2694         {
       
  2695         ERR_PRINTF3(_L("Client Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
       
  2696         }
       
  2697 
       
  2698     // Now test when the server-side FbServ heap fails...
       
  2699     rep = 0;
       
  2700     err = KErrNoMemory;
       
  2701     
       
  2702     while (err == KErrNoMemory)
       
  2703         {
       
  2704         User::LeaveIfError(iTs->GetNearestFontInPixels((CFont*&)font, GenerateDejaVuFontSpec(11)));
       
  2705         iFbs->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeServerMemory, rep);
       
  2706         RFbsGlyphDataIterator iter;
       
  2707         err = iter.Open(*font, iGlyphCodesLatin, KNumGlyphCodesLatin);
       
  2708         if (err == KErrNone)
       
  2709             {
       
  2710             while (err == KErrNone) 
       
  2711                {
       
  2712                err = iter.Next();
       
  2713                }
       
  2714             err = (err == KErrNotFound) ? KErrNone : err;
       
  2715             }
       
  2716         iter.Close();
       
  2717         iFbs->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeServerMemory);
       
  2718         iTs->ReleaseFont(font);
       
  2719         font = NULL;
       
  2720         ++rep;
       
  2721         }
       
  2722 
       
  2723 	TESTE(err == KErrNone, err);
       
  2724     if (err == KErrNone)
       
  2725         {
       
  2726         INFO_PRINTF2(_L("FBServ Heap OOM : Test passed after rep %d"), rep);
       
  2727         }
       
  2728     else
       
  2729         {
       
  2730         ERR_PRINTF3(_L("FBServ Heap OOM : Test failed with err=%d, after rep %d"), err, rep);
       
  2731         }
       
  2732     __UHEAP_MARKEND;
       
  2733     }
       
  2734 
       
  2735 /**
       
  2736 Utility function. Prints out a description of the font's fontspec to the log.
       
  2737  */
       
  2738 void CTFbsGlyphData::InfoPrintFontSpec(const CFont& aFont)
       
  2739 	{
       
  2740 	_LIT(KMonochromeBitmap, "Mono");
       
  2741 	_LIT(KAntiAliasedBitmap, "AA");
       
  2742 	_LIT(KStyleItalic, "Italic");
       
  2743 	_LIT(KStyleBold, "Bold");
       
  2744 	_LIT(KStyleNormal, "Normal");
       
  2745 	_LIT(KUnknown, "Unknown");
       
  2746 	TBufC<9> bitmapType;
       
  2747 	TBuf<12> fontStyle;
       
  2748 	TFontSpec fontSpec = aFont.FontSpecInTwips();
       
  2749 	switch(fontSpec.iFontStyle.BitmapType())
       
  2750 		{
       
  2751 		case EMonochromeGlyphBitmap:
       
  2752 			bitmapType = KMonochromeBitmap;
       
  2753 			break;
       
  2754 		case EAntiAliasedGlyphBitmap:
       
  2755 			bitmapType = KAntiAliasedBitmap;
       
  2756 			break;
       
  2757 		default:
       
  2758 			bitmapType = KUnknown;
       
  2759 		}
       
  2760 
       
  2761 	if (fontSpec.iFontStyle.StrokeWeight() == EStrokeWeightBold)
       
  2762 		{
       
  2763 		fontStyle.Append(KStyleBold);
       
  2764 		}
       
  2765 	if (fontSpec.iFontStyle.Posture() == EPostureItalic)
       
  2766 		{
       
  2767 		fontStyle.Append(KStyleItalic);
       
  2768 		}
       
  2769 	if (fontStyle.Length() == 0)
       
  2770 		{
       
  2771 		fontStyle = KStyleNormal;
       
  2772 		}
       
  2773 
       
  2774 	INFO_PRINTF5(_L("Font: name=%S size=%dtw type=%S style=%S"), &(fontSpec.iTypeface.iName), fontSpec.iHeight, &bitmapType, &fontStyle);
       
  2775 	}
       
  2776 
       
  2777 
       
  2778 /**
       
  2779 Static utility function. Performs a per-pixel comparison of two open RSgImages.
       
  2780 To do this requires access to the binary data of the images, only accessable
       
  2781 via EGL and Khronos APIs. This function will bind the RSgImages to VGImages 
       
  2782 and uses OpenVG to retrieve the image data in 8bpp.
       
  2783 @param aEGL An EGL Helper to read the SgImages into system memory.
       
  2784 @param aImageA The first image to compare.
       
  2785 @param aRectA A rectangular portion in pixels of the first image to compare.
       
  2786 @param aImageB The second image to compare.
       
  2787 @param aRectB A rectangular portion in pixels fo the second image to compare.
       
  2788 @param aMatch A boolean value, which on return tells the caller whether the two
       
  2789 	images were deemed to match.
       
  2790 @return KErrNone, if the comparison took place, otherwise one of the system-wide
       
  2791 	error codes.
       
  2792 */
       
  2793 TInt CTFbsGlyphData::CompareSgImages(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, const RSgImage& aImageB, const TRect& aRectB, TBool& aMatch)
       
  2794 	{
       
  2795 	return CTFbsGlyphData::CompareSgImages(aEGL, aImageA, aRectA, NULL, aImageB, aRectB, NULL, aMatch);
       
  2796 	}
       
  2797 
       
  2798 /**
       
  2799 Static utility function. Performs a per-pixel comparison of two open RSgImages.
       
  2800 To do this requires access to the binary data of the images, only accessable
       
  2801 via EGL and Khronos APIs. This function will bind the RSgImages to VGImages 
       
  2802 and uses OpenVG to retrieve the image data in 8bpp.
       
  2803 This version allows pre-created memory to be used in the comparison, to avoid
       
  2804 allocation failure in low memory testing.
       
  2805 @param aEGL An EGL Helper to read the SgImages into system memory buffers.
       
  2806 @param aImageA The first image to compare.
       
  2807 @param aRectA A rectangular portion in pixels of the first image to compare.
       
  2808 @param aBufferA If non-NULL, specifies a memory buffer to read the data of
       
  2809 	aImageA into, otherwise a buffer is dynamically allocated.
       
  2810 @param aImageB The second image to compare.
       
  2811 @param aRectB A rectangular portion in pixels fo the second image to compare.
       
  2812 @param aBufferB If non-NULL, specifies a memory buffer to read the data of
       
  2813 	aImageB into, otherwise a buffer is dynamically allocated.
       
  2814 @param aMatch A boolean value, which on return tells the caller whether the two
       
  2815 	images were deemed to match.
       
  2816 @return KErrNone, if the comparison took place, otherwise one of the system-wide
       
  2817 	error codes.
       
  2818 */
       
  2819 TInt CTFbsGlyphData::CompareSgImages(CEGLHelper* aEGL, const RSgImage& aImageA, const TRect& aRectA, TUint8* aBufferA, const RSgImage& aImageB, const TRect& aRectB, TUint8* aBufferB, TBool& aMatch)
       
  2820 	{
       
  2821 	// By default, assume they do not match.
       
  2822 	aMatch = EFalse;
       
  2823 	
       
  2824 #ifdef SAVEGLYPHSTOMBMDURINGCOMPARISON
       
  2825 	
       
  2826 	static TInt countToAppend = 0;
       
  2827 	
       
  2828 	CFbsBitmap* bitmap = NULL;
       
  2829 	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageA, aRectA, bitmap))
       
  2830 		{
       
  2831 		TBuf<KMaxFileName> buf;
       
  2832 		buf.AppendNum( countToAppend );
       
  2833 		TPtrC nameAppend( buf );
       
  2834 		
       
  2835 		SaveBmp(bitmap, &nameAppend, EFalse);
       
  2836 		}
       
  2837 	delete bitmap;	
       
  2838 	if (KErrNone == CreateBitmapFromSgImage(aEGL, aImageB, aRectB, bitmap))
       
  2839 		{
       
  2840 		TBuf<KMaxFileName> buf;
       
  2841 		buf.AppendNum( countToAppend );
       
  2842 		TPtrC nameAppend( buf );
       
  2843 	
       
  2844 		SaveBmp(bitmap, &nameAppend, ETrue);
       
  2845 		}
       
  2846 	delete bitmap;
       
  2847 	
       
  2848 	countToAppend++;
       
  2849 	
       
  2850 #endif // SAVEGLYPHSTOMBMDURINGCOMPARISON
       
  2851 	
       
  2852 	TSgImageInfo imageInfoA;
       
  2853 	TSgImageInfo imageInfoB;
       
  2854 	if (aImageA.GetInfo(imageInfoA) != KErrNone ||
       
  2855 		aImageB.GetInfo(imageInfoB) != KErrNone)
       
  2856 		{
       
  2857 		return KErrBadHandle;
       
  2858 		}
       
  2859 		
       
  2860 	// Check the sizes of the images match, and the rects reside on the images.
       
  2861 	if (aRectA.Size() != aRectB.Size() ||
       
  2862 		!TRect(imageInfoA.iSizeInPixels).Intersects(aRectA) ||
       
  2863 		!TRect(imageInfoB.iSizeInPixels).Intersects(aRectB))
       
  2864 		{
       
  2865 		return KErrNone;		
       
  2866 		}
       
  2867 	const TSize KBufferSize = aRectA.Size();
       
  2868 	const TInt KDataStride = KBufferSize.iWidth;
       
  2869 
       
  2870 	TBool freeTempBufA = EFalse;
       
  2871 	TBool freeTempBufB = EFalse;
       
  2872 	if (!aBufferA)
       
  2873 		{
       
  2874 		aBufferA = (TUint8*) User::AllocZ(KDataStride * KBufferSize.iHeight);
       
  2875 		freeTempBufA = ETrue;
       
  2876 		}
       
  2877 	if (!aBufferA)
       
  2878 		{
       
  2879 		return KErrNoMemory;
       
  2880 		}
       
  2881 	TInt err = aEGL->GetSgImageData(aImageA, aRectA, aBufferA);
       
  2882 	if (err != KErrNone)
       
  2883 		{
       
  2884 		if (freeTempBufA)
       
  2885 			{
       
  2886 			User::Free(aBufferA);
       
  2887 			aBufferA = NULL;
       
  2888 			}
       
  2889 		return err;
       
  2890 		}
       
  2891 	if (!aBufferB)
       
  2892 		{
       
  2893 		aBufferB = (TUint8*) User::AllocZ(KDataStride * KBufferSize.iHeight);
       
  2894 		freeTempBufB = ETrue;
       
  2895 		}
       
  2896 	if (!aBufferB)
       
  2897 		{
       
  2898 		if (freeTempBufA)
       
  2899 			{
       
  2900 			User::Free(aBufferA);
       
  2901 			aBufferA = NULL;
       
  2902 			}
       
  2903 		return KErrNoMemory;
       
  2904 		}
       
  2905 	err = aEGL->GetSgImageData(aImageB, aRectB, aBufferB);
       
  2906 	if (err != KErrNone)
       
  2907 		{
       
  2908 		if (freeTempBufA)
       
  2909 			{
       
  2910 			User::Free(aBufferA);
       
  2911 			aBufferA = NULL;
       
  2912 			}
       
  2913 		if (freeTempBufB)
       
  2914 			{
       
  2915 			User::Free(aBufferB);
       
  2916 			aBufferB = NULL;
       
  2917 			}
       
  2918 		return err;
       
  2919 		}	
       
  2920 
       
  2921 	// Perform a per-pixel comparison, scanline by scanline.
       
  2922 	// The loop will break as soon as a mismatch is detected.
       
  2923 	aMatch = ETrue;
       
  2924 	for (TInt scanline = 0; (scanline < KBufferSize.iHeight) && aMatch; ++scanline)
       
  2925 		{
       
  2926 		TUint8* scanlineImageA = aBufferA + (scanline * KDataStride);
       
  2927 		TUint8* scanlineImageB = aBufferB + (scanline * KDataStride);
       
  2928 		aMatch = (Mem::Compare(scanlineImageA, KBufferSize.iWidth, scanlineImageB, KBufferSize.iWidth) == 0);
       
  2929 		}
       
  2930 
       
  2931 	if (freeTempBufA)
       
  2932 		{
       
  2933 		User::Free(aBufferA);
       
  2934 		aBufferA = NULL;
       
  2935 		}
       
  2936 	if (freeTempBufB)
       
  2937 		{
       
  2938 		User::Free(aBufferB);
       
  2939 		aBufferB = NULL;
       
  2940 		}
       
  2941 	
       
  2942 	return KErrNone;
       
  2943 	}
       
  2944 
       
  2945 /**
       
  2946 Second thread entry function for multi-threaded tests.
       
  2947 */
       
  2948 TInt CTFbsGlyphData::ThreadFunction(TAny* aParam)
       
  2949 	{
       
  2950 	__UHEAP_MARK;
       
  2951 	CTrapCleanup* cleanupStack = CTrapCleanup::New();
       
  2952 	if (!cleanupStack)
       
  2953 		{
       
  2954 		return KErrNoMemory;
       
  2955 		}
       
  2956 
       
  2957 	TGlyphDataThreadInfo* info = static_cast<TGlyphDataThreadInfo*>(aParam);
       
  2958 	TRAPD(result,
       
  2959 	switch(info->iTest)
       
  2960 		{
       
  2961 		case EGlyphDataMultiSessionTestShareGlyphs:
       
  2962 			CTFbsGlyphData::ThreadShareGlyphsL(info->iThreadNum, info->iParams, info->iStep);
       
  2963 			break;
       
  2964 		case EGlyphDataMultiSessionTestStressAtlas:
       
  2965 			CTFbsGlyphData::ThreadStressAtlasL(info->iThreadNum, info->iParams, info->iStep);
       
  2966 			break;
       
  2967 		default:
       
  2968 			User::Leave(KErrArgument);
       
  2969 		}
       
  2970 	);
       
  2971 
       
  2972 	delete cleanupStack;
       
  2973 	__UHEAP_MARKEND;
       
  2974 	return result;
       
  2975 	}
       
  2976 
       
  2977 
       
  2978 
       
  2979 /*
       
  2980 	-----------------------------------------
       
  2981 	Static utility Methods used by the tests.
       
  2982 	-----------------------------------------
       
  2983 */
       
  2984 
       
  2985 
       
  2986 
       
  2987 /**
       
  2988 Utility method that fills the RSgImage memory with RSgImages until either KErrNoMemory
       
  2989 or KErrNoGraphicsMemory is returned.
       
  2990 
       
  2991 @param aSize The size of the image used to fill the graphics memory - a form of granularity
       
  2992 @param aImages Returns the array of the images used to fill the graphics memory.
       
  2993 @return KErrNoGraphicsMemory or KErrNoMemory if successful, otherwise one of the system
       
  2994 	wide error codes.
       
  2995  */
       
  2996 /*static TInt FillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages)
       
  2997 	{
       
  2998 	TInt err = KErrNone;
       
  2999 	while (KErrNone == err)
       
  3000 		{
       
  3001 		RSgImage sgImage;
       
  3002 		err = sgImage.Create(TSgImageInfo(aSize, ESgPixelFormatA_8, ESgUsageBitOpenVgImage));
       
  3003 		if (KErrNone == err)
       
  3004 			{
       
  3005 			err = aImages.Append(sgImage);
       
  3006 			}
       
  3007 		}
       
  3008 	return err;
       
  3009 	}*/
       
  3010 
       
  3011 /**
       
  3012 Utility method that fills the RSgImage memory with RSgImages until either KErrNoMemory
       
  3013 or KErrNoGraphicsMemory is returned and then closes one RSgImage to free up some memory.
       
  3014 
       
  3015 @param aSize The size of the image used to fill the graphics memory - a form of granularity
       
  3016 @param aImages Returns the array of the images used to fill the graphics memory.
       
  3017 @return KErrNone if successful, otherwise one of the system	wide error codes.
       
  3018  */
       
  3019 /*static TInt NearlyFillGraphicsMemoryWithImages(const TSize& aSize, RArray<RSgImage>& aImages)
       
  3020 	{
       
  3021 	TInt err = FillGraphicsMemoryWithImages(aSize, aImages);
       
  3022 	if (err == KErrNoMemory || err == KErrNoGraphicsMemory)
       
  3023 		{
       
  3024 		if (aImages.Count() > 0)
       
  3025 			{
       
  3026 			// Remove an image to free up some memory.
       
  3027 			TInt lastIndex = aImages.Count() - 1;
       
  3028 			aImages[lastIndex].Close();
       
  3029 			aImages.Remove(lastIndex);
       
  3030 			}
       
  3031 		err = KErrNone;
       
  3032 		}
       
  3033 	return err;
       
  3034 	}*/
       
  3035 
       
  3036 /**
       
  3037 Static utility function. Creates an 8bpp RSgImage from 1bpp or 8bpp character
       
  3038 data, with VGImage usage flag set.
       
  3039 @param aData The character image data. Either in 8bpp or 1bpp RLE format.
       
  3040 @param aSize The size of the character image in pixels.
       
  3041 @param aType The type of glyph - Monochrome or Antialiased. 
       
  3042 @param aSgImage A closed image which will be populated with 8bpp image data.
       
  3043 */
       
  3044 static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage)
       
  3045 	{
       
  3046 	return CreateSgImageFromCharacterData(aData, aSize, aType, aImage, NULL, NULL);
       
  3047 	}
       
  3048 
       
  3049 /**
       
  3050 Static utility function. Creates an 8bpp RSgImage from 1bpp or 8bpp character
       
  3051 data, with VGImage usage flag set. 
       
  3052 This overload allows the memory for the buffers to be pre-created to avoid
       
  3053 memory allocation failure during low-memory testing.
       
  3054 @param aData The character image data. Either in 8bpp or 1bpp RLE format.
       
  3055 @param aSize The size of the character image in pixels.
       
  3056 @param aType The type of glyph - Monochrome or Antialiased. 
       
  3057 @param aSgImage A closed image which will be populated with 8bpp image data.
       
  3058 @param aBuffer1 If non-NULL, used as a memory buffer for reading the decoded 
       
  3059 	image data into for monochrome images.
       
  3060 @param aBuffer2 If non-NULL, used as a memory buffer for the decoded image
       
  3061 	data for monochrome images.
       
  3062 */
       
  3063 static TInt CreateSgImageFromCharacterData(const TUint8* aData, const TSize& aSize, TGlyphBitmapType aType, RSgImage& aImage, TUint8* aBuffer1, TUint8* aBuffer2)
       
  3064 	{
       
  3065 	TInt err = KErrNone;	
       
  3066 	if (aSize == TSize(0, 0))
       
  3067 		{
       
  3068 		return KErrArgument;
       
  3069 		}
       
  3070 	TUint8* dataBuf = NULL;
       
  3071 	TInt dataStride = 0;
       
  3072 	TBool freeDataBuf = EFalse;
       
  3073 	if (aType == EAntiAliasedGlyphBitmap)
       
  3074 		{
       
  3075 		dataBuf = const_cast<TUint8*>(aData);
       
  3076 		dataStride = aSize.iWidth;
       
  3077 		}
       
  3078 	else if (aType == EMonochromeGlyphBitmap)
       
  3079 		{
       
  3080 		TUint8* binaryData = NULL;
       
  3081 		TUint8* tempBuf = NULL;
       
  3082 		TInt binaryDataStride = ((aSize.iWidth + 31) / 32) << 2;
       
  3083 		TInt binaryDataSize = binaryDataStride * aSize.iHeight;
       
  3084 		if (aBuffer1 && User::AllocLen(aBuffer1) >= binaryDataSize)
       
  3085 			{
       
  3086 			binaryData = aBuffer1;
       
  3087 			}
       
  3088 		else
       
  3089 			{
       
  3090 			tempBuf = (TUint8*) User::AllocZ(binaryDataSize);
       
  3091 			if (!tempBuf)
       
  3092 				{
       
  3093 				return KErrNoMemory;
       
  3094 				}
       
  3095 			binaryData = tempBuf;
       
  3096 			}
       
  3097 		// Unpack the run length encoded data into 1bpp
       
  3098 		DecodeBinaryData(aSize, aData, binaryDataStride, reinterpret_cast<TUint32*&>(binaryData));
       
  3099 		dataStride = aSize.iWidth;
       
  3100 		TInt byteDataSize = dataStride * aSize.iHeight;
       
  3101 		TUint8* byteData = NULL;
       
  3102 		// If aByteBuf supplied, use that instead of allocating a new buffer here.
       
  3103 		if (aBuffer2 && User::AllocLen(aBuffer2) >= byteDataSize)
       
  3104 			{
       
  3105 			byteData = aBuffer2;
       
  3106 			}
       
  3107 		else
       
  3108 			{
       
  3109 			byteData = (TUint8*) User::AllocZ(byteDataSize);
       
  3110 			if (!byteData)
       
  3111 				{
       
  3112 				User::Free(tempBuf);
       
  3113 				return KErrNoMemory;
       
  3114 				}
       
  3115 			freeDataBuf = ETrue;
       
  3116 			}
       
  3117 		dataBuf = byteData;
       
  3118 		for (TInt scanline = 0; scanline < aSize.iHeight; ++scanline)
       
  3119 			{
       
  3120 			TUint8* srcByte = binaryData;
       
  3121 			for (TInt pixel = 0; pixel < aSize.iWidth; pixel++)
       
  3122 				{
       
  3123 				*(byteData+pixel) = ((*srcByte & (1 << (pixel % 8))) == 0) ? 0 : 0xFF;
       
  3124 				if (((pixel + 1) % 8) == 0) srcByte++;
       
  3125 				}
       
  3126 			byteData += dataStride;
       
  3127 			binaryData += binaryDataStride;
       
  3128 			}
       
  3129 		User::Free(tempBuf);
       
  3130 		}
       
  3131 	else
       
  3132 		{
       
  3133 		return KErrArgument;
       
  3134 		}
       
  3135 
       
  3136 	// Create RSgImage from CFbsBitmap.
       
  3137 	TSgImageInfo sgImageInfo(aSize, ESgPixelFormatA_8, ESgUsageBitOpenVgImage);
       
  3138 	err = aImage.Create(sgImageInfo, dataBuf, dataStride);
       
  3139 	if (freeDataBuf)
       
  3140 		{
       
  3141 		User::Free(dataBuf);
       
  3142 		}
       
  3143 	return err;
       
  3144 	}
       
  3145 
       
  3146 
       
  3147 /**
       
  3148 Static utility function, Copies image data line(s) to a destination.
       
  3149 @param aBinaryDataPtr pointer to a destination buffer.
       
  3150 @param aBufferWords Stride of the image.
       
  3151 @param aData Pointer to a source buffer.
       
  3152 @param aBitShift Number of bits, binary data will be shifted. 
       
  3153 @param aCharWidth Width of the image.
       
  3154 @param aRepeatCount Number of lines to copy.
       
  3155 */
       
  3156 static void CopyCharLine(TUint32*& aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth, TInt16 aRepeatCount)
       
  3157 	{
       
  3158 	aBitShift&=7;
       
  3159 	TInt wordstocopy=(aCharWidth+31)>>5;
       
  3160 	if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
       
  3161 	TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
       
  3162 	TUint32* dataword=(TUint32*)(TInt(aData)&~3);
       
  3163 	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
       
  3164 	
       
  3165 	TUint32* startBinaryDataPtr = aBinaryDataPtr;
       
  3166 	while(aBinaryDataPtr<ptrlimit)
       
  3167 		{
       
  3168 		*aBinaryDataPtr=*dataword++;
       
  3169 		*aBinaryDataPtr>>=aBitShift;
       
  3170 		if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
       
  3171 		aBinaryDataPtr++;
       
  3172 		}
       
  3173 	
       
  3174 	TUint32* curStartBinaryDataPtr = aBinaryDataPtr;
       
  3175 	TInt byteToCopy = wordstocopy << 2;
       
  3176 	while(aRepeatCount > 1)
       
  3177 		{
       
  3178 		Mem::Copy(curStartBinaryDataPtr, startBinaryDataPtr, byteToCopy);
       
  3179 		curStartBinaryDataPtr += wordstocopy;
       
  3180 		
       
  3181 		aRepeatCount--;
       
  3182 		}
       
  3183 	aBinaryDataPtr = curStartBinaryDataPtr;
       
  3184 	}
       
  3185 
       
  3186 /**
       
  3187 Static utility function. Decodes a monochrome glyph whose data is run length encoded, 
       
  3188 into a 1bpp bitmap.
       
  3189 @param aDataSize Image size in pixels.
       
  3190 @param aData Pointer to a source buffer.
       
  3191 @param aStride Image data stride.
       
  3192 @param aBinaryData Pointer to a destination buffer. This buffer must be allocated 
       
  3193 	by the caller.
       
  3194 */
       
  3195 static void DecodeBinaryData(const TSize& aDataSize, const TUint8* aData, TInt aStride,
       
  3196 											TUint32* aBinaryData)
       
  3197 	{
       
  3198 	const TInt datalength = aDataSize.iWidth;
       
  3199 	const TInt dataheight = aDataSize.iHeight;
       
  3200 	TInt bitindex=0;
       
  3201 	TInt16 repeatcount=0;
       
  3202 	TUint32* slbuffer=aBinaryData;
       
  3203 	const TInt slwords=aStride;
       
  3204 
       
  3205 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
       
  3206 		{
       
  3207 		repeatcount=CFbsBitGc::Load16(aData+(bitindex>>3));
       
  3208 		repeatcount>>=bitindex&7;
       
  3209 		const TInt multilineflag=repeatcount&1;
       
  3210 		repeatcount>>=1;
       
  3211 		repeatcount&=0xf;
       
  3212 		bitindex+=5;
       
  3213 		if(multilineflag)
       
  3214 			{
       
  3215 			for(TInt currentline=0;currentline<repeatcount;currentline++)
       
  3216 				{
       
  3217 				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength, 1);
       
  3218 				bitindex+=datalength;
       
  3219 				}
       
  3220 			}
       
  3221 		else
       
  3222 			{
       
  3223 			CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength, repeatcount);
       
  3224 			bitindex+=datalength;
       
  3225 			}
       
  3226 		}
       
  3227 	}
       
  3228 //--------------
       
  3229 __CONSTRUCT_STEP__(FbsGlyphData)