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 + }