os/graphics/graphicstest/uibench/src/tfbsglyphdata.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicstest/uibench/src/tfbsglyphdata.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,996 @@
     1.4 +// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +/**
    1.20 + @file
    1.21 + @test
    1.22 + @internalComponent - Internal Symbian test code 
    1.23 +*/
    1.24 +
    1.25 +#include <test/graphicsfontutils.h>
    1.26 +#include <graphics/fbsglyphdataiterator.h>
    1.27 +#include <graphics/fbsglyphmetricsarray.h>
    1.28 +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    1.29 +#include <sgresource/sgimage.h>
    1.30 +#include <egl/egl.h>
    1.31 +#include <vg/openvg.h>
    1.32 +typedef EGLBoolean (*TvgCreateEGLImageTargetKHRTypefPtr) (VGeglImageKHR image);
    1.33 +#endif
    1.34 +#include "tfbsglyphdata.h"
    1.35 +
    1.36 +// Size of EGLSurface used for rendering to, in pixels.
    1.37 +const TSize KEglTargetSize(512, 512);
    1.38 +
    1.39 +CTFbsGlyphData::CTFbsGlyphData()
    1.40 +	{
    1.41 +	SetTestStepName(KTFbsGlyphData);
    1.42 +	}
    1.43 +
    1.44 +CTFbsGlyphData::~CTFbsGlyphData()
    1.45 +	{
    1.46 +	}
    1.47 +
    1.48 +TVerdict CTFbsGlyphData::doTestStepPreambleL()
    1.49 +    {
    1.50 +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    1.51 +    User::LeaveIfError(iFbs.Connect());
    1.52 +	User::LeaveIfError(iSgDriver.Open());
    1.53 +#endif
    1.54 +	iCharCodeConverter = CCharCodeConverter::NewL();
    1.55 +    return CTe_graphicsperformanceSuiteStepBase::doTestStepPreambleL();
    1.56 +    }
    1.57 +
    1.58 +TVerdict CTFbsGlyphData::doTestStepPostambleL()
    1.59 +    {
    1.60 +    delete iCharCodeConverter;
    1.61 +    iCharCodeConverter = NULL;
    1.62 +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    1.63 +    iSgDriver.Close();
    1.64 +    iFbs.Disconnect();
    1.65 +#endif
    1.66 +    return CTe_graphicsperformanceSuiteStepBase::doTestStepPostambleL();
    1.67 +    }
    1.68 +
    1.69 +TVerdict CTFbsGlyphData::doTestStepL()
    1.70 +	{
    1.71 +#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
    1.72 +    INFO_PRINTF1(_L("CTFbsGlyphData can only be run with SgImage 'Lite'"));
    1.73 +    return TestStepResult();
    1.74 +#else
    1.75 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0178"));
    1.76 +	GlyphMetricsArrayL(ETestLanguageLatin, ETrue, 1000);
    1.77 +	RecordTestResultL();
    1.78 +
    1.79 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0179"));
    1.80 +	GlyphMetricsArrayL(ETestLanguageLatin, EFalse, 50000);
    1.81 +	RecordTestResultL();
    1.82 +	
    1.83 +    // Tests 180 and 181 require a CMap table in order to convert CharacterCodes to GlyphCodes.
    1.84 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0180"));
    1.85 +	GlyphMetricsArrayL(ETestLanguageHindi, ETrue, 25);
    1.86 +	RecordTestResultL();
    1.87 +	
    1.88 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0181"));
    1.89 +	GlyphMetricsArrayL(ETestLanguageHindi, EFalse, 50000);
    1.90 +	RecordTestResultL();
    1.91 +	
    1.92 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0182"));
    1.93 +	GlyphMetricsQuerySingleGlyphL();
    1.94 +	RecordTestResultL();
    1.95 +	
    1.96 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0183"));
    1.97 +	GlyphDataIteratorOpenL(ETestLanguageLatin, ETrue, 50);
    1.98 +	RecordTestResultL();
    1.99 +
   1.100 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0184"));
   1.101 +	GlyphDataIteratorOpenL(ETestLanguageLatin, EFalse, 500);
   1.102 +	RecordTestResultL();
   1.103 +	
   1.104 +    // Tests 185 and 186 require a CMap table in order to convert CharacterCodes to GlyphCodes.
   1.105 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0185"));
   1.106 +	GlyphDataIteratorOpenL(ETestLanguageHindi, ETrue, 10);
   1.107 +	RecordTestResultL();
   1.108 +	
   1.109 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0186"));
   1.110 +	GlyphDataIteratorOpenL(ETestLanguageHindi, EFalse, 5000);
   1.111 +	RecordTestResultL();
   1.112 +	
   1.113 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0187"));
   1.114 +	GlyphDataIteratorOpenSingleFontL();
   1.115 +	RecordTestResultL();
   1.116 +	
   1.117 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0188"));
   1.118 +	GlyphMetricsQueryUnrasterizedL();
   1.119 +	RecordTestResultL();
   1.120 +	
   1.121 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0189"));
   1.122 +	GlyphMetricsQueryPreRasterizedL();
   1.123 +	RecordTestResultL();
   1.124 +	
   1.125 +	SetTestStepID(_L("GRAPHICS-UI-BENCH-0190"));
   1.126 +	GlyphRenderingL();
   1.127 +	RecordTestResultL();
   1.128 +
   1.129 +	return TestStepResult();
   1.130 +#endif
   1.131 +    }
   1.132 +
   1.133 +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
   1.134 +/**
   1.135 +@SYMTestCaseID GRAPHICS-UI-BENCH-0178...0181
   1.136 +
   1.137 +@SYMTestType UT
   1.138 +
   1.139 +@SYMPREQ PREQ2678
   1.140 +
   1.141 +@SYMTestCaseDesc 
   1.142 +Measures the performance of calling RFbsGlyphMetricsArray::Get() with different sample data.
   1.143 +The sample data can be a single word, or a very long array of glyphs, in latin or non-latin
   1.144 +alphabets. At each repetition a different font is used, cycled over nine fonts, to reduce the
   1.145 +effect of having cached glyphs.
   1.146 +
   1.147 +@SYMTestActions
   1.148 +i. Create some sample fonts to cycle through. 
   1.149 +ii. Load sample data from config file, specified by aSampleDataKey.
   1.150 +iii. Create RFbsGlyphMetricsArray, open on sample data.
   1.151 +iv. For each repetition, call RFbsGlyphMetricsArray::Get(), adjusting font at each repetition.
   1.152 +v. Measure time from from first to last repetition.
   1.153 +
   1.154 +@param aLanguage The language this test will use.
   1.155 +@param aLongData If ETrue, tells the test to use the long sample data string for the test, EFalse
   1.156 +	will make the test use the short string data.
   1.157 +@param aReps The number of times to repeat the test.
   1.158 +*/
   1.159 +void CTFbsGlyphData::GlyphMetricsArrayL(TTestLanguage aLanguage, TBool aLongData, TInt aReps)
   1.160 +	{
   1.161 +	TBuf<128> KTestName;
   1.162 +	TPtrC KTestVariant = ConfigKeyNameL(aLanguage, aLongData);
   1.163 +	KTestName.Format(_L("GlyphMetricsArray %S"), &KTestVariant);
   1.164 +	
   1.165 +	// Create some test fonts using the font factory.
   1.166 +	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   1.167 +	fontFactory->CreateFontsL(aLanguage, 9);
   1.168 +
   1.169 +	// Load the sample string data from the config file.
   1.170 +	TInt numGlyphCodes = 0;
   1.171 +	TUint* glyphCodes;
   1.172 +	LoadConfigSampleDataL(fontFactory->NextFont(), aLanguage, aLongData, glyphCodes, numGlyphCodes);
   1.173 +
   1.174 +	// Run the test.
   1.175 +	TInt err = KErrNone;
   1.176 +	RFbsGlyphMetricsArray array;
   1.177 +	CleanupClosePushL(array);
   1.178 +	iProfiler->InitResults();
   1.179 +	for (TInt rep = aReps; (rep != 0) && (err == KErrNone); --rep)
   1.180 +		{
   1.181 +		err = array.Get(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
   1.182 +		}
   1.183 +	iProfiler->MarkResultSetL();
   1.184 +	TESTE(err == KErrNone, err);
   1.185 +	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, aReps, numGlyphCodes);
   1.186 +	
   1.187 +	CleanupStack::PopAndDestroy(2); // array, fontFactory
   1.188 +	delete [] glyphCodes;
   1.189 +	}
   1.190 +
   1.191 +/**
   1.192 +@SYMTestCaseID GRAPHICS-UI-BENCH-0182
   1.193 +
   1.194 +@SYMTestType UT
   1.195 +
   1.196 +@SYMPREQ PREQ2678
   1.197 +
   1.198 +@SYMTestCaseDesc 
   1.199 +Measures the performance of calling RFbsGlyphDataIterator::Get() with a single glyph,
   1.200 +versus CFont::GetCharacterData(). Using a single glyph code is a very common use case.
   1.201 +The glyph and the font is changed at each iteration.
   1.202 +
   1.203 +@SYMTestActions
   1.204 +i. Create some sample fonts to cycle through. 
   1.205 +ii. Create RFbsGlyphMetricsArray.
   1.206 +iii. For each repetition, call RFbsGlyphMetricsArray::Get(), adjusting the glyph at 
   1.207 +	each iteration.
   1.208 +iv. Measure time from from first to last iteration.
   1.209 +v. Repeat steps iii. and iv. with CFont::GetCharacterData().
   1.210 +*/
   1.211 +void CTFbsGlyphData::GlyphMetricsQuerySingleGlyphL()
   1.212 +	{
   1.213 +	_LIT(KTestName, "GlyphMetricsQuerySingleGlyph");
   1.214 +	const TInt KNumIterations = 50000;
   1.215 +	TInt err = KErrNone;
   1.216 +	TBuf<128> KTestNameVariant;
   1.217 +
   1.218 +	// Create some test fonts using the font factory.
   1.219 +	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   1.220 +	
   1.221 +	// Run the test for RFbsGlyphMetricsArray, with a different character 
   1.222 +	// and font for each iteration.
   1.223 +	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
   1.224 +	fontFactory->CreateFontsL(ETestLanguageLatin, 9);
   1.225 +	RFbsGlyphMetricsArray array;
   1.226 +	CleanupClosePushL(array);
   1.227 +	iProfiler->InitResults();
   1.228 +	for (TInt rep = KNumIterations; rep != 0 && (err == KErrNone); --rep)
   1.229 +		{
   1.230 +		const TUint KGlyphCode = 32 + (rep % 96);
   1.231 +		err = array.Get(*(fontFactory->NextFont()), &KGlyphCode, 1);
   1.232 +		}
   1.233 +	iProfiler->MarkResultSetL();
   1.234 +	TESTE(err == KErrNone, err);
   1.235 +	CleanupStack::PopAndDestroy(1); // array
   1.236 +	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, 1);
   1.237 +	fontFactory->ReleaseFonts();
   1.238 +	
   1.239 +	// Run the test for GetCharacterData(), with a different character
   1.240 +	// and font for each iteration.
   1.241 +	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
   1.242 +	fontFactory->CreateFontsL(ETestLanguageLatin, 9);
   1.243 +	TOpenFontCharMetrics metrics;
   1.244 +	const TUint8* bitmapData = NULL;
   1.245 +	TSize bitmapSize;
   1.246 +	iProfiler->InitResults();
   1.247 +	for (TInt rep = KNumIterations; rep != 0; --rep)
   1.248 +		{
   1.249 +		const TUint KGlyphCode = 32 + (rep % 96);
   1.250 +		fontFactory->NextFont()->GetCharacterData(KGlyphCode, metrics, bitmapData, bitmapSize);
   1.251 +		}
   1.252 +	iProfiler->MarkResultSetL();
   1.253 +	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, 1);
   1.254 +	
   1.255 +	CleanupStack::PopAndDestroy(1); // fontFactory
   1.256 +	}
   1.257 +
   1.258 +/**
   1.259 +@SYMTestCaseID GRAPHICS-UI-BENCH-0183...0186
   1.260 +
   1.261 +@SYMTestType UT
   1.262 +
   1.263 +@SYMPREQ PREQ2678
   1.264 +
   1.265 +@SYMTestCaseDesc 
   1.266 +Measures the performance of calling RFbsGlyphDataIterator::Open() with different 
   1.267 +sample data, and iterating through the data with RFbsGlyphDataIterator::Next(). 
   1.268 +The sample data can be a single word, or a very long array of glyphs,
   1.269 +in various languages. At each repetition a different font is used, cycled
   1.270 +over nine fonts.
   1.271 +
   1.272 +@SYMTestActions
   1.273 +i. Create some sample fonts to cycle through. 
   1.274 +ii. Create RFbsGlyphDataIterator.
   1.275 +iii. For each repetition, call RFbsGlyphDataIterator::Open(), adjusting the glyph at each 
   1.276 +	iteration. The font is changed at each repetition.
   1.277 +iv. Measure time from from first to last repetition.
   1.278 +
   1.279 +@param aLanguage The language this test will use.
   1.280 +@param aLongData If ETrue, tells the test to use the long sample data string for the test, EFalse
   1.281 +	will make the test use the short string data.
   1.282 +@param aReps The number of times to repeat the test.
   1.283 + */
   1.284 +void CTFbsGlyphData::GlyphDataIteratorOpenL(TTestLanguage aLanguage, TBool aLongData, TInt aReps)
   1.285 +	{
   1.286 +	TBuf<128> KTestName;
   1.287 +	TPtrC KTestVariant = ConfigKeyNameL(aLanguage, aLongData);
   1.288 +	KTestName.Format(_L("GlyphDataIteratorOpen %S"), &KTestVariant);
   1.289 +	
   1.290 +	// Create some test fonts using the font factory.
   1.291 +	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   1.292 +	fontFactory->CreateFontsL(aLanguage, 9);
   1.293 +	
   1.294 +	// Load the sample string data from the config file.
   1.295 +	TInt numGlyphCodes = 0;
   1.296 +	TUint* glyphCodes;
   1.297 +	LoadConfigSampleDataL(fontFactory->NextFont(), aLanguage, aLongData, glyphCodes, numGlyphCodes);
   1.298 +
   1.299 +	// Run the test.
   1.300 +	TInt err = KErrNotFound;
   1.301 +	RFbsGlyphDataIterator iter;
   1.302 +	CleanupClosePushL(iter);
   1.303 +	iProfiler->InitResults();
   1.304 +	for (TInt rep = aReps; (rep != 0) && (err == KErrNotFound); --rep)
   1.305 +		{
   1.306 +		err = iter.Open(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
   1.307 +		for (; err == KErrNone; err = iter.Next())
   1.308 +			{
   1.309 +			// no operation
   1.310 +			}
   1.311 +		iter.Close();
   1.312 +		}
   1.313 +	iProfiler->MarkResultSetL();
   1.314 +	TESTE(err == KErrNotFound, err);
   1.315 +
   1.316 +	CleanupStack::PopAndDestroy(2); // iter, fontFactory
   1.317 +	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, aReps, numGlyphCodes);
   1.318 +	delete [] glyphCodes;
   1.319 +	}
   1.320 +
   1.321 +/**
   1.322 +@SYMTestCaseID GRAPHICS-UI-BENCH-0187
   1.323 +
   1.324 +@SYMTestType UT
   1.325 +
   1.326 +@SYMPREQ PREQ2678
   1.327 +
   1.328 +@SYMTestCaseDesc 
   1.329 +Measures the performance of calling RFbsGlyphDataIterator::Open() with different 
   1.330 +lengthed arrays but the same font. The sample data is a long array of characters.
   1.331 +
   1.332 +@SYMTestActions
   1.333 +i. Create a single test font 
   1.334 +ii. Create RFbsGlyphDataIterator.
   1.335 +iii. Pass an array to RFbsGlyphDataIterator::Open(), starting with a single glyph.
   1.336 +	For each iteration, increase the length of the array by one until the entire
   1.337 +	string has been opened.
   1.338 +iv. Measure the time to perform all the iterations.
   1.339 +
   1.340 +@param aSampleDataKey The string key to lookup under the GlyphArraySampleText section of the 
   1.341 +	config file where the sample data is read.
   1.342 +@param aReps The number of times to repeat the test.
   1.343 + */
   1.344 +void CTFbsGlyphData::GlyphDataIteratorOpenSingleFontL()
   1.345 +	{
   1.346 +	_LIT(KTestName, "GlyphDataIteratorOpenSingleFont");
   1.347 +	// A cap on the max number of iterations to complete.
   1.348 +	const TInt KMaxNumIterations = 200;
   1.349 +    const TTestLanguage KTestLanguage = ETestLanguageHindi;
   1.350 +	
   1.351 +	// Create some test fonts using the font factory.
   1.352 +	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   1.353 +	fontFactory->CreateFontsL(KTestLanguage, 1);
   1.354 +	CFbsFont* font = fontFactory->NextFont();
   1.355 +	
   1.356 +	// Load the sample string data from the config file.
   1.357 +	TInt numGlyphCodes = 0;
   1.358 +	TUint* glyphCodes;
   1.359 +	LoadConfigSampleDataL(font, KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
   1.360 +	
   1.361 +	const TInt KNumRepetitions = Min<TInt>(numGlyphCodes - 1, KMaxNumIterations);
   1.362 +	RFbsGlyphDataIterator iter;
   1.363 +	CleanupClosePushL(iter);
   1.364 +	TInt iterErr = KErrNone;
   1.365 +	TInt glyphCount = 0;
   1.366 +	iProfiler->InitResults();
   1.367 +	for (glyphCount = 1; (glyphCount < KNumRepetitions); ++glyphCount)
   1.368 +		{
   1.369 +		iterErr = iter.Open(*font, glyphCodes, glyphCount);
   1.370 +		for (; iterErr == KErrNone; iterErr = iter.Next())
   1.371 +			{
   1.372 +			// no operation
   1.373 +			}
   1.374 +		iter.Close();
   1.375 +		}
   1.376 +	iProfiler->MarkResultSetL();
   1.377 +	TEST(glyphCount == KNumRepetitions);
   1.378 +	TESTE(iterErr == KErrNotFound, iterErr);
   1.379 +	
   1.380 +	const TInt KAvgNumCharsPerIteration = KNumRepetitions/2;
   1.381 +	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, KNumRepetitions, KAvgNumCharsPerIteration);
   1.382 +	
   1.383 +	CleanupStack::PopAndDestroy(2); // iter, fontFactory
   1.384 +	delete [] glyphCodes;
   1.385 +	}
   1.386 +/**
   1.387 +@SYMTestCaseID GRAPHICS-UI-BENCH-0188
   1.388 +
   1.389 +@SYMTestType UT
   1.390 +
   1.391 +@SYMPREQ PREQ2678
   1.392 +
   1.393 +@SYMTestCaseDesc 
   1.394 +Measures the performance of querying the TOpenFontCharMetrics using the different
   1.395 +available APIs. RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData()
   1.396 +are compared against each other, using the same fonts, and same sample data.
   1.397 +This test uses glyphs that have not been rasterized before, therefore for certain
   1.398 +APIs this will mean rasterizing the glyphs.
   1.399 +
   1.400 +@SYMTestActions
   1.401 +i. Load sample text data from config file.
   1.402 +ii. For each of RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData():
   1.403 +	1. Create 50 new fonts.
   1.404 +	2. Run the test, calling the necessary API once per font/loop.
   1.405 +	3. For GetCharacterData() and RFbsGlyphDataIterator(), cycle through each glyph
   1.406 +		to ensure all metrics have been retrieved. This is not necessary for 
   1.407 +		RFbsGlyphMetricsArray.
   1.408 +	4. Measure time between first and last font/loop.
   1.409 +	5. Destroy test fonts so that next test has to re-rasterize the glyphs.	
   1.410 +
   1.411 +@SYMTestExpectedResults
   1.412 +Since this test uses non-rasterized fonts, RFbsGlyphMetricsArray should be faster than
   1.413 +GetCharacterData() and RFbsGlyphDataIterator, which both rasterize the glyphs in order to 
   1.414 +get their metrics information.
   1.415 + */
   1.416 +void CTFbsGlyphData::GlyphMetricsQueryUnrasterizedL()
   1.417 +	{
   1.418 +	_LIT(KTestName, "GlyphMetricsQueryUnrasterized");
   1.419 +	
   1.420 +	TBuf<128> KTestNameVariant;
   1.421 +	// First do the test for the iterator. To ensure fair comparison with
   1.422 +    // RFbsGlyphMetricsArray, cycle through each iteration to ensure the metrics
   1.423 +    // for each glyph is found.
   1.424 +    KTestNameVariant.Format(_L("%S RFbsGlyphDataIterator"), &KTestName);
   1.425 +    
   1.426 +	const TInt KNumFonts = 50;
   1.427 +	const TTestLanguage KTestLanguage = ETestLanguageLatin;
   1.428 +	
   1.429 +	// Create some test fonts using the font factory.
   1.430 +	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   1.431 +    fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
   1.432 +	    
   1.433 +	// Load the sample string data from the config file. Both the iterator and the
   1.434 +	// array will use this same sample data.
   1.435 +	TInt numGlyphCodes = 0;
   1.436 +	TUint* glyphCodes;
   1.437 +	LoadConfigSampleDataL(fontFactory->NextFont(), KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
   1.438 +	
   1.439 +	RFbsGlyphDataIterator iter;
   1.440 +	CleanupClosePushL(iter);
   1.441 +	TInt iterErr = KErrNone;
   1.442 +	TInt rep = 0;
   1.443 +	iProfiler->InitResults();
   1.444 +	for (rep = KNumFonts; (rep != 0); --rep)
   1.445 +		{
   1.446 +		iterErr = iter.Open(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
   1.447 +		for (; iterErr == KErrNone; iterErr = iter.Next())
   1.448 +			{
   1.449 +			// no operation
   1.450 +			}
   1.451 +		iter.Close();
   1.452 +		}
   1.453 +	iProfiler->MarkResultSetL();
   1.454 +	TEST(rep == 0);
   1.455 +	TESTE(iterErr == KErrNotFound, iterErr);
   1.456 +	CleanupStack::PopAndDestroy(1); // iter		
   1.457 +	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
   1.458 +	
   1.459 +	// Second, do the test for the array. This should be faster.
   1.460 +	// Destroy the fonts and re-create them so that they have to be re-rasterized
   1.461 +	// for a fair comparison.
   1.462 +	TInt arrayErr = KErrNone;
   1.463 +	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
   1.464 +	fontFactory->ReleaseFonts();
   1.465 +	fontFactory->CreateFontsL(KTestLanguage, KNumFonts);
   1.466 +	RFbsGlyphMetricsArray array;
   1.467 +	CleanupClosePushL(array);
   1.468 +	iProfiler->InitResults();	
   1.469 +	for (TInt rep = KNumFonts; (rep != 0) && (arrayErr == KErrNone); --rep)
   1.470 +		{
   1.471 +		arrayErr = array.Get(*(fontFactory->NextFont()), glyphCodes, numGlyphCodes);
   1.472 +		}
   1.473 +	iProfiler->MarkResultSetL();
   1.474 +	CleanupStack::PopAndDestroy(1); // array
   1.475 +	TEST(rep == 0);
   1.476 +	TESTE(arrayErr == KErrNone, arrayErr);
   1.477 +	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
   1.478 +	
   1.479 +	// Third, do the test using GetCharacterData() to get the metrics.
   1.480 +	// Destroy the fonts and re-create them so that they have to be re-rasterized
   1.481 +	// for a fair comparison.
   1.482 +	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
   1.483 +	fontFactory->ReleaseFonts();
   1.484 +	fontFactory->CreateFontsL(KTestLanguage, KNumFonts);	
   1.485 +	iProfiler->InitResults();
   1.486 +	const TUint8* bitmapData = NULL;
   1.487 +	TSize bitmapSize;
   1.488 +	TOpenFontCharMetrics metrics;	
   1.489 +	for (TInt rep = KNumFonts; (rep != 0); --rep)
   1.490 +		{
   1.491 +		CFbsFont* font = fontFactory->NextFont(); 
   1.492 +		for (TInt glyphIndex = 0; glyphIndex < numGlyphCodes; glyphIndex++)
   1.493 +			{
   1.494 +			font->GetCharacterData(glyphCodes[glyphIndex], metrics, bitmapData, bitmapSize);
   1.495 +			}
   1.496 +		}
   1.497 +	iProfiler->MarkResultSetL();
   1.498 +	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumFonts, numGlyphCodes);
   1.499 +	
   1.500 +	CleanupStack::PopAndDestroy(1); // fontFactory
   1.501 +	delete [] glyphCodes;
   1.502 +	}
   1.503 +
   1.504 +/**
   1.505 +@SYMTestCaseID GRAPHICS-UI-BENCH-0189
   1.506 +
   1.507 +@SYMTestType UT
   1.508 +
   1.509 +@SYMPREQ PREQ2678
   1.510 +
   1.511 +@SYMTestCaseDesc 
   1.512 +Measures the performance of querying the TOpenFontCharMetrics using the different
   1.513 +available APIs. RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData()
   1.514 +are compared against each other, using the same fonts, and same sample data.
   1.515 +This test uses glyphs that have already been rasterized, thereby possibly reducing the 
   1.516 +extra overhead this has.
   1.517 +
   1.518 +@SYMTestActions
   1.519 +i. Load sample text data from config file.
   1.520 +ii. Create test font.
   1.521 +iii. Pre-rasterize glyphs using RFbsGlyphDataIterator. This will rasterize the glyphs 
   1.522 +	and cause them to be cached for use by all the APIs tested here.
   1.523 +iv. For each of RFbsGlyphMetricsArray, RFbsGlyphDataIterator, and CFont::GetCharacterData():
   1.524 +	1. Begin the loop, calling the necessary API once per font/loop.
   1.525 +	2. For each glyph, request the glyph metrics.
   1.526 +	3. Measure time between first and last font/loop.
   1.527 +v. Destroy test font.
   1.528 +
   1.529 +@SYMTestExpectedResults
   1.530 +All results should be improved over GlyphMetricsQueryUnrasterized (GRAPHICS-UI-BENCH-0187).
   1.531 +since no rasterizing should take place during these tests.
   1.532 + */
   1.533 +void CTFbsGlyphData::GlyphMetricsQueryPreRasterizedL()
   1.534 +	{
   1.535 +	_LIT(KTestName, "GlyphMetricsQueryPreRasterized");
   1.536 +	TBuf<128> KTestNameVariant;
   1.537 +	const TInt KNumIterations = 500;
   1.538 +	const TTestLanguage KTestLanguage = ETestLanguageLatin;
   1.539 +
   1.540 +	// Create a test font using the font factory.
   1.541 +    CTFontFactory* fontFactory = CTFontFactory::NewLC();
   1.542 +    fontFactory->CreateFontsL(ETestLanguageLatin, 1);   
   1.543 +    CFbsFont* font = fontFactory->NextFont();
   1.544 +	    
   1.545 +    TInt numGlyphCodes = 0;
   1.546 +	TUint* glyphCodes;
   1.547 +	LoadConfigSampleDataL(font, KTestLanguage, ETrue, glyphCodes, numGlyphCodes); 
   1.548 +	
   1.549 +	TInt iterErr = KErrNone;
   1.550 +	TInt rep = 0;
   1.551 +	// Rasterize the glyphs first.
   1.552 +	RFbsGlyphDataIterator iter;
   1.553 +	CleanupClosePushL(iter);
   1.554 +	for (rep = KNumIterations; (rep != 0) ; --rep)
   1.555 +		{
   1.556 +		iterErr = iter.Open(*font, glyphCodes, numGlyphCodes);
   1.557 +		for (; iterErr == KErrNone; iterErr = iter.Next())
   1.558 +			{
   1.559 +			// no operation
   1.560 +			}
   1.561 +		iter.Close();
   1.562 +		}
   1.563 +	TEST(rep == 0);
   1.564 +	TESTE(iterErr == KErrNotFound, iterErr);
   1.565 +	
   1.566 +	TOpenFontCharMetrics metrics;
   1.567 +		
   1.568 +	// First do the test for the iterator. To ensure fair comparison with
   1.569 +	// RFbsGlyphMetricsArray, cycle through each iteration to ensure the metrics
   1.570 +	// for each glyph is found.
   1.571 +	iterErr = KErrNone;
   1.572 +	KTestNameVariant.Format(_L("%S RFbsGlyphDataIterator"), &KTestName);
   1.573 +	iProfiler->InitResults();
   1.574 +	for (TInt rep = KNumIterations; (rep != 0); --rep)
   1.575 +		{
   1.576 +		for (iterErr = iter.Open(*font, glyphCodes, numGlyphCodes); iterErr == KErrNone; iterErr = iter.Next())
   1.577 +			{
   1.578 +			metrics = iter.Metrics();
   1.579 +			}
   1.580 +		iter.Close();
   1.581 +		}
   1.582 +	iProfiler->MarkResultSetL();
   1.583 +	TESTE(iterErr == KErrNotFound, iterErr);
   1.584 +	CleanupStack::PopAndDestroy(1); // iter
   1.585 +	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
   1.586 +	
   1.587 +	
   1.588 +	// Second, do the test for the array. This should be faster.
   1.589 +	TInt arrayErr = KErrNone;
   1.590 +	KTestNameVariant.Format(_L("%S RFbsGlyphMetricsArray"), &KTestName);
   1.591 +	RFbsGlyphMetricsArray array;
   1.592 +	CleanupClosePushL(array);
   1.593 +	iProfiler->InitResults();
   1.594 +	for (TInt rep = KNumIterations; (rep != 0) && (arrayErr == KErrNone); --rep)
   1.595 +		{
   1.596 +		arrayErr = array.Get(*font, glyphCodes, numGlyphCodes);
   1.597 +		for (TInt i = 0; i < numGlyphCodes; ++i)
   1.598 +			{
   1.599 +			metrics = array[i];
   1.600 +			}
   1.601 +		}
   1.602 +	iProfiler->MarkResultSetL();
   1.603 +	TESTE(arrayErr == KErrNone, arrayErr);
   1.604 +	CleanupStack::PopAndDestroy(1); // array
   1.605 +	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
   1.606 +	
   1.607 +	
   1.608 +	// Third, do the test using GetCharacterData() to get the metrics.
   1.609 +	KTestNameVariant.Format(_L("%S GetCharacterData"), &KTestName);
   1.610 +	const TUint8* bitmapData;
   1.611 +	TSize bitmapSize;
   1.612 +
   1.613 +	iProfiler->InitResults();
   1.614 +	for (TInt rep = KNumIterations; (rep != 0); --rep)
   1.615 +		{
   1.616 +		for (TInt glyphIndex = 0; glyphIndex < numGlyphCodes; glyphIndex++)
   1.617 +			{
   1.618 +			font->GetCharacterData(glyphCodes[glyphIndex], metrics, bitmapData, bitmapSize);
   1.619 +			}
   1.620 +		}
   1.621 +	iProfiler->MarkResultSetL();
   1.622 +	iProfiler->ResultsAnalysisGlyphRate(KTestNameVariant, 0, 0, 0, KNumIterations, numGlyphCodes);
   1.623 +	
   1.624 +	CleanupStack::PopAndDestroy(1); // fontFactory
   1.625 +	delete [] glyphCodes;
   1.626 +	}
   1.627 +
   1.628 +/**
   1.629 +@SYMTestCaseID GRAPHICS-UI-BENCH-0190
   1.630 +
   1.631 +@SYMTestType UT
   1.632 +
   1.633 +@SYMPREQ PREQ2678
   1.634 +
   1.635 +@SYMTestCaseDesc 
   1.636 +Measures the end-to-end performance of using Khronos APIs to render glyphs using the
   1.637 +RFbsGlyphDataIterator API. Positioning is very basic and is not reflective of a production-
   1.638 +quality text-rendering algorithm, but serves as a useful benchmark of the overall
   1.639 +text-rendering performance using this API.
   1.640 +
   1.641 +@SYMTestActions
   1.642 +i. Create a sample font to use. 
   1.643 +ii. Create a RSgImage to be used as a target for Khronos API rendering.
   1.644 +iii. Set-up EGL and OpenVG.
   1.645 +iv. Construct RFbsGlyphDataIterator, and open on sample data. At each iteration:
   1.646 +	1. Create an EGLImage from the RSgImage.
   1.647 +	2. Create a VGImage from the EGLImage.
   1.648 +	3. Render the VGImage using vgDrawImage().
   1.649 +	4. Destroy VGImage.
   1.650 +	5. Destroy EGLImage.
   1.651 +	6. Advance the current rendering position for the next glyph, ensuring that every glyph
   1.652 +	will be within the bounds of the target surface.
   1.653 +v. Measure time from from first to last iteration.
   1.654 +*/
   1.655 +void CTFbsGlyphData::GlyphRenderingL()
   1.656 +	{
   1.657 +	_LIT(KTestName, "GlyphRendering");
   1.658 +	const TInt KNumIterations = 500;
   1.659 +    const TTestLanguage KTestLanguage = ETestLanguageHindi;
   1.660 +	
   1.661 +	// Create some test fonts using the font factory.
   1.662 +	CTFontFactory* fontFactory = CTFontFactory::NewLC();
   1.663 +	fontFactory->CreateFontsL(KTestLanguage, 1, 20);
   1.664 +	CFbsFont* font = fontFactory->NextFont();
   1.665 +	const TInt KFontHeightInPixels = font->HeightInPixels();
   1.666 +
   1.667 +	// Create RSgImage to be used as OpenVG Pixmap Surface
   1.668 +
   1.669 +	RSgImage target;
   1.670 +	TInt err = target.Create(TSgImageInfo(KEglTargetSize, ESgPixelFormatARGB_8888_PRE, ESgUsageBitOpenVgSurface));
   1.671 +	TESTL(err == KErrNone);
   1.672 +	CleanupClosePushL(target);
   1.673 +	
   1.674 +	// Initialize EGL/OpenVG for rendering.
   1.675 +	EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   1.676 +	if (display == EGL_NO_DISPLAY)
   1.677 +		{
   1.678 +		ERR_PRINTF2(_L("Failed to get EGLDisplay. [eglError=%X]"), eglGetError());
   1.679 +		User::Leave(KErrGeneral);
   1.680 +		}
   1.681 +	TESTL(display != EGL_NO_DISPLAY);
   1.682 +	if (EGL_FALSE == eglInitialize(display, NULL, NULL))
   1.683 +		{
   1.684 +		ERR_PRINTF2(_L("Failed to initialize EGLDisplay. [eglError=%X]"), eglGetError());
   1.685 +		User::Leave(KErrGeneral);
   1.686 +		}
   1.687 +	eglBindAPI(EGL_OPENVG_API);
   1.688 +	
   1.689 +	EGLint imageAttribs[] =
   1.690 +	    {
   1.691 +	    EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, 
   1.692 +	    EGL_NONE
   1.693 +	    };
   1.694 +	EGLint configAttribs[] = 
   1.695 +		{
   1.696 +		EGL_MATCH_NATIVE_PIXMAP, (EGLint)&target,
   1.697 +		EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
   1.698 +		EGL_SURFACE_TYPE, EGL_PIXMAP_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT, 
   1.699 +		EGL_NONE
   1.700 +		};
   1.701 +	
   1.702 +	const EGLint KPixmapAttribsVgAlphaFormatPre[] = 
   1.703 +	    {
   1.704 +	    EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE,
   1.705 +	    EGL_NONE
   1.706 +	    };
   1.707 +		
   1.708 +	EGLint configId = 0;
   1.709 +	EGLint numConfigs = 0;
   1.710 +	if (EGL_FALSE == eglChooseConfig(display, configAttribs, &configId, 1, &numConfigs) || numConfigs == 0)
   1.711 +		{
   1.712 +		ERR_PRINTF3(_L("Failed to find suitable EGLConfig. [eglError=%X, configs=%d]"), eglGetError(), numConfigs);
   1.713 +		User::Leave(KErrGeneral);
   1.714 +		}
   1.715 +	EGLContext context = eglCreateContext(display, configId, EGL_NO_CONTEXT, NULL);
   1.716 +	if (context == EGL_NO_CONTEXT)
   1.717 +		{
   1.718 +		ERR_PRINTF2(_L("Failed to create EGLContext. [eglError=%X]"), eglGetError());
   1.719 +		User::Leave(KErrGeneral);
   1.720 +		}
   1.721 +	EGLSurface surface = eglCreatePixmapSurface(display, configId, &target, KPixmapAttribsVgAlphaFormatPre);
   1.722 +	if (EGL_FALSE == eglMakeCurrent(display, surface, surface, context))
   1.723 +		{
   1.724 +		ERR_PRINTF2(_L("Failed to create make surface and context current. [eglError=%X]"), eglGetError());
   1.725 +		eglDestroyContext(display, context);
   1.726 +		User::Leave(KErrGeneral);
   1.727 +		}
   1.728 +	
   1.729 +	// Load the necessary EGL extensions...
   1.730 +	TvgCreateEGLImageTargetKHRTypefPtr vgCreateImageTargetKHR;
   1.731 +	PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
   1.732 +	PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
   1.733 +	eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
   1.734 +	eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
   1.735 +	vgCreateImageTargetKHR = reinterpret_cast<TvgCreateEGLImageTargetKHRTypefPtr>(eglGetProcAddress("vgCreateEGLImageTargetKHR"));
   1.736 +	if (!eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateImageTargetKHR)
   1.737 +		{
   1.738 +		ERR_PRINTF1(_L("Failed to get EGL Image extension functions."));
   1.739 +		User::Leave(KErrNotSupported);
   1.740 +		}
   1.741 +	// Now we have an OpenVG window to render to!
   1.742 +	
   1.743 +	TInt numGlyphCodes = 0;
   1.744 +	TUint* glyphCodes;
   1.745 +	LoadConfigSampleDataL(font, KTestLanguage, EFalse, glyphCodes, numGlyphCodes); 
   1.746 +
   1.747 +	// Set up an identity matrix compatible with the Symbian co-ordinate system.
   1.748 +	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
   1.749 +	vgScale(1.f, -1.f);
   1.750 +	vgTranslate(0, -KFontHeightInPixels);	
   1.751 +	VGfloat vgIdentityMatrix[16];
   1.752 +	vgGetMatrix(vgIdentityMatrix);
   1.753 +	
   1.754 +	RFbsGlyphDataIterator iter;
   1.755 +	CleanupClosePushL(iter);
   1.756 +		
   1.757 +	// Render some glyphs.
   1.758 +	TInt iterErr = KErrNone;
   1.759 +	TInt rep = 0;
   1.760 +	vgClear(0, 0, KEglTargetSize.iWidth, KEglTargetSize.iHeight);
   1.761 +	TPoint glyphOrigin(0, 0);
   1.762 +	iProfiler->InitResults();
   1.763 +	for (rep = 0; rep < KNumIterations; rep++)
   1.764 +		{
   1.765 +		iterErr = iter.Open(*font, glyphCodes, numGlyphCodes);
   1.766 +		for (;iterErr == KErrNone; iterErr = iter.Next())
   1.767 +			{
   1.768 +			const TOpenFontCharMetrics& metrics = iter.Metrics();
   1.769 +			const RSgImage& glyphSgImage = iter.Image();
   1.770 +			EGLImageKHR eglImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, 
   1.771 +					reinterpret_cast<EGLClientBuffer>(&glyphSgImage), imageAttribs);
   1.772 +			VGImage vgImage = vgCreateImageTargetKHR(eglImage);
   1.773 +			
   1.774 +			// wrapped text placement.			
   1.775 +			TInt horizAdvance = metrics.HorizAdvance();
   1.776 +			if (glyphOrigin.iX + horizAdvance >= KEglTargetSize.iWidth)
   1.777 +				{
   1.778 +				vgLoadMatrix(vgIdentityMatrix);
   1.779 +				glyphOrigin.iX = 0;
   1.780 +				glyphOrigin.iY -= KFontHeightInPixels;
   1.781 +				if (glyphOrigin.iY - KFontHeightInPixels < -KEglTargetSize.iHeight)
   1.782 +					{
   1.783 +					glyphOrigin.iY = 0;
   1.784 +					}
   1.785 +				vgTranslate(glyphOrigin.iX, glyphOrigin.iY);
   1.786 +				}
   1.787 +			
   1.788 +			vgDrawImage(vgImage);
   1.789 +			vgDestroyImage(vgImage);
   1.790 +			eglDestroyImageKHR(display, eglImage);
   1.791 +				
   1.792 +			// Move to next glyph position.
   1.793 +			glyphOrigin.iX += horizAdvance;
   1.794 +			vgTranslate(horizAdvance, 0);
   1.795 +			}
   1.796 +		iter.Close();
   1.797 +		eglSwapBuffers(display, surface);
   1.798 +		}
   1.799 +	iProfiler->MarkResultSetL();
   1.800 +	iProfiler->ResultsAnalysisGlyphRate(KTestName, 0, 0, 0, KNumIterations, numGlyphCodes);
   1.801 +	TEST(rep == KNumIterations);
   1.802 +	TESTE(iterErr == KErrNotFound, iterErr);	
   1.803 +	WriteTargetOutput(KTestName());
   1.804 +	
   1.805 +	eglDestroySurface(display, surface);
   1.806 +	eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   1.807 +	eglTerminate(display);
   1.808 +	eglReleaseThread();
   1.809 +	
   1.810 +	CleanupStack::PopAndDestroy(3); // iter, target, fontFactory
   1.811 +	delete [] glyphCodes;
   1.812 +	}
   1.813 +#endif
   1.814 +
   1.815 +/**
   1.816 +Captures the EGL Surface (it is assumed to be an OpenVG surface) to a 256-grey CFbsBitmap,
   1.817 +used when sanity-checking bitmaps are enabled. 
   1.818 +*/
   1.819 +CFbsBitmap* CTFbsGlyphData::GetTargetAsBitmapL()
   1.820 +	{
   1.821 +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
   1.822 +	// For debugging purposes only.
   1.823 +	// Capture the final state of the EGL Pixmap surface as an mbm.
   1.824 +	const TInt KDataStride = KEglTargetSize.iWidth;
   1.825 +
   1.826 +	TUint8* imageScanline = reinterpret_cast<TUint8*>(User::AllocZL(KDataStride));
   1.827 +	CleanupStack::PushL(imageScanline);
   1.828 +	CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
   1.829 +	CleanupStack::PushL(bitmap);
   1.830 +	User::LeaveIfError(bitmap->Create(KEglTargetSize, EGray256));
   1.831 +	bitmap->BeginDataAccess();
   1.832 +	TUint8* dataAddress = reinterpret_cast<TUint8*>(bitmap->DataAddress());
   1.833 +	const TInt dataStride = bitmap->DataStride();	
   1.834 +	for (TInt scanline = 0; scanline < KEglTargetSize.iHeight; scanline++)
   1.835 +		{
   1.836 +	    vgReadPixels(imageScanline, KDataStride, VG_A_8, 0, scanline, KEglTargetSize.iWidth, 1);
   1.837 +		Mem::Copy(dataAddress, imageScanline, KEglTargetSize.iWidth);
   1.838 +		dataAddress += dataStride;
   1.839 +		}
   1.840 +	bitmap->EndDataAccess(EFalse);
   1.841 +	CleanupStack::Pop(2); // bitmap, imageScanline
   1.842 +	return bitmap;
   1.843 +#else
   1.844 +	return NULL;
   1.845 +#endif
   1.846 +	}
   1.847 +
   1.848 +/**
   1.849 +Utility method. Loads sample glyph code data from the config ini file
   1.850 +into a TUint array.
   1.851 +@param aFont The font that the glyph codes will be associated with.
   1.852 +@param aLanguage The language variant to load from the config file as sample data.
   1.853 +@param aLongData Whether to use the long variant (ETrue) or short variant (EFalse) 
   1.854 +    of the sample data for the given language.
   1.855 +@param aGlyphCodes On success, holds an array of glyph codes, to be freed by the caller.
   1.856 +@param aNumGlyphCodes On success, holds the count of the glyph code array.
   1.857 +@leave KErrNotFound if the test data cannot be found or is empty in the config file.
   1.858 + */
   1.859 +void CTFbsGlyphData::LoadConfigSampleDataL(CFbsFont* aFont, TTestLanguage aLanguage, TBool aLongData, TUint*& aGlyphCodes, TInt& aNumGlyphCodes)
   1.860 +	{
   1.861 +	// The name of the section in the config file to look-up the sample data
   1.862 +	_LIT(KConfigFileSampleData, "GlyphDataSampleText");
   1.863 +
   1.864 +	TBuf<32> keyName = ConfigKeyNameL(aLanguage, aLongData);
   1.865 +	
   1.866 +	// Setup the converter to use the passed font.
   1.867 +	iCharCodeConverter->UseFontL(aFont);
   1.868 +
   1.869 +	// Load the sample string data from the config file.
   1.870 +	TPtrC sampleText;
   1.871 +	TESTL(GetStringFromConfig(KConfigFileSampleData, keyName, sampleText));
   1.872 +	aNumGlyphCodes = sampleText.Length();
   1.873 +	if (aNumGlyphCodes <= 0)
   1.874 +		{
   1.875 +		User::Leave(KErrNotFound);
   1.876 +		}
   1.877 +	aGlyphCodes = new(ELeave) TUint[aNumGlyphCodes];
   1.878 +	for (TInt code = 0; code < aNumGlyphCodes; ++code)
   1.879 +		{
   1.880 +		aGlyphCodes[code] = iCharCodeConverter->GlyphCodeL(sampleText[code]); 
   1.881 +		}
   1.882 +	}
   1.883 +
   1.884 +/**
   1.885 +Creates the name of the key to look for in the config file for the test
   1.886 +with the specified parameters.
   1.887 +@param aLanguage The language the test will use.
   1.888 +@param aLongData Whether to use long or short sample data.
   1.889 +@return A descriptor value of the language.
   1.890 +@leave KErrNotSupported if aLanguage is not recognised.
   1.891 + */
   1.892 +TBufC<32> CTFbsGlyphData::ConfigKeyNameL(TTestLanguage aLanguage, TBool aLongData)
   1.893 +	{
   1.894 +	if (aLanguage < 0 || aLanguage > 1)
   1.895 +		{
   1.896 +		User::Leave(KErrNotSupported);
   1.897 +		}
   1.898 +	TBuf<32> langName[2];
   1.899 +	langName[ETestLanguageLatin].Append(_L("Latin"));
   1.900 +	langName[ETestLanguageHindi].Append(_L("Hindi"));	
   1.901 +	langName[aLanguage].Append((aLongData) ? _L("Long") : _L("Short"));
   1.902 +	return langName[aLanguage];
   1.903 +	}
   1.904 +
   1.905 +/**
   1.906 +Font factory.
   1.907 +Utiltiy class for providing fonts for the performance tests.
   1.908 +*/
   1.909 +
   1.910 +CTFontFactory::CTFontFactory()
   1.911 +	{
   1.912 +	}
   1.913 +
   1.914 +CTFontFactory::~CTFontFactory()
   1.915 +	{
   1.916 +	ReleaseFonts();
   1.917 +	delete iTs;
   1.918 +	}
   1.919 +
   1.920 +/**
   1.921 +@return A new Font Factory ready to create fonts.
   1.922 +*/
   1.923 +CTFontFactory* CTFontFactory::NewLC()
   1.924 +	{
   1.925 +	CTFontFactory* fontFactory = new (ELeave) CTFontFactory();
   1.926 +	CleanupStack::PushL(fontFactory);
   1.927 +	fontFactory->iTs = static_cast<CFbsTypefaceStore*>(CFbsTypefaceStore::NewL(NULL));
   1.928 +	return fontFactory;
   1.929 +	}
   1.930 +
   1.931 +/**
   1.932 +Creates a number of fonts for use by tests. All the fonts are created up-front so 
   1.933 +that NextFont() can be called as a very lightweight call, so it can be used inside
   1.934 +tests with minimal impact.
   1.935 +Once fonts are created, the factory must not be destroyed until the fonts it created
   1.936 +are finished with.
   1.937 +@param aLanaugeMask Which language needs to be supported by the returned fonts.
   1.938 +@param aNumFonts The number of fonts to create
   1.939 +@param aStartSizeInPixels The lower bound font height of the fonts that are created. All
   1.940 +	fonts will be at least as big as this value.
   1.941 +*/
   1.942 +void CTFontFactory::CreateFontsL(TTestLanguage aLanguageMask, TInt aNumFonts, TInt aStartSizeInPixels)
   1.943 +	{
   1.944 +	ReleaseFonts();
   1.945 +	
   1.946 +	RArray <TPtrC> typefaceNames;
   1.947 +	CleanupClosePushL(typefaceNames);
   1.948 +	switch(aLanguageMask)
   1.949 +		{
   1.950 +		case ETestLanguageHindi:	
   1.951 +			User::LeaveIfError(typefaceNames.Reserve(1));
   1.952 +			typefaceNames.Append(_L("Devanagari OT Eval"));
   1.953 +			break;
   1.954 +		case ETestLanguageLatin:
   1.955 +			User::LeaveIfError(typefaceNames.Reserve(3));
   1.956 +			typefaceNames.Append(_L("DejaVu Sans Condensed"));
   1.957 +			typefaceNames.Append(_L("DejaVu Serif"));
   1.958 +			typefaceNames.Append(_L("DejaVu Sans Mono"));
   1.959 +			break;
   1.960 +		default:
   1.961 +			User::Leave(KErrNotSupported);
   1.962 +		}
   1.963 +	const TInt KNumTypefaces = typefaceNames.Count();
   1.964 +		
   1.965 +	iFont = new CFbsFont*[aNumFonts];
   1.966 +	for (TInt count = 0; count < aNumFonts; ++count)
   1.967 +		{
   1.968 +		// After every KNumTypefaces font, increase size by 5.
   1.969 +		TInt size = aStartSizeInPixels + (5 *(count / KNumTypefaces));
   1.970 +		TPtrC typefaceName = typefaceNames[count % KNumTypefaces];
   1.971 +		TFontSpec fontSpec(typefaceName, size);
   1.972 +		User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont[count], fontSpec));
   1.973 +		++iNumFonts;
   1.974 +		}
   1.975 +	iCurFont = -1;
   1.976 +	CleanupStack::PopAndDestroy(1); // typefaceNames
   1.977 +	}
   1.978 +/**
   1.979 +Releases all created fonts and frees associated memory.
   1.980 +*/
   1.981 +void CTFontFactory::ReleaseFonts()
   1.982 +	{
   1.983 +	for (TInt font = 0; font < iNumFonts; ++font)
   1.984 +		{
   1.985 +		iTs->ReleaseFont(iFont[font]);
   1.986 +		}
   1.987 +	delete [] iFont;
   1.988 +	iFont = NULL;
   1.989 +	iNumFonts = 0;
   1.990 +	}
   1.991 +
   1.992 +/**
   1.993 +@return The next font to be used. If it reaches the last font, the next font will
   1.994 +	cycle back around to the first font.
   1.995 +*/
   1.996 +CFbsFont* CTFontFactory::NextFont()
   1.997 +	{
   1.998 +	return iFont[++iCurFont%iNumFonts];
   1.999 +	}