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