sl@0: /* sl@0: * Copyright (c) 2003-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: * TInterpreter.cpp unit tests for RTmBoundingRectInterpreter sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include "TestPicture.h" sl@0: #include "TestLayout.h" sl@0: #include "TGraphicsContext.h" sl@0: #include "TMINTERP.H" sl@0: #include "tinterpreter.h" sl@0: #include sl@0: #include sl@0: sl@0: sl@0: namespace LocalToTInterpreter sl@0: { sl@0: _LIT(KLeftToRight1, "abc \x5D0 def abc \x5D0\x5D1\x5D2 \x5D0\x5D1\x5D2 xyz abc a\tb\tc\td\te."); sl@0: _LIT(KLeftToRight2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); sl@0: _LIT(KContingentBreak, "\xFFFC"); sl@0: sl@0: CTInterpreterStep* TestStep = NULL; 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: using namespace LocalToTInterpreter; sl@0: sl@0: sl@0: /** sl@0: Checks if one region is a subset of another. sl@0: @param aRegion sl@0: The potential superset. sl@0: @param aPotentialSubset sl@0: The potential subset. sl@0: @return sl@0: ETrue if and only if aPotentialSubset is contained within aRegion. sl@0: @internalComponent sl@0: */ sl@0: TBool IsSubsetL(const TRegion& aRegion, const TRegion& aPotentialSubset) sl@0: { sl@0: RRegion sub; sl@0: sub.Copy(aPotentialSubset); sl@0: sub.SubRegion(aRegion); sl@0: if (sub.CheckError()) sl@0: User::Leave(KErrNoMemory); sl@0: return sub.IsEmpty(); sl@0: } sl@0: sl@0: /** sl@0: Checks if two regions are equal. sl@0: @param aA First region. sl@0: @param aB Second region. sl@0: @return sl@0: ETrue if the regions are equal, false otherwise. sl@0: @internalComponent sl@0: */ sl@0: TBool RegionsEqualL(const TRegion& aA, const TRegion& aB) sl@0: { sl@0: return IsSubsetL(aA, aB) && IsSubsetL(aB, aA); sl@0: } sl@0: sl@0: /** sl@0: Gets the region corresponding to the selection. Builds it up by adding sl@0: selections together. The selections are at (n * aStartStep, aEnd + n * sl@0: aEndStep) for n <- {0, 1, 2...}. The iteration ends when either the start would sl@0: be beyond the length of the document or when the start is at 0 and the end is sl@0: beyond the length of the document. sl@0: @param aRegion Returns the region. sl@0: @param aLayout The layout to get the selection of. sl@0: @param aStartStep How different the starts of successive selections are. sl@0: @param aEnd The end of the first selection. sl@0: @param aEndStep How different the ends of the successive selections are. sl@0: sl@0: @internalComponent sl@0: */ sl@0: void GetSelectionL(TRegion& aRegion, CTestTmTextLayout& aLayout, sl@0: TInt aStartStep, TInt aEnd, TInt aEndStep) sl@0: { sl@0: aRegion.Clear(); sl@0: TRect rect; sl@0: TInt documentLength = aLayout.Source().DocumentLength(); sl@0: TInt start = 0; sl@0: while (start < documentLength && !(documentLength < aEnd && start == 0)) sl@0: { sl@0: TTmInterpreterParam param(aLayout.Layout()); sl@0: RTmBoundingRectInterpreter interp(aLayout.Source(), param); sl@0: if (interp.FirstRect(start, aEnd, rect)) sl@0: { sl@0: aRegion.AddRect(rect); sl@0: while (interp.NextRect(rect)) sl@0: aRegion.AddRect(rect); sl@0: } sl@0: start += aStartStep; sl@0: aEnd += aEndStep; sl@0: interp.Close(); sl@0: } sl@0: if (aRegion.CheckError()) sl@0: User::Leave(KErrNoMemory); sl@0: } sl@0: sl@0: /** sl@0: Tests RTmBoundingRectInterpreter for a particular piece of text. sl@0: @internalComponent sl@0: */ sl@0: void TestTextL(CTestTmTextLayout& aLayout) sl@0: { sl@0: RRegion region1; sl@0: RRegion region2; sl@0: RRegion region3; sl@0: CleanupClosePushL(region1); sl@0: CleanupClosePushL(region2); sl@0: CleanupClosePushL(region3); sl@0: sl@0: GetSelectionL(region1, aLayout, 1, 1, 1); sl@0: GetSelectionL(region2, aLayout, 0, 1, 1); sl@0: GetSelectionL(region3, aLayout, 0, aLayout.Source().DocumentLength(), 1); sl@0: sl@0: TESTPOINT(RegionsEqualL(region1, region2)); sl@0: TESTPOINT(RegionsEqualL(region1, region3)); sl@0: sl@0: CleanupStack::PopAndDestroy(®ion3); sl@0: CleanupStack::PopAndDestroy(®ion2); sl@0: CleanupStack::PopAndDestroy(®ion1); sl@0: } sl@0: sl@0: sl@0: void TestsL() sl@0: { sl@0: CParaFormatLayer* paraLayer = CParaFormatLayer::NewL(); sl@0: CleanupStack::PushL(paraLayer); sl@0: CCharFormatLayer* charLayer = CCharFormatLayer::NewL(); sl@0: CleanupStack::PushL(charLayer); sl@0: CRichText* richText = CRichText::NewL(paraLayer, charLayer); sl@0: CleanupStack::PushL(richText); sl@0: sl@0: TESTPRINT(_L("RTmBoundingRectInterpreter consistency of coverage")); sl@0: richText->Reset(); sl@0: richText->InsertL(0, KLeftToRight1); sl@0: CTestTmTextLayout* text1 = CTestTmTextLayout::NewLC(*richText, 100); sl@0: TSize pictureSize(15, 15); sl@0: CTestPicture* picture = new (ELeave) CTestPicture; sl@0: picture->SetSizeInPixels( pictureSize, text1->Device() ); sl@0: TPictureHeader pictureHeader; sl@0: pictureHeader.iPicture = picture; sl@0: pictureHeader.iSize = pictureSize; sl@0: richText->InsertL(19, pictureHeader); sl@0: TTmReformatParam param; sl@0: param.iStartChar = 19; sl@0: param.iOldLength = 0; sl@0: param.iNewLength = 1; sl@0: param.iMaxExtraLines = KMaxTInt; sl@0: param.iParFormatChanged = ETrue; sl@0: param.iParInvalid = EFalse; sl@0: TTmReformatResult out; sl@0: text1->FormatL(param, out); sl@0: TestTextL(*text1); sl@0: sl@0: //Test for finding text chunks adjoining a given document position sl@0: text1->TestAdjacentChunks(); sl@0: sl@0: CleanupStack::PopAndDestroy(text1); sl@0: CleanupStack::PopAndDestroy(richText); sl@0: CleanupStack::PopAndDestroy(charLayer); sl@0: CleanupStack::PopAndDestroy(paraLayer); sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-FORM-UT-1591 sl@0: @SYMTestCaseDesc Tests to make sure when contingent line breaks, "\xFFFC", are inserted into richtext sl@0: (with and without a picture attached) and FormatL is called it does not lead to a sl@0: panic in 'IsLegalBreakBeforeL' or 'IsLegalBreakAfterL'. sl@0: @SYMTestPriority High sl@0: @SYMTestActions Insert some richtext, then insert a TPictureHeader into the text (which inserts a sl@0: contingent line break), then call FormatL. Then insert just a contingent line break, sl@0: with no TPictureHeader associated with it and call FormatL (for IsLegalBreakAfterL). sl@0: Then repeat the process, but making sure the text is scanned in the opposite sl@0: direction, so IsLegalBreakBeforeL is called. sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMDEF DEF077884 sl@0: */ sl@0: sl@0: void Def077884L() sl@0: { sl@0: TInt testStartLength = 52; sl@0: TInt testEndLength = 56; sl@0: sl@0: CParaFormatLayer* paraLayer = CParaFormatLayer::NewL(); sl@0: CleanupStack::PushL(paraLayer); sl@0: CCharFormatLayer* charLayer = CCharFormatLayer::NewL(); sl@0: CleanupStack::PushL(charLayer); sl@0: CRichText* richText = CRichText::NewL(paraLayer, charLayer); sl@0: CleanupStack::PushL(richText); sl@0: sl@0: TESTPRINT(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-1591 DEF077884: TSourcePictureBreaker crashes when picture not found. ")); sl@0: sl@0: sl@0: richText->Reset(); sl@0: sl@0: richText->InsertL(0, KLeftToRight2); sl@0: sl@0: TESTPOINT(testStartLength == richText->DocumentLength()); sl@0: sl@0: CTestTmTextLayout* text1 = CTestTmTextLayout::NewLC(*richText, 100); sl@0: sl@0: TTmReformatResult out; sl@0: TTmReformatParam param; sl@0: param.iStartChar = 0; sl@0: param.iOldLength = 0; sl@0: param.iNewLength = 1; sl@0: param.iMaxExtraLines = KMaxTInt; sl@0: param.iParFormatChanged = ETrue; sl@0: param.iParInvalid = EFalse; sl@0: sl@0: richText->InsertL(14, KContingentBreak); // Insert a contingent linebreak with no picture sl@0: sl@0: text1->FormatL(param, out); // Scans the text from right to left. sl@0: sl@0: sl@0: TSize pictureSize(100, 100); sl@0: CTestPicture* picture = new (ELeave) CTestPicture; sl@0: picture->SetSizeInPixels(pictureSize, text1->Device()); sl@0: sl@0: TPictureHeader pictureHeader; sl@0: pictureHeader.iPicture = picture; sl@0: pictureHeader.iSize = pictureSize; sl@0: sl@0: richText->InsertL(15, pictureHeader); // Insert a contingent linebreak with picture sl@0: sl@0: param.iOldLength = 1; sl@0: param.iNewLength = 2; sl@0: sl@0: text1->FormatL(param, out); // Scans the text from right to left. sl@0: sl@0: sl@0: TTmFormatParam formatParam; sl@0: formatParam.iFlags = 0; sl@0: // iFlags now need to be set to make sure the text is scanned in the opposite direction when sl@0: // FormatL is called. sl@0: formatParam.iFlags = formatParam.iFlags | TTmFormatParamBase::ELegalLineBreaksOnly; sl@0: formatParam.iFlags = formatParam.iFlags | TTmFormatParamBase::EWrap; sl@0: formatParam.iWrapWidth = 12; sl@0: formatParam.iMaxHeight = 100; sl@0: formatParam.iMaxLines = 10; sl@0: formatParam.iEllipsis = 0xFFFF; sl@0: formatParam.iStartChar = 0; sl@0: formatParam.iEndChar = 50; sl@0: formatParam.iLineInPar = 0; sl@0: sl@0: param.iOldLength = 2; sl@0: param.iNewLength = 3; sl@0: sl@0: CTmTextLayout* text2 = new (ELeave) CTmTextLayout; sl@0: sl@0: text2->SetTextL(text1->Source(),formatParam); sl@0: sl@0: richText->InsertL(28, KContingentBreak); // Insert a contingent linebreak with no picture sl@0: sl@0: text2->FormatL(formatParam, param, out); // Scans the text from left to right. sl@0: sl@0: sl@0: CTestPicture* picture2 = new (ELeave) CTestPicture; sl@0: picture2->SetSizeInPixels( pictureSize, text1->Device() ); sl@0: sl@0: TPictureHeader pictureHeader2; sl@0: pictureHeader2.iPicture = picture2; sl@0: pictureHeader2.iSize = pictureSize; sl@0: sl@0: richText->InsertL(34, pictureHeader2); // Insert a contingent linebreak with picture sl@0: sl@0: param.iOldLength = 3; sl@0: param.iNewLength = 4; sl@0: sl@0: text2->FormatL(formatParam, param, out); // Scans the text from left to right. sl@0: sl@0: sl@0: TestTextL(*text1); sl@0: sl@0: TESTPOINT(testEndLength == richText->DocumentLength()); sl@0: sl@0: CleanupStack::PopAndDestroy(text1); sl@0: CleanupStack::PopAndDestroy(richText); sl@0: CleanupStack::PopAndDestroy(charLayer); sl@0: CleanupStack::PopAndDestroy(paraLayer); sl@0: } sl@0: sl@0: /** sl@0: Tests RTmBoundingRectInterpreter. sl@0: @internalComponent sl@0: */ sl@0: TVerdict CTInterpreterStep::doTestStepL() sl@0: { sl@0: SetTestStepResult(EPass); sl@0: TestStep = this; sl@0: TESTPRINT(_L("TInterpreter unit")); sl@0: TESTPRINT(_L("Start TInterpreter.exe Tests")); sl@0: TestsL(); sl@0: Def077884L(); sl@0: return TestStepResult(); sl@0: } sl@0: sl@0: