os/textandloc/textrendering/textformatting/test/src/tformhindi.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/textandloc/textrendering/textformatting/test/src/tformhindi.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,388 @@
     1.4 +/*
     1.5 +* Copyright (c) 2005-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 +* @file
    1.19 +* @internalComponent 
    1.20 +*
    1.21 +*/
    1.22 +
    1.23 +
    1.24 +#include <e32std.h>
    1.25 +#include <e32test.h>
    1.26 +#include <frmtlay.h>
    1.27 +#include <frmtview.h>
    1.28 +#include <txtlaydc.h>
    1.29 +#include <fbs.h>
    1.30 +#include <w32std.h>
    1.31 +#include <bitdev.h>
    1.32 +#include <txtrich.h>
    1.33 +#include "tformhindi.h"
    1.34 +
    1.35 +namespace LocalToTFormHindi {
    1.36 +
    1.37 +_LIT(KTformhindi, "tformhindi");
    1.38 +const TInt KDisplayWidth = 100;
    1.39 +const TInt KDisplayHeight = 100;
    1.40 +_LIT(KDevanagariFontName, "Devanagari OT Eval");
    1.41 +
    1.42 +CTFormHindiStep* TestStep = NULL;
    1.43 +#define TESTPOINT(p) TestStep->testpoint(p,(TText8*)__FILE__,__LINE__)
    1.44 +#define TESTPRINT(p) TestStep->print(p,(TText8*)__FILE__,__LINE__)
    1.45 +
    1.46 +}
    1.47 +using namespace LocalToTFormHindi;
    1.48 +
    1.49 +_LIT(KTestDeva, "|\x915\x94d\x92b|\x907|\x920\x94d\x920|");
    1.50 +_LIT(KTestBidi, "|\x915|\x644|\x920|");
    1.51 +_LIT(KTestDeva2, "|\x917|\x91c|\x92f\x93f|\x924\x94d\x932\x940|\x917|");
    1.52 +
    1.53 +static const TInt KZeroWidthJoiner = 0x200d;
    1.54 +
    1.55 +/** Test that the deletions occur in expected places.
    1.56 +Expected places should be marked by '|' (pipe character).
    1.57 +These will be removed prior to the test.
    1.58 +@internalComponent
    1.59 +*/
    1.60 +void TestDeletePosition(const TDesC& aTestText, CRichText* aRichText,
    1.61 +	CTextView* aTextView)
    1.62 +	{
    1.63 +	TBuf<100> text;
    1.64 +	TInt positions[20];
    1.65 +	TInt positionCount = 0;
    1.66 +
    1.67 +	TInt ttlen = aTestText.Length();
    1.68 +	for (TInt i = 0; i != ttlen; ++i)
    1.69 +		{
    1.70 +		TInt c = aTestText[i];
    1.71 +		if (c == '|')
    1.72 +			{
    1.73 +			positions[positionCount] = text.Length();
    1.74 +			++positionCount;
    1.75 +			}
    1.76 +		else
    1.77 +			text.Append(c);
    1.78 +		}
    1.79 +
    1.80 +	aRichText->Reset();
    1.81 +	aRichText->InsertL(0, text);
    1.82 +	TCharFormat format(KDevanagariFontName, 200);
    1.83 +	TCharFormatMask mask;
    1.84 +	mask.SetAttrib(EAttFontTypeface);
    1.85 +	aRichText->ApplyCharFormatL(format, mask, 0, text.Length());
    1.86 +	aTextView->FormatTextL();
    1.87 +
    1.88 +	for (TInt j = 0; j < positionCount - 1; ++j)
    1.89 +		{
    1.90 +		aTextView->SetDocPosL(positions[j], EFalse);
    1.91 +		TInt pos = aTextView->GetForwardDeletePositionL().HigherPos();
    1.92 +		TESTPOINT(pos == positions[j + 1]);
    1.93 +		aTextView->SetDocPosL(positions[j], ETrue);
    1.94 +		pos = aTextView->GetForwardDeletePositionL().HigherPos();
    1.95 +		TESTPOINT(pos == positions[j + 1]);
    1.96 +		aTextView->SetDocPosL(positions[j + 1], EFalse);
    1.97 +		pos = aTextView->GetBackwardDeletePositionL().LowerPos();
    1.98 +		TESTPOINT(pos == positions[j]);
    1.99 +		aTextView->SetDocPosL(positions[j + 1], ETrue);
   1.100 +		pos = aTextView->GetBackwardDeletePositionL().LowerPos();
   1.101 +		TESTPOINT(pos == positions[j]);
   1.102 +		}
   1.103 +
   1.104 +	aRichText->Reset();
   1.105 +	}
   1.106 +
   1.107 +
   1.108 +// DEF101191: FORM always splits chunks at ZWJ character
   1.109 +
   1.110 +class CPDEF_101617_CustomDraw : public MFormCustomDraw
   1.111 +{
   1.112 +public:
   1.113 +	CPDEF_101617_CustomDraw() :
   1.114 +		iLeftChunk(),
   1.115 +		iRightChunk(),
   1.116 +		iChunk(0)
   1.117 +		{
   1.118 +		}
   1.119 +	virtual ~CPDEF_101617_CustomDraw() {}
   1.120 +
   1.121 +	void setExpectedChunk(const TDesC& aChunk)
   1.122 +	{
   1.123 +		iLeftChunk = aChunk;
   1.124 +		iRightChunk.Zero();
   1.125 +		iChunk = 0;
   1.126 +	}
   1.127 +	void setExpectedChunks(const TDesC& aLeftChunk, const TDesC& aRightChunk)
   1.128 +	{
   1.129 +		iLeftChunk = aLeftChunk;
   1.130 +		iRightChunk = aRightChunk;
   1.131 +		iChunk = 0;
   1.132 +	}
   1.133 +
   1.134 +	// MFormCustomDraw
   1.135 +	virtual void DrawText(const TParam& /*aParam*/, const TLineInfo& /*aLineInfo*/, const TCharFormat& /*aFormat*/,
   1.136 +		const TDesC& aText, const TPoint& /*aTextOrigin*/, TInt /*aExtraPixels*/) const
   1.137 +		{
   1.138 +		TBool containsZWJ = EFalse;
   1.139 +
   1.140 +		TBuf<100> text;
   1.141 +		TInt len = aText.Length();
   1.142 +		for (TInt i = 0; i < len; i++)
   1.143 +			{
   1.144 +			// remove 0xffff
   1.145 +			if (0xffff != aText[i])
   1.146 +				{
   1.147 +				text.Append(aText[i]);
   1.148 +				if (KZeroWidthJoiner == aText[i])
   1.149 +					{
   1.150 +					containsZWJ = ETrue;
   1.151 +					}
   1.152 +				}
   1.153 +			}
   1.154 +
   1.155 +		// check that the text was splitted as expected
   1.156 +		if (containsZWJ || iChunk > 0)
   1.157 +			{
   1.158 +			// the first chunk with a LZW should be equal to iLeftChunk
   1.159 +			if (0 == iChunk)
   1.160 +				{
   1.161 +                TESTPOINT(text == iLeftChunk);
   1.162 +				iChunk++;
   1.163 +				}
   1.164 +			// the following chunk should be equal to iRightChunk, if it is not-null.
   1.165 +			else if (1 == iChunk && iRightChunk.Size() > 0)
   1.166 +				{
   1.167 +                TESTPOINT(text == iRightChunk);
   1.168 +				iChunk++;
   1.169 +				}
   1.170 +			// just ignore the following chunks
   1.171 +			}
   1.172 +		}
   1.173 +
   1.174 +private:
   1.175 +	TBuf<100> iLeftChunk;
   1.176 +	TBuf<100> iRightChunk;
   1.177 +	mutable TInt iChunk; // modified in a const method
   1.178 +};
   1.179 +
   1.180 +void PDEF_101617_DefectL(CRichText* aRichText, CTextView* aTextView)
   1.181 +	{
   1.182 +	TCharFormat format(KDevanagariFontName, 200);
   1.183 +	TCharFormatMask mask;
   1.184 +	mask.SetAttrib(EAttFontTypeface);
   1.185 +
   1.186 +	CPDEF_101617_CustomDraw* customDrawer = new CPDEF_101617_CustomDraw;
   1.187 +	CleanupStack::PushL(customDrawer);
   1.188 +
   1.189 +	CTextLayout* layout = const_cast<CTextLayout*>(aTextView->Layout());
   1.190 +	layout->SetCustomDraw(customDrawer);
   1.191 +
   1.192 +	TRect rect(0, 0, 300, 100);
   1.193 +
   1.194 +	// 1. test the sequence Sha, Virama, ZWJ, Va,Sha, EndOfParagraph
   1.195 +	_LIT(KTestDevaZWJ1, "\x0936\x094d\x200d\x0935\x0936\x2029");
   1.196 +	TPtrC text1(KTestDevaZWJ1().Ptr(), KTestDevaZWJ1().Length());
   1.197 +
   1.198 +	// the text should not be split and should remain a single chunk...
   1.199 +	_LIT(KTestDevaZWJ1_LeftChunk, "\x0936\x094d\x200d\x0935\x0936");
   1.200 +
   1.201 +	customDrawer->setExpectedChunk(KTestDevaZWJ1_LeftChunk);
   1.202 +
   1.203 +	aRichText->Reset();
   1.204 +	aRichText->InsertL(0, text1);
   1.205 +	aRichText->ApplyCharFormatL(format, mask, 0, text1.Length());
   1.206 +	aTextView->FormatTextL();
   1.207 +	aTextView->DrawL(rect);
   1.208 +
   1.209 +
   1.210 +	// 2. test the sequence Sha,ZWJ,Virama, Va, EndOfParagraph
   1.211 +	_LIT(KTestDevaZWJ2, "\x0936\x200d\x094d\x0935\x2029");
   1.212 +	TPtrC text2(KTestDevaZWJ2().Ptr(), KTestDevaZWJ2().Length());
   1.213 +
   1.214 +	// the text should be split at the bidirectionality change
   1.215 +	_LIT(KTestDevaZWJ2_LeftChunk, "\x0936\x200d\x094d\x0935");
   1.216 +
   1.217 +	customDrawer->setExpectedChunk(KTestDevaZWJ2_LeftChunk);
   1.218 +
   1.219 +	aRichText->Reset();
   1.220 +	aRichText->InsertL(0, text2);
   1.221 +	aRichText->ApplyCharFormatL(format, mask, 0, text2.Length());
   1.222 +	aTextView->FormatTextL();
   1.223 +	aTextView->DrawL(rect);
   1.224 +
   1.225 +	// 3. test the sequence Sha, Virama, ZWJ,Alef(Hebrew) EndOfParagraph
   1.226 +	_LIT(KTestDevaZWJ3, "\x0936\x094d\x200d\x05D0\x2029");
   1.227 +	TPtrC text3(KTestDevaZWJ3().Ptr(), KTestDevaZWJ3().Length());
   1.228 +
   1.229 +	// the text should be split keeping ZWJ (0x200d) at the end of the first chunk...
   1.230 +	_LIT(KTestDevaZWJ3_LeftChunk, "\x0936\x094d\x200d");
   1.231 +	// ... and placing another ZWJ at the start of the second chunk (right to left text)
   1.232 +	_LIT(KTestDevaZWJ3_RightChunk, "\x05D0\x200d");
   1.233 +
   1.234 +	customDrawer->setExpectedChunks(KTestDevaZWJ3_LeftChunk, KTestDevaZWJ3_RightChunk);
   1.235 +
   1.236 +	aRichText->Reset();
   1.237 +	aRichText->InsertL(0, text3);
   1.238 +	aRichText->ApplyCharFormatL(format, mask, 0, text3.Length());
   1.239 +	aTextView->FormatTextL();
   1.240 +	aTextView->DrawL(rect);
   1.241 +
   1.242 +	// 4. test the sequence Sha, Virama, ZWJ, Va,Alef(Hebrew) EndOfParagraph
   1.243 +	_LIT(KTestDevaZWJ4, "\x0936\x094d\x200d\x0935\x05D0\x2029");
   1.244 +	TPtrC text4(KTestDevaZWJ4().Ptr(), KTestDevaZWJ4().Length());
   1.245 +
   1.246 +	// the text should be split at the bidirectionality change
   1.247 +	_LIT(KTestDevaZWJ4_LeftChunk, "\x0936\x094d\x200d\x0935");
   1.248 +	_LIT(KTestDevaZWJ4_RightChunk, "\x05D0");
   1.249 +
   1.250 +	customDrawer->setExpectedChunks(KTestDevaZWJ4_LeftChunk, KTestDevaZWJ4_RightChunk);
   1.251 +
   1.252 +	aRichText->Reset();
   1.253 +	aRichText->InsertL(0, text4);
   1.254 +	aRichText->ApplyCharFormatL(format, mask, 0, text4.Length());
   1.255 +	aTextView->FormatTextL();
   1.256 +	aTextView->DrawL(rect);
   1.257 +
   1.258 +	aRichText->Reset();
   1.259 +
   1.260 +	layout->SetCustomDraw(NULL);
   1.261 +	CleanupStack::PopAndDestroy(customDrawer);
   1.262 +	}
   1.263 +
   1.264 +
   1.265 +/** @SYMTestCaseID SYSLIB-FORM-UT-1532
   1.266 +@SYMTestCaseDesc
   1.267 +	Test delete-by-syllable within Hindi text.
   1.268 +@SYMTestPriority High
   1.269 +@SYMTestActions
   1.270 +	Format some Devanagari, test result of calling GetForwardDeletePositionL
   1.271 +	and GetBackwardDeletePositionL for various inputs.
   1.272 +@SYMTestExpectedResults
   1.273 +	Success if the font "Devanagari OT Eval" is present, Not Run if it is not.
   1.274 +	This font is licensed to Symbian by Monotype Imaging Ltd. for internal
   1.275 +	testing only and so is not distributed with the SDK. Therefore users
   1.276 +	outside of Symbian will experience Not Run unless they have also
   1.277 +	obtained this font.
   1.278 +@SYMPREQ PREQ18 */
   1.279 +void TestTextViewL(CRichText* aRichText,
   1.280 +	CTextView* aTextView)
   1.281 +	{
   1.282 +	// Test devanagari delete-by-syllable
   1.283 +	TESTPRINT(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-1532 Test some simple Hindi "));
   1.284 +	TestDeletePosition(KTestDeva, aRichText, aTextView);
   1.285 +
   1.286 +	// Test Bidi
   1.287 +	// The Arabic character is not present in this font, not even
   1.288 +	// as a fallback glyph. This allows us to exercise a fixes for
   1.289 +	// a latent defect.
   1.290 +	TESTPRINT(_L("Test with characters not in font"));
   1.291 +	TestDeletePosition(KTestBidi, aRichText, aTextView);
   1.292 +
   1.293 +	// Test sample suggested by customer
   1.294 +	TESTPRINT(_L("Test Hindi #2"));
   1.295 +	TestDeletePosition(KTestDeva2, aRichText, aTextView);
   1.296 +
   1.297 +	// regression test for PDEF101617: FORM always splits chunks at ZWJ character
   1.298 +	TESTPRINT(_L("Regression test: PDEF101617"));
   1.299 +	PDEF_101617_DefectL(aRichText, aTextView);
   1.300 +
   1.301 +	}
   1.302 +
   1.303 +void TestL(CFbsScreenDevice* aDevice)
   1.304 +	{
   1.305 +	CParaFormatLayer* paraFormat = CParaFormatLayer::NewL();
   1.306 +	CleanupStack::PushL(paraFormat);
   1.307 +	CCharFormatLayer* charFormat = CCharFormatLayer::NewL();
   1.308 +	CleanupStack::PushL(charFormat);
   1.309 +	CRichText* text = CRichText::NewL(paraFormat, charFormat);
   1.310 +	CleanupStack::PushL(text);
   1.311 +	TRect displayRect(0, 0, KDisplayWidth, KDisplayHeight);
   1.312 +	CTextLayout* layout = CTextLayout::NewL(text, displayRect.Width());
   1.313 +	CleanupStack::PushL(layout);
   1.314 +	CTextView* view = CTextView::NewL(layout, displayRect,
   1.315 +		aDevice, aDevice, 0, 0, 0);
   1.316 +	CleanupStack::PushL(view);
   1.317 +	TestTextViewL(text, view);
   1.318 +	CleanupStack::PopAndDestroy(view);
   1.319 +	CleanupStack::PopAndDestroy(layout);
   1.320 +	CleanupStack::PopAndDestroy(text);
   1.321 +	CleanupStack::PopAndDestroy(charFormat);
   1.322 +	CleanupStack::PopAndDestroy(paraFormat);
   1.323 +	}
   1.324 +
   1.325 +TVerdict CTFormHindiStep::doTestStepL()
   1.326 +	{
   1.327 +    SetTestStepResult(EPass);
   1.328 +    TestStep = this;
   1.329 +    TESTPRINT(KTformhindi);
   1.330 +    
   1.331 +	TInt error = RFbsSession::Connect();
   1.332 +	if (error == KErrNotFound)
   1.333 +		{
   1.334 +		FbsStartup();
   1.335 +		User::LeaveIfError(RFbsSession::Connect());
   1.336 +		}
   1.337 +	CFbsScreenDevice* screenDevice = 0;
   1.338 +	
   1.339 +	TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16M));
   1.340 +	if (error == KErrNotSupported)
   1.341 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16MA));
   1.342 +	if (error == KErrNotSupported)
   1.343 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16MU));
   1.344 +	if (error == KErrNotSupported)
   1.345 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor64K));
   1.346 +	if (error == KErrNotSupported)
   1.347 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor4K));
   1.348 +	if (error == KErrNotSupported)
   1.349 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor256));
   1.350 +	if (error == KErrNotSupported)
   1.351 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16));
   1.352 +	if (error == KErrNotSupported)
   1.353 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray256));
   1.354 +	if (error == KErrNotSupported)
   1.355 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray16));
   1.356 +	if (error == KErrNotSupported)
   1.357 +		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray4));
   1.358 +	if (error == KErrNotSupported)
   1.359 +		screenDevice = CFbsScreenDevice::NewL(0,EGray2);
   1.360 +	
   1.361 +	CleanupStack::PushL(screenDevice);
   1.362 +	screenDevice->ChangeScreenDevice(0);
   1.363 +	screenDevice->SetAutoUpdate(ETrue);
   1.364 +	CGraphicsContext* gc;
   1.365 +	User::LeaveIfError(screenDevice->CreateContext(gc));
   1.366 +	CleanupStack::PushL(gc);
   1.367 +	TFontSpec fs(KDevanagariFontName, 16);
   1.368 +	CFont* devaFont;
   1.369 +	User::LeaveIfError(screenDevice->GetNearestFontInPixels(devaFont, fs));
   1.370 +	TFontSpec fontSpec = devaFont->FontSpecInTwips();
   1.371 +	if(0 != fontSpec.iTypeface.iName.Compare(KDevanagariFontName))
   1.372 +		{
   1.373 +		// Test font not found.
   1.374 +		User::Leave(KErrNotFound);
   1.375 +		}
   1.376 +	CActiveScheduler* scheduler = new(ELeave) CActiveScheduler;
   1.377 +	CleanupStack::PushL(scheduler);
   1.378 +	CActiveScheduler::Install(scheduler);
   1.379 +
   1.380 +	// We know that we have everything we need now, so we'll start the test!
   1.381 +	// A failure before this point would show up in the logs as "not run" rather
   1.382 +	// than "failed".
   1.383 +	TESTPRINT(_L("Test forward/backward delete for Hindi"));
   1.384 +	TRAP(error, TestL(screenDevice));
   1.385 +	CleanupStack::PopAndDestroy(scheduler);
   1.386 +	CleanupStack::PopAndDestroy(gc);
   1.387 +	CleanupStack::PopAndDestroy(screenDevice);
   1.388 +	RFbsSession::Disconnect();
   1.389 +	User::LeaveIfError(error);
   1.390 +	return TestStepResult();
   1.391 +	}