--- /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 <e32test.h>
+
+#include "TGraphicsContext.h"
+#include <gdi.h>
+#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<TTmDocPosSpec::TType>(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<TTmDocPosSpec::TType>(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;
+ }