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 + }