--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/textrendering/textformatting/test/src/tformhindi.cpp Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,393 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* @file
+* @internalComponent
+*
+*/
+
+
+#include <e32std.h>
+#include <e32test.h>
+#include <frmtlay.h>
+#include <frmtview.h>
+#include <txtlaydc.h>
+#include <fbs.h>
+#include <w32std.h>
+#include <bitdev.h>
+#include <txtrich.h>
+
+namespace LocalToFile {
+
+_LIT(KTformhindi, "tformhindi");
+const TInt KDisplayWidth = 100;
+const TInt KDisplayHeight = 100;
+RTest test(KTformhindi);
+_LIT(KDevanagariFontName, "Devanagari OT Eval");
+
+}
+using namespace LocalToFile;
+
+_LIT(KTestDeva, "|\x915\x94d\x92b|\x907|\x920\x94d\x920|");
+_LIT(KTestBidi, "|\x915|\x644|\x920|");
+_LIT(KTestDeva2, "|\x917|\x91c|\x92f\x93f|\x924\x94d\x932\x940|\x917|");
+
+static const TInt KZeroWidthJoiner = 0x200d;
+
+/** Test that the deletions occur in expected places.
+Expected places should be marked by '|' (pipe character).
+These will be removed prior to the test.
+@internalComponent
+*/
+void TestDeletePosition(const TDesC& aTestText, CRichText* aRichText,
+ CTextView* aTextView)
+ {
+ TBuf<100> text;
+ TInt positions[20];
+ TInt positionCount = 0;
+
+ TInt ttlen = aTestText.Length();
+ for (TInt i = 0; i != ttlen; ++i)
+ {
+ TInt c = aTestText[i];
+ if (c == '|')
+ {
+ positions[positionCount] = text.Length();
+ ++positionCount;
+ }
+ else
+ text.Append(c);
+ }
+
+ aRichText->Reset();
+ aRichText->InsertL(0, text);
+ TCharFormat format(KDevanagariFontName, 200);
+ TCharFormatMask mask;
+ mask.SetAttrib(EAttFontTypeface);
+ aRichText->ApplyCharFormatL(format, mask, 0, text.Length());
+ aTextView->FormatTextL();
+
+ for (TInt j = 0; j < positionCount - 1; ++j)
+ {
+ aTextView->SetDocPosL(positions[j], EFalse);
+ TInt pos = aTextView->GetForwardDeletePositionL().HigherPos();
+ test(pos == positions[j + 1]);
+ aTextView->SetDocPosL(positions[j], ETrue);
+ pos = aTextView->GetForwardDeletePositionL().HigherPos();
+ test(pos == positions[j + 1]);
+ aTextView->SetDocPosL(positions[j + 1], EFalse);
+ pos = aTextView->GetBackwardDeletePositionL().LowerPos();
+ test(pos == positions[j]);
+ aTextView->SetDocPosL(positions[j + 1], ETrue);
+ pos = aTextView->GetBackwardDeletePositionL().LowerPos();
+ test(pos == positions[j]);
+ }
+
+ aRichText->Reset();
+ }
+
+
+// DEF101191: FORM always splits chunks at ZWJ character
+
+class CPDEF_101617_CustomDraw : public MFormCustomDraw
+{
+public:
+ CPDEF_101617_CustomDraw() :
+ iLeftChunk(),
+ iRightChunk(),
+ iChunk(0)
+ {
+ }
+ virtual ~CPDEF_101617_CustomDraw() {}
+
+ void setExpectedChunk(const TDesC& aChunk)
+ {
+ iLeftChunk = aChunk;
+ iRightChunk.Zero();
+ iChunk = 0;
+ }
+ void setExpectedChunks(const TDesC& aLeftChunk, const TDesC& aRightChunk)
+ {
+ iLeftChunk = aLeftChunk;
+ iRightChunk = aRightChunk;
+ iChunk = 0;
+ }
+
+ // MFormCustomDraw
+ virtual void DrawText(const TParam& /*aParam*/, const TLineInfo& /*aLineInfo*/, const TCharFormat& /*aFormat*/,
+ const TDesC& aText, const TPoint& /*aTextOrigin*/, TInt /*aExtraPixels*/) const
+ {
+ TBool containsZWJ = EFalse;
+
+ TBuf<100> text;
+ TInt len = aText.Length();
+ for (TInt i = 0; i < len; i++)
+ {
+ // remove 0xffff
+ if (0xffff != aText[i])
+ {
+ text.Append(aText[i]);
+ if (KZeroWidthJoiner == aText[i])
+ {
+ containsZWJ = ETrue;
+ }
+ }
+ }
+
+ // check that the text was splitted as expected
+ if (containsZWJ || iChunk > 0)
+ {
+ // the first chunk with a LZW should be equal to iLeftChunk
+ if (0 == iChunk)
+ {
+ test(text == iLeftChunk);
+ iChunk++;
+ }
+ // the following chunk should be equal to iRightChunk, if it is not-null.
+ else if (1 == iChunk && iRightChunk.Size() > 0)
+ {
+ test(text == iRightChunk);
+ iChunk++;
+ }
+ // just ignore the following chunks
+ }
+ }
+
+private:
+ TBuf<100> iLeftChunk;
+ TBuf<100> iRightChunk;
+ mutable TInt iChunk; // modified in a const method
+};
+
+void PDEF_101617_DefectL(CRichText* aRichText, CTextView* aTextView)
+ {
+ TCharFormat format(KDevanagariFontName, 200);
+ TCharFormatMask mask;
+ mask.SetAttrib(EAttFontTypeface);
+
+ CPDEF_101617_CustomDraw* customDrawer = new CPDEF_101617_CustomDraw;
+ CleanupStack::PushL(customDrawer);
+
+ CTextLayout* layout = const_cast<CTextLayout*>(aTextView->Layout());
+ layout->SetCustomDraw(customDrawer);
+
+ TRect rect(0, 0, 300, 100);
+
+ // 1. test the sequence Sha, Virama, ZWJ, Va,Sha, EndOfParagraph
+ _LIT(KTestDevaZWJ1, "\x0936\x094d\x200d\x0935\x0936\x2029");
+ TPtrC text1(KTestDevaZWJ1().Ptr(), KTestDevaZWJ1().Length());
+
+ // the text should not be split and should remain a single chunk...
+ _LIT(KTestDevaZWJ1_LeftChunk, "\x0936\x094d\x200d\x0935\x0936");
+
+ customDrawer->setExpectedChunk(KTestDevaZWJ1_LeftChunk);
+
+ aRichText->Reset();
+ aRichText->InsertL(0, text1);
+ aRichText->ApplyCharFormatL(format, mask, 0, text1.Length());
+ aTextView->FormatTextL();
+ aTextView->DrawL(rect);
+
+
+ // 2. test the sequence Sha,ZWJ,Virama, Va, EndOfParagraph
+ _LIT(KTestDevaZWJ2, "\x0936\x200d\x094d\x0935\x2029");
+ TPtrC text2(KTestDevaZWJ2().Ptr(), KTestDevaZWJ2().Length());
+
+ // the text should be split at the bidirectionality change
+ _LIT(KTestDevaZWJ2_LeftChunk, "\x0936\x200d\x094d\x0935");
+
+ customDrawer->setExpectedChunk(KTestDevaZWJ2_LeftChunk);
+
+ aRichText->Reset();
+ aRichText->InsertL(0, text2);
+ aRichText->ApplyCharFormatL(format, mask, 0, text2.Length());
+ aTextView->FormatTextL();
+ aTextView->DrawL(rect);
+
+ // 3. test the sequence Sha, Virama, ZWJ,Alef(Hebrew) EndOfParagraph
+ _LIT(KTestDevaZWJ3, "\x0936\x094d\x200d\x05D0\x2029");
+ TPtrC text3(KTestDevaZWJ3().Ptr(), KTestDevaZWJ3().Length());
+
+ // the text should be split keeping ZWJ (0x200d) at the end of the first chunk...
+ _LIT(KTestDevaZWJ3_LeftChunk, "\x0936\x094d\x200d");
+ // ... and placing another ZWJ at the start of the second chunk (right to left text)
+ _LIT(KTestDevaZWJ3_RightChunk, "\x05D0\x200d");
+
+ customDrawer->setExpectedChunks(KTestDevaZWJ3_LeftChunk, KTestDevaZWJ3_RightChunk);
+
+ aRichText->Reset();
+ aRichText->InsertL(0, text3);
+ aRichText->ApplyCharFormatL(format, mask, 0, text3.Length());
+ aTextView->FormatTextL();
+ aTextView->DrawL(rect);
+
+ // 4. test the sequence Sha, Virama, ZWJ, Va,Alef(Hebrew) EndOfParagraph
+ _LIT(KTestDevaZWJ4, "\x0936\x094d\x200d\x0935\x05D0\x2029");
+ TPtrC text4(KTestDevaZWJ4().Ptr(), KTestDevaZWJ4().Length());
+
+ // the text should be split at the bidirectionality change
+ _LIT(KTestDevaZWJ4_LeftChunk, "\x0936\x094d\x200d\x0935");
+ _LIT(KTestDevaZWJ4_RightChunk, "\x05D0");
+
+ customDrawer->setExpectedChunks(KTestDevaZWJ4_LeftChunk, KTestDevaZWJ4_RightChunk);
+
+ aRichText->Reset();
+ aRichText->InsertL(0, text4);
+ aRichText->ApplyCharFormatL(format, mask, 0, text4.Length());
+ aTextView->FormatTextL();
+ aTextView->DrawL(rect);
+
+ aRichText->Reset();
+
+ layout->SetCustomDraw(NULL);
+ CleanupStack::PopAndDestroy(customDrawer);
+ }
+
+
+/** @SYMTestCaseID SYSLIB-FORM-UT-1532
+@SYMTestCaseDesc
+ Test delete-by-syllable within Hindi text.
+@SYMTestPriority High
+@SYMTestActions
+ Format some Devanagari, test result of calling GetForwardDeletePositionL
+ and GetBackwardDeletePositionL for various inputs.
+@SYMTestExpectedResults
+ Success if the font "Devanagari OT Eval" is present, Not Run if it is not.
+ This font is licensed to Symbian by Monotype Imaging Ltd. for internal
+ testing only and so is not distributed with the SDK. Therefore users
+ outside of Symbian will experience Not Run unless they have also
+ obtained this font.
+@SYMPREQ PREQ18 */
+void TestTextViewL(CRichText* aRichText,
+ CTextView* aTextView)
+ {
+ // Test devanagari delete-by-syllable
+ test.Start(_L(" @SYMTestCaseID:SYSLIB-FORM-UT-1532 Test some simple Hindi "));
+ TestDeletePosition(KTestDeva, aRichText, aTextView);
+
+ // Test Bidi
+ // The Arabic character is not present in this font, not even
+ // as a fallback glyph. This allows us to exercise a fixes for
+ // a latent defect.
+ test.Next(_L("Test with characters not in font"));
+ TestDeletePosition(KTestBidi, aRichText, aTextView);
+
+ // Test sample suggested by customer
+ test.Next(_L("Test Hindi #2"));
+ TestDeletePosition(KTestDeva2, aRichText, aTextView);
+
+ // regression test for PDEF101617: FORM always splits chunks at ZWJ character
+ test.Next(_L("Regression test: PDEF101617"));
+ PDEF_101617_DefectL(aRichText, aTextView);
+
+ test.End();
+ }
+
+void TestL(CFbsScreenDevice* aDevice)
+ {
+ CParaFormatLayer* paraFormat = CParaFormatLayer::NewL();
+ CleanupStack::PushL(paraFormat);
+ CCharFormatLayer* charFormat = CCharFormatLayer::NewL();
+ CleanupStack::PushL(charFormat);
+ CRichText* text = CRichText::NewL(paraFormat, charFormat);
+ CleanupStack::PushL(text);
+ TRect displayRect(0, 0, KDisplayWidth, KDisplayHeight);
+ CTextLayout* layout = CTextLayout::NewL(text, displayRect.Width());
+ CleanupStack::PushL(layout);
+ CTextView* view = CTextView::NewL(layout, displayRect,
+ aDevice, aDevice, 0, 0, 0);
+ CleanupStack::PushL(view);
+ TestTextViewL(text, view);
+ CleanupStack::PopAndDestroy(view);
+ CleanupStack::PopAndDestroy(layout);
+ CleanupStack::PopAndDestroy(text);
+ CleanupStack::PopAndDestroy(charFormat);
+ CleanupStack::PopAndDestroy(paraFormat);
+ }
+
+void MainL()
+ {
+ TInt error = RFbsSession::Connect();
+ if (error == KErrNotFound)
+ {
+ FbsStartup();
+ User::LeaveIfError(RFbsSession::Connect());
+ }
+ CFbsScreenDevice* screenDevice = 0;
+
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16M));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16MA));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16MU));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor64K));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor4K));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor256));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EColor16));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray256));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray16));
+ if (error == KErrNotSupported)
+ TRAP(error, screenDevice = CFbsScreenDevice::NewL(0,EGray4));
+ if (error == KErrNotSupported)
+ screenDevice = CFbsScreenDevice::NewL(0,EGray2);
+
+ CleanupStack::PushL(screenDevice);
+ screenDevice->ChangeScreenDevice(0);
+ screenDevice->SetAutoUpdate(ETrue);
+ CGraphicsContext* gc;
+ User::LeaveIfError(screenDevice->CreateContext(gc));
+ CleanupStack::PushL(gc);
+ TFontSpec fs(KDevanagariFontName, 16);
+ CFont* devaFont;
+ User::LeaveIfError(screenDevice->GetNearestFontInPixels(devaFont, fs));
+ TFontSpec fontSpec = devaFont->FontSpecInTwips();
+ if(0 != fontSpec.iTypeface.iName.Compare(KDevanagariFontName))
+ {
+ // Test font not found.
+ User::Leave(KErrNotFound);
+ }
+ CActiveScheduler* scheduler = new(ELeave) CActiveScheduler;
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ // We know that we have everything we need now, so we'll start the test!
+ // A failure before this point would show up in the logs as "not run" rather
+ // than "failed".
+ test.Title();
+ test.Start(_L("Test forward/backward delete for Hindi"));
+ TRAP(error, TestL(screenDevice));
+ test.End();
+ test.Close();
+ CleanupStack::PopAndDestroy(scheduler);
+ CleanupStack::PopAndDestroy(gc);
+ CleanupStack::PopAndDestroy(screenDevice);
+ RFbsSession::Disconnect();
+ User::LeaveIfError(error);
+ }
+
+TInt E32Main()
+ {
+ static CTrapCleanup* TrapCleanup = CTrapCleanup::New();
+ if (!TrapCleanup)
+ return KErrNoMemory;
+ TRAPD(error, MainL());
+ delete TrapCleanup;
+ return error;
+ }