|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @test |
|
19 @internalComponent - Internal Symbian test code |
|
20 */ |
|
21 |
|
22 |
|
23 #include "tcomplexfonts.h" |
|
24 #include "fontdefs.h" |
|
25 #include "twindow.h" |
|
26 |
|
27 #include <w32std.h> |
|
28 #include <coefontprovider.h> |
|
29 |
|
30 |
|
31 _LIT(KTestStep0010, "GRAPHICS-UI-BENCH-S60-0010"); |
|
32 |
|
33 _LIT(KSemaphore, "SemDrawSync"); // Name of the global semaphore |
|
34 |
|
35 |
|
36 // constants to define the format of the text |
|
37 const TInt KHeadingParagraph = 0; |
|
38 const TInt KClassParagraph = 2; |
|
39 const TInt KDescriptionHeading = 4; |
|
40 const TInt KDerivationHeading = 10; |
|
41 const TInt KFirstDerivation = 12; |
|
42 const TInt KLastDerivation = 16; |
|
43 |
|
44 const TInt KHeaderFontSize = 13 * 20; // in TWIPs |
|
45 const TInt KBodyFontSize = 8 * 20; // in TWIPs |
|
46 const TInt KBodyLineSpacing = 10; // in TWIPs |
|
47 const TInt KBodyIndent = 300; // in TWIPs |
|
48 |
|
49 const TInt KIterationsToTest = 50; // number of iterations |
|
50 |
|
51 |
|
52 CTComplexFonts::CTComplexFonts() |
|
53 { |
|
54 SetTestStepName(KTComplexFonts); |
|
55 } |
|
56 |
|
57 void CTComplexFonts::InitUIL(CCoeEnv* aCoeEnv) |
|
58 { |
|
59 CComplexFontsAppUi* appUi = new(ELeave) CComplexFontsAppUi(); |
|
60 CleanupStack::PushL(appUi); |
|
61 appUi->ConstructL(); |
|
62 aCoeEnv->SetAppUi(appUi); |
|
63 CleanupStack::Pop(appUi); |
|
64 } |
|
65 |
|
66 TVerdict CTComplexFonts::doTestStepPreambleL() |
|
67 { |
|
68 // The semaphore has to be created before, otherwise the control can't open it. |
|
69 TESTNOERRORL(iSemaphore.CreateGlobal(KSemaphore, 0)); |
|
70 return CTe_ConeStepBase::doTestStepPreambleL(); |
|
71 } |
|
72 |
|
73 TVerdict CTComplexFonts::doTestStepPostambleL() |
|
74 { |
|
75 GenerateEventL(TRawEvent::EButton1Up); |
|
76 iSemaphore.Close(); |
|
77 return CTe_ConeStepBase::doTestStepPostambleL(); |
|
78 } |
|
79 |
|
80 /** |
|
81 Override of base class pure virtual |
|
82 Our implementation only gets called if the base class doTestStepPreambleL() did |
|
83 not leave. |
|
84 |
|
85 @return - TVerdict code |
|
86 */ |
|
87 TVerdict CTComplexFonts::doTestStepL() |
|
88 { |
|
89 SetTestStepName(KTestStep0010); |
|
90 TRAPD(err, DrawComplexFontsL()); |
|
91 if (err != KErrNone) |
|
92 { |
|
93 SetTestStepResult(EAbort); |
|
94 } |
|
95 return TestStepResult(); |
|
96 } |
|
97 |
|
98 /** |
|
99 @SYMTestCaseID |
|
100 GRAPHICS-UI-BENCH-S60-0010 |
|
101 |
|
102 @SYMTestCaseDesc |
|
103 Tests how long it takes format and draw a CRichText object. |
|
104 |
|
105 @SYMTestActions |
|
106 Create a complex font control. Format and draw the text control each time |
|
107 it receives a left pointer down event. The test step and the drawing of the |
|
108 control is synchronized with a Semaphore. |
|
109 |
|
110 @SYMTestExpectedResults |
|
111 Test should pass and display the average framerate for the test. |
|
112 */ |
|
113 void CTComplexFonts::DrawComplexFontsL() |
|
114 { |
|
115 iProfiler->InitResults(); |
|
116 for(TInt i = KIterationsToTest; i > 0; --i) |
|
117 { |
|
118 GenerateEventL(TRawEvent::EButton1Down); |
|
119 iSemaphore.Wait(); |
|
120 } |
|
121 iProfiler->MarkResultSetL(); |
|
122 TSize screenSize = CTWindow::GetDisplaySizeInPixels(); |
|
123 iProfiler->ResultsAnalysisFrameRate(KTestStep0010, 0, 0, 0, KIterationsToTest, screenSize.iWidth * screenSize.iHeight); |
|
124 } |
|
125 |
|
126 /** |
|
127 * Generates events to communicate with the control. Each time the control receives an event |
|
128 * it redraws itself. That's necessary because the draw method can't be called directly from |
|
129 * a different thread. |
|
130 */ |
|
131 void CTComplexFonts::GenerateEventL(TRawEvent::TType aEventType) |
|
132 { |
|
133 TRawEvent rawEvent; |
|
134 rawEvent.Set(aEventType, 0, 0); |
|
135 User::LeaveIfError(UserSvr::AddEvent(rawEvent)); |
|
136 } |
|
137 |
|
138 |
|
139 CComplexFontsAppUi::CComplexFontsAppUi() |
|
140 { |
|
141 // Empty |
|
142 } |
|
143 |
|
144 void CComplexFontsAppUi::ConstructL() |
|
145 { |
|
146 BaseConstructL(ENoAppResourceFile); |
|
147 iComplexFontsControl = CComplexFontsControl::NewL(); |
|
148 AddToStackL(iComplexFontsControl); |
|
149 } |
|
150 |
|
151 CComplexFontsAppUi::~CComplexFontsAppUi() |
|
152 { |
|
153 RemoveFromStack(iComplexFontsControl); |
|
154 delete iComplexFontsControl; |
|
155 } |
|
156 |
|
157 |
|
158 CComplexFontsControl* CComplexFontsControl::NewLC(const CCoeControl* aParent) |
|
159 { |
|
160 CComplexFontsControl* self; |
|
161 self = new(ELeave) CComplexFontsControl(); |
|
162 CleanupStack::PushL(self); |
|
163 self->ConstructL(aParent); |
|
164 return self; |
|
165 } |
|
166 |
|
167 CComplexFontsControl* CComplexFontsControl::NewL(const CCoeControl* aParent) |
|
168 { |
|
169 CComplexFontsControl* self; |
|
170 self = CComplexFontsControl::NewLC(aParent); |
|
171 CleanupStack::Pop(self); |
|
172 return self; |
|
173 } |
|
174 |
|
175 CComplexFontsControl::CComplexFontsControl() : iWsSession(CCoeEnv::Static()->WsSession()) |
|
176 { |
|
177 // empty |
|
178 } |
|
179 |
|
180 CComplexFontsControl::~CComplexFontsControl() |
|
181 { |
|
182 delete iTextView; |
|
183 delete iLayout; |
|
184 delete iRichText; |
|
185 delete iCharFormatLayer; |
|
186 delete iParaFormatLayer; |
|
187 delete iScreen; |
|
188 iSemaphore.Close(); |
|
189 } |
|
190 |
|
191 /** |
|
192 * Constructs the text control with the complex fonts. |
|
193 */ |
|
194 void CComplexFontsControl::ConstructL(const CCoeControl* aParent) |
|
195 { |
|
196 User::LeaveIfError(iSemaphore.OpenGlobal(KSemaphore)); |
|
197 if (aParent) |
|
198 { |
|
199 SetContainerWindowL(*aParent); |
|
200 } |
|
201 else |
|
202 { |
|
203 CreateWindowL(); |
|
204 } |
|
205 // Create text object, text view and layout. |
|
206 iParaFormatLayer = CParaFormatLayer::NewL(); |
|
207 iCharFormatLayer = CCharFormatLayer::NewL(); |
|
208 // Create an empty rich text object |
|
209 iRichText = CRichText::NewL(iParaFormatLayer, iCharFormatLayer); |
|
210 |
|
211 iScreen = new(ELeave) CWsScreenDevice(ControlEnv()->WsSession()); |
|
212 User::LeaveIfError(iScreen->Construct()); // default screen used |
|
213 |
|
214 TPixelsAndRotation pixelsAndRotation; |
|
215 iScreen->GetDefaultScreenSizeAndRotation(pixelsAndRotation); |
|
216 |
|
217 // Create the text layout, (required by text view), |
|
218 // with the text object and a wrap width (=width of view rect) |
|
219 iLayout = CTextLayout::NewL(iRichText,pixelsAndRotation.iPixelSize.iWidth); |
|
220 |
|
221 // Create text view |
|
222 iTextView = CTextView::NewL(iLayout, pixelsAndRotation.iPixelSize, |
|
223 iScreen, iScreen, &Window(), 0, // no window group |
|
224 &iCoeEnv->WsSession()); // new view |
|
225 |
|
226 SetRect(TRect(TPoint(0, 0), pixelsAndRotation.iPixelSize)); |
|
227 |
|
228 // load up text |
|
229 iRichText->InsertL(0, KComplexFontsText); |
|
230 |
|
231 // break up into paragraphs for CRichText by replacing \n characters in original text |
|
232 // with CEditableText::EParagraphDelimiter |
|
233 TPtrC complexFontsTextPtr(KComplexFontsText); |
|
234 TInt eos = complexFontsTextPtr.Length(); |
|
235 for (TInt paragraphBreakLocation = 0; paragraphBreakLocation < eos; paragraphBreakLocation++) |
|
236 { |
|
237 if (complexFontsTextPtr[paragraphBreakLocation] == '\n') |
|
238 { |
|
239 iRichText->DeleteL(paragraphBreakLocation, 1); |
|
240 iRichText->InsertL(paragraphBreakLocation, CEditableText::EParagraphDelimiter); |
|
241 } |
|
242 } |
|
243 |
|
244 TCharFormat charFormat; |
|
245 TCharFormatMask charFormatMask; |
|
246 // format the first paragraph "Class RWindow" as orange and a bit bigger than the body |
|
247 charFormat.iFontPresentation.iTextColor= TLogicalRgb(TRgb(0x0099ff)); |
|
248 charFormatMask.SetAttrib(EAttColor); |
|
249 charFormat.iFontSpec.iHeight = KHeaderFontSize; |
|
250 charFormatMask.SetAttrib(EAttFontHeight); |
|
251 |
|
252 TInt headerLength = 0; |
|
253 TInt headerStart = iRichText->CharPosOfParagraph(headerLength, KHeadingParagraph); |
|
254 iRichText->ApplyCharFormatL(charFormat, charFormatMask, headerStart, headerLength); |
|
255 charFormatMask.ClearAll(); |
|
256 |
|
257 // format "Class" as Sans Serif |
|
258 charFormat.iFontSpec.iTypeface.iName = KNokiaSeries60Font; |
|
259 charFormatMask.SetAttrib(EAttFontTypeface); |
|
260 iRichText->ApplyCharFormatL(charFormat, charFormatMask, headerStart, 5); |
|
261 charFormatMask.ClearAll(); |
|
262 |
|
263 // make the rest of the text smaller |
|
264 charFormat.iFontSpec.iHeight = KBodyFontSize; |
|
265 charFormatMask.SetAttrib(EAttFontHeight); |
|
266 TInt textLength = iRichText->DocumentLength(); |
|
267 iRichText->ApplyCharFormatL(charFormat, charFormatMask, headerLength, textLength - headerLength); |
|
268 charFormatMask.ClearAll(); |
|
269 |
|
270 TParaFormatMask paraFormatMask; |
|
271 // crunch main body a bit closer together to show more on the little screen |
|
272 // and indent left margin |
|
273 iParaFormat.iLineSpacingInTwips = KBodyLineSpacing; |
|
274 paraFormatMask.SetAttrib(EAttLineSpacing); |
|
275 iParaFormat.iLineSpacingControl = CParaFormat::ELineSpacingExactlyInPixels; |
|
276 paraFormatMask.SetAttrib(EAttLineSpacingControl); |
|
277 iParaFormat.iLeftMarginInTwips = KBodyIndent; |
|
278 paraFormatMask.SetAttrib(EAttLeftMargin); |
|
279 iRichText->ApplyParaFormatL(&iParaFormat, paraFormatMask, headerLength, textLength - headerLength); |
|
280 paraFormatMask.ClearAll(); |
|
281 |
|
282 TInt length = 0; |
|
283 TInt start = 0; |
|
284 |
|
285 // put a grey background on "class RWindow : public RDrawableWindow;" |
|
286 start = iRichText->CharPosOfParagraph(length, KClassParagraph); |
|
287 iParaFormat.iFillColor = TLogicalRgb(TRgb(0xdddddd)); |
|
288 paraFormatMask.SetAttrib(EAttFillColor); |
|
289 iRichText->ApplyParaFormatL(&iParaFormat, paraFormatMask, start, length); |
|
290 paraFormatMask.ClearAll(); |
|
291 |
|
292 // make "Description" and "Derivation" subheadings bold |
|
293 charFormat.iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold); |
|
294 charFormatMask.SetAttrib(EAttFontStrokeWeight); |
|
295 start = iRichText->CharPosOfParagraph(length, KDescriptionHeading); |
|
296 iRichText->ApplyCharFormatL(charFormat, charFormatMask, start, length); |
|
297 start = iRichText->CharPosOfParagraph(length, KDerivationHeading); |
|
298 iRichText->ApplyCharFormatL(charFormat, charFormatMask, start, length); |
|
299 charFormatMask.ClearAll(); |
|
300 |
|
301 // all the paragraphs between and including "Description" and "Derivation" are in sans serif |
|
302 // (the default CRichText font is serif) |
|
303 TInt paragraphNumber = 0; |
|
304 |
|
305 charFormat.iFontSpec.iTypeface.iName = KNokiaSeries60Font; |
|
306 charFormatMask.SetAttrib(EAttFontTypeface); |
|
307 for (paragraphNumber = KDescriptionHeading; paragraphNumber <= KDerivationHeading; paragraphNumber++) |
|
308 { |
|
309 start = iRichText->CharPosOfParagraph(length, paragraphNumber); |
|
310 iRichText->ApplyCharFormatL(charFormat, charFormatMask, start, length); |
|
311 } |
|
312 charFormatMask.ClearAll(); |
|
313 |
|
314 // for each line in the "Derivation" section |
|
315 // progressively indent left margin |
|
316 // make class name blue underlined (it starts two characters after the |
|
317 // beginning of each paragraph and goes to the space before the '-') |
|
318 // make descriptive text sans serif (from the '-' to the end of the paragraph) |
|
319 paraFormatMask.SetAttrib(EAttLeftMargin); |
|
320 charFormat.iFontPresentation.iTextColor= TLogicalRgb(TRgb(0xA27316)); |
|
321 charFormat.iFontPresentation.iUnderline = EUnderlineOn; |
|
322 for (paragraphNumber = KFirstDerivation; paragraphNumber <= KLastDerivation; paragraphNumber++) |
|
323 { |
|
324 iParaFormat.iLeftMarginInTwips = (paragraphNumber - KFirstDerivation + 2)*KBodyIndent; |
|
325 start = iRichText->CharPosOfParagraph(length, paragraphNumber); |
|
326 iRichText->ApplyParaFormatL(&iParaFormat, paraFormatMask, start, length); |
|
327 TInt dash = 0; |
|
328 for (dash = start; dash < start + length; dash++) |
|
329 { |
|
330 if (complexFontsTextPtr[dash] == '-') |
|
331 { |
|
332 break; |
|
333 } |
|
334 } |
|
335 charFormatMask.SetAttrib(EAttColor); |
|
336 charFormatMask.SetAttrib(EAttFontUnderline); |
|
337 TInt classNameLength = (dash - 1) - (start + 2); |
|
338 iRichText->ApplyCharFormatL(charFormat, charFormatMask, start + 2, classNameLength); |
|
339 charFormatMask.ClearAll(); |
|
340 charFormatMask.SetAttrib(EAttFontTypeface); |
|
341 TInt descriptionLength = length - classNameLength - 4; |
|
342 iRichText->ApplyCharFormatL(charFormat, charFormatMask, dash, descriptionLength); |
|
343 charFormatMask.ClearAll(); |
|
344 } |
|
345 paraFormatMask.ClearAll(); |
|
346 |
|
347 if (!aParent) |
|
348 { |
|
349 ActivateL(); |
|
350 } |
|
351 } |
|
352 |
|
353 /** |
|
354 * The test meassures how long it takes to format and draw the text view. |
|
355 * Most time is spend with formatting the text. |
|
356 */ |
|
357 void CComplexFontsControl::Draw(const TRect& aRect) const |
|
358 { |
|
359 TRAPD(err,iTextView->FormatTextL()); |
|
360 if (err == KErrNone) |
|
361 { |
|
362 TRAP(err,iTextView->DrawL(aRect)); |
|
363 } |
|
364 } |
|
365 |
|
366 /** |
|
367 * Draws the text control if a pointer down event is received. |
|
368 */ |
|
369 void CComplexFontsControl::HandlePointerEventL(const TPointerEvent& aPointerEvent) |
|
370 { |
|
371 if (aPointerEvent.iType == TPointerEvent::EButton1Down) |
|
372 { |
|
373 DrawNow(); |
|
374 iWsSession.Flush(); |
|
375 iWsSession.Finish(); |
|
376 iSemaphore.Signal(); |
|
377 } |
|
378 } |