|
1 /* |
|
2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 // Test code for GetNextVisualCursorPos functionality |
|
19 #include <e32test.h> |
|
20 |
|
21 #include "TGraphicsContext.h" |
|
22 #include <gdi.h> |
|
23 #include "TAGMA.H" |
|
24 #include "TmLayoutImp.h" |
|
25 #include "TMINTERP.H" |
|
26 |
|
27 CTrapCleanup* TrapCleanup; |
|
28 RTest test(_L("TBidiCursorPos - GetNextVisualCursorPos tests")); |
|
29 |
|
30 class CTestSource : public CBase, public MTmSource |
|
31 { |
|
32 public: |
|
33 static CTestSource* NewLC(); |
|
34 ~CTestSource(); |
|
35 void ConstructL(); |
|
36 // from MTmSource |
|
37 MGraphicsDeviceMap& FormatDevice() const { return *iScreenDevice; } |
|
38 MGraphicsDeviceMap& InterpretDevice() const { return *iScreenDevice; } |
|
39 TInt DocumentLength() const |
|
40 { |
|
41 return iText->Length(); |
|
42 } |
|
43 void GetText(TInt aPos,TPtrC& aText, TTmCharFormat& aFormat) const |
|
44 { |
|
45 TTmCharFormat f; |
|
46 aFormat = f; |
|
47 aText.Set(iText->Mid(aPos)); |
|
48 } |
|
49 void GetParagraphFormatL(TInt, RTmParFormat& aFormat) const |
|
50 { |
|
51 aFormat.CopyL(iParFormat); |
|
52 } |
|
53 TInt ParagraphStart(TInt) const { return 0; } |
|
54 |
|
55 void SetText(HBufC* aText) { iText = aText; } |
|
56 |
|
57 private: |
|
58 CTestSource() {} |
|
59 |
|
60 public: |
|
61 RTmParFormat iParFormat; |
|
62 private: |
|
63 CTestGraphicsDevice* iScreenDevice; |
|
64 CWindowGc* iGc; |
|
65 HBufC* iText; |
|
66 }; |
|
67 |
|
68 // static |
|
69 CTestSource* CTestSource::NewLC() |
|
70 { |
|
71 CTestSource* self = new(ELeave) CTestSource(); |
|
72 CleanupStack::PushL(self); |
|
73 self->ConstructL(); |
|
74 return self; |
|
75 } |
|
76 |
|
77 void CTestSource::ConstructL() |
|
78 { |
|
79 TSize size(100, 100); |
|
80 iScreenDevice = CTestGraphicsDevice::NewL(size, 0); |
|
81 User::LeaveIfError(iScreenDevice->CreateContext(iGc)); |
|
82 } |
|
83 |
|
84 CTestSource::~CTestSource() |
|
85 { |
|
86 delete iScreenDevice; |
|
87 delete iGc; |
|
88 } |
|
89 |
|
90 #define NO_OF_TEST_CASES 8 |
|
91 |
|
92 class TPos |
|
93 { |
|
94 public: |
|
95 TInt iPos; |
|
96 TBool iLeading; |
|
97 }; |
|
98 class TAugmentedPos |
|
99 { |
|
100 public: |
|
101 TInt iPos; |
|
102 TBool iLeading; |
|
103 TBool iOptional; |
|
104 }; |
|
105 |
|
106 const TAugmentedPos expectedCursorPos[NO_OF_TEST_CASES][40] = { |
|
107 { {1, 0, 0}, {2, 0, 0}, {3, 0, 0}, {5, 1, 0}, |
|
108 {4, 1, 0}, {3, 1, 0}, {7, 0, 0}, {8, 0, 0}, |
|
109 {9, 0, 0} }, |
|
110 { {1, 0, 0}, {2, 0, 0}, {10, 1, 0}, {9, 1, 0}, |
|
111 {8, 1, 0}, {7, 1, 0}, {6, 0, 0}, {7, 0, 0}, |
|
112 {4, 1, 0}, {3, 1, 0}, {2, 1, 0}, {12, 0, 0}, |
|
113 {13, 0, 0} }, |
|
114 { {1, 0, 0}, {2, 0, 0}, {5, 1, 1}, {4, 1, 0}, |
|
115 {3, 1, 1}, {2, 1, 1}, {7, 0, 0}, {8, 0, 0}, |
|
116 {9, 0, 0} }, |
|
117 { {1, 0, 0}, {2, 0, 0}, {3, 0, 0}, {5, 1, 0}, |
|
118 {4, 1, 0}, {3, 1, 0}, {7, 0, 0}, {8, 0, 0}, |
|
119 {9, 0, 0}, {11, 1, 0}, {10, 1, 0}, {9, 1, 0}, |
|
120 {13, 0, 0}, {14, 0, 0}, {15, 0, 0} }, |
|
121 { {2, 0, 0}, {3, 0, 0}, {4, 0, 0} }, |
|
122 { {3, 0, 0}, {4, 0, 0} }, |
|
123 { {1, 0, 0}, {2, 0, 0}, {6, 1, 0}, {5, 1, 0}, |
|
124 {4, 1, 0}, {3, 1, 0}, {2, 1, 0}, {8, 0, 0}, |
|
125 {9, 0, 0} }, |
|
126 { {1, 0, 0}, {2, 0, 0}, {8, 1, 0}, {7, 1, 0}, |
|
127 {6, 1, 0}, {5, 1, 0}, {4, 1, 0}, {3, 1, 0}, |
|
128 {2, 1, 0}, {10, 0, 0}, {11, 0, 0} } |
|
129 }; |
|
130 |
|
131 const TPos startPos[NO_OF_TEST_CASES] = { {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} }; |
|
132 |
|
133 const TInt numberOfCursorPositionsToCheck[NO_OF_TEST_CASES] = {9, 13, 9, 15, 3, 2, 9, 11}; |
|
134 const TBool moveToLeft[NO_OF_TEST_CASES] = {EFalse, EFalse, EFalse, ETrue, ETrue, EFalse, ETrue, ETrue}; |
|
135 const TBool rightToLeftPara[NO_OF_TEST_CASES] = {EFalse, EFalse, EFalse, ETrue, EFalse, EFalse, ETrue, ETrue}; |
|
136 |
|
137 void GetNextVisualCursorPosTestsL(CTmTextLayout* aLayout, CTestSource* aSource) |
|
138 { |
|
139 // Testcase 1 |
|
140 _LIT(KBidi1, "abc\x644\x644\x644zzz\x2029"); |
|
141 |
|
142 // Testcase 2 (0x32 and 0x39 changed to 0x6F2 and 0x0F9, see note below) |
|
143 _LIT(KBidi2, "ab\x644\x644\x644\x6F2\x6F9\x644\x644\x644\x644zy\x2029"); |
|
144 |
|
145 // Testcase 3 |
|
146 _LIT(KBidi3, "ab\x202ejk\x202cjkl\x2029"); |
|
147 |
|
148 // Testcase 4 |
|
149 _LIT(KBidi4, "\x644\x644\x644xyz\x644\x644\x644xyz\x644\x644\x644\x2029"); |
|
150 |
|
151 // Testcase 5 |
|
152 _LIT(KBidi5, "\x647\x64b\x647\x647\x2029"); |
|
153 |
|
154 // Testcase 6 |
|
155 _LIT(KBidi6, "a\x302\x317z\x2029"); |
|
156 |
|
157 // Testcase 7 (0x31 and 0x32 changed to 0x6F1 and 0x0F2, see note below) |
|
158 _LIT(KBidi7, "\x644\x644\x6F1\x6F2\x2e\x33\x34\x644\x644\x2029"); |
|
159 |
|
160 // Testcase 8 (0x31 - 0x35 changed to 0x6F1 - 0x0F5, see note below) |
|
161 _LIT(KBidi8, "\x644\x644\x6F1\x2c\x6F2\x6F3\x2e\x6F4\x6F5\x644\x644\x2029"); |
|
162 |
|
163 // Note: Test cases 2 and 7 have been changed to use \x6F0-\x6F9, Extended Arabic Digits, |
|
164 // These have the bidirectional class "EN",the same as ASCII digits. |
|
165 // These have been used in preference to ASCII digits |
|
166 // to work around a CodeWarrior preprocessor/C-Cover problem. |
|
167 // For more detils see DEF042186 |
|
168 |
|
169 HBufC* logicalText[NO_OF_TEST_CASES]; |
|
170 logicalText[0] = KBidi1().AllocLC(); |
|
171 logicalText[1] = KBidi2().AllocLC(); |
|
172 logicalText[2] = KBidi3().AllocLC(); |
|
173 logicalText[3] = KBidi4().AllocLC(); |
|
174 logicalText[4] = KBidi5().AllocLC(); |
|
175 logicalText[5] = KBidi6().AllocLC(); |
|
176 logicalText[6] = KBidi7().AllocLC(); |
|
177 logicalText[7] = KBidi8().AllocLC(); |
|
178 |
|
179 TTmFormatParam format; |
|
180 format.iStartChar = 0; |
|
181 format.iEndChar = 0; |
|
182 format.iLineInPar = 0; |
|
183 |
|
184 TTmDocPos pos(0, ETrue); |
|
185 TTmPosInfo2 info; |
|
186 int charIndex; |
|
187 TBuf<40> msg; |
|
188 |
|
189 for (TInt ii = 0; ii < NO_OF_TEST_CASES; ii++) |
|
190 { |
|
191 msg.Format(_L("GetNextVisualCursorPos test case %d\n"), ii + 1); |
|
192 test.Next(msg); |
|
193 aSource->SetText(logicalText[ii]); |
|
194 format.iEndChar = logicalText[ii]->Length(); |
|
195 if (rightToLeftPara[ii]) |
|
196 aSource->iParFormat.iFlags |= RTmParFormat::ERightToLeft; |
|
197 aLayout->SetTextL(*aSource, format); |
|
198 |
|
199 charIndex = 0; |
|
200 pos.iPos = startPos[ii].iPos; |
|
201 pos.iLeadingEdge = startPos[ii].iLeading; |
|
202 while (aLayout->GetNextVisualCursorPos(pos, info, moveToLeft[ii])) |
|
203 { |
|
204 while (info.iDocPos.iPos != expectedCursorPos[ii][charIndex].iPos |
|
205 || info.iDocPos.iLeadingEdge != expectedCursorPos[ii][charIndex].iLeading) |
|
206 { |
|
207 test(expectedCursorPos[ii][charIndex].iOptional); |
|
208 ++charIndex; |
|
209 test(charIndex != numberOfCursorPositionsToCheck[ii]); |
|
210 } |
|
211 pos = info.iDocPos; |
|
212 ++charIndex; |
|
213 test(charIndex <= numberOfCursorPositionsToCheck[ii]); |
|
214 } |
|
215 test(charIndex == numberOfCursorPositionsToCheck[ii]); |
|
216 aSource->iParFormat.iFlags &= ~(RTmParFormat::ERightToLeft); // reset back to default of LeftToRight |
|
217 } |
|
218 |
|
219 CleanupStack::PopAndDestroy(NO_OF_TEST_CASES); // cleanup all HBufC* stored in logicalText array |
|
220 } |
|
221 |
|
222 /** |
|
223 @SYMTestCaseID SYSLIB-FORM-UT-3610 |
|
224 @SYMTestCaseDesc Testing behaviour of r2l text when wrapping occurs and bidirectional text allowed |
|
225 @SYMTestPriority High |
|
226 @SYMTestActions 1. Have some arabic text |
|
227 2. Set wrap width to 10 chars |
|
228 3. Set alignment to NormalBidirectional |
|
229 4. Call CTmTextLayout::SetTextL |
|
230 5. Retrieve the cursor position |
|
231 6. Check the lineinfo to ensure that the innerRect TL.iX parameter is positive. |
|
232 @SYMTestExpectedResults The innerRect that holds text top left x position is positive. |
|
233 @SYMDEF DEF109737,PDEF110819,PDEF110820,PDEF110821 |
|
234 */ |
|
235 void DEF109737(CTmTextLayout* aLayout, CTestSource* aSource) |
|
236 { |
|
237 //R2L paragraph wrapping |
|
238 _LIT(KLllHahHah1, "lll\x62D\x62D\x2029\x62D\x62D\x2029"); |
|
239 HBufC* buf = HBufC::NewLC(KLllHahHah1().Length()); |
|
240 *buf = KLllHahHah1; |
|
241 aSource->SetText(buf); |
|
242 aSource->iParFormat.iFlags = 1; |
|
243 aSource->iParFormat.iAlignment = RTmParFormat::EAlignNormalBidirectional; |
|
244 TTmFormatParam format; |
|
245 format.iStartChar = 0; |
|
246 format.iEndChar = buf->Length(); |
|
247 format.iLineInPar = 0; |
|
248 format.iWrapWidth = 10; |
|
249 aLayout->SetTextL(*aSource, format); |
|
250 TTmLineInfo lineInfo; |
|
251 TPoint position; |
|
252 TInt width; |
|
253 TInt ascent; |
|
254 TInt descent; |
|
255 TInt type = 0; |
|
256 TInt pos = 0; |
|
257 TTmDocPosSpec posSpec(pos,static_cast<TTmDocPosSpec::TType>(type)); |
|
258 TBool result = aLayout->GetCursor(posSpec, ECursorVertical, |
|
259 lineInfo, position, width, ascent, descent); |
|
260 test(result); |
|
261 //Test that the LHS is non negative. Because we are allowing bidirectional text the |
|
262 //text shouldnt wrap to next line but instead the cursor can scroll left or right to see the text. |
|
263 test(lineInfo.iInnerRect.iTl.iX >= 0); |
|
264 CleanupStack::PopAndDestroy(buf); |
|
265 } |
|
266 |
|
267 /** INC041367 - Cursor in wrong position when it is one char before the |
|
268 beginning of RTL text. |
|
269 |
|
270 Tests that the cursor is always hanging to the right in a left to right |
|
271 paragraph. This prevents the cursor from being confusingly positioned on top of |
|
272 a little L, for example. |
|
273 */ |
|
274 void INC041367(CTmTextLayout* aLayout, CTestSource* aSource) |
|
275 { |
|
276 _LIT(KLllHahHah, "lll\x62D\x62D\x2029"); |
|
277 |
|
278 HBufC* buf = HBufC::NewLC(KLllHahHah().Length()); |
|
279 *buf = KLllHahHah; |
|
280 aSource->SetText(buf); |
|
281 aSource->iParFormat.iFlags = 0; |
|
282 TTmFormatParam format; |
|
283 format.iStartChar = 0; |
|
284 format.iEndChar = buf->Length(); |
|
285 format.iLineInPar = 0; |
|
286 aLayout->SetTextL(*aSource, format); |
|
287 TTmLineInfo lineInfo; |
|
288 for (TInt pos = 0; pos != 6; ++pos) |
|
289 { |
|
290 for (TInt type = 0; type != 4; ++type) |
|
291 { |
|
292 TPoint position; |
|
293 TInt width; |
|
294 TInt ascent; |
|
295 TInt descent; |
|
296 TTmDocPosSpec posSpec(pos, |
|
297 static_cast<TTmDocPosSpec::TType>(type)); |
|
298 TBool result = aLayout->GetCursor(posSpec, ECursorVertical, |
|
299 lineInfo, position, width, ascent, descent); |
|
300 test(result); |
|
301 test(0 < width); |
|
302 } |
|
303 } |
|
304 CleanupStack::PopAndDestroy(buf); |
|
305 } |
|
306 |
|
307 void RunTestsL() |
|
308 { |
|
309 CTmTextLayout* layout = new(ELeave) CTmTextLayout; |
|
310 CleanupStack::PushL(layout); |
|
311 CTestSource* source = CTestSource::NewLC(); |
|
312 test.Start(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-3610 GetNextVisualCursorPos tests ")); |
|
313 GetNextVisualCursorPosTestsL(layout, source); |
|
314 test.Next(_L("INC041367")); |
|
315 INC041367(layout, source); |
|
316 test.Next(_L("DEF109737")); |
|
317 DEF109737(layout, source); |
|
318 test.End(); |
|
319 CleanupStack::PopAndDestroy(source); |
|
320 CleanupStack::PopAndDestroy(layout); |
|
321 } |
|
322 |
|
323 TInt E32Main() |
|
324 { |
|
325 TrapCleanup = CTrapCleanup::New(); |
|
326 TRAPD(err, RunTestsL()); |
|
327 test(err == KErrNone); |
|
328 test.Close(); |
|
329 delete TrapCleanup; |
|
330 return 0; |
|
331 } |