textrendering/textformatting/test/src/TBidiCursorPos.cpp
changeset 0 1fb32624e06b
child 16 748ec5531811
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     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 	}