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