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