diff -r 000000000000 -r 1fb32624e06b textrendering/textformatting/test/src/TBidiCursorPos.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textrendering/textformatting/test/src/TBidiCursorPos.cpp Tue Feb 02 02:02:46 2010 +0200 @@ -0,0 +1,331 @@ +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +// Test code for GetNextVisualCursorPos functionality +#include + +#include "TGraphicsContext.h" +#include +#include "TAGMA.H" +#include "TmLayoutImp.h" +#include "TMINTERP.H" + +CTrapCleanup* TrapCleanup; +RTest test(_L("TBidiCursorPos - GetNextVisualCursorPos tests")); + +class CTestSource : public CBase, public MTmSource + { +public: + static CTestSource* NewLC(); + ~CTestSource(); + void ConstructL(); + // from MTmSource + MGraphicsDeviceMap& FormatDevice() const { return *iScreenDevice; } + MGraphicsDeviceMap& InterpretDevice() const { return *iScreenDevice; } + TInt DocumentLength() const + { + return iText->Length(); + } + void GetText(TInt aPos,TPtrC& aText, TTmCharFormat& aFormat) const + { + TTmCharFormat f; + aFormat = f; + aText.Set(iText->Mid(aPos)); + } + void GetParagraphFormatL(TInt, RTmParFormat& aFormat) const + { + aFormat.CopyL(iParFormat); + } + TInt ParagraphStart(TInt) const { return 0; } + + void SetText(HBufC* aText) { iText = aText; } + +private: + CTestSource() {} + +public: + RTmParFormat iParFormat; +private: + CTestGraphicsDevice* iScreenDevice; + CWindowGc* iGc; + HBufC* iText; + }; + +// static +CTestSource* CTestSource::NewLC() + { + CTestSource* self = new(ELeave) CTestSource(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +void CTestSource::ConstructL() + { + TSize size(100, 100); + iScreenDevice = CTestGraphicsDevice::NewL(size, 0); + User::LeaveIfError(iScreenDevice->CreateContext(iGc)); + } + +CTestSource::~CTestSource() + { + delete iScreenDevice; + delete iGc; + } + +#define NO_OF_TEST_CASES 8 + +class TPos + { +public: + TInt iPos; + TBool iLeading; + }; +class TAugmentedPos + { +public: + TInt iPos; + TBool iLeading; + TBool iOptional; + }; + +const TAugmentedPos expectedCursorPos[NO_OF_TEST_CASES][40] = { + { {1, 0, 0}, {2, 0, 0}, {3, 0, 0}, {5, 1, 0}, + {4, 1, 0}, {3, 1, 0}, {7, 0, 0}, {8, 0, 0}, + {9, 0, 0} }, + { {1, 0, 0}, {2, 0, 0}, {10, 1, 0}, {9, 1, 0}, + {8, 1, 0}, {7, 1, 0}, {6, 0, 0}, {7, 0, 0}, + {4, 1, 0}, {3, 1, 0}, {2, 1, 0}, {12, 0, 0}, + {13, 0, 0} }, + { {1, 0, 0}, {2, 0, 0}, {5, 1, 1}, {4, 1, 0}, + {3, 1, 1}, {2, 1, 1}, {7, 0, 0}, {8, 0, 0}, + {9, 0, 0} }, + { {1, 0, 0}, {2, 0, 0}, {3, 0, 0}, {5, 1, 0}, + {4, 1, 0}, {3, 1, 0}, {7, 0, 0}, {8, 0, 0}, + {9, 0, 0}, {11, 1, 0}, {10, 1, 0}, {9, 1, 0}, + {13, 0, 0}, {14, 0, 0}, {15, 0, 0} }, + { {2, 0, 0}, {3, 0, 0}, {4, 0, 0} }, + { {3, 0, 0}, {4, 0, 0} }, + { {1, 0, 0}, {2, 0, 0}, {6, 1, 0}, {5, 1, 0}, + {4, 1, 0}, {3, 1, 0}, {2, 1, 0}, {8, 0, 0}, + {9, 0, 0} }, + { {1, 0, 0}, {2, 0, 0}, {8, 1, 0}, {7, 1, 0}, + {6, 1, 0}, {5, 1, 0}, {4, 1, 0}, {3, 1, 0}, + {2, 1, 0}, {10, 0, 0}, {11, 0, 0} } + }; + +const TPos startPos[NO_OF_TEST_CASES] = { {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} }; + +const TInt numberOfCursorPositionsToCheck[NO_OF_TEST_CASES] = {9, 13, 9, 15, 3, 2, 9, 11}; +const TBool moveToLeft[NO_OF_TEST_CASES] = {EFalse, EFalse, EFalse, ETrue, ETrue, EFalse, ETrue, ETrue}; +const TBool rightToLeftPara[NO_OF_TEST_CASES] = {EFalse, EFalse, EFalse, ETrue, EFalse, EFalse, ETrue, ETrue}; + +void GetNextVisualCursorPosTestsL(CTmTextLayout* aLayout, CTestSource* aSource) + { + // Testcase 1 + _LIT(KBidi1, "abc\x644\x644\x644zzz\x2029"); + + // Testcase 2 (0x32 and 0x39 changed to 0x6F2 and 0x0F9, see note below) + _LIT(KBidi2, "ab\x644\x644\x644\x6F2\x6F9\x644\x644\x644\x644zy\x2029"); + + // Testcase 3 + _LIT(KBidi3, "ab\x202ejk\x202cjkl\x2029"); + + // Testcase 4 + _LIT(KBidi4, "\x644\x644\x644xyz\x644\x644\x644xyz\x644\x644\x644\x2029"); + + // Testcase 5 + _LIT(KBidi5, "\x647\x64b\x647\x647\x2029"); + + // Testcase 6 + _LIT(KBidi6, "a\x302\x317z\x2029"); + + // Testcase 7 (0x31 and 0x32 changed to 0x6F1 and 0x0F2, see note below) + _LIT(KBidi7, "\x644\x644\x6F1\x6F2\x2e\x33\x34\x644\x644\x2029"); + + // Testcase 8 (0x31 - 0x35 changed to 0x6F1 - 0x0F5, see note below) + _LIT(KBidi8, "\x644\x644\x6F1\x2c\x6F2\x6F3\x2e\x6F4\x6F5\x644\x644\x2029"); + +// Note: Test cases 2 and 7 have been changed to use \x6F0-\x6F9, Extended Arabic Digits, +// These have the bidirectional class "EN",the same as ASCII digits. +// These have been used in preference to ASCII digits +// to work around a CodeWarrior preprocessor/C-Cover problem. +// For more detils see DEF042186 + + HBufC* logicalText[NO_OF_TEST_CASES]; + logicalText[0] = KBidi1().AllocLC(); + logicalText[1] = KBidi2().AllocLC(); + logicalText[2] = KBidi3().AllocLC(); + logicalText[3] = KBidi4().AllocLC(); + logicalText[4] = KBidi5().AllocLC(); + logicalText[5] = KBidi6().AllocLC(); + logicalText[6] = KBidi7().AllocLC(); + logicalText[7] = KBidi8().AllocLC(); + + TTmFormatParam format; + format.iStartChar = 0; + format.iEndChar = 0; + format.iLineInPar = 0; + + TTmDocPos pos(0, ETrue); + TTmPosInfo2 info; + int charIndex; + TBuf<40> msg; + + for (TInt ii = 0; ii < NO_OF_TEST_CASES; ii++) + { + msg.Format(_L("GetNextVisualCursorPos test case %d\n"), ii + 1); + test.Next(msg); + aSource->SetText(logicalText[ii]); + format.iEndChar = logicalText[ii]->Length(); + if (rightToLeftPara[ii]) + aSource->iParFormat.iFlags |= RTmParFormat::ERightToLeft; + aLayout->SetTextL(*aSource, format); + + charIndex = 0; + pos.iPos = startPos[ii].iPos; + pos.iLeadingEdge = startPos[ii].iLeading; + while (aLayout->GetNextVisualCursorPos(pos, info, moveToLeft[ii])) + { + while (info.iDocPos.iPos != expectedCursorPos[ii][charIndex].iPos + || info.iDocPos.iLeadingEdge != expectedCursorPos[ii][charIndex].iLeading) + { + test(expectedCursorPos[ii][charIndex].iOptional); + ++charIndex; + test(charIndex != numberOfCursorPositionsToCheck[ii]); + } + pos = info.iDocPos; + ++charIndex; + test(charIndex <= numberOfCursorPositionsToCheck[ii]); + } + test(charIndex == numberOfCursorPositionsToCheck[ii]); + aSource->iParFormat.iFlags &= ~(RTmParFormat::ERightToLeft); // reset back to default of LeftToRight + } + + CleanupStack::PopAndDestroy(NO_OF_TEST_CASES); // cleanup all HBufC* stored in logicalText array + } + +/** +@SYMTestCaseID SYSLIB-FORM-UT-3610 +@SYMTestCaseDesc Testing behaviour of r2l text when wrapping occurs and bidirectional text allowed +@SYMTestPriority High +@SYMTestActions 1. Have some arabic text + 2. Set wrap width to 10 chars + 3. Set alignment to NormalBidirectional + 4. Call CTmTextLayout::SetTextL + 5. Retrieve the cursor position + 6. Check the lineinfo to ensure that the innerRect TL.iX parameter is positive. +@SYMTestExpectedResults The innerRect that holds text top left x position is positive. +@SYMDEF DEF109737,PDEF110819,PDEF110820,PDEF110821 +*/ +void DEF109737(CTmTextLayout* aLayout, CTestSource* aSource) + { + //R2L paragraph wrapping + _LIT(KLllHahHah1, "lll\x62D\x62D\x2029\x62D\x62D\x2029"); + HBufC* buf = HBufC::NewLC(KLllHahHah1().Length()); + *buf = KLllHahHah1; + aSource->SetText(buf); + aSource->iParFormat.iFlags = 1; + aSource->iParFormat.iAlignment = RTmParFormat::EAlignNormalBidirectional; + TTmFormatParam format; + format.iStartChar = 0; + format.iEndChar = buf->Length(); + format.iLineInPar = 0; + format.iWrapWidth = 10; + aLayout->SetTextL(*aSource, format); + TTmLineInfo lineInfo; + TPoint position; + TInt width; + TInt ascent; + TInt descent; + TInt type = 0; + TInt pos = 0; + TTmDocPosSpec posSpec(pos,static_cast(type)); + TBool result = aLayout->GetCursor(posSpec, ECursorVertical, + lineInfo, position, width, ascent, descent); + test(result); + //Test that the LHS is non negative. Because we are allowing bidirectional text the + //text shouldnt wrap to next line but instead the cursor can scroll left or right to see the text. + test(lineInfo.iInnerRect.iTl.iX >= 0); + CleanupStack::PopAndDestroy(buf); + } + +/** INC041367 - Cursor in wrong position when it is one char before the +beginning of RTL text. + +Tests that the cursor is always hanging to the right in a left to right +paragraph. This prevents the cursor from being confusingly positioned on top of +a little L, for example. +*/ +void INC041367(CTmTextLayout* aLayout, CTestSource* aSource) + { + _LIT(KLllHahHah, "lll\x62D\x62D\x2029"); + + HBufC* buf = HBufC::NewLC(KLllHahHah().Length()); + *buf = KLllHahHah; + aSource->SetText(buf); + aSource->iParFormat.iFlags = 0; + TTmFormatParam format; + format.iStartChar = 0; + format.iEndChar = buf->Length(); + format.iLineInPar = 0; + aLayout->SetTextL(*aSource, format); + TTmLineInfo lineInfo; + for (TInt pos = 0; pos != 6; ++pos) + { + for (TInt type = 0; type != 4; ++type) + { + TPoint position; + TInt width; + TInt ascent; + TInt descent; + TTmDocPosSpec posSpec(pos, + static_cast(type)); + TBool result = aLayout->GetCursor(posSpec, ECursorVertical, + lineInfo, position, width, ascent, descent); + test(result); + test(0 < width); + } + } + CleanupStack::PopAndDestroy(buf); + } + +void RunTestsL() + { + CTmTextLayout* layout = new(ELeave) CTmTextLayout; + CleanupStack::PushL(layout); + CTestSource* source = CTestSource::NewLC(); + test.Start(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-3610 GetNextVisualCursorPos tests ")); + GetNextVisualCursorPosTestsL(layout, source); + test.Next(_L("INC041367")); + INC041367(layout, source); + test.Next(_L("DEF109737")); + DEF109737(layout, source); + test.End(); + CleanupStack::PopAndDestroy(source); + CleanupStack::PopAndDestroy(layout); + } + +TInt E32Main() + { + TrapCleanup = CTrapCleanup::New(); + TRAPD(err, RunTestsL()); + test(err == KErrNone); + test.Close(); + delete TrapCleanup; + return 0; + }