textrendering/texthandling/ttext/T_STYLE.CPP
changeset 0 1fb32624e06b
child 16 748ec5531811
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/textrendering/texthandling/ttext/T_STYLE.CPP	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,581 @@
+/*
+* Copyright (c) 1997-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: 
+*
+*/
+
+
+#include <e32std.h>
+#include <e32base.h>
+
+#include <gdi.h>
+#include <s32file.h>
+#include <e32test.h>
+
+#include <txtrich.h>
+#include <txtfmlyr.h>
+#include <txtfrmat.h>
+#include <txtstyle.h>
+
+#define UNUSED_VAR(a) a = a
+
+const TInt KTestCleanupStack=0x40;
+
+LOCAL_D RTest test(_L("Testing Paragraph Styles"));
+LOCAL_D CTrapCleanup* TheTrapCleanup;
+
+LOCAL_D CRichText* TheText;
+LOCAL_D CStyleList* TheStyleList;
+LOCAL_D CParaFormatLayer* TheNormalParaLayer;
+LOCAL_D CCharFormatLayer* TheNormalCharLayer;
+LOCAL_D CParagraphStyle* TheStyleOne;
+LOCAL_D CParagraphStyle* TheStyleTwo;
+
+
+_LIT(KOutputFile, "c:\\etext\\t_style.tst");
+template <class T>
+void testStoreRestoreL(T& aCopy,const T& aOriginal)
+// Test document persistance.
+//
+    {
+	// set up the store
+	RFs	theFs;
+	theFs.Connect();
+	//
+	theFs.Delete(KOutputFile);
+	theFs.MkDirAll(KOutputFile);
+	CFileStore* theStore=CDirectFileStore::CreateL(theFs,KOutputFile,EFileRead|EFileWrite);
+	CleanupStack::PushL(theStore);
+	theStore->SetTypeL(KDirectFileStoreLayoutUid);
+	//
+	// store the original
+	TStreamId id(0);
+	TRAPD(ret,id=aOriginal.StoreL(*theStore));
+		test(ret==KErrNone);
+	//
+	// restore into the copy
+	TRAP(ret,aCopy.RestoreL(*theStore,id));
+		test(ret==KErrNone);
+	//
+	// tidy up
+	CleanupStack::PopAndDestroy();  // theStore
+	theFs.Close();
+    }
+
+
+LOCAL_C TInt IsEqual(const CRichText* aCopy,const CRichText* aOriginal)
+//
+// Returns true if aCopy contents matches aOriginal contents.
+// Takes account of multiple segments of a segmented text component.
+//
+	{
+	TInt lengthOfOriginal=aOriginal->DocumentLength();
+	TInt lengthOfCopy=aCopy->DocumentLength();
+	test(lengthOfOriginal==lengthOfCopy);
+//
+	TPtrC copy,orig;
+//
+	TInt lengthRead=0;
+	while(lengthRead<=lengthOfOriginal)
+		{
+		copy.Set((aCopy->Read(lengthRead)));
+		orig.Set((aOriginal->Read(lengthRead)));
+		for (TInt offset=0; offset<orig.Length(); offset++)
+			test(copy[offset]==orig[offset]);
+		lengthRead+=orig.Length();
+		}
+	test(lengthRead==lengthOfOriginal+1);
+//
+	CStyleList* origStyle=aOriginal->StyleList();
+	CStyleList* copyStyle=aCopy->StyleList();
+	TInt origStyleCount=origStyle->Count();
+	TInt copyStyleCount=copyStyle->Count();
+	test(origStyleCount==copyStyleCount);
+	for (TInt ii=0;ii<origStyleCount;ii++)
+		{
+		RParagraphStyleInfo oInfo=origStyle->At(ii);
+		RParagraphStyleInfo cInfo=copyStyle->At(ii);
+		test(oInfo.iStyle->iName==cInfo.iStyle->iName);
+		if (oInfo.iStyleForNextPara==NULL)
+			test(cInfo.iStyleForNextPara==NULL);
+		}
+
+	return 1;
+	}
+
+
+LOCAL_C void ConstructEnvWithNullParaFormat()
+	{
+	// Create global layers
+	CParaFormat* normalPara=CParaFormat::NewLC();
+	TParaFormatMask paraFormatMask;
+	normalPara->iHorizontalAlignment=CParaFormat::ELeftAlign;
+	paraFormatMask.SetAttrib(EAttAlignment);
+	TheNormalParaLayer=CParaFormatLayer::NewL(normalPara,paraFormatMask);
+	CleanupStack::PopAndDestroy();  // normalPara
+	TCharFormat charFormat;
+	TCharFormatMask charFormatMask;
+	TheNormalCharLayer=CCharFormatLayer::NewL(charFormat,charFormatMask);
+	//
+	// Create some paragraph styles
+	TheStyleOne=CParagraphStyle::NewL(*TheNormalParaLayer,*TheNormalCharLayer);
+	TheStyleOne->iName=_L("Style1");
+	
+	//	Style two is based on style one
+	TheStyleTwo=CParagraphStyle::NewL( *TheStyleOne, *(TheStyleOne->CharFormatLayer()));
+	TheStyleTwo->iName=_L("Style2");
+	//
+	CParaFormat* styleFormat=CParaFormat::NewLC();
+	TParaFormatMask styleMask;
+	styleFormat->iHorizontalAlignment=CParaFormat::ECenterAlign;
+	styleMask.SetAttrib(EAttAlignment);
+	TheStyleOne->SetL(styleFormat,styleMask);
+	//
+	styleFormat->iHorizontalAlignment=CParaFormat::ERightAlign;
+	//	Set paragraph format to NULL
+	TheStyleTwo->SetL( NULL,styleMask);	
+	CleanupStack::PopAndDestroy();  // styleFormat
+	//
+	// Create style table and insert styles.
+	TheStyleList=CStyleList::NewL();	
+	RParagraphStyleInfo info(TheStyleOne);
+	TInt error=TheStyleList->AppendL(&info);
+	test(error==KErrNone);
+	RParagraphStyleInfo info1=TheStyleList->At(0);
+	CParagraphStyle* style=info1.iStyle;
+	style=NULL;
+
+	RParagraphStyleInfo info2(TheStyleTwo,TheStyleOne);
+	error=TheStyleList->AppendL(&info2);
+	test(error==KErrNone);
+	
+	error=TheStyleList->AppendL(&info2);
+	test(error==KErrAlreadyExists);
+	test(TheStyleList->Count()==2);
+	
+	style=TheStyleList->At(1).iStyle;
+	test(style->iName==_L("Style2"));
+	//
+	// Create the rich text with styles.
+	TheText=CRichText::NewL(TheNormalParaLayer,TheNormalCharLayer,*TheStyleList);
+}
+
+LOCAL_C void ConstructEnvironment()
+// Create some styles.
+//
+	{
+	// Create global layers
+	CParaFormat* normalPara=CParaFormat::NewLC();
+	TParaFormatMask paraFormatMask;
+	normalPara->iHorizontalAlignment=CParaFormat::ELeftAlign;
+	paraFormatMask.SetAttrib(EAttAlignment);
+	TheNormalParaLayer=CParaFormatLayer::NewL(normalPara,paraFormatMask);
+	CleanupStack::PopAndDestroy();  // normalPara
+	TCharFormat charFormat;
+	TCharFormatMask charFormatMask;
+	TheNormalCharLayer=CCharFormatLayer::NewL(charFormat,charFormatMask);
+	//
+	// Create some paragraph styles
+	TheStyleOne=CParagraphStyle::NewL(*TheNormalParaLayer,*TheNormalCharLayer);
+	TheStyleOne->iName=_L("Style1");
+	TheStyleTwo=CParagraphStyle::NewL(*TheNormalParaLayer,*TheNormalCharLayer);
+	TheStyleTwo->iName=_L("Style2");
+	//
+	CParaFormat* styleFormat=CParaFormat::NewLC();
+	TParaFormatMask styleMask;
+	styleFormat->iHorizontalAlignment=CParaFormat::ECenterAlign;
+	styleMask.SetAttrib(EAttAlignment);
+	TheStyleOne->SetL(styleFormat,styleMask);
+	//
+	styleFormat->iHorizontalAlignment=CParaFormat::ERightAlign;
+	TheStyleTwo->SetL(styleFormat,styleMask);
+	CleanupStack::PopAndDestroy();  // styleFormat
+	//
+	// Create style table and insert styles.
+	TheStyleList=CStyleList::NewL();	
+	RParagraphStyleInfo info(TheStyleOne);
+	TInt error=TheStyleList->AppendL(&info);
+	test(error==KErrNone);
+	RParagraphStyleInfo info1=TheStyleList->At(0);
+	CParagraphStyle* style=info1.iStyle;
+	style=NULL;
+
+	RParagraphStyleInfo info2(TheStyleTwo,TheStyleOne);
+	error=TheStyleList->AppendL(&info2);
+	test(error==KErrNone);
+	
+	error=TheStyleList->AppendL(&info2);
+	test(error==KErrAlreadyExists);
+	test(TheStyleList->Count()==2);
+	
+	style=TheStyleList->At(1).iStyle;
+	test(style->iName==_L("Style2"));
+	//
+	// Create the rich text with styles.
+	TheText=CRichText::NewL(TheNormalParaLayer,TheNormalCharLayer,*TheStyleList);
+	}
+
+
+LOCAL_C void KillEnvironment()
+// Kill everything
+//
+	{
+	delete TheText;
+	// the style table is owned by the rich text, and is destroyed there.
+	delete TheNormalParaLayer;
+	delete TheNormalCharLayer;
+	}
+
+
+LOCAL_C void TestConstruction()
+// Test the construction/destruction of rich text with styles
+//
+	{
+	__UHEAP_MARK;
+
+	ConstructEnvironment();
+	KillEnvironment();
+
+	__UHEAP_MARKEND;
+	}
+
+
+LOCAL_C void TestParaWithNullParaFormat()
+	{
+	CParagraphStyle::TApplyParaStyleMode applyMode=CParagraphStyle::ERetainNoSpecificFormats;
+
+	test.Next(_L("Apply style to paragraph with NULL para format"));
+	ConstructEnvWithNullParaFormat();
+	TheText->InsertL(0,_L("HEADINGBODYTEXT"));
+	//
+	TheText->ApplyParagraphStyleL(*TheStyleList->At(1).iStyle,0,1,applyMode);
+	CParaFormat* paraFormat=CParaFormat::NewLC();
+	TheText->GetParagraphFormatL(paraFormat,0);
+	test(paraFormat->iHorizontalAlignment==CParaFormat::ECenterAlign);
+	//
+	TChar delimiter=CEditableText::EParagraphDelimiter;
+	TheText->InsertL(7,delimiter);
+	TheText->GetParagraphFormatL(paraFormat,6);
+	test(paraFormat->iHorizontalAlignment==CParaFormat::ECenterAlign);
+	TheText->GetParagraphFormatL(paraFormat,8);
+	test(paraFormat->iHorizontalAlignment==CParaFormat::ECenterAlign);
+	CleanupStack::PopAndDestroy();
+	KillEnvironment();	
+	}
+
+LOCAL_C void TestSharedPara()
+// Test
+//
+	{
+	CParagraphStyle::TApplyParaStyleMode applyMode=CParagraphStyle::ERetainNoSpecificFormats;
+
+	test.Next(_L("Apply style to shared paragraph"));
+	ConstructEnvironment();
+	TheText->InsertL(0,_L("HEADINGBODYTEXT"));
+	//
+	TheText->ApplyParagraphStyleL(*TheStyleList->At(0).iStyle,0,1,applyMode);
+	CParaFormat* paraFormat=CParaFormat::NewLC();
+	TheText->GetParagraphFormatL(paraFormat,0);
+	test(paraFormat->iHorizontalAlignment==CParaFormat::ECenterAlign);
+	//
+	TChar delimiter=CEditableText::EParagraphDelimiter;
+	TheText->InsertL(7,delimiter);
+	TheText->GetParagraphFormatL(paraFormat,6);
+	test(paraFormat->iHorizontalAlignment==CParaFormat::ECenterAlign);
+	TheText->GetParagraphFormatL(paraFormat,8);
+	test(paraFormat->iHorizontalAlignment==CParaFormat::ECenterAlign);
+	CleanupStack::PopAndDestroy();
+	KillEnvironment();
+	}
+
+
+LOCAL_C void TestNonSharedPara()
+//
+	{
+	CParagraphStyle::TApplyParaStyleMode applyMode=CParagraphStyle::ERetainNoSpecificFormats;
+
+	test.Next(_L("Apply style to non-shared paragraph"));
+	ConstructEnvironment();
+	//
+	TheText->InsertL(0,_L("This is paragraph one.This is paragraph number two."));
+	TChar delimiter=CEditableText::EParagraphDelimiter;
+	TheText->InsertL(22,delimiter);
+	//
+	TCharFormat charFormat;
+	TCharFormatMask charFormatMask;
+	charFormat.iFontPresentation.iStrikethrough=EStrikethroughOn;
+	charFormatMask.SetAttrib(EAttFontStrikethrough);
+	TheText->ApplyCharFormatL(charFormat,charFormatMask,0,4);
+	//
+	TheText->ApplyParagraphStyleL(*(TheStyleList->At(1).iStyle),0,TheText->DocumentLength(),applyMode);
+	//
+	CParaFormat* paraFormat=CParaFormat::NewLC();
+	TheText->GetParagraphFormatL(paraFormat,0);
+	test(paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign);
+	//
+	TheText->GetParagraphFormatL(paraFormat,10);
+	test(paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign);
+	//
+	TheText->GetParagraphFormatL(paraFormat,30);
+	test(paraFormat->iHorizontalAlignment=CParaFormat::ERightAlign);
+	//
+	CleanupStack::PopAndDestroy();  // para format
+	//
+	/*TEtextComponentInfo info=*/TheText->ComponentInfo();
+	CRichText* theCopy=CRichText::NewL(TheNormalParaLayer,TheNormalCharLayer);
+	testStoreRestoreL(*theCopy,*TheText);
+	test(IsEqual(theCopy,TheText));
+	//
+	theCopy->ApplyParagraphStyleL(*(TheStyleList->At(0).iStyle),25,1,applyMode);
+	CParagraphStyle* tempStyle = CParagraphStyle::NewL(*TheNormalParaLayer,*TheNormalCharLayer);
+	theCopy->InsertL(28,delimiter);
+	theCopy->InsertL(31,delimiter);
+	charFormat.iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+	charFormatMask.ClearAll();
+	charFormatMask.SetAttrib(EAttFontStrokeWeight);
+	theCopy->ApplyCharFormatL(charFormat, charFormatMask, 33, 1);
+	theCopy->NotifyStyleChangedL(tempStyle, TheStyleList->At(0).iStyle);
+	//
+	delete theCopy;
+	delete tempStyle;
+	KillEnvironment();
+	}
+
+
+LOCAL_C void TestStyles()
+// Perform tests
+//
+	{
+	TestSharedPara();
+	TestNonSharedPara();
+	}
+
+LOCAL_C void TestStyleWithNullParaFormat()
+	{
+	TestParaWithNullParaFormat();
+	}
+
+LOCAL_C void TestStyleList()
+	{
+	__UHEAP_MARK;
+	// Test 1
+	// Construction under OOM
+	test.Start(_L("Construction under OOM"));
+	CStyleList* list=NULL;
+	TInt nn;
+	for (nn=0; ;nn++)
+		{
+		__UHEAP_RESET;
+		__UHEAP_SETFAIL(RHeap::EDeterministic,nn);
+		__UHEAP_MARK;
+		TRAPD(ret,
+			list=CStyleList::NewL());
+		if (ret!=KErrNone)
+			{
+			__UHEAP_MARKEND;
+			test(list==NULL);
+			}
+		else
+			{
+			test(list!=NULL);
+			delete list;
+			list=NULL;
+			__UHEAP_MARKEND;
+			break;
+			}
+		}
+	__UHEAP_RESET;
+	TBuf<36> answer;
+	answer.Format(_L("        #allocs for full c'tion: %d\n"),nn-1);
+	test.Printf(answer);
+
+
+	// Test 2
+	// Populated style list, Append under OOM;
+	test.Next(_L("AppendL() under OOM"));
+	CParaFormatLayer* paraLayer=CParaFormatLayer::NewL();
+	CCharFormatLayer* charLayer=CCharFormatLayer::NewL();
+	__UHEAP_MARK;
+	list=CStyleList::NewL();
+	CParagraphStyle* style=NULL;
+	for (TInt mm=0;mm<KMaxStyleListGranularity;mm++)
+		{
+		style=CParagraphStyle::NewL(*paraLayer,*charLayer);
+		RParagraphStyleInfo info(style,NULL);
+		TInt r=list->AppendL(&info);
+		test(r==KErrNone);
+		}
+	test(list->Count()==KMaxStyleListGranularity);
+	
+	for (TInt oo=0; ;oo++)
+		{
+		style=CParagraphStyle::NewL(*paraLayer,*charLayer);
+		RParagraphStyleInfo info(style);
+		__UHEAP_RESET;
+		__UHEAP_SETFAIL(RHeap::EDeterministic,oo);
+		TInt r=KErrNone;
+		TRAPD(ret,
+				r=list->AppendL(&info));
+		if (ret!=KErrNone)
+			{
+			test(r!=KErrAlreadyExists);
+			test(list->Count()==KMaxStyleListGranularity);
+			}
+		else
+			{
+			test(r==KErrNone);
+			test(list->Count()==KMaxStyleListGranularity+1);
+			break;
+			}
+		__UHEAP_RESET;
+		}
+	delete list;
+	list=NULL;
+	style=NULL;
+	__UHEAP_MARKEND;
+	__UHEAP_RESET;
+
+
+	// Test 3
+	// Inserting a duplicate
+	test.Next(_L("AppendL() a duplicate"));
+	list=CStyleList::NewL();
+	style=NULL;
+	for (TInt pp=0;pp<KMaxStyleListGranularity;pp++)
+		{
+		style=CParagraphStyle::NewL(*paraLayer,*charLayer);
+		RParagraphStyleInfo info(style,NULL);
+		list->AppendL(&info);
+		}
+	test(list->Count()==KMaxStyleListGranularity);
+	RParagraphStyleInfo info=list->At(0);
+	TInt r=list->AppendL(&info);
+	test(r==KErrAlreadyExists);
+	test(list->Count()==KMaxStyleListGranularity);
+	test(info.iStyle->CharFormatLayer()!=NULL);  // the duplicate style has not been deleted.
+	delete list;
+
+
+	// Test 4
+	// Looking for a style by name that does not exist.
+	test.Next(_L("IndexByName() where style not present"));
+	list=CStyleList::NewL();
+	style=NULL;
+	TUint name='A';
+	for (TInt qq=0;qq<KMaxStyleListGranularity;qq++)
+		{
+		style=CParagraphStyle::NewL(*paraLayer,*charLayer);
+		style->iName.Append(name);
+		name++;
+		RParagraphStyleInfo info(style,NULL);
+		list->AppendL(&info);
+		}
+	test(list->Count()==KMaxStyleListGranularity);
+	TParagraphStyleName search=_L("not present");
+	/*TInt index=*/list->IndexByName(search);
+
+	delete list;
+
+	delete paraLayer;
+	delete charLayer;
+
+	__UHEAP_MARKEND;
+	test.End();
+	}
+
+
+LOCAL_C void TestHarness()
+// Test rich text style usage.
+//
+    {
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-TTEXT-LEGACY-T_STYLE-0001 RichText Styles "));
+	// Do the tests.
+	TestConstruction();
+	TestStyles();
+	TestStyleWithNullParaFormat();
+	test.Next(_L("CStyleList"));
+	TestStyleList();
+	//
+    }
+
+
+LOCAL_C void setupCleanup()
+//
+// Initialise the cleanup stack.
+//
+    {
+
+	TheTrapCleanup=CTrapCleanup::New();
+	TRAPD(r,\
+		{\
+		for (TInt i=KTestCleanupStack;i>0;i--)\
+			CleanupStack::PushL((TAny*)1);\
+		test(r==KErrNone);\
+		CleanupStack::Pop(KTestCleanupStack);\
+		});
+	}
+
+
+LOCAL_C void DeleteDataFile(const TDesC& aFullName)
+	{
+	RFs fsSession;
+	TInt err = fsSession.Connect();
+	if(err == KErrNone)
+		{
+		TEntry entry;
+		if(fsSession.Entry(aFullName, entry) == KErrNone)
+			{
+			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
+			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
+			if(err != KErrNone) 
+				{
+				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
+				}
+			err = fsSession.Delete(aFullName);
+			if(err != KErrNone) 
+				{
+				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
+				}
+			}
+		fsSession.Close();
+		}
+	else
+		{
+		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
+		}
+	}
+
+GLDEF_C TInt E32Main()
+//
+// Test the streaming framework.
+//
+    {
+
+	test.Title();	
+	__UHEAP_MARK;
+	setupCleanup();
+	TRAPD(r,TestHarness());
+    test(r == KErrNone);
+
+	delete TheTrapCleanup;
+	
+	__UHEAP_MARKEND;
+	
+	::DeleteDataFile(KOutputFile);		//deletion of data files must be before call to End() - DEF047652
+	
+	test.End();
+	test.Close();
+
+	return 0;
+    }