1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/textrendering/textformatting/test/src/TBidiCursorPos.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,334 @@
1.4 +/*
1.5 +* Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +// Test code for GetNextVisualCursorPos functionality
1.22 +#include <e32test.h>
1.23 +
1.24 +#include "TGraphicsContext.h"
1.25 +#include <gdi.h>
1.26 +#include "TAGMA.H"
1.27 +#include "TmLayoutImp.h"
1.28 +#include "TMINTERP.H"
1.29 +#include "tbidicursorpos.h"
1.30 +
1.31 +namespace LocalToTBidiCursorPos
1.32 +{
1.33 +CTBidiCursorPosStep* TestStep;
1.34 +#define TESTPOINT(p) TestStep->testpoint(p,(TText8*)__FILE__,__LINE__)
1.35 +#define TESTPRINT(p) TestStep->print(p,(TText8*)__FILE__,__LINE__)
1.36 +
1.37 +}
1.38 +
1.39 +using namespace LocalToTBidiCursorPos;
1.40 +
1.41 +class CTestSource : public CBase, public MTmSource
1.42 + {
1.43 +public:
1.44 + static CTestSource* NewLC();
1.45 + ~CTestSource();
1.46 + void ConstructL();
1.47 + // from MTmSource
1.48 + MGraphicsDeviceMap& FormatDevice() const { return *iScreenDevice; }
1.49 + MGraphicsDeviceMap& InterpretDevice() const { return *iScreenDevice; }
1.50 + TInt DocumentLength() const
1.51 + {
1.52 + return iText->Length();
1.53 + }
1.54 + void GetText(TInt aPos,TPtrC& aText, TTmCharFormat& aFormat) const
1.55 + {
1.56 + TTmCharFormat f;
1.57 + aFormat = f;
1.58 + aText.Set(iText->Mid(aPos));
1.59 + }
1.60 + void GetParagraphFormatL(TInt, RTmParFormat& aFormat) const
1.61 + {
1.62 + aFormat.CopyL(iParFormat);
1.63 + }
1.64 + TInt ParagraphStart(TInt) const { return 0; }
1.65 +
1.66 + void SetText(HBufC* aText) { iText = aText; }
1.67 +
1.68 +private:
1.69 + CTestSource() {}
1.70 +
1.71 +public:
1.72 + RTmParFormat iParFormat;
1.73 +private:
1.74 + CTestGraphicsDevice* iScreenDevice;
1.75 + CWindowGc* iGc;
1.76 + HBufC* iText;
1.77 + };
1.78 +
1.79 +// static
1.80 +CTestSource* CTestSource::NewLC()
1.81 + {
1.82 + CTestSource* self = new(ELeave) CTestSource();
1.83 + CleanupStack::PushL(self);
1.84 + self->ConstructL();
1.85 + return self;
1.86 + }
1.87 +
1.88 +void CTestSource::ConstructL()
1.89 + {
1.90 + TSize size(100, 100);
1.91 + iScreenDevice = CTestGraphicsDevice::NewL(size, 0);
1.92 + User::LeaveIfError(iScreenDevice->CreateContext(iGc));
1.93 + }
1.94 +
1.95 +CTestSource::~CTestSource()
1.96 + {
1.97 + delete iScreenDevice;
1.98 + delete iGc;
1.99 + }
1.100 +
1.101 +#define NO_OF_TEST_CASES 8
1.102 +
1.103 +class TPos
1.104 + {
1.105 +public:
1.106 + TInt iPos;
1.107 + TBool iLeading;
1.108 + };
1.109 +class TAugmentedPos
1.110 + {
1.111 +public:
1.112 + TInt iPos;
1.113 + TBool iLeading;
1.114 + TBool iOptional;
1.115 + };
1.116 +
1.117 +const TAugmentedPos expectedCursorPos[NO_OF_TEST_CASES][40] = {
1.118 + { {1, 0, 0}, {2, 0, 0}, {3, 0, 0}, {5, 1, 0},
1.119 + {4, 1, 0}, {3, 1, 0}, {7, 0, 0}, {8, 0, 0},
1.120 + {9, 0, 0} },
1.121 + { {1, 0, 0}, {2, 0, 0}, {10, 1, 0}, {9, 1, 0},
1.122 + {8, 1, 0}, {7, 1, 0}, {6, 0, 0}, {7, 0, 0},
1.123 + {4, 1, 0}, {3, 1, 0}, {2, 1, 0}, {12, 0, 0},
1.124 + {13, 0, 0} },
1.125 + { {1, 0, 0}, {2, 0, 0}, {5, 1, 1}, {4, 1, 0},
1.126 + {3, 1, 1}, {2, 1, 1}, {7, 0, 0}, {8, 0, 0},
1.127 + {9, 0, 0} },
1.128 + { {1, 0, 0}, {2, 0, 0}, {3, 0, 0}, {5, 1, 0},
1.129 + {4, 1, 0}, {3, 1, 0}, {7, 0, 0}, {8, 0, 0},
1.130 + {9, 0, 0}, {11, 1, 0}, {10, 1, 0}, {9, 1, 0},
1.131 + {13, 0, 0}, {14, 0, 0}, {15, 0, 0} },
1.132 + { {2, 0, 0}, {3, 0, 0}, {4, 0, 0} },
1.133 + { {3, 0, 0}, {4, 0, 0} },
1.134 + { {1, 0, 0}, {2, 0, 0}, {6, 1, 0}, {5, 1, 0},
1.135 + {4, 1, 0}, {3, 1, 0}, {2, 1, 0}, {8, 0, 0},
1.136 + {9, 0, 0} },
1.137 + { {1, 0, 0}, {2, 0, 0}, {8, 1, 0}, {7, 1, 0},
1.138 + {6, 1, 0}, {5, 1, 0}, {4, 1, 0}, {3, 1, 0},
1.139 + {2, 1, 0}, {10, 0, 0}, {11, 0, 0} }
1.140 + };
1.141 +
1.142 +const TPos startPos[NO_OF_TEST_CASES] = { {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} };
1.143 +
1.144 +const TInt numberOfCursorPositionsToCheck[NO_OF_TEST_CASES] = {9, 13, 9, 15, 3, 2, 9, 11};
1.145 +const TBool moveToLeft[NO_OF_TEST_CASES] = {EFalse, EFalse, EFalse, ETrue, ETrue, EFalse, ETrue, ETrue};
1.146 +const TBool rightToLeftPara[NO_OF_TEST_CASES] = {EFalse, EFalse, EFalse, ETrue, EFalse, EFalse, ETrue, ETrue};
1.147 +
1.148 +void GetNextVisualCursorPosTestsL(CTmTextLayout* aLayout, CTestSource* aSource)
1.149 + {
1.150 + // Testcase 1
1.151 + _LIT(KBidi1, "abc\x644\x644\x644zzz\x2029");
1.152 +
1.153 + // Testcase 2 (0x32 and 0x39 changed to 0x6F2 and 0x0F9, see note below)
1.154 + _LIT(KBidi2, "ab\x644\x644\x644\x6F2\x6F9\x644\x644\x644\x644zy\x2029");
1.155 +
1.156 + // Testcase 3
1.157 + _LIT(KBidi3, "ab\x202ejk\x202cjkl\x2029");
1.158 +
1.159 + // Testcase 4
1.160 + _LIT(KBidi4, "\x644\x644\x644xyz\x644\x644\x644xyz\x644\x644\x644\x2029");
1.161 +
1.162 + // Testcase 5
1.163 + _LIT(KBidi5, "\x647\x64b\x647\x647\x2029");
1.164 +
1.165 + // Testcase 6
1.166 + _LIT(KBidi6, "a\x302\x317z\x2029");
1.167 +
1.168 + // Testcase 7 (0x31 and 0x32 changed to 0x6F1 and 0x0F2, see note below)
1.169 + _LIT(KBidi7, "\x644\x644\x6F1\x6F2\x2e\x33\x34\x644\x644\x2029");
1.170 +
1.171 + // Testcase 8 (0x31 - 0x35 changed to 0x6F1 - 0x0F5, see note below)
1.172 + _LIT(KBidi8, "\x644\x644\x6F1\x2c\x6F2\x6F3\x2e\x6F4\x6F5\x644\x644\x2029");
1.173 +
1.174 +// Note: Test cases 2 and 7 have been changed to use \x6F0-\x6F9, Extended Arabic Digits,
1.175 +// These have the bidirectional class "EN",the same as ASCII digits.
1.176 +// These have been used in preference to ASCII digits
1.177 +// to work around a CodeWarrior preprocessor/C-Cover problem.
1.178 +// For more detils see DEF042186
1.179 +
1.180 + HBufC* logicalText[NO_OF_TEST_CASES];
1.181 + logicalText[0] = KBidi1().AllocLC();
1.182 + logicalText[1] = KBidi2().AllocLC();
1.183 + logicalText[2] = KBidi3().AllocLC();
1.184 + logicalText[3] = KBidi4().AllocLC();
1.185 + logicalText[4] = KBidi5().AllocLC();
1.186 + logicalText[5] = KBidi6().AllocLC();
1.187 + logicalText[6] = KBidi7().AllocLC();
1.188 + logicalText[7] = KBidi8().AllocLC();
1.189 +
1.190 + TTmFormatParam format;
1.191 + format.iStartChar = 0;
1.192 + format.iEndChar = 0;
1.193 + format.iLineInPar = 0;
1.194 +
1.195 + TTmDocPos pos(0, ETrue);
1.196 + TTmPosInfo2 info;
1.197 + int charIndex;
1.198 + TBuf<40> msg;
1.199 +
1.200 + for (TInt ii = 0; ii < NO_OF_TEST_CASES; ii++)
1.201 + {
1.202 + msg.Format(_L("GetNextVisualCursorPos test case %d\n"), ii + 1);
1.203 + TESTPRINT(msg);
1.204 + aSource->SetText(logicalText[ii]);
1.205 + format.iEndChar = logicalText[ii]->Length();
1.206 + if (rightToLeftPara[ii])
1.207 + aSource->iParFormat.iFlags |= RTmParFormat::ERightToLeft;
1.208 + aLayout->SetTextL(*aSource, format);
1.209 +
1.210 + charIndex = 0;
1.211 + pos.iPos = startPos[ii].iPos;
1.212 + pos.iLeadingEdge = startPos[ii].iLeading;
1.213 + while (aLayout->GetNextVisualCursorPos(pos, info, moveToLeft[ii]))
1.214 + {
1.215 + while (info.iDocPos.iPos != expectedCursorPos[ii][charIndex].iPos
1.216 + || info.iDocPos.iLeadingEdge != expectedCursorPos[ii][charIndex].iLeading)
1.217 + {
1.218 + TESTPOINT(expectedCursorPos[ii][charIndex].iOptional);
1.219 + ++charIndex;
1.220 + TESTPOINT(charIndex != numberOfCursorPositionsToCheck[ii]);
1.221 + }
1.222 + pos = info.iDocPos;
1.223 + ++charIndex;
1.224 + TESTPOINT(charIndex <= numberOfCursorPositionsToCheck[ii]);
1.225 + }
1.226 + TESTPOINT(charIndex == numberOfCursorPositionsToCheck[ii]);
1.227 + aSource->iParFormat.iFlags &= ~(RTmParFormat::ERightToLeft); // reset back to default of LeftToRight
1.228 + }
1.229 +
1.230 + CleanupStack::PopAndDestroy(NO_OF_TEST_CASES); // cleanup all HBufC* stored in logicalText array
1.231 + }
1.232 +
1.233 +/**
1.234 +@SYMTestCaseID SYSLIB-FORM-UT-3610
1.235 +@SYMTestCaseDesc Testing behaviour of r2l text when wrapping occurs and bidirectional text allowed
1.236 +@SYMTestPriority High
1.237 +@SYMTestActions 1. Have some arabic text
1.238 + 2. Set wrap width to 10 chars
1.239 + 3. Set alignment to NormalBidirectional
1.240 + 4. Call CTmTextLayout::SetTextL
1.241 + 5. Retrieve the cursor position
1.242 + 6. Check the lineinfo to ensure that the innerRect TL.iX parameter is positive.
1.243 +@SYMTestExpectedResults The innerRect that holds text top left x position is positive.
1.244 +@SYMDEF DEF109737,PDEF110819,PDEF110820,PDEF110821
1.245 +*/
1.246 +void DEF109737(CTmTextLayout* aLayout, CTestSource* aSource)
1.247 + {
1.248 + //R2L paragraph wrapping
1.249 + _LIT(KLllHahHah1, "lll\x62D\x62D\x2029\x62D\x62D\x2029");
1.250 + HBufC* buf = HBufC::NewLC(KLllHahHah1().Length());
1.251 + *buf = KLllHahHah1;
1.252 + aSource->SetText(buf);
1.253 + aSource->iParFormat.iFlags = 1;
1.254 + aSource->iParFormat.iAlignment = RTmParFormat::EAlignNormalBidirectional;
1.255 + TTmFormatParam format;
1.256 + format.iStartChar = 0;
1.257 + format.iEndChar = buf->Length();
1.258 + format.iLineInPar = 0;
1.259 + format.iWrapWidth = 10;
1.260 + aLayout->SetTextL(*aSource, format);
1.261 + TTmLineInfo lineInfo;
1.262 + TPoint position;
1.263 + TInt width;
1.264 + TInt ascent;
1.265 + TInt descent;
1.266 + TInt type = 0;
1.267 + TInt pos = 0;
1.268 + TTmDocPosSpec posSpec(pos,static_cast<TTmDocPosSpec::TType>(type));
1.269 + TBool result = aLayout->GetCursor(posSpec, ECursorVertical,
1.270 + lineInfo, position, width, ascent, descent);
1.271 + TESTPOINT(result);
1.272 + //Test that the LHS is non negative. Because we are allowing bidirectional text the
1.273 + //text shouldnt wrap to next line but instead the cursor can scroll left or right to see the text.
1.274 + TESTPOINT(lineInfo.iInnerRect.iTl.iX >= 0);
1.275 + CleanupStack::PopAndDestroy(buf);
1.276 + }
1.277 +
1.278 +/** INC041367 - Cursor in wrong position when it is one char before the
1.279 +beginning of RTL text.
1.280 +
1.281 +Tests that the cursor is always hanging to the right in a left to right
1.282 +paragraph. This prevents the cursor from being confusingly positioned on top of
1.283 +a little L, for example.
1.284 +*/
1.285 +void INC041367(CTmTextLayout* aLayout, CTestSource* aSource)
1.286 + {
1.287 + _LIT(KLllHahHah, "lll\x62D\x62D\x2029");
1.288 +
1.289 + HBufC* buf = HBufC::NewLC(KLllHahHah().Length());
1.290 + *buf = KLllHahHah;
1.291 + aSource->SetText(buf);
1.292 + aSource->iParFormat.iFlags = 0;
1.293 + TTmFormatParam format;
1.294 + format.iStartChar = 0;
1.295 + format.iEndChar = buf->Length();
1.296 + format.iLineInPar = 0;
1.297 + aLayout->SetTextL(*aSource, format);
1.298 + TTmLineInfo lineInfo;
1.299 + for (TInt pos = 0; pos != 6; ++pos)
1.300 + {
1.301 + for (TInt type = 0; type != 4; ++type)
1.302 + {
1.303 + TPoint position;
1.304 + TInt width;
1.305 + TInt ascent;
1.306 + TInt descent;
1.307 + TTmDocPosSpec posSpec(pos,
1.308 + static_cast<TTmDocPosSpec::TType>(type));
1.309 + TBool result = aLayout->GetCursor(posSpec, ECursorVertical,
1.310 + lineInfo, position, width, ascent, descent);
1.311 + TESTPOINT(result);
1.312 + TESTPOINT(0 < width);
1.313 + }
1.314 + }
1.315 + CleanupStack::PopAndDestroy(buf);
1.316 + }
1.317 +
1.318 +TVerdict CTBidiCursorPosStep::doTestStepL()
1.319 + {
1.320 + SetTestStepResult(EPass);
1.321 + TestStep = this;
1.322 + TESTPRINT(_L("TBidiCursorPos - GetNextVisualCursorPos tests"));
1.323 + CTmTextLayout* layout = new(ELeave) CTmTextLayout;
1.324 + CleanupStack::PushL(layout);
1.325 + CTestSource* source = CTestSource::NewLC();
1.326 + TESTPRINT(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-3610 GetNextVisualCursorPos tests "));
1.327 + GetNextVisualCursorPosTestsL(layout, source);
1.328 + TESTPRINT(_L("INC041367"));
1.329 + INC041367(layout, source);
1.330 + TESTPRINT(_L("DEF109737"));
1.331 + DEF109737(layout, source);
1.332 +
1.333 + CleanupStack::PopAndDestroy(source);
1.334 + CleanupStack::PopAndDestroy(layout);
1.335 + return TestStepResult();
1.336 + }
1.337 +