os/graphics/graphicstest/uibench/src/tfbsglyphdata.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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  @test
    19  @internalComponent - Internal Symbian test code 
    20 */
    21 
    22 #include <test/graphicsfontutils.h>
    23 #include <graphics/fbsglyphdataiterator.h>
    24 #include <graphics/fbsglyphmetricsarray.h>
    25 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    26 #include <sgresource/sgimage.h>
    27 #include <egl/egl.h>
    28 #include <vg/openvg.h>
    29 typedef EGLBoolean (*TvgCreateEGLImageTargetKHRTypefPtr) (VGeglImageKHR image);
    30 #endif
    31 #include "tfbsglyphdata.h"
    32 
    33 // Size of EGLSurface used for rendering to, in pixels.
    34 const TSize KEglTargetSize(512, 512);
    35 
    36 CTFbsGlyphData::CTFbsGlyphData()
    37 	{
    38 	SetTestStepName(KTFbsGlyphData);
    39 	}
    40 
    41 CTFbsGlyphData::~CTFbsGlyphData()
    42 	{
    43 	}
    44 
    45 TVerdict CTFbsGlyphData::doTestStepPreambleL()
    46     {
    47 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    48     User::LeaveIfError(iFbs.Connect());
    49 	User::LeaveIfError(iSgDriver.Open());
    50 #endif
    51 	iCharCodeConverter = CCharCodeConverter::NewL();
    52     return CTe_graphicsperformanceSuiteStepBase::doTestStepPreambleL();
    53     }
    54 
    55 TVerdict CTFbsGlyphData::doTestStepPostambleL()
    56     {
    57     delete iCharCodeConverter;
    58     iCharCodeConverter = NULL;
    59 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    60     iSgDriver.Close();
    61     iFbs.Disconnect();
    62 #endif
    63     return CTe_graphicsperformanceSuiteStepBase::doTestStepPostambleL();
    64     }
    65 
    66 TVerdict CTFbsGlyphData::doTestStepL()
    67 	{
    68 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    69     INFO_PRINTF1(_L("CTFbsGlyphData can only be run with SgImage 'Lite'"));
    70     return TestStepResult();
    71 #else
    72 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0178"));
    73 	GlyphMetricsArrayL(ETestLanguageLatin, ETrue, 1000);
    74 	RecordTestResultL();
    75 
    76 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0179"));
    77 	GlyphMetricsArrayL(ETestLanguageLatin, EFalse, 50000);
    78 	RecordTestResultL();
    79 	
    80     // Tests 180 and 181 require a CMap table in order to convert CharacterCodes to GlyphCodes.
    81 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0180"));
    82 	GlyphMetricsArrayL(ETestLanguageHindi, ETrue, 25);
    83 	RecordTestResultL();
    84 	
    85 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0181"));
    86 	GlyphMetricsArrayL(ETestLanguageHindi, EFalse, 50000);
    87 	RecordTestResultL();
    88 	
    89 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0182"));
    90 	GlyphMetricsQuerySingleGlyphL();
    91 	RecordTestResultL();
    92 	
    93 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0183"));
    94 	GlyphDataIteratorOpenL(ETestLanguageLatin, ETrue, 50);
    95 	RecordTestResultL();
    96 
    97 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0184"));
    98 	GlyphDataIteratorOpenL(ETestLanguageLatin, EFalse, 500);
    99 	RecordTestResultL();
   100 	
   101     // Tests 185 and 186 require a CMap table in order to convert CharacterCodes to GlyphCodes.
   102 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0185"));
   103 	GlyphDataIteratorOpenL(ETestLanguageHindi, ETrue, 10);
   104 	RecordTestResultL();
   105 	
   106 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0186"));
   107 	GlyphDataIteratorOpenL(ETestLanguageHindi, EFalse, 5000);
   108 	RecordTestResultL();
   109 	
   110 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0187"));
   111 	GlyphDataIteratorOpenSingleFontL();
   112 	RecordTestResultL();
   113 	
   114 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0188"));
   115 	GlyphMetricsQueryUnrasterizedL();
   116 	RecordTestResultL();
   117 	
   118 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0189"));
   119 	GlyphMetricsQueryPreRasterizedL();
   120 	RecordTestResultL();
   121 	
   122 	SetTestStepID(_L("GRAPHICS-UI-BENCH-0190"));
   123 	GlyphRenderingL();
   124 	RecordTestResultL();
   125 
   126 	return TestStepResult();
   127 #endif
   128     }
   129 
   130 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
   131 /**
   132 @SYMTestCaseID GRAPHICS-UI-BENCH-0178...0181
   133 
   134 @SYMTestType UT
   135 
   136 @SYMPREQ PREQ2678
   137 
   138 @SYMTestCaseDesc 
   139 Measures the performance of calling RFbsGlyphMetricsArray::Get() with different sample data.
   140 The sample data can be a single word, or a very long array of glyphs, in latin or non-latin
   141 alphabets. At each repetition a different font is used, cycled over nine fonts, to reduce the
   142 effect of having cached glyphs.
   143 
   144 @SYMTestActions
   145 i. Create some sample fonts to cycle through. 
   146 ii. Load sample data from config file, specified by aSampleDataKey.
   147 iii. Create RFbsGlyphMetricsArray, open on sample data.
   148 iv. For each repetition, call RFbsGlyphMetricsArray::Get(), adjusting font at each repetition.
   149 v. Measure time from from first to last repetition.
   150 
   151 @param aLanguage The language this test will use.
   152 @param aLongData If ETrue, tells the test to use the long sample data string for the test, EFalse
   153 	will make the test use the short string data.
   154 @param aReps The number of times to repeat the test.
   155 */
   156 void CTFbsGlyphData::GlyphMetricsArrayL(TTestLanguage aLanguage, TBool aLongData, TInt aReps)
   157 	{
   158 	TBuf<128> KTestName;
   159 	TPtrC KTestVariant = ConfigKeyNameL(aLanguage, aLongData);
   160 	KTestName.Format(_L("GlyphMetricsArray %S"), &KTestVariant);
   161 	
   162 	// Create some test fonts using the font factory.
   163 	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   164 	fontFactory->CreateFontsL(aLanguage, 9);
   165 
   166 	// Load the sample string data from the config file.
   167 	TInt numGlyphCodes = 0;
   168 	TUint* glyphCodes;
   169 	LoadConfigSampleDataL(fontFactory->NextFont(), aLanguage, aLongData, glyphCodes, numGlyphCodes);
   170 
   171 	// Run the test.
   172 	TInt err = KErrNone;
   173 	RFbsGlyphMetricsArray array;
   174 	CleanupClosePushL(array);
   175 	iProfiler->InitResults();
   176 	for (TInt rep = aReps; (rep != 0) && (err == KErrNone); --rep)
   177 		{
   178 		err = array.Get(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
   179 		}
   180 	iProfiler->MarkResultSetL();
   181 	TESTE(err == KErrNone, err);
   182 	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, aReps, numGlyphCodes);
   183 	
   184 	CleanupStack::PopAndDestroy(2); // array, fontFactory
   185 	delete [] glyphCodes;
   186 	}
   187 
   188 /**
   189 @SYMTestCaseID GRAPHICS-UI-BENCH-0182
   190 
   191 @SYMTestType UT
   192 
   193 @SYMPREQ PREQ2678
   194 
   195 @SYMTestCaseDesc 
   196 Measures the performance of calling RFbsGlyphDataIterator::Get() with a single glyph,
   197 versus CFont::GetCharacterData(). Using a single glyph code is a very common use case.
   198 The glyph and the font is changed at each iteration.
   199 
   200 @SYMTestActions
   201 i. Create some sample fonts to cycle through. 
   202 ii. Create RFbsGlyphMetricsArray.
   203 iii. For each repetition, call RFbsGlyphMetricsArray::Get(), adjusting the glyph at 
   204 	each iteration.
   205 iv. Measure time from from first to last iteration.
   206 v. Repeat steps iii. and iv. with CFont::GetCharacterData().
   207 */
   208 void CTFbsGlyphData::GlyphMetricsQuerySingleGlyphL()
   209 	{
   210 	_LIT(KTestName, "GlyphMetricsQuerySingleGlyph");
   211 	const TInt KNumIterations = 50000;
   212 	TInt err = KErrNone;
   213 	TBuf<128> KTestNameVariant;
   214 
   215 	// Create some test fonts using the font factory.
   216 	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   217 	
   218 	// Run the test for RFbsGlyphMetricsArray, with a different character 
   219 	// and font for each iteration.
   220 	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
   221 	fontFactory->CreateFontsL(ETestLanguageLatin, 9);
   222 	RFbsGlyphMetricsArray array;
   223 	CleanupClosePushL(array);
   224 	iProfiler->InitResults();
   225 	for (TInt rep = KNumIterations; rep != 0 && (err == KErrNone); --rep)
   226 		{
   227 		const TUint KGlyphCode = 32 + (rep % 96);
   228 		err = array.Get(*(fontFactory->NextFont()), &KGlyphCode, 1);
   229 		}
   230 	iProfiler->MarkResultSetL();
   231 	TESTE(err == KErrNone, err);
   232 	CleanupStack::PopAndDestroy(1); // array
   233 	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, 1);
   234 	fontFactory->ReleaseFonts();
   235 	
   236 	// Run the test for GetCharacterData(), with a different character
   237 	// and font for each iteration.
   238 	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
   239 	fontFactory->CreateFontsL(ETestLanguageLatin, 9);
   240 	TOpenFontCharMetrics metrics;
   241 	const TUint8* bitmapData = NULL;
   242 	TSize bitmapSize;
   243 	iProfiler->InitResults();
   244 	for (TInt rep = KNumIterations; rep != 0; --rep)
   245 		{
   246 		const TUint KGlyphCode = 32 + (rep % 96);
   247 		fontFactory->NextFont()->GetCharacterData(KGlyphCode, metrics, bitmapData, bitmapSize);
   248 		}
   249 	iProfiler->MarkResultSetL();
   250 	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, 1);
   251 	
   252 	CleanupStack::PopAndDestroy(1); // fontFactory
   253 	}
   254 
   255 /**
   256 @SYMTestCaseID GRAPHICS-UI-BENCH-0183...0186
   257 
   258 @SYMTestType UT
   259 
   260 @SYMPREQ PREQ2678
   261 
   262 @SYMTestCaseDesc 
   263 Measures the performance of calling RFbsGlyphDataIterator::Open() with different 
   264 sample data, and iterating through the data with RFbsGlyphDataIterator::Next(). 
   265 The sample data can be a single word, or a very long array of glyphs,
   266 in various languages. At each repetition a different font is used, cycled
   267 over nine fonts.
   268 
   269 @SYMTestActions
   270 i. Create some sample fonts to cycle through. 
   271 ii. Create RFbsGlyphDataIterator.
   272 iii. For each repetition, call RFbsGlyphDataIterator::Open(), adjusting the glyph at each 
   273 	iteration. The font is changed at each repetition.
   274 iv. Measure time from from first to last repetition.
   275 
   276 @param aLanguage The language this test will use.
   277 @param aLongData If ETrue, tells the test to use the long sample data string for the test, EFalse
   278 	will make the test use the short string data.
   279 @param aReps The number of times to repeat the test.
   280  */
   281 void CTFbsGlyphData::GlyphDataIteratorOpenL(TTestLanguage aLanguage, TBool aLongData, TInt aReps)
   282 	{
   283 	TBuf<128> KTestName;
   284 	TPtrC KTestVariant = ConfigKeyNameL(aLanguage, aLongData);
   285 	KTestName.Format(_L("GlyphDataIteratorOpen %S"), &KTestVariant);
   286 	
   287 	// Create some test fonts using the font factory.
   288 	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   289 	fontFactory->CreateFontsL(aLanguage, 9);
   290 	
   291 	// Load the sample string data from the config file.
   292 	TInt numGlyphCodes = 0;
   293 	TUint* glyphCodes;
   294 	LoadConfigSampleDataL(fontFactory->NextFont(), aLanguage, aLongData, glyphCodes, numGlyphCodes);
   295 
   296 	// Run the test.
   297 	TInt err = KErrNotFound;
   298 	RFbsGlyphDataIterator iter;
   299 	CleanupClosePushL(iter);
   300 	iProfiler->InitResults();
   301 	for (TInt rep = aReps; (rep != 0) && (err == KErrNotFound); --rep)
   302 		{
   303 		err = iter.Open(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
   304 		for (; err == KErrNone; err = iter.Next())
   305 			{
   306 			// no operation
   307 			}
   308 		iter.Close();
   309 		}
   310 	iProfiler->MarkResultSetL();
   311 	TESTE(err == KErrNotFound, err);
   312 
   313 	CleanupStack::PopAndDestroy(2); // iter, fontFactory
   314 	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, aReps, numGlyphCodes);
   315 	delete [] glyphCodes;
   316 	}
   317 
   318 /**
   319 @SYMTestCaseID GRAPHICS-UI-BENCH-0187
   320 
   321 @SYMTestType UT
   322 
   323 @SYMPREQ PREQ2678
   324 
   325 @SYMTestCaseDesc 
   326 Measures the performance of calling RFbsGlyphDataIterator::Open() with different 
   327 lengthed arrays but the same font. The sample data is a long array of characters.
   328 
   329 @SYMTestActions
   330 i. Create a single test font 
   331 ii. Create RFbsGlyphDataIterator.
   332 iii. Pass an array to RFbsGlyphDataIterator::Open(), starting with a single glyph.
   333 	For each iteration, increase the length of the array by one until the entire
   334 	string has been opened.
   335 iv. Measure the time to perform all the iterations.
   336 
   337 @param aSampleDataKey The string key to lookup under the GlyphArraySampleText section of the 
   338 	config file where the sample data is read.
   339 @param aReps The number of times to repeat the test.
   340  */
   341 void CTFbsGlyphData::GlyphDataIteratorOpenSingleFontL()
   342 	{
   343 	_LIT(KTestName, "GlyphDataIteratorOpenSingleFont");
   344 	// A cap on the max number of iterations to complete.
   345 	const TInt KMaxNumIterations = 200;
   346     const TTestLanguage KTestLanguage = ETestLanguageHindi;
   347 	
   348 	// Create some test fonts using the font factory.
   349 	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   350 	fontFactory->CreateFontsL(KTestLanguage, 1);
   351 	CFbsFont* font = fontFactory->NextFont();
   352 	
   353 	// Load the sample string data from the config file.
   354 	TInt numGlyphCodes = 0;
   355 	TUint* glyphCodes;
   356 	LoadConfigSampleDataL(font, KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
   357 	
   358 	const TInt KNumRepetitions = Min<TInt>(numGlyphCodes - 1, KMaxNumIterations);
   359 	RFbsGlyphDataIterator iter;
   360 	CleanupClosePushL(iter);
   361 	TInt iterErr = KErrNone;
   362 	TInt glyphCount = 0;
   363 	iProfiler->InitResults();
   364 	for (glyphCount = 1; (glyphCount < KNumRepetitions); ++glyphCount)
   365 		{
   366 		iterErr = iter.Open(*font, glyphCodes, glyphCount);
   367 		for (; iterErr == KErrNone; iterErr = iter.Next())
   368 			{
   369 			// no operation
   370 			}
   371 		iter.Close();
   372 		}
   373 	iProfiler->MarkResultSetL();
   374 	TEST(glyphCount == KNumRepetitions);
   375 	TESTE(iterErr == KErrNotFound, iterErr);
   376 	
   377 	const TInt KAvgNumCharsPerIteration = KNumRepetitions/2;
   378 	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, KNumRepetitions, KAvgNumCharsPerIteration);
   379 	
   380 	CleanupStack::PopAndDestroy(2); // iter, fontFactory
   381 	delete [] glyphCodes;
   382 	}
   383 /**
   384 @SYMTestCaseID GRAPHICS-UI-BENCH-0188
   385 
   386 @SYMTestType UT
   387 
   388 @SYMPREQ PREQ2678
   389 
   390 @SYMTestCaseDesc 
   391 Measures the performance of querying the TOpenFontCharMetrics using the different
   392 available APIs. RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData()
   393 are compared against each other, using the same fonts, and same sample data.
   394 This test uses glyphs that have not been rasterized before, therefore for certain
   395 APIs this will mean rasterizing the glyphs.
   396 
   397 @SYMTestActions
   398 i. Load sample text data from config file.
   399 ii. For each of RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData():
   400 	1. Create 50 new fonts.
   401 	2. Run the test, calling the necessary API once per font/loop.
   402 	3. For GetCharacterData() and RFbsGlyphDataIterator(), cycle through each glyph
   403 		to ensure all metrics have been retrieved. This is not necessary for 
   404 		RFbsGlyphMetricsArray.
   405 	4. Measure time between first and last font/loop.
   406 	5. Destroy test fonts so that next test has to re-rasterize the glyphs.	
   407 
   408 @SYMTestExpectedResults
   409 Since this test uses non-rasterized fonts, RFbsGlyphMetricsArray should be faster than
   410 GetCharacterData() and RFbsGlyphDataIterator, which both rasterize the glyphs in order to 
   411 get their metrics information.
   412  */
   413 void CTFbsGlyphData::GlyphMetricsQueryUnrasterizedL()
   414 	{
   415 	_LIT(KTestName, "GlyphMetricsQueryUnrasterized");
   416 	
   417 	TBuf<128> KTestNameVariant;
   418 	// First do the test for the iterator. To ensure fair comparison with
   419     // RFbsGlyphMetricsArray, cycle through each iteration to ensure the metrics
   420     // for each glyph is found.
   421     KTestNameVariant.Format(_L("%S RFbsGlyphDataIterator"), &KTestName);
   422     
   423 	const TInt KNumFonts = 50;
   424 	const TTestLanguage KTestLanguage = ETestLanguageLatin;
   425 	
   426 	// Create some test fonts using the font factory.
   427 	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   428     fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
   429 	    
   430 	// Load the sample string data from the config file. Both the iterator and the
   431 	// array will use this same sample data.
   432 	TInt numGlyphCodes = 0;
   433 	TUint* glyphCodes;
   434 	LoadConfigSampleDataL(fontFactory->NextFont(), KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
   435 	
   436 	RFbsGlyphDataIterator iter;
   437 	CleanupClosePushL(iter);
   438 	TInt iterErr = KErrNone;
   439 	TInt rep = 0;
   440 	iProfiler->InitResults();
   441 	for (rep = KNumFonts; (rep != 0); --rep)
   442 		{
   443 		iterErr = iter.Open(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
   444 		for (; iterErr == KErrNone; iterErr = iter.Next())
   445 			{
   446 			// no operation
   447 			}
   448 		iter.Close();
   449 		}
   450 	iProfiler->MarkResultSetL();
   451 	TEST(rep == 0);
   452 	TESTE(iterErr == KErrNotFound, iterErr);
   453 	CleanupStack::PopAndDestroy(1); // iter		
   454 	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
   455 	
   456 	// Second, do the test for the array. This should be faster.
   457 	// Destroy the fonts and re-create them so that they have to be re-rasterized
   458 	// for a fair comparison.
   459 	TInt arrayErr = KErrNone;
   460 	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
   461 	fontFactory->ReleaseFonts();
   462 	fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
   463 	RFbsGlyphMetricsArray array;
   464 	CleanupClosePushL(array);
   465 	iProfiler->InitResults();	
   466 	for (TInt rep = KNumFonts; (rep != 0) && (arrayErr == KErrNone); --rep)
   467 		{
   468 		arrayErr = array.Get(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
   469 		}
   470 	iProfiler->MarkResultSetL();
   471 	CleanupStack::PopAndDestroy(1); // array
   472 	TEST(rep == 0);
   473 	TESTE(arrayErr == KErrNone, arrayErr);
   474 	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
   475 	
   476 	// Third, do the test using GetCharacterData() to get the metrics.
   477 	// Destroy the fonts and re-create them so that they have to be re-rasterized
   478 	// for a fair comparison.
   479 	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
   480 	fontFactory->ReleaseFonts();
   481 	fontFactory->CreateFontsL(KTestLanguage, KNumFonts);	
   482 	iProfiler->InitResults();
   483 	const TUint8* bitmapData = NULL;
   484 	TSize bitmapSize;
   485 	TOpenFontCharMetrics metrics;	
   486 	for (TInt rep = KNumFonts; (rep != 0); --rep)
   487 		{
   488 		CFbsFont* font = fontFactory->NextFont(); 
   489 		for (TInt glyphIndex = 0; glyphIndex < numGlyphCodes; glyphIndex++)
   490 			{
   491 			font->GetCharacterData(glyphCodes[glyphIndex], metrics, bitmapData, bitmapSize);
   492 			}
   493 		}
   494 	iProfiler->MarkResultSetL();
   495 	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
   496 	
   497 	CleanupStack::PopAndDestroy(1); // fontFactory
   498 	delete [] glyphCodes;
   499 	}
   500 
   501 /**
   502 @SYMTestCaseID GRAPHICS-UI-BENCH-0189
   503 
   504 @SYMTestType UT
   505 
   506 @SYMPREQ PREQ2678
   507 
   508 @SYMTestCaseDesc 
   509 Measures the performance of querying the TOpenFontCharMetrics using the different
   510 available APIs. RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData()
   511 are compared against each other, using the same fonts, and same sample data.
   512 This test uses glyphs that have already been rasterized, thereby possibly reducing the 
   513 extra overhead this has.
   514 
   515 @SYMTestActions
   516 i. Load sample text data from config file.
   517 ii. Create test font.
   518 iii. Pre-rasterize glyphs using RFbsGlyphDataIterator. This will rasterize the glyphs 
   519 	and cause them to be cached for use by all the APIs tested here.
   520 iv. For each of RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData():
   521 	1. Begin the loop, calling the necessary API once per font/loop.
   522 	2. For each glyph, request the glyph metrics.
   523 	3. Measure time between first and last font/loop.
   524 v. Destroy test font.
   525 
   526 @SYMTestExpectedResults
   527 All results should be improved over GlyphMetricsQueryUnrasterized (GRAPHICS-UI-BENCH-0187).
   528 since no rasterizing should take place during these tests.
   529  */
   530 void CTFbsGlyphData::GlyphMetricsQueryPreRasterizedL()
   531 	{
   532 	_LIT(KTestName, "GlyphMetricsQueryPreRasterized");
   533 	TBuf<128> KTestNameVariant;
   534 	const TInt KNumIterations = 500;
   535 	const TTestLanguage KTestLanguage = ETestLanguageLatin;
   536 
   537 	// Create a test font using the font factory.
   538     CTFontFactory* fontFactory = CTFontFactory::NewLC();
   539     fontFactory->CreateFontsL(ETestLanguageLatin, 1);   
   540     CFbsFont* font = fontFactory->NextFont();
   541 	    
   542     TInt numGlyphCodes = 0;
   543 	TUint* glyphCodes;
   544 	LoadConfigSampleDataL(font, KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
   545 	
   546 	TInt iterErr = KErrNone;
   547 	TInt rep = 0;
   548 	// Rasterize the glyphs first.
   549 	RFbsGlyphDataIterator iter;
   550 	CleanupClosePushL(iter);
   551 	for (rep = KNumIterations; (rep != 0) ; --rep)
   552 		{
   553 		iterErr = iter.Open(*font, glyphCodes, numGlyphCodes);
   554 		for (; iterErr == KErrNone; iterErr = iter.Next())
   555 			{
   556 			// no operation
   557 			}
   558 		iter.Close();
   559 		}
   560 	TEST(rep == 0);
   561 	TESTE(iterErr == KErrNotFound, iterErr);
   562 	
   563 	TOpenFontCharMetrics metrics;
   564 		
   565 	// First do the test for the iterator. To ensure fair comparison with
   566 	// RFbsGlyphMetricsArray, cycle through each iteration to ensure the metrics
   567 	// for each glyph is found.
   568 	iterErr = KErrNone;
   569 	KTestNameVariant.Format(_L("%S RFbsGlyphDataIterator"), &KTestName);
   570 	iProfiler->InitResults();
   571 	for (TInt rep = KNumIterations; (rep != 0); --rep)
   572 		{
   573 		for (iterErr = iter.Open(*font, glyphCodes, numGlyphCodes); iterErr == KErrNone; iterErr = iter.Next())
   574 			{
   575 			metrics = iter.Metrics();
   576 			}
   577 		iter.Close();
   578 		}
   579 	iProfiler->MarkResultSetL();
   580 	TESTE(iterErr == KErrNotFound, iterErr);
   581 	CleanupStack::PopAndDestroy(1); // iter
   582 	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
   583 	
   584 	
   585 	// Second, do the test for the array. This should be faster.
   586 	TInt arrayErr = KErrNone;
   587 	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
   588 	RFbsGlyphMetricsArray array;
   589 	CleanupClosePushL(array);
   590 	iProfiler->InitResults();
   591 	for (TInt rep = KNumIterations; (rep != 0) && (arrayErr == KErrNone); --rep)
   592 		{
   593 		arrayErr = array.Get(*font, glyphCodes, numGlyphCodes);
   594 		for (TInt i = 0; i < numGlyphCodes; ++i)
   595 			{
   596 			metrics = array[i];
   597 			}
   598 		}
   599 	iProfiler->MarkResultSetL();
   600 	TESTE(arrayErr == KErrNone, arrayErr);
   601 	CleanupStack::PopAndDestroy(1); // array
   602 	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
   603 	
   604 	
   605 	// Third, do the test using GetCharacterData() to get the metrics.
   606 	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
   607 	const TUint8* bitmapData;
   608 	TSize bitmapSize;
   609 
   610 	iProfiler->InitResults();
   611 	for (TInt rep = KNumIterations; (rep != 0); --rep)
   612 		{
   613 		for (TInt glyphIndex = 0; glyphIndex < numGlyphCodes; glyphIndex++)
   614 			{
   615 			font->GetCharacterData(glyphCodes[glyphIndex], metrics, bitmapData, bitmapSize);
   616 			}
   617 		}
   618 	iProfiler->MarkResultSetL();
   619 	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
   620 	
   621 	CleanupStack::PopAndDestroy(1); // fontFactory
   622 	delete [] glyphCodes;
   623 	}
   624 
   625 /**
   626 @SYMTestCaseID GRAPHICS-UI-BENCH-0190
   627 
   628 @SYMTestType UT
   629 
   630 @SYMPREQ PREQ2678
   631 
   632 @SYMTestCaseDesc 
   633 Measures the end-to-end performance of using Khronos APIs to render glyphs using the
   634 RFbsGlyphDataIterator API. Positioning is very basic and is not reflective of a production-
   635 quality text-rendering algorithm, but serves as a useful benchmark of the overall
   636 text-rendering performance using this API.
   637 
   638 @SYMTestActions
   639 i. Create a sample font to use. 
   640 ii. Create a RSgImage to be used as a target for Khronos API rendering.
   641 iii. Set-up EGL and OpenVG.
   642 iv. Construct RFbsGlyphDataIterator, and open on sample data. At each iteration:
   643 	1. Create an EGLImage from the RSgImage.
   644 	2. Create a VGImage from the EGLImage.
   645 	3. Render the VGImage using vgDrawImage().
   646 	4. Destroy VGImage.
   647 	5. Destroy EGLImage.
   648 	6. Advance the current rendering position for the next glyph, ensuring that every glyph
   649 	will be within the bounds of the target surface.
   650 v. Measure time from from first to last iteration.
   651 */
   652 void CTFbsGlyphData::GlyphRenderingL()
   653 	{
   654 	_LIT(KTestName, "GlyphRendering");
   655 	const TInt KNumIterations = 500;
   656     const TTestLanguage KTestLanguage = ETestLanguageHindi;
   657 	
   658 	// Create some test fonts using the font factory.
   659 	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   660 	fontFactory->CreateFontsL(KTestLanguage, 1, 20);
   661 	CFbsFont* font = fontFactory->NextFont();
   662 	const TInt KFontHeightInPixels = font->HeightInPixels();
   663 
   664 	// Create RSgImage to be used as OpenVG Pixmap Surface
   665 
   666 	RSgImage target;
   667 	TInt err = target.Create(TSgImageInfo(KEglTargetSize, ESgPixelFormatARGB_8888_PRE, ESgUsageBitOpenVgSurface));
   668 	TESTL(err == KErrNone);
   669 	CleanupClosePushL(target);
   670 	
   671 	// Initialize EGL/OpenVG for rendering.
   672 	EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   673 	if (display == EGL_NO_DISPLAY)
   674 		{
   675 		ERR_PRINTF2(_L("Failed to get EGLDisplay. [eglError=%X]"), eglGetError());
   676 		User::Leave(KErrGeneral);
   677 		}
   678 	TESTL(display != EGL_NO_DISPLAY);
   679 	if (EGL_FALSE == eglInitialize(display, NULL, NULL))
   680 		{
   681 		ERR_PRINTF2(_L("Failed to initialize EGLDisplay. [eglError=%X]"), eglGetError());
   682 		User::Leave(KErrGeneral);
   683 		}
   684 	eglBindAPI(EGL_OPENVG_API);
   685 	
   686 	EGLint imageAttribs[] =
   687 	    {
   688 	    EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, 
   689 	    EGL_NONE
   690 	    };
   691 	EGLint configAttribs[] = 
   692 		{
   693 		EGL_MATCH_NATIVE_PIXMAP, (EGLint)&target,
   694 		EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
   695 		EGL_SURFACE_TYPE, EGL_PIXMAP_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT, 
   696 		EGL_NONE
   697 		};
   698 	
   699 	const EGLint KPixmapAttribsVgAlphaFormatPre[] = 
   700 	    {
   701 	    EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE,
   702 	    EGL_NONE
   703 	    };
   704 		
   705 	EGLint configId = 0;
   706 	EGLint numConfigs = 0;
   707 	if (EGL_FALSE == eglChooseConfig(display, configAttribs, &configId, 1, &numConfigs) || numConfigs == 0)
   708 		{
   709 		ERR_PRINTF3(_L("Failed to find suitable EGLConfig. [eglError=%X, configs=%d]"), eglGetError(), numConfigs);
   710 		User::Leave(KErrGeneral);
   711 		}
   712 	EGLContext context = eglCreateContext(display, configId, EGL_NO_CONTEXT, NULL);
   713 	if (context == EGL_NO_CONTEXT)
   714 		{
   715 		ERR_PRINTF2(_L("Failed to create EGLContext. [eglError=%X]"), eglGetError());
   716 		User::Leave(KErrGeneral);
   717 		}
   718 	EGLSurface surface = eglCreatePixmapSurface(display, configId, &target, KPixmapAttribsVgAlphaFormatPre);
   719 	if (EGL_FALSE == eglMakeCurrent(display, surface, surface, context))
   720 		{
   721 		ERR_PRINTF2(_L("Failed to create make surface and context current. [eglError=%X]"), eglGetError());
   722 		eglDestroyContext(display, context);
   723 		User::Leave(KErrGeneral);
   724 		}
   725 	
   726 	// Load the necessary EGL extensions...
   727 	TvgCreateEGLImageTargetKHRTypefPtr vgCreateImageTargetKHR;
   728 	PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
   729 	PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
   730 	eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
   731 	eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
   732 	vgCreateImageTargetKHR = reinterpret_cast<TvgCreateEGLImageTargetKHRTypefPtr>(eglGetProcAddress("vgCreateEGLImageTargetKHR"));
   733 	if (!eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateImageTargetKHR)
   734 		{
   735 		ERR_PRINTF1(_L("Failed to get EGL Image extension functions."));
   736 		User::Leave(KErrNotSupported);
   737 		}
   738 	// Now we have an OpenVG window to render to!
   739 	
   740 	TInt numGlyphCodes = 0;
   741 	TUint* glyphCodes;
   742 	LoadConfigSampleDataL(font, KTestLanguage, EFalse, glyphCodes, numGlyphCodes); 
   743 
   744 	// Set up an identity matrix compatible with the Symbian co-ordinate system.
   745 	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
   746 	vgScale(1.f, -1.f);
   747 	vgTranslate(0, -KFontHeightInPixels);	
   748 	VGfloat vgIdentityMatrix[16];
   749 	vgGetMatrix(vgIdentityMatrix);
   750 	
   751 	RFbsGlyphDataIterator iter;
   752 	CleanupClosePushL(iter);
   753 		
   754 	// Render some glyphs.
   755 	TInt iterErr = KErrNone;
   756 	TInt rep = 0;
   757 	vgClear(0, 0, KEglTargetSize.iWidth, KEglTargetSize.iHeight);
   758 	TPoint glyphOrigin(0, 0);
   759 	iProfiler->InitResults();
   760 	for (rep = 0; rep < KNumIterations; rep++)
   761 		{
   762 		iterErr = iter.Open(*font, glyphCodes, numGlyphCodes);
   763 		for (;iterErr == KErrNone; iterErr = iter.Next())
   764 			{
   765 			const TOpenFontCharMetrics& metrics = iter.Metrics();
   766 			const RSgImage& glyphSgImage = iter.Image();
   767 			EGLImageKHR eglImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, 
   768 					reinterpret_cast<EGLClientBuffer>(&glyphSgImage), imageAttribs);
   769 			VGImage vgImage = vgCreateImageTargetKHR(eglImage);
   770 			
   771 			// wrapped text placement.			
   772 			TInt horizAdvance = metrics.HorizAdvance();
   773 			if (glyphOrigin.iX + horizAdvance >= KEglTargetSize.iWidth)
   774 				{
   775 				vgLoadMatrix(vgIdentityMatrix);
   776 				glyphOrigin.iX = 0;
   777 				glyphOrigin.iY -= KFontHeightInPixels;
   778 				if (glyphOrigin.iY - KFontHeightInPixels < -KEglTargetSize.iHeight)
   779 					{
   780 					glyphOrigin.iY = 0;
   781 					}
   782 				vgTranslate(glyphOrigin.iX, glyphOrigin.iY);
   783 				}
   784 			
   785 			vgDrawImage(vgImage);
   786 			vgDestroyImage(vgImage);
   787 			eglDestroyImageKHR(display, eglImage);
   788 				
   789 			// Move to next glyph position.
   790 			glyphOrigin.iX += horizAdvance;
   791 			vgTranslate(horizAdvance, 0);
   792 			}
   793 		iter.Close();
   794 		eglSwapBuffers(display, surface);
   795 		}
   796 	iProfiler->MarkResultSetL();
   797 	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, KNumIterations, numGlyphCodes);
   798 	TEST(rep == KNumIterations);
   799 	TESTE(iterErr == KErrNotFound, iterErr);	
   800 	WriteTargetOutput(KTestName());
   801 	
   802 	eglDestroySurface(display, surface);
   803 	eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   804 	eglTerminate(display);
   805 	eglReleaseThread();
   806 	
   807 	CleanupStack::PopAndDestroy(3); // iter, target, fontFactory
   808 	delete [] glyphCodes;
   809 	}
   810 #endif
   811 
   812 /**
   813 Captures the EGL Surface (it is assumed to be an OpenVG surface) to a 256-grey CFbsBitmap,
   814 used when sanity-checking bitmaps are enabled. 
   815 */
   816 CFbsBitmap* CTFbsGlyphData::GetTargetAsBitmapL()
   817 	{
   818 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
   819 	// For debugging purposes only.
   820 	// Capture the final state of the EGL Pixmap surface as an mbm.
   821 	const TInt KDataStride = KEglTargetSize.iWidth;
   822 
   823 	TUint8* imageScanline = reinterpret_cast<TUint8*>(User::AllocZL(KDataStride));
   824 	CleanupStack::PushL(imageScanline);
   825 	CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
   826 	CleanupStack::PushL(bitmap);
   827 	User::LeaveIfError(bitmap->Create(KEglTargetSize, EGray256));
   828 	bitmap->BeginDataAccess();
   829 	TUint8* dataAddress = reinterpret_cast<TUint8*>(bitmap->DataAddress());
   830 	const TInt dataStride = bitmap->DataStride();	
   831 	for (TInt scanline = 0; scanline < KEglTargetSize.iHeight; scanline++)
   832 		{
   833 	    vgReadPixels(imageScanline, KDataStride, VG_A_8, 0, scanline, KEglTargetSize.iWidth, 1);
   834 		Mem::Copy(dataAddress, imageScanline, KEglTargetSize.iWidth);
   835 		dataAddress += dataStride;
   836 		}
   837 	bitmap->EndDataAccess(EFalse);
   838 	CleanupStack::Pop(2); // bitmap, imageScanline
   839 	return bitmap;
   840 #else
   841 	return NULL;
   842 #endif
   843 	}
   844 
   845 /**
   846 Utility method. Loads sample glyph code data from the config ini file
   847 into a TUint array.
   848 @param aFont The font that the glyph codes will be associated with.
   849 @param aLanguage The language variant to load from the config file as sample data.
   850 @param aLongData Whether to use the long variant (ETrue) or short variant (EFalse) 
   851     of the sample data for the given language.
   852 @param aGlyphCodes On success, holds an array of glyph codes, to be freed by the caller.
   853 @param aNumGlyphCodes On success, holds the count of the glyph code array.
   854 @leave KErrNotFound if the test data cannot be found or is empty in the config file.
   855  */
   856 void CTFbsGlyphData::LoadConfigSampleDataL(CFbsFont* aFont, TTestLanguage aLanguage, TBool aLongData, TUint*& aGlyphCodes, TInt& aNumGlyphCodes)
   857 	{
   858 	// The name of the section in the config file to look-up the sample data
   859 	_LIT(KConfigFileSampleData, "GlyphDataSampleText");
   860 
   861 	TBuf<32> keyName = ConfigKeyNameL(aLanguage, aLongData);
   862 	
   863 	// Setup the converter to use the passed font.
   864 	iCharCodeConverter->UseFontL(aFont);
   865 
   866 	// Load the sample string data from the config file.
   867 	TPtrC sampleText;
   868 	TESTL(GetStringFromConfig(KConfigFileSampleData, keyName, sampleText));
   869 	aNumGlyphCodes = sampleText.Length();
   870 	if (aNumGlyphCodes <= 0)
   871 		{
   872 		User::Leave(KErrNotFound);
   873 		}
   874 	aGlyphCodes = new(ELeave) TUint[aNumGlyphCodes];
   875 	for (TInt code = 0; code < aNumGlyphCodes; ++code)
   876 		{
   877 		aGlyphCodes[code] = iCharCodeConverter->GlyphCodeL(sampleText[code]); 
   878 		}
   879 	}
   880 
   881 /**
   882 Creates the name of the key to look for in the config file for the test
   883 with the specified parameters.
   884 @param aLanguage The language the test will use.
   885 @param aLongData Whether to use long or short sample data.
   886 @return A descriptor value of the language.
   887 @leave KErrNotSupported if aLanguage is not recognised.
   888  */
   889 TBufC<32> CTFbsGlyphData::ConfigKeyNameL(TTestLanguage aLanguage, TBool aLongData)
   890 	{
   891 	if (aLanguage < 0 || aLanguage > 1)
   892 		{
   893 		User::Leave(KErrNotSupported);
   894 		}
   895 	TBuf<32> langName[2];
   896 	langName[ETestLanguageLatin].Append(_L("Latin"));
   897 	langName[ETestLanguageHindi].Append(_L("Hindi"));	
   898 	langName[aLanguage].Append((aLongData) ? _L("Long") : _L("Short"));
   899 	return langName[aLanguage];
   900 	}
   901 
   902 /**
   903 Font factory.
   904 Utiltiy class for providing fonts for the performance tests.
   905 */
   906 
   907 CTFontFactory::CTFontFactory()
   908 	{
   909 	}
   910 
   911 CTFontFactory::~CTFontFactory()
   912 	{
   913 	ReleaseFonts();
   914 	delete iTs;
   915 	}
   916 
   917 /**
   918 @return A new Font Factory ready to create fonts.
   919 */
   920 CTFontFactory* CTFontFactory::NewLC()
   921 	{
   922 	CTFontFactory* fontFactory = new (ELeave) CTFontFactory();
   923 	CleanupStack::PushL(fontFactory);
   924 	fontFactory->iTs = static_cast<CFbsTypefaceStore*>(CFbsTypefaceStore::NewL(NULL));
   925 	return fontFactory;
   926 	}
   927 
   928 /**
   929 Creates a number of fonts for use by tests. All the fonts are created up-front so 
   930 that NextFont() can be called as a very lightweight call, so it can be used inside
   931 tests with minimal impact.
   932 Once fonts are created, the factory must not be destroyed until the fonts it created
   933 are finished with.
   934 @param aLanaugeMask Which language needs to be supported by the returned fonts.
   935 @param aNumFonts The number of fonts to create
   936 @param aStartSizeInPixels The lower bound font height of the fonts that are created. All
   937 	fonts will be at least as big as this value.
   938 */
   939 void CTFontFactory::CreateFontsL(TTestLanguage aLanguageMask, TInt aNumFonts, TInt aStartSizeInPixels)
   940 	{
   941 	ReleaseFonts();
   942 	
   943 	RArray <TPtrC> typefaceNames;
   944 	CleanupClosePushL(typefaceNames);
   945 	switch(aLanguageMask)
   946 		{
   947 		case ETestLanguageHindi:	
   948 			User::LeaveIfError(typefaceNames.Reserve(1));
   949 			typefaceNames.Append(_L("Devanagari OT Eval"));
   950 			break;
   951 		case ETestLanguageLatin:
   952 			User::LeaveIfError(typefaceNames.Reserve(3));
   953 			typefaceNames.Append(_L("DejaVu Sans Condensed"));
   954 			typefaceNames.Append(_L("DejaVu Serif"));
   955 			typefaceNames.Append(_L("DejaVu Sans Mono"));
   956 			break;
   957 		default:
   958 			User::Leave(KErrNotSupported);
   959 		}
   960 	const TInt KNumTypefaces = typefaceNames.Count();
   961 		
   962 	iFont = new CFbsFont*[aNumFonts];
   963 	for (TInt count = 0; count < aNumFonts; ++count)
   964 		{
   965 		// After every KNumTypefaces font, increase size by 5.
   966 		TInt size = aStartSizeInPixels + (5 *(count / KNumTypefaces));
   967 		TPtrC typefaceName = typefaceNames[count % KNumTypefaces];
   968 		TFontSpec fontSpec(typefaceName, size);
   969 		User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont[count], fontSpec));
   970 		++iNumFonts;
   971 		}
   972 	iCurFont = -1;
   973 	CleanupStack::PopAndDestroy(1); // typefaceNames
   974 	}
   975 /**
   976 Releases all created fonts and frees associated memory.
   977 */
   978 void CTFontFactory::ReleaseFonts()
   979 	{
   980 	for (TInt font = 0; font < iNumFonts; ++font)
   981 		{
   982 		iTs->ReleaseFont(iFont[font]);
   983 		}
   984 	delete [] iFont;
   985 	iFont = NULL;
   986 	iNumFonts = 0;
   987 	}
   988 
   989 /**
   990 @return The next font to be used. If it reaches the last font, the next font will
   991 	cycle back around to the first font.
   992 */
   993 CFbsFont* CTFontFactory::NextFont()
   994 	{
   995 	return iFont[++iCurFont%iNumFonts];
   996 	}