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