textrendering/textformatting/test/src/tformhindi.cpp
changeset 0 1fb32624e06b
child 16 748ec5531811
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * @file
       
    16 * @internalComponent 
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 #include <e32std.h>
       
    22 #include <e32test.h>
       
    23 #include <frmtlay.h>
       
    24 #include <frmtview.h>
       
    25 #include <txtlaydc.h>
       
    26 #include <fbs.h>
       
    27 #include <w32std.h>
       
    28 #include <bitdev.h>
       
    29 #include <txtrich.h>
       
    30 
       
    31 namespace LocalToFile {
       
    32 
       
    33 _LIT(KTformhindi, "tformhindi");
       
    34 const TInt KDisplayWidth = 100;
       
    35 const TInt KDisplayHeight = 100;
       
    36 RTest test(KTformhindi);
       
    37 _LIT(KDevanagariFontName, "Devanagari OT Eval");
       
    38 
       
    39 }
       
    40 using namespace LocalToFile;
       
    41 
       
    42 _LIT(KTestDeva, "|\x915\x94d\x92b|\x907|\x920\x94d\x920|");
       
    43 _LIT(KTestBidi, "|\x915|\x644|\x920|");
       
    44 _LIT(KTestDeva2, "|\x917|\x91c|\x92f\x93f|\x924\x94d\x932\x940|\x917|");
       
    45 
       
    46 static const TInt KZeroWidthJoiner = 0x200d;
       
    47 
       
    48 /** Test that the deletions occur in expected places.
       
    49 Expected places should be marked by '|' (pipe character).
       
    50 These will be removed prior to the test.
       
    51 @internalComponent
       
    52 */
       
    53 void TestDeletePosition(const TDesC& aTestText, CRichText* aRichText,
       
    54 	CTextView* aTextView)
       
    55 	{
       
    56 	TBuf<100> text;
       
    57 	TInt positions[20];
       
    58 	TInt positionCount = 0;
       
    59 
       
    60 	TInt ttlen = aTestText.Length();
       
    61 	for (TInt i = 0; i != ttlen; ++i)
       
    62 		{
       
    63 		TInt c = aTestText[i];
       
    64 		if (c == '|')
       
    65 			{
       
    66 			positions[positionCount] = text.Length();
       
    67 			++positionCount;
       
    68 			}
       
    69 		else
       
    70 			text.Append(c);
       
    71 		}
       
    72 
       
    73 	aRichText->Reset();
       
    74 	aRichText->InsertL(0, text);
       
    75 	TCharFormat format(KDevanagariFontName, 200);
       
    76 	TCharFormatMask mask;
       
    77 	mask.SetAttrib(EAttFontTypeface);
       
    78 	aRichText->ApplyCharFormatL(format, mask, 0, text.Length());
       
    79 	aTextView->FormatTextL();
       
    80 
       
    81 	for (TInt j = 0; j < positionCount - 1; ++j)
       
    82 		{
       
    83 		aTextView->SetDocPosL(positions[j], EFalse);
       
    84 		TInt pos = aTextView->GetForwardDeletePositionL().HigherPos();
       
    85 		test(pos == positions[j + 1]);
       
    86 		aTextView->SetDocPosL(positions[j], ETrue);
       
    87 		pos = aTextView->GetForwardDeletePositionL().HigherPos();
       
    88 		test(pos == positions[j + 1]);
       
    89 		aTextView->SetDocPosL(positions[j + 1], EFalse);
       
    90 		pos = aTextView->GetBackwardDeletePositionL().LowerPos();
       
    91 		test(pos == positions[j]);
       
    92 		aTextView->SetDocPosL(positions[j + 1], ETrue);
       
    93 		pos = aTextView->GetBackwardDeletePositionL().LowerPos();
       
    94 		test(pos == positions[j]);
       
    95 		}
       
    96 
       
    97 	aRichText->Reset();
       
    98 	}
       
    99 
       
   100 
       
   101 // DEF101191: FORM always splits chunks at ZWJ character
       
   102 
       
   103 class CPDEF_101617_CustomDraw : public MFormCustomDraw
       
   104 {
       
   105 public:
       
   106 	CPDEF_101617_CustomDraw() :
       
   107 		iLeftChunk(),
       
   108 		iRightChunk(),
       
   109 		iChunk(0)
       
   110 		{
       
   111 		}
       
   112 	virtual ~CPDEF_101617_CustomDraw() {}
       
   113 
       
   114 	void setExpectedChunk(const TDesC& aChunk)
       
   115 	{
       
   116 		iLeftChunk = aChunk;
       
   117 		iRightChunk.Zero();
       
   118 		iChunk = 0;
       
   119 	}
       
   120 	void setExpectedChunks(const TDesC& aLeftChunk, const TDesC& aRightChunk)
       
   121 	{
       
   122 		iLeftChunk = aLeftChunk;
       
   123 		iRightChunk = aRightChunk;
       
   124 		iChunk = 0;
       
   125 	}
       
   126 
       
   127 	// MFormCustomDraw
       
   128 	virtual void DrawText(const TParam& /*aParam*/, const TLineInfo& /*aLineInfo*/, const TCharFormat& /*aFormat*/,
       
   129 		const TDesC& aText, const TPoint& /*aTextOrigin*/, TInt /*aExtraPixels*/) const
       
   130 		{
       
   131 		TBool containsZWJ = EFalse;
       
   132 
       
   133 		TBuf<100> text;
       
   134 		TInt len = aText.Length();
       
   135 		for (TInt i = 0; i < len; i++)
       
   136 			{
       
   137 			// remove 0xffff
       
   138 			if (0xffff != aText[i])
       
   139 				{
       
   140 				text.Append(aText[i]);
       
   141 				if (KZeroWidthJoiner == aText[i])
       
   142 					{
       
   143 					containsZWJ = ETrue;
       
   144 					}
       
   145 				}
       
   146 			}
       
   147 
       
   148 		// check that the text was splitted as expected
       
   149 		if (containsZWJ || iChunk > 0)
       
   150 			{
       
   151 			// the first chunk with a LZW should be equal to iLeftChunk
       
   152 			if (0 == iChunk)
       
   153 				{
       
   154 				test(text == iLeftChunk);
       
   155 				iChunk++;
       
   156 				}
       
   157 			// the following chunk should be equal to iRightChunk, if it is not-null.
       
   158 			else if (1 == iChunk && iRightChunk.Size() > 0)
       
   159 				{
       
   160 				test(text == iRightChunk);
       
   161 				iChunk++;
       
   162 				}
       
   163 			// just ignore the following chunks
       
   164 			}
       
   165 		}
       
   166 
       
   167 private:
       
   168 	TBuf<100> iLeftChunk;
       
   169 	TBuf<100> iRightChunk;
       
   170 	mutable TInt iChunk; // modified in a const method
       
   171 };
       
   172 
       
   173 void PDEF_101617_DefectL(CRichText* aRichText, CTextView* aTextView)
       
   174 	{
       
   175 	TCharFormat format(KDevanagariFontName, 200);
       
   176 	TCharFormatMask mask;
       
   177 	mask.SetAttrib(EAttFontTypeface);
       
   178 
       
   179 	CPDEF_101617_CustomDraw* customDrawer = new CPDEF_101617_CustomDraw;
       
   180 	CleanupStack::PushL(customDrawer);
       
   181 
       
   182 	CTextLayout* layout = const_cast<CTextLayout*>(aTextView->Layout());
       
   183 	layout->SetCustomDraw(customDrawer);
       
   184 
       
   185 	TRect rect(0, 0, 300, 100);
       
   186 
       
   187 	// 1. test the sequence Sha, Virama, ZWJ, Va,Sha, EndOfParagraph
       
   188 	_LIT(KTestDevaZWJ1, "\x0936\x094d\x200d\x0935\x0936\x2029");
       
   189 	TPtrC text1(KTestDevaZWJ1().Ptr(), KTestDevaZWJ1().Length());
       
   190 
       
   191 	// the text should not be split and should remain a single chunk...
       
   192 	_LIT(KTestDevaZWJ1_LeftChunk, "\x0936\x094d\x200d\x0935\x0936");
       
   193 
       
   194 	customDrawer->setExpectedChunk(KTestDevaZWJ1_LeftChunk);
       
   195 
       
   196 	aRichText->Reset();
       
   197 	aRichText->InsertL(0, text1);
       
   198 	aRichText->ApplyCharFormatL(format, mask, 0, text1.Length());
       
   199 	aTextView->FormatTextL();
       
   200 	aTextView->DrawL(rect);
       
   201 
       
   202 
       
   203 	// 2. test the sequence Sha,ZWJ,Virama, Va, EndOfParagraph
       
   204 	_LIT(KTestDevaZWJ2, "\x0936\x200d\x094d\x0935\x2029");
       
   205 	TPtrC text2(KTestDevaZWJ2().Ptr(), KTestDevaZWJ2().Length());
       
   206 
       
   207 	// the text should be split at the bidirectionality change
       
   208 	_LIT(KTestDevaZWJ2_LeftChunk, "\x0936\x200d\x094d\x0935");
       
   209 
       
   210 	customDrawer->setExpectedChunk(KTestDevaZWJ2_LeftChunk);
       
   211 
       
   212 	aRichText->Reset();
       
   213 	aRichText->InsertL(0, text2);
       
   214 	aRichText->ApplyCharFormatL(format, mask, 0, text2.Length());
       
   215 	aTextView->FormatTextL();
       
   216 	aTextView->DrawL(rect);
       
   217 
       
   218 	// 3. test the sequence Sha, Virama, ZWJ,Alef(Hebrew) EndOfParagraph
       
   219 	_LIT(KTestDevaZWJ3, "\x0936\x094d\x200d\x05D0\x2029");
       
   220 	TPtrC text3(KTestDevaZWJ3().Ptr(), KTestDevaZWJ3().Length());
       
   221 
       
   222 	// the text should be split keeping ZWJ (0x200d) at the end of the first chunk...
       
   223 	_LIT(KTestDevaZWJ3_LeftChunk, "\x0936\x094d\x200d");
       
   224 	// ... and placing another ZWJ at the start of the second chunk (right to left text)
       
   225 	_LIT(KTestDevaZWJ3_RightChunk, "\x05D0\x200d");
       
   226 
       
   227 	customDrawer->setExpectedChunks(KTestDevaZWJ3_LeftChunk, KTestDevaZWJ3_RightChunk);
       
   228 
       
   229 	aRichText->Reset();
       
   230 	aRichText->InsertL(0, text3);
       
   231 	aRichText->ApplyCharFormatL(format, mask, 0, text3.Length());
       
   232 	aTextView->FormatTextL();
       
   233 	aTextView->DrawL(rect);
       
   234 
       
   235 	// 4. test the sequence Sha, Virama, ZWJ, Va,Alef(Hebrew) EndOfParagraph
       
   236 	_LIT(KTestDevaZWJ4, "\x0936\x094d\x200d\x0935\x05D0\x2029");
       
   237 	TPtrC text4(KTestDevaZWJ4().Ptr(), KTestDevaZWJ4().Length());
       
   238 
       
   239 	// the text should be split at the bidirectionality change
       
   240 	_LIT(KTestDevaZWJ4_LeftChunk, "\x0936\x094d\x200d\x0935");
       
   241 	_LIT(KTestDevaZWJ4_RightChunk, "\x05D0");
       
   242 
       
   243 	customDrawer->setExpectedChunks(KTestDevaZWJ4_LeftChunk, KTestDevaZWJ4_RightChunk);
       
   244 
       
   245 	aRichText->Reset();
       
   246 	aRichText->InsertL(0, text4);
       
   247 	aRichText->ApplyCharFormatL(format, mask, 0, text4.Length());
       
   248 	aTextView->FormatTextL();
       
   249 	aTextView->DrawL(rect);
       
   250 
       
   251 	aRichText->Reset();
       
   252 
       
   253 	layout->SetCustomDraw(NULL);
       
   254 	CleanupStack::PopAndDestroy(customDrawer);
       
   255 	}
       
   256 
       
   257 
       
   258 /** @SYMTestCaseID SYSLIB-FORM-UT-1532
       
   259 @SYMTestCaseDesc
       
   260 	Test delete-by-syllable within Hindi text.
       
   261 @SYMTestPriority High
       
   262 @SYMTestActions
       
   263 	Format some Devanagari, test result of calling GetForwardDeletePositionL
       
   264 	and GetBackwardDeletePositionL for various inputs.
       
   265 @SYMTestExpectedResults
       
   266 	Success if the font "Devanagari OT Eval" is present, Not Run if it is not.
       
   267 	This font is licensed to Symbian by Monotype Imaging Ltd. for internal
       
   268 	testing only and so is not distributed with the SDK. Therefore users
       
   269 	outside of Symbian will experience Not Run unless they have also
       
   270 	obtained this font.
       
   271 @SYMPREQ PREQ18 */
       
   272 void TestTextViewL(CRichText* aRichText,
       
   273 	CTextView* aTextView)
       
   274 	{
       
   275 	// Test devanagari delete-by-syllable
       
   276 	test.Start(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-1532 Test some simple Hindi "));
       
   277 	TestDeletePosition(KTestDeva, aRichText, aTextView);
       
   278 
       
   279 	// Test Bidi
       
   280 	// The Arabic character is not present in this font, not even
       
   281 	// as a fallback glyph. This allows us to exercise a fixes for
       
   282 	// a latent defect.
       
   283 	test.Next(_L("Test with characters not in font"));
       
   284 	TestDeletePosition(KTestBidi, aRichText, aTextView);
       
   285 
       
   286 	// Test sample suggested by customer
       
   287 	test.Next(_L("Test Hindi #2"));
       
   288 	TestDeletePosition(KTestDeva2, aRichText, aTextView);
       
   289 
       
   290 	// regression test for PDEF101617: FORM always splits chunks at ZWJ character
       
   291 	test.Next(_L("Regression test: PDEF101617"));
       
   292 	PDEF_101617_DefectL(aRichText, aTextView);
       
   293 
       
   294 	test.End();
       
   295 	}
       
   296 
       
   297 void TestL(CFbsScreenDevice* aDevice)
       
   298 	{
       
   299 	CParaFormatLayer* paraFormat = CParaFormatLayer::NewL();
       
   300 	CleanupStack::PushL(paraFormat);
       
   301 	CCharFormatLayer* charFormat = CCharFormatLayer::NewL();
       
   302 	CleanupStack::PushL(charFormat);
       
   303 	CRichText* text = CRichText::NewL(paraFormat, charFormat);
       
   304 	CleanupStack::PushL(text);
       
   305 	TRect displayRect(0, 0, KDisplayWidth, KDisplayHeight);
       
   306 	CTextLayout* layout = CTextLayout::NewL(text, displayRect.Width());
       
   307 	CleanupStack::PushL(layout);
       
   308 	CTextView* view = CTextView::NewL(layout, displayRect,
       
   309 		aDevice, aDevice, 0, 0, 0);
       
   310 	CleanupStack::PushL(view);
       
   311 	TestTextViewL(text, view);
       
   312 	CleanupStack::PopAndDestroy(view);
       
   313 	CleanupStack::PopAndDestroy(layout);
       
   314 	CleanupStack::PopAndDestroy(text);
       
   315 	CleanupStack::PopAndDestroy(charFormat);
       
   316 	CleanupStack::PopAndDestroy(paraFormat);
       
   317 	}
       
   318 
       
   319 void MainL()
       
   320 	{
       
   321 	TInt error = RFbsSession::Connect();
       
   322 	if (error == KErrNotFound)
       
   323 		{
       
   324 		FbsStartup();
       
   325 		User::LeaveIfError(RFbsSession::Connect());
       
   326 		}
       
   327 	CFbsScreenDevice* screenDevice = 0;
       
   328 	
       
   329 	TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16M));
       
   330 	if (error == KErrNotSupported)
       
   331 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16MA));
       
   332 	if (error == KErrNotSupported)
       
   333 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16MU));
       
   334 	if (error == KErrNotSupported)
       
   335 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor64K));
       
   336 	if (error == KErrNotSupported)
       
   337 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor4K));
       
   338 	if (error == KErrNotSupported)
       
   339 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor256));
       
   340 	if (error == KErrNotSupported)
       
   341 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16));
       
   342 	if (error == KErrNotSupported)
       
   343 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray256));
       
   344 	if (error == KErrNotSupported)
       
   345 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray16));
       
   346 	if (error == KErrNotSupported)
       
   347 		TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray4));
       
   348 	if (error == KErrNotSupported)
       
   349 		screenDevice = CFbsScreenDevice::NewL(0,EGray2);
       
   350 	
       
   351 	CleanupStack::PushL(screenDevice);
       
   352 	screenDevice->ChangeScreenDevice(0);
       
   353 	screenDevice->SetAutoUpdate(ETrue);
       
   354 	CGraphicsContext* gc;
       
   355 	User::LeaveIfError(screenDevice->CreateContext(gc));
       
   356 	CleanupStack::PushL(gc);
       
   357 	TFontSpec fs(KDevanagariFontName, 16);
       
   358 	CFont* devaFont;
       
   359 	User::LeaveIfError(screenDevice->GetNearestFontInPixels(devaFont, fs));
       
   360 	TFontSpec fontSpec = devaFont->FontSpecInTwips();
       
   361 	if(0 != fontSpec.iTypeface.iName.Compare(KDevanagariFontName))
       
   362 		{
       
   363 		// Test font not found.
       
   364 		User::Leave(KErrNotFound);
       
   365 		}
       
   366 	CActiveScheduler* scheduler = new(ELeave) CActiveScheduler;
       
   367 	CleanupStack::PushL(scheduler);
       
   368 	CActiveScheduler::Install(scheduler);
       
   369 
       
   370 	// We know that we have everything we need now, so we'll start the test!
       
   371 	// A failure before this point would show up in the logs as "not run" rather
       
   372 	// than "failed".
       
   373 	test.Title();
       
   374 	test.Start(_L("Test forward/backward delete for Hindi"));
       
   375 	TRAP(error, TestL(screenDevice));
       
   376 	test.End();
       
   377 	test.Close();
       
   378 	CleanupStack::PopAndDestroy(scheduler);
       
   379 	CleanupStack::PopAndDestroy(gc);
       
   380 	CleanupStack::PopAndDestroy(screenDevice);
       
   381 	RFbsSession::Disconnect();
       
   382 	User::LeaveIfError(error);
       
   383 	}
       
   384 
       
   385 TInt E32Main()
       
   386 	{
       
   387 	static CTrapCleanup* TrapCleanup = CTrapCleanup::New();
       
   388 	if (!TrapCleanup)
       
   389 		return KErrNoMemory;
       
   390 	TRAPD(error, MainL());
       
   391 	delete TrapCleanup;
       
   392 	return error;
       
   393 	}