sl@0: /*
sl@0: * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: * All rights reserved.
sl@0: * This component and the accompanying materials are made available
sl@0: * under the terms of "Eclipse Public License v1.0"
sl@0: * which accompanies this distribution, and is available
sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: *
sl@0: * Initial Contributors:
sl@0: * Nokia Corporation - initial contribution.
sl@0: *
sl@0: * Contributors:
sl@0: *
sl@0: * Description: 
sl@0: *
sl@0: */
sl@0: 
sl@0: 
sl@0: /**
sl@0:  @file
sl@0:  @test
sl@0:  @internalComponent
sl@0: */
sl@0: 
sl@0: #include "T_LinkedFonts2.h"
sl@0: #include "linkedfontsprivate.h"
sl@0: #include <graphics/openfontlinkedtypefacespecification.h>
sl@0: #include <openfontlinkedtypefaceelementspec.h>
sl@0: 
sl@0: CTLinkedFonts2::CTLinkedFonts2(CTestStep* aStep)
sl@0: :	CTGraphicsBase(aStep)
sl@0: 	{
sl@0: 	
sl@0: 	}
sl@0: 
sl@0: CTLinkedFonts2::~CTLinkedFonts2()
sl@0: 	{
sl@0: 	delete iGc;
sl@0: 	delete iDev;
sl@0: 	if (iFbs)
sl@0: 		iFbs->Disconnect();
sl@0: 	}
sl@0: 
sl@0: void CTLinkedFonts2::TestPanic(TInt aPanic)
sl@0: 	{
sl@0: 	_LIT(KFntTestStorePanicCategory,"TestFntStore");
sl@0: 	User::Panic(KFntTestStorePanicCategory,aPanic);
sl@0: 	}
sl@0: 
sl@0: void CTLinkedFonts2::RunTestCaseL(TInt aCurTestCase)
sl@0: 	{
sl@0: 	((CTLinkedFonts2Step*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
sl@0: 	switch (aCurTestCase)
sl@0: 		{
sl@0: 		case 1:
sl@0: 			((CTLinkedFonts2Step*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-LINKEDFONTS-0046"));
sl@0: 			InitializeTestHarnessL();
sl@0: 			break;
sl@0: 		case 2:
sl@0: 			((CTLinkedFonts2Step*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-LINKEDFONTS-0001"));
sl@0: 			TestLinkedClientGettersAndSettersL();
sl@0: 			break;
sl@0: 		case 3:
sl@0: 			((CTLinkedFonts2Step*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-LINKEDFONTS-0002"));
sl@0: 			TestLinkedClientAddAndRemoveL();
sl@0: 			break;
sl@0: 		case 4:
sl@0: 			((CTLinkedFonts2Step*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-LINKEDFONTS-0003"));
sl@0: 			TestOpenClientAddAndRemoveL();
sl@0: 			break;
sl@0: 		case 5:
sl@0: /**
sl@0: @SYMTestCaseID GRAPHICS-FNTSTORE-LINKEDFONTS-0004
sl@0: */
sl@0: 			((CTLinkedFonts2Step*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-LINKEDFONTS-0004"));
sl@0: 			TestLinkedRegistrationAndFetchL();
sl@0: 			break;
sl@0: 		case 6:
sl@0: 			((CTLinkedFonts2Step*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-LINKEDFONTS-0100"));
sl@0: 			TestComplexLinkedFontsBasicL();
sl@0: 			break;
sl@0: 		case 7:
sl@0: 			((CTLinkedFonts2Step*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
sl@0: 			//((CTLinkedFonts2Step*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-LINKEDFONTS-0101"));
sl@0: 			//TestBitmapFontsL();
sl@0: 			break;
sl@0: 		default:
sl@0: 			CloseTestHarnessL();
sl@0: 			TestComplete();
sl@0: 			((CTLinkedFonts2Step*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
sl@0: 			((CTLinkedFonts2Step*)iStep)->CloseTMSGraphicsStep();
sl@0: 			break;
sl@0: 		}
sl@0: 	((CTLinkedFonts2Step*)iStep)->RecordTestResultL();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: 	@SYMTestCaseID
sl@0: 	GRAPHICS-FNTSTORE-LINKEDFONTS-0046
sl@0: 
sl@0: 	@SYMTestCaseDesc
sl@0: 	Starts a server session with the font and bitmap server.
sl@0: 
sl@0: 	@SYMTestActions
sl@0: 	1. Creates a session with the Font and Bitmap server.
sl@0: 	2. Gets the current Font and Bitmap server session.
sl@0: 	3. Creates a CFbsScreenDevice object.
sl@0: 	4. Sets screen device to null.
sl@0: 	5. Sets auto update to true.
sl@0: 	6. Creates a font and bitmap server graphics context for the 
sl@0: 	   device and activates it.
sl@0: 	
sl@0: 	@SYMTestExpectedResults
sl@0: 	All steps 1-6 above succeed.  
sl@0: */
sl@0: void CTLinkedFonts2::StartServer()
sl@0: 	{
sl@0: 	TInt ret = RFbsSession::Connect();
sl@0: 	TEST2(ret, KErrNone);
sl@0: 	iFbs = RFbsSession::GetSession();
sl@0: 	TEST(iFbs != NULL);
sl@0: 	
sl@0: 	if (iFbs==NULL)
sl@0: 		{
sl@0: 		//cannot continue
sl@0: 		TestComplete();
sl@0: 		return;
sl@0: 		}
sl@0: 
sl@0: 	TInt err;
sl@0: 	TDisplayMode mode[4] = {EColor16MA,EColor16MU,EColor64K,EColor16MAP};
sl@0: 
sl@0: 	TInt count;
sl@0: 	for (count=0; count < (sizeof(mode)/sizeof(mode[0])) ;count++)
sl@0: 		{
sl@0: 		TRAP(err, iDev = CFbsScreenDevice::NewL(KNullDesC, mode[count]));
sl@0: 		if (err!=KErrNotSupported)
sl@0: 			{
sl@0: 			break;
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	if(err == KErrNone)
sl@0: 		{
sl@0: 		INFO_PRINTF2(_L("%d screen mode created"),mode[count]);
sl@0: 		iDev->ChangeScreenDevice(NULL);
sl@0: 		iDev->SetAutoUpdate(ETrue);
sl@0: 		iDev->CreateContext(iGc);
sl@0: 		
sl@0: 		//use and create a font
sl@0: 		//otherwise for memory tests there is a leak reported since the first AllocL
sl@0: 		//creates the space for the array (e.g. CTypefaceStore::AddFontL()) and 
sl@0: 		//although the array is emptied the array element storage is not deleted
sl@0: 		//until everything is closed
sl@0: 		_LIT(KSansSerif, "DejaVu Sans Condensed");
sl@0: 		TTypeface typeface;
sl@0: 		typeface.iName = KSansSerif;
sl@0: 		TFontSpec fs;
sl@0: 		fs.iTypeface = typeface;
sl@0: 		fs.iHeight = 20;
sl@0: 		CFbsFont* font = NULL;
sl@0: 		TInt err1 = iDev->GetNearestFontToDesignHeightInPixels(font, fs);
sl@0: 		TEST(err1==KErrNone);
sl@0: 		if (err1 == KErrNone)
sl@0: 			{
sl@0: 			TSize scrSize = iDev->SizeInPixels();
sl@0: 			iGc->UseFont(font);
sl@0: 			_LIT(KTestText,"TEST");
sl@0: 			iGc->DrawText(KTestText, TPoint((scrSize.iWidth / 2) + 50, 50));
sl@0: 			iGc->DiscardFont();
sl@0: 			iDev->ReleaseFont(font);
sl@0: 			}	
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		INFO_PRINTF2(_L("Could not create screen mode error %d"),err);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void CTLinkedFonts2::InitializeTestHarnessL()
sl@0: 	{
sl@0: 	INFO_PRINTF1(_L("Initialising the test harness T_LinkedFonts2 (PREQ2146)"));
sl@0: 	StartServer();
sl@0: 	}
sl@0: 
sl@0: void CTLinkedFonts2::CloseTestHarnessL()
sl@0: 	{
sl@0: 	}
sl@0: /**
sl@0: @SYMTestCaseID
sl@0: GRAPHICS-FNTSTORE-LINKEDFONTS-0001
sl@0: 
sl@0: @SYMPREQ
sl@0: PREQ2146
sl@0: 
sl@0: @SYMREQ
sl@0: PREQ2146
sl@0: 
sl@0: @SYMTestCaseDesc
sl@0: Create a linked typeface element & group. Set the parameters they provide.
sl@0: 
sl@0: @SYMTestPriority
sl@0: Critical
sl@0: 
sl@0: @SYMTestStatus
sl@0: Implemented
sl@0: 
sl@0: @SYMTestActions
sl@0: Tests that the values set are stored correctly by the linked typeface element & group.
sl@0: 
sl@0: @SYMTestExpectedResults
sl@0: Values are set correctly
sl@0: */
sl@0: void CTLinkedFonts2::TestLinkedClientGettersAndSettersL()
sl@0: 	{
sl@0: 	INFO_PRINTF1(_L("CTLinkedFonts2::TestLinkedClientGettersAndSettersL"));
sl@0: 	CLinkedTypefaceElementSpec *elementSpec;
sl@0: 	_LIT(KLinkedTypefaceName, "TypefaceNumberOne");
sl@0: 	elementSpec = CLinkedTypefaceElementSpec::NewLC(KLinkedTypefaceName, 10);
sl@0: 	
sl@0: 	elementSpec->SetCanonical(ETrue);
sl@0: 	TEST(elementSpec->Canonical());
sl@0: 	
sl@0: 	//Test Remaining Getters & Setters
sl@0: 	elementSpec->SetCanonical(EFalse);
sl@0: 
sl@0: 	CleanupStack::PopAndDestroy(elementSpec);
sl@0: 	
sl@0: 	CLinkedTypefaceGroup* grp = CLinkedTypefaceGroup::NewLC(10);
sl@0: 	const TInt KPercentageValue = 50;
sl@0: 	TInt ret;
sl@0: 	
sl@0: 	grp->SetBoldnessPercentage(KPercentageValue);
sl@0: 	ret = grp->BoldnessPercentage();
sl@0: 	TEST2(ret, KPercentageValue);
sl@0: 	
sl@0: 	grp->SetItalicAngle(KPercentageValue);
sl@0: 	ret = grp->ItalicAngle();
sl@0: 	TEST2(ret, KPercentageValue);
sl@0: 	
sl@0: 	grp->SetBaselineShift(CLinkedTypefaceGroup::ENoBaselineShift);
sl@0: 	CLinkedTypefaceGroup::TBaselineShift ret2 = grp->BaselineShift();
sl@0: 	TEST2(ret2, CLinkedTypefaceGroup::ENoBaselineShift);
sl@0: 	
sl@0: 	CleanupStack::PopAndDestroy(grp);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID
sl@0: GRAPHICS-FNTSTORE-LINKEDFONTS-0002
sl@0: 
sl@0: @SYMPREQ
sl@0: PREQ2146
sl@0: 
sl@0: @SYMREQ
sl@0: PREQ2146
sl@0: 
sl@0: @SYMTestCaseDesc
sl@0: Tests construction of a Linked Typeface specification with both valid & invalid data.
sl@0: 
sl@0: @SYMTestPriority
sl@0: Critical
sl@0: 
sl@0: @SYMTestStatus
sl@0: Implemented
sl@0: 
sl@0: @SYMTestActions
sl@0: Tests a number of different combinations (listed) of adding, removing and updating groups and
sl@0: elements from a linked typeface specification.
sl@0: 
sl@0: Tests applicable to CLinkedTypefaceGroup / CLinkedTypefaceSpecification
sl@0: 
sl@0: 1. Adding a valid group
sl@0: 2. Adding a duplicate group
sl@0: 3. Adding a group with the same Id as an existing one
sl@0: 4. Removal of group
sl@0: 12. Remove invalid GroupId
sl@0: 13. Adding more than KMaxLinkedTypefaceGroups groups
sl@0: 14. Retrieve Group with index out of bounds
sl@0: 
sl@0: 
sl@0: Tests applicable to CLinkedTypefaceElementSpec / CLinkedTypefaceSpecification
sl@0: 
sl@0: 5. Adding a valid element
sl@0: 6. Adding a duplicate element
sl@0: 7. Ensuring ordering of elements is as specified
sl@0: 8. Ensure canonical index is correct when element moved/removed
sl@0: 9. Ensuring correct error if extra canonical added
sl@0: 10. Ensuring correct error if canonical activated "in-place"
sl@0: 11. Removal of element
sl@0: 15. Create Specification & Element with too short (0)/long (KMaxTypefaceNameLength) names.
sl@0: 16. Adding more than KMaxLinkedTypefaces Elements
sl@0: 17. Retrieve Typeface with index out of bounds
sl@0: 
sl@0: @SYMTestExpectedResults
sl@0: The canonical index is expected to be set to the values provided through the test after the 
sl@0: various operations performed. Addition & removal should provide success or fail error codes
sl@0: as indicated throughout the test. Actions are referenced within the code with expected results.
sl@0: */
sl@0: void CTLinkedFonts2::TestLinkedClientAddAndRemoveL()
sl@0: 	{
sl@0: 	INFO_PRINTF1(_L("TestLinkedClientAddAndRemoveL"));
sl@0: 	
sl@0: 	CFbsTypefaceStore* store = CFbsTypefaceStore::NewL(NULL);
sl@0: 	CleanupStack::PushL(store);
sl@0: 	
sl@0: 	_LIT(KTestLinkedFont, "TestLinkedFont");
sl@0: 	CLinkedTypefaceSpecification* typefaceSpec = 
sl@0: 		CLinkedTypefaceSpecification::NewLC(KTestLinkedFont);
sl@0: 	
sl@0: 	TInt canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == KErrNotFound);
sl@0: 	TRAPD(ret, typefaceSpec->RegisterLinkedTypefaceL(*store));
sl@0: 	TEST(ret == KErrNotFound);
sl@0: 
sl@0: 	
sl@0: 	const TInt KGroup1Id = 1;
sl@0: 	CLinkedTypefaceGroup* group1 = CLinkedTypefaceGroup::NewLC(KGroup1Id);
sl@0: 	//Action 1 : Valid group
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group1));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(group1);
sl@0: 	
sl@0: 	//Action 2 : Same group again
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group1));
sl@0: 	TEST(ret == KErrAlreadyExists);
sl@0: 	
sl@0: 	//Action 3 : Group with existing Id
sl@0: 	CLinkedTypefaceGroup* duplicateGroup = CLinkedTypefaceGroup::NewLC(KGroup1Id);
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*duplicateGroup));
sl@0: 	TEST(ret == KErrAlreadyExists);
sl@0: 	CleanupStack::PopAndDestroy(duplicateGroup);
sl@0: 	
sl@0: 	//Action 1 : Valid group
sl@0: 	const TInt KGroup2Id = 2;
sl@0: 	CLinkedTypefaceGroup* group2 = CLinkedTypefaceGroup::NewLC(KGroup2Id);
sl@0: 	group2->SetBaselineShift(CLinkedTypefaceGroup::EBaselineShift);
sl@0: 	group2->SetScalingOption(CLinkedTypefaceGroup::EScalingUpOrDown);
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group2));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(group2);
sl@0: 	
sl@0: 	const TInt KGroup3Id = 4;
sl@0: 	CLinkedTypefaceGroup* group3 = CLinkedTypefaceGroup::NewLC(KGroup3Id);
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group3));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(group3);
sl@0: 	
sl@0: 	//Action 5 : Japanese typefaces
sl@0: 	_LIT(KJapaneseElement, "Japanese");
sl@0: 	CLinkedTypefaceElementSpec* element1 = CLinkedTypefaceElementSpec::NewLC(KJapaneseElement, KGroup2Id);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtBackL(*element1));
sl@0: 	CleanupStack::Pop(element1);
sl@0: 	
sl@0: 	//Action 5: Add the canonical element (Latin)
sl@0: 	_LIT(KLatinElement, "DejaVu Sans Mono Bold");
sl@0: 	CLinkedTypefaceElementSpec* element2 = CLinkedTypefaceElementSpec::NewLC(KLatinElement, KGroup1Id);
sl@0: 	element2->SetCanonical(ETrue);
sl@0: 	
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtIndexL(*element2,0));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(element2);
sl@0: 	
sl@0: 	//Action 8 : Check Canonical Index is correct
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == 0);
sl@0: 	
sl@0: 	//Action 5 : Hindi typefaces
sl@0: 	_LIT(KHindiElement, "Chandas");
sl@0: 	CLinkedTypefaceElementSpec* element3 = CLinkedTypefaceElementSpec::NewLC(KHindiElement, KGroup3Id);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtBackL(*element3));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(element3);
sl@0: 	
sl@0: 	//Action 6 : Same element again
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtBackL(*element3));
sl@0: 	TEST(ret == KErrAlreadyExists);
sl@0: 	
sl@0: 	//Action 7 : Check ordering is correct
sl@0: 	TEST2(element1, typefaceSpec->Typeface(1));
sl@0: 	TEST2(element2, typefaceSpec->Typeface(0));
sl@0: 	TEST2(element3, typefaceSpec->Typeface(2));
sl@0: 	
sl@0: 	_LIT(KDummyTypeface, "DummyTypeface");
sl@0: 	CLinkedTypefaceElementSpec* dummyElement1 = CLinkedTypefaceElementSpec::NewLC(KDummyTypeface, KGroup2Id);
sl@0: 	
sl@0: 	//Action 9 : Add second canonical
sl@0: 	dummyElement1->SetCanonical(ETrue);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtBackL(*dummyElement1));
sl@0: 	TEST(ret == KErrArgument);
sl@0: 
sl@0: 	//Add at front of typeface to check canonical index is updated.
sl@0: 	dummyElement1->SetCanonical(EFalse);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtIndexL(*dummyElement1, 0));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(dummyElement1);
sl@0: 	
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == 1);
sl@0: 	
sl@0: 	dummyElement1 = CLinkedTypefaceElementSpec::NewLC(KDummyTypeface, 180);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtIndexL(*dummyElement1, 0));
sl@0: 	TEST(ret == KErrArgument);
sl@0: 	CleanupStack::PopAndDestroy(dummyElement1);
sl@0: 	
sl@0: 	//Action 11 : Remove Element
sl@0: 	typefaceSpec->RemoveTypeface(0);
sl@0: 	TEST2(element2, typefaceSpec->Typeface(0));
sl@0: 	
sl@0: 	//Action 8 : Check canonical index is correct
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == 0);
sl@0: 	
sl@0: 	//Action 10 : Check error if extra canonical activated "in place"
sl@0: 	typefaceSpec->Typeface(1)->SetCanonical(ETrue);
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == KErrOverflow);
sl@0: 	TRAP(ret, typefaceSpec->RegisterLinkedTypefaceL(*store));
sl@0: 	TEST(ret == KErrOverflow);
sl@0: 	//Reset back to be non-canonical
sl@0: 	typefaceSpec->Typeface(1)->SetCanonical(EFalse);
sl@0: 	
sl@0: 	//Action 8 : Check canonical index is correct
sl@0: 	typefaceSpec->RemoveTypeface(0);
sl@0: 	TEST2(element1, typefaceSpec->Typeface(0));
sl@0: 	
sl@0: 	//Action 8 : Check canonical index is correct
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == -1);
sl@0: 
sl@0: 	//Action 4 : Remove the group
sl@0: 	TRAP(ret, typefaceSpec->RemoveLinkedTypefaceGroup(KGroup3Id));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CLinkedTypefaceGroup* groupRet = typefaceSpec->GroupById(KGroup3Id);
sl@0: 	TEST(groupRet == NULL);
sl@0: 	
sl@0: 	TEST2(element1, typefaceSpec->Typeface(0));
sl@0: 
sl@0: 	//Action 12 : Remove invalid group
sl@0: 	ret = typefaceSpec->RemoveLinkedTypefaceGroup(180);
sl@0: 	TEST(ret == KErrNotFound);
sl@0: 	//Action 4 : Remove group
sl@0: 	ret = typefaceSpec->RemoveLinkedTypefaceGroup(KGroup1Id);
sl@0: 	TEST(ret == KErrNone);
sl@0: 	groupRet = typefaceSpec->GroupById(KGroup1Id);
sl@0: 	TEST(groupRet == NULL);
sl@0: 	
sl@0: 	CleanupStack::PopAndDestroy(typefaceSpec);
sl@0: 	
sl@0: 	//Negative Name length tests
sl@0: 	_LIT(KEmptyTypefaceName, "");
sl@0: 	//Action 15 : Create Specification & Element with 0 length names
sl@0: 	TRAP(ret, typefaceSpec = CLinkedTypefaceSpecification::NewLC(KEmptyTypefaceName));
sl@0: 	TEST(ret == KErrArgument);
sl@0: 	TRAP(ret, dummyElement1 = CLinkedTypefaceElementSpec::NewLC(KEmptyTypefaceName,1));
sl@0: 	TEST(ret < KErrNone);
sl@0: 	//Action 15: Create Specification & Element with name longer than KMaxTypefaceNameLength
sl@0: 	_LIT(KLongTypefaceName, "KErrArgumentKErrArgumentKErrArgument");
sl@0: 	TRAP(ret, typefaceSpec = CLinkedTypefaceSpecification::NewLC(KLongTypefaceName));
sl@0: 	TEST(ret == KErrArgument);
sl@0: 	TRAP(ret, dummyElement1 = CLinkedTypefaceElementSpec::NewLC(KLongTypefaceName,1));
sl@0: 	TEST(ret < KErrNone);
sl@0: 	
sl@0: 	typefaceSpec = CLinkedTypefaceSpecification::NewLC(KTestLinkedFont);
sl@0: 	TInt i;
sl@0: 	for (i = 0 ; i <= KMaxLinkedTypefaceGroups+1 ; i++)
sl@0: 		{
sl@0: 		CLinkedTypefaceGroup* group = CLinkedTypefaceGroup::NewLC(i);
sl@0: 		
sl@0: 		if (i < KMaxLinkedTypefaceGroups)
sl@0: 			{
sl@0: 			//Add Groups 1-KMaxLinkedTypefaceGroups
sl@0: 			TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group));
sl@0: 			CleanupStack::Pop(group);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			//Action 13 : Add group at KMaxLinkedTypefaceGroups+1
sl@0: 			TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group));
sl@0: 			TEST(ret == KErrOverflow);
sl@0: 			CleanupStack::PopAndDestroy(group);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	_LIT(KFormatElementName, "Element%d");
sl@0: 	for (i = 0 ; i <= KMaxLinkedTypefaces ; i++)
sl@0: 		{
sl@0: 		TBuf<18> elementName;
sl@0: 		elementName.Format(KFormatElementName,i);
sl@0: 		CLinkedTypefaceElementSpec* element = CLinkedTypefaceElementSpec::NewLC(elementName,i);
sl@0: 		if (i < KMaxLinkedTypefaces)
sl@0: 			{
sl@0: 			//Add Elements 1-KMaxLinkedTypefaces
sl@0: 			TRAP(ret,typefaceSpec->AddTypefaceAtBackL(*element));
sl@0: 			CleanupStack::Pop(element);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			//Action 16 : Add element KMaxLinkedTypefaces+1
sl@0: 			TRAP(ret,typefaceSpec->AddTypefaceAtBackL(*element));
sl@0: 			TEST(ret == KErrOverflow);
sl@0: 			CleanupStack::PopAndDestroy(element);
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 	//Action 14 : Retrieve out of bounds groups
sl@0: 	TEST2(typefaceSpec->Group(-1), NULL);
sl@0: 	TEST2(typefaceSpec->Group(typefaceSpec->GroupCount()+1), NULL);
sl@0: 	//Action 17 : Retrieve typeface with index out of bounds
sl@0: 	TEST2(typefaceSpec->Typeface(-1), NULL);
sl@0: 	TEST2(typefaceSpec->Typeface(typefaceSpec->TypefaceCount()+1), NULL);
sl@0: 	//Action 11 : Remove typeface with index out of bounds
sl@0: 	TEST2(typefaceSpec->RemoveTypeface(-1), KErrNotFound);
sl@0: 	TEST2(typefaceSpec->RemoveTypeface(typefaceSpec->TypefaceCount()+1), KErrNotFound);
sl@0: 	
sl@0: 	CleanupStack::PopAndDestroy(2, store);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID
sl@0: GRAPHICS-FNTSTORE-LINKEDFONTS-0003
sl@0: 
sl@0: @SYMPREQ
sl@0: PREQ2146
sl@0: 
sl@0: @SYMREQ
sl@0: PREQ2146
sl@0: 
sl@0: @SYMTestCaseDesc
sl@0: Tests the Add & RemoveTypeface functions provided by COpenFontLinkedTypefaceSpecification
sl@0: 
sl@0: @SYMTestPriority
sl@0: Critical
sl@0: 
sl@0: @SYMTestStatus
sl@0: Implemented
sl@0: 
sl@0: @SYMTestActions
sl@0: Tests applicable to CLinkedTypefaceGroup / COpenFontLinkedTypefaceSpecification
sl@0: 
sl@0: 1. Adding a valid group
sl@0: 2. Adding a duplicate group (same object)
sl@0: 3. Adding a group with the same Id as an existing one
sl@0: 4. Removal of group
sl@0: 12. Remove invalid GroupId
sl@0: 13. Adding more than KMaxLinkedTypefaceGroups groups
sl@0: 14. Retrieve Group with index out of bounds
sl@0: 
sl@0: Tests applicable to COpenFontLinkedTypefaceElementSpec / COpenFontLinkedTypefaceSpecification
sl@0: 
sl@0: 5. Adding a valid element
sl@0: 6. Adding a duplicate element (same object)
sl@0: 7. Ensuring ordering of elements is as specified
sl@0: 8. Ensure canonical index is correct when element moved/removed
sl@0: 9. Ensuring correct error if extra canonical added
sl@0: 10. Ensuring correct error if canonical activated "in-place"
sl@0: 11. Removal of element
sl@0: 15. Create Specification & Element with too short (0)/long (KMaxTypefaceNameLength) names.
sl@0: 16. Adding more than KMaxLinkedTypefaces Elements
sl@0: 17. Retrieve Typeface with index out of bounds
sl@0: 
sl@0: @SYMTestExpectedResults
sl@0: The canonical index is expected to be set to the values provided through the test after the 
sl@0: various operations performed. Addition & removal should provide success or fail error codes
sl@0: as indicated throughout the test. Actions are referenced within the code with expected results.
sl@0: */
sl@0: void CTLinkedFonts2::TestOpenClientAddAndRemoveL()
sl@0: 	{
sl@0: 	INFO_PRINTF1(_L("TestOpenClientAddAndRemoveL"));
sl@0: 	
sl@0: 	_LIT(KTestLinkedFont, "TestLinkedFont");
sl@0: 	COpenFontLinkedTypefaceSpecification* typefaceSpec = 
sl@0: 		COpenFontLinkedTypefaceSpecification::NewLC(KTestLinkedFont);
sl@0: 	
sl@0: 	TInt canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == -1);
sl@0: 	
sl@0: 	TInt ret;
sl@0: 	
sl@0: 	//Action 1 : Add a valid group
sl@0: 	const TInt KGroup1Id = 1;
sl@0: 	CLinkedTypefaceGroup* group1 = CLinkedTypefaceGroup::NewLC(KGroup1Id);
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group1));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(group1);
sl@0: 	
sl@0: 	//Action 2 : Add a duplicate group
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group1));
sl@0: 	TEST(ret == KErrAlreadyExists);
sl@0: 	
sl@0: 	//Action 3 : Add a group with the same id
sl@0: 	CLinkedTypefaceGroup* duplicateGroup = CLinkedTypefaceGroup::NewLC(KGroup1Id);
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*duplicateGroup));
sl@0: 	TEST(ret == KErrAlreadyExists);
sl@0: 	CleanupStack::PopAndDestroy(duplicateGroup);
sl@0: 	
sl@0: 	//Action 5 : Add a valid element
sl@0: 	const TInt KGroup2Id = 2;
sl@0: 	CLinkedTypefaceGroup* group2 = CLinkedTypefaceGroup::NewLC(KGroup2Id);
sl@0: 	group2->SetBaselineShift(CLinkedTypefaceGroup::EBaselineShift);
sl@0: 	group2->SetScalingOption(CLinkedTypefaceGroup::EScalingUpOrDown);
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group2));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(group2);
sl@0: 	
sl@0: 	const TInt KGroup3Id = 4;
sl@0: 	CLinkedTypefaceGroup* group3 = CLinkedTypefaceGroup::NewLC(KGroup3Id);
sl@0: 	TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group3));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(group3);
sl@0: 	
sl@0: 	//Action 5 : Add a valid element
sl@0: 	_LIT(KJapaneseElement, "Japanese");
sl@0: 	COpenFontLinkedTypefaceElementSpec* element1 = COpenFontLinkedTypefaceElementSpec::NewLC(KJapaneseElement, KGroup2Id);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtBackL(*element1));
sl@0: 	CleanupStack::Pop(element1);
sl@0: 	
sl@0: 	//Action 5 : Add a valid element
sl@0: 	_LIT(KLatinElement, "DejaVu Sans Mono Bold");
sl@0: 	COpenFontLinkedTypefaceElementSpec* element2 = COpenFontLinkedTypefaceElementSpec::NewLC(KLatinElement, KGroup1Id);
sl@0: 	element2->SetCanonical(ETrue);
sl@0: 	
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtIndexL(*element2,0));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(element2);
sl@0: 	
sl@0: 	//Action 8 : Ensure canonical index correct
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == 0);
sl@0: 	
sl@0: 	_LIT(KHindiElement, "Chandas");
sl@0: 	COpenFontLinkedTypefaceElementSpec* element3 = COpenFontLinkedTypefaceElementSpec::NewLC(KHindiElement, KGroup3Id);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtBackL(*element3));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(element3);
sl@0: 	
sl@0: 	//Action 6 : Duplicate element
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtBackL(*element3));
sl@0: 	TEST(ret == KErrAlreadyExists);
sl@0: 	
sl@0: 	//Action 7 : Ensure ordering correct
sl@0: 	TEST2(element1, typefaceSpec->Typeface(1));
sl@0: 	TEST2(element2, typefaceSpec->Typeface(0));
sl@0: 	TEST2(element3, typefaceSpec->Typeface(2));
sl@0: 	
sl@0: 	_LIT(KDummyTypeface, "DummyTypeface");
sl@0: 	COpenFontLinkedTypefaceElementSpec* dummyElement1 = COpenFontLinkedTypefaceElementSpec::NewLC(KDummyTypeface, KGroup2Id);
sl@0: 	
sl@0: 	//Action 9 : Add 2nd canonical
sl@0: 	dummyElement1->SetCanonical(ETrue);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtBackL(*dummyElement1));
sl@0: 	TEST(ret == KErrArgument);
sl@0: 	
sl@0: 	//Add at front of typeface to check canonical index is updated.
sl@0: 	dummyElement1->SetCanonical(EFalse);
sl@0: 	TRAP(ret, typefaceSpec->AddTypefaceAtIndexL(*dummyElement1, 0));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CleanupStack::Pop(dummyElement1);
sl@0: 	
sl@0: 	//Action 8 : Check canonical updated
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == 1);
sl@0: 	
sl@0: 	//Action 11 : Remove element
sl@0: 	typefaceSpec->RemoveTypeface(0);
sl@0: 	TEST2(element2, typefaceSpec->Typeface(0));
sl@0: 	
sl@0: 	//Action 8 : Check canonical updated
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == 0);
sl@0: 	
sl@0: 	//Action 10 : Additional canonical set in-place
sl@0: 	typefaceSpec->Typeface(1)->SetCanonical(ETrue);
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == KErrOverflow);
sl@0: 	typefaceSpec->Typeface(1)->SetCanonical(EFalse);
sl@0: 	
sl@0: 	//Action 11 : Remove element
sl@0: 	typefaceSpec->RemoveTypeface(0);
sl@0: 	TEST2(element1, typefaceSpec->Typeface(0));
sl@0: 	
sl@0: 	//Action 8 : Canonical updated
sl@0: 	canIndex = typefaceSpec->CanonicalIndex();
sl@0: 	TEST(canIndex == -1);
sl@0: 
sl@0: 	//Action 4 : Remove group
sl@0: 	TRAP(ret, typefaceSpec->RemoveLinkedTypefaceGroup(KGroup3Id));
sl@0: 	TEST(ret == KErrNone);
sl@0: 	CLinkedTypefaceGroup* groupRet = typefaceSpec->GroupById(KGroup3Id);
sl@0: 	TEST(groupRet == NULL);
sl@0: 	
sl@0: 	TEST2(element1, typefaceSpec->Typeface(0));
sl@0: 	
sl@0: 	//Action 12 : Remove invalid group Id
sl@0: 	ret = typefaceSpec->RemoveLinkedTypefaceGroup(180);
sl@0: 	TEST(ret == KErrNotFound);
sl@0: 	ret = typefaceSpec->RemoveLinkedTypefaceGroup(KGroup1Id);
sl@0: 	TEST(ret == KErrNone);
sl@0: 		
sl@0: 	CleanupStack::PopAndDestroy(typefaceSpec);	
sl@0: 	
sl@0: 	//Negative Name length tests
sl@0: 	_LIT(KEmptyTypefaceName, "");
sl@0: 	//Action 15 : Create Specifications 
sl@0: 	TRAP(ret, typefaceSpec = COpenFontLinkedTypefaceSpecification::NewLC(KEmptyTypefaceName));
sl@0: 	TEST(ret == KErrArgument);
sl@0: 	TRAP(ret, dummyElement1 = COpenFontLinkedTypefaceElementSpec::NewLC(KEmptyTypefaceName,1));
sl@0: 	TEST(ret < KErrNone);
sl@0: 	_LIT(KLongTypefaceName, "KErrArgumentKErrArgumentKErrArgument");
sl@0: 	TRAP(ret, typefaceSpec = COpenFontLinkedTypefaceSpecification::NewLC(KLongTypefaceName));
sl@0: 	TEST(ret == KErrArgument);
sl@0: 	TRAP(ret, dummyElement1 = COpenFontLinkedTypefaceElementSpec::NewLC(KLongTypefaceName,1));
sl@0: 	TEST(ret < KErrNone);
sl@0: 	
sl@0: 	typefaceSpec = COpenFontLinkedTypefaceSpecification::NewLC(KTestLinkedFont);
sl@0: 	TInt i;
sl@0: 	for (i = 0 ; i <= KMaxLinkedTypefaceGroups+1 ; i++)
sl@0: 		{
sl@0: 		CLinkedTypefaceGroup* group = CLinkedTypefaceGroup::NewLC(i);
sl@0: 		
sl@0: 		if (i < KMaxLinkedTypefaceGroups)
sl@0: 			{
sl@0: 			TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group));
sl@0: 			CleanupStack::Pop(group);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TRAP(ret, typefaceSpec->AddLinkedTypefaceGroupL(*group));
sl@0: 			TEST(ret == KErrOverflow);
sl@0: 			CleanupStack::PopAndDestroy(group);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	_LIT(KFormatElementName, "Element%d");
sl@0: 	for (i = 0 ; i <= KMaxLinkedTypefaces ; i++)
sl@0: 		{
sl@0: 		TBuf<18> elementName;
sl@0: 		elementName.Format(KFormatElementName,i);
sl@0: 		COpenFontLinkedTypefaceElementSpec* element = COpenFontLinkedTypefaceElementSpec::NewLC(elementName,i);
sl@0: 		if (i < KMaxLinkedTypefaces)
sl@0: 			{
sl@0: 			TRAP(ret,typefaceSpec->AddTypefaceAtBackL(*element));
sl@0: 			CleanupStack::Pop(element);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TRAP(ret,typefaceSpec->AddTypefaceAtBackL(*element));
sl@0: 			TEST(ret == KErrOverflow);
sl@0: 			CleanupStack::PopAndDestroy(element);
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 	TEST2(typefaceSpec->Group(-1), NULL);
sl@0: 	TEST2(typefaceSpec->Group(typefaceSpec->GroupCount()+1), NULL);
sl@0: 	TEST2(typefaceSpec->Typeface(-1), NULL);
sl@0: 	TEST2(typefaceSpec->Typeface(typefaceSpec->TypefaceCount()+1), NULL);
sl@0: 	TEST2(typefaceSpec->RemoveTypeface(-1), KErrNotFound);
sl@0: 	TEST2(typefaceSpec->RemoveTypeface(typefaceSpec->TypefaceCount()+1), KErrNotFound);
sl@0: 	CleanupStack::PopAndDestroy(typefaceSpec);
sl@0: 	}
sl@0: 
sl@0: /* Function is used to determine if complex fonts are available.  It looks for a 
sl@0: test Devanagari font
sl@0: */
sl@0: TBool CTLinkedFonts2::ComplexFontAvailable()
sl@0: 	{
sl@0: 	_LIT(KTypefaceOT, "Chandas");
sl@0: 
sl@0: 	// Create the linked font
sl@0: 	TTypeface typeface;
sl@0: 	typeface.iName = KTypefaceOT;
sl@0: 	TFontSpec fs1;
sl@0: 	fs1.iTypeface = typeface;
sl@0: 	fs1.iHeight = 4;
sl@0: 	CFbsFont* font = NULL;
sl@0: 	TInt err = iDev->GetNearestFontToDesignHeightInPixels(font, fs1);
sl@0: 	if (font)
sl@0: 		{
sl@0: 		TFontSpec fs2 = font->FontSpecInTwips();
sl@0: 		iDev->ReleaseFont(font);
sl@0: 		if (fs2.iTypeface.iName.Compare(KTypefaceOT) == 0)
sl@0: 			{
sl@0: 			return ETrue;
sl@0: 			}
sl@0: 		}
sl@0: 	INFO_PRINTF1(_L("(N.B. Complex font not available so complex parts of test skipped)"));
sl@0: 	return EFalse;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:    @SYMTestCaseID			GRAPHICS-FNTSTORE-LINKEDFONTS-0100
sl@0: 
sl@0:    @SYMPREQ					PREQ2146
sl@0: 
sl@0:    @SYMREQ					REQ10924, REQ10925, REQ10926
sl@0: 
sl@0:    @SYMTestCaseDesc			To ensure that a linked typeface including a complex font can be created
sl@0: 							and used.  Test access to characters in a complex linked font.
sl@0: 
sl@0:    @SYMTestPriority			Critical
sl@0: 
sl@0:    @SYMTestStatus			Implemented
sl@0: 
sl@0:    @SYMTestActions			(1) Create a linked font with a complex typeface. Draw text, 
sl@0:    								and compare	against text drawn using a non-linked font.
sl@0: 
sl@0:    @SYMTestExpectedResults	(1) - test allows a linked font with a complex typeface to be created
sl@0: */
sl@0: void CTLinkedFonts2::TestComplexLinkedFontsBasicL()
sl@0: 	{
sl@0: 	INFO_PRINTF1(_L("LinkedFonts2::TestComplexLinkedFontsBasicL"));
sl@0: 
sl@0: 	CFbsTypefaceStore* store = CFbsTypefaceStore::NewL(iDev);
sl@0: 	CleanupStack::PushL(store);
sl@0: 
sl@0: 	TBool testComplex = ComplexFontAvailable();
sl@0: 	if (testComplex)
sl@0: 		{
sl@0: 		// Create typeface to be linked
sl@0: 		_LIT(KLinkedTypefaceTT, "DejaVu Sans Condensed");
sl@0: 		_LIT(KLinkedTypefaceOT, "Chandas");
sl@0: 
sl@0: 		CLinkedTypefaceSpecification *typefaceSpec;
sl@0: 		_LIT(KLinkedTypefaceTTOT, "LinkedTypefaceComp");
sl@0: 		
sl@0: 		typefaceSpec = CLinkedTypefaceSpecification::NewLC(KLinkedTypefaceTTOT);
sl@0: 		
sl@0: 		CLinkedTypefaceGroup* group1 = CLinkedTypefaceGroup::NewLC(1);
sl@0: 		typefaceSpec->AddLinkedTypefaceGroupL(*group1);
sl@0: 		CleanupStack::Pop();
sl@0: 		
sl@0: 		CLinkedTypefaceGroup* group2 = CLinkedTypefaceGroup::NewLC(2);
sl@0: 		typefaceSpec->AddLinkedTypefaceGroupL(*group2);
sl@0: 		CleanupStack::Pop();
sl@0: 		
sl@0: 		// Add first typeface
sl@0: 		CLinkedTypefaceElementSpec *elementSpec1;
sl@0: 		elementSpec1 = CLinkedTypefaceElementSpec::NewLC(KLinkedTypefaceTT, 1);
sl@0: 		
sl@0: 		CLinkedTypefaceElementSpec *elementSpec2;
sl@0: 		elementSpec2 = CLinkedTypefaceElementSpec::NewLC(KLinkedTypefaceOT, 2);
sl@0: 		elementSpec2->SetCanonical(ETrue);
sl@0: 		
sl@0: 		typefaceSpec->AddTypefaceAtBackL(*elementSpec1);
sl@0: 		typefaceSpec->AddTypefaceAtBackL(*elementSpec2);
sl@0: 		CleanupStack::Pop(2, elementSpec1);
sl@0: 		
sl@0: 		TEST(typefaceSpec->TypefaceCount() == 2);
sl@0: 		TEST(typefaceSpec->Name() == KLinkedTypefaceTTOT);
sl@0: 
sl@0: 		// Now try registering the linked typeface
sl@0: 		TRAPD(ret, typefaceSpec->RegisterLinkedTypefaceL(*store));
sl@0: 
sl@0: 		if (ret == KErrNotSupported)
sl@0: 			{
sl@0: 			INFO_PRINTF1(_L("No Rasterizer is present that supports the extended Font Linking interface. This test case has been skipped."));
sl@0: 			CleanupStack::PopAndDestroy(2,store);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TEST(ret == KErrNone);
sl@0: 			
sl@0: 			// Create the linked font
sl@0: 			TTypeface typeface;
sl@0: 			typeface.iName = KLinkedTypefaceTTOT;
sl@0: 			TFontSpec fs;
sl@0: 			fs.iTypeface = typeface;
sl@0: 			fs.iHeight = 35;
sl@0: 			CFbsFont* font = NULL;
sl@0: 			TInt err = iDev->GetNearestFontToDesignHeightInPixels(font, fs);
sl@0: 			
sl@0: 			//check the font is the one requested
sl@0: 			TFontSpec fontSpec = font->FontSpecInTwips();
sl@0: 			TEST(fontSpec.iTypeface.iName == KLinkedTypefaceTTOT);
sl@0: 	
sl@0: 			_LIT16(KEnglish1,"ABCD12345 ");
sl@0: 			_LIT16(KHindi1,"\x0915\x094D\x0937\x0924\x094D\x0930\x093F\x092F\x0020");
sl@0: 			TEST(font != NULL);
sl@0: 			const TPoint englishLinked(10,75);
sl@0: 			const TPoint hindiLinked(10,150);
sl@0: 			if (font)
sl@0: 				{
sl@0: 				// Use the font
sl@0: 				iGc->UseFont(font);
sl@0: 				iGc->Clear();
sl@0: 				iGc->DrawText(KEnglish1, englishLinked);
sl@0: 				iGc->DrawText(KHindi1, hindiLinked);
sl@0: 				iGc->DiscardFont();
sl@0: 				iDev->Update();
sl@0: 				User::After(1000*1000*5);
sl@0: 				}
sl@0: 	
sl@0: 			// All the CFont functions can use a linked font and a non-linked
sl@0: 			// font - with the same base font, results should be the same.
sl@0: 			// Compare with the test function.
sl@0: 			
sl@0: 			//output the Hindi text
sl@0: 			TTypeface typeface2;
sl@0: 			typeface2.iName = KLinkedTypefaceOT;
sl@0: 			TFontSpec fs2;
sl@0: 			fs2.iTypeface = typeface2;
sl@0: 			fs2.iHeight = 35;
sl@0: 			CFbsFont* font2 = NULL;
sl@0: 			err = iDev->GetNearestFontToDesignHeightInPixels(font2, fs2);
sl@0: 			TEST(font2 != NULL);
sl@0: 			
sl@0: 			//check the font is the one requested
sl@0: 			fontSpec = font2->FontSpecInTwips();
sl@0: 			TEST(fontSpec.iTypeface.iName == KLinkedTypefaceOT);
sl@0: 	
sl@0: 			const TPoint englishHindiFont(240, 75);
sl@0: 			const TPoint hindiHindiFont(240, 150);
sl@0: 			if (font2)
sl@0: 				{
sl@0: 				// Use the font
sl@0: 				iGc->UseFont(font2);
sl@0: 				iGc->DrawText(KEnglish1, englishHindiFont);
sl@0: 				iGc->DrawText(KHindi1, hindiHindiFont);
sl@0: 				iGc->DiscardFont();
sl@0: 				iDev->Update();
sl@0: 				User::After(1000*1000);
sl@0: 				iDev->ReleaseFont(font2);
sl@0: 				}
sl@0: 			
sl@0: 			//output the English text
sl@0: 			TTypeface typeface3;
sl@0: 			typeface3.iName = KLinkedTypefaceTT;
sl@0: 			TFontSpec fs3;
sl@0: 			fs3.iTypeface = typeface3;
sl@0: 			fs3.iHeight = 35;
sl@0: 			CFbsFont* font3 = NULL;
sl@0: 			err = iDev->GetNearestFontToDesignHeightInPixels(font3, fs3);
sl@0: 			TEST(font3 != NULL);
sl@0: 	
sl@0: 			//check the font is the one requested
sl@0: 			fontSpec = font3->FontSpecInTwips();
sl@0: 			TEST(fontSpec.iTypeface.iName == KLinkedTypefaceTT);
sl@0: 	
sl@0: 			const TPoint englishSansSerifFont(440, 75);
sl@0: 			const TPoint hindiSansSerifFont(440, 150);
sl@0: 			if (font3)
sl@0: 				{
sl@0: 				// Use the font
sl@0: 				iGc->UseFont(font3);
sl@0: 				iGc->DrawText(KEnglish1, englishSansSerifFont);
sl@0: 				iGc->DrawText(KHindi1, hindiSansSerifFont);
sl@0: 				iGc->DiscardFont();
sl@0: 				iDev->Update();
sl@0: 				User::After(1000*1000);
sl@0: 				iDev->ReleaseFont(font3);
sl@0: 				}
sl@0: 			
sl@0: 			//compare rects.
sl@0: 			if (font)
sl@0: 				{
sl@0: 				CFont::TMeasureTextOutput compareEnglish;
sl@0: 				CFont::TMeasureTextOutput compareHindi;
sl@0: 				//get the size of a text box to do the comparison
sl@0: 				font->MeasureText(KEnglish1, NULL, &compareEnglish);
sl@0: 				font->MeasureText(KHindi1, NULL, &compareHindi);
sl@0: 				
sl@0: 				//compare English
sl@0: 				TRect englishLinkedRect (englishLinked.iX,englishLinked.iY,
sl@0: 							englishLinked.iX+compareEnglish.iBounds.Width(),
sl@0: 							englishLinked.iY+compareEnglish.iBounds.Height());
sl@0: 				TRect englishSansSerifRect  (englishSansSerifFont.iX,englishSansSerifFont.iY,
sl@0: 						englishSansSerifFont.iX+compareEnglish.iBounds.Width(),
sl@0: 						englishSansSerifFont.iY+compareEnglish.iBounds.Height());
sl@0: 				
sl@0: 				TBool val = iDev->RectCompare(englishLinkedRect, *iDev,englishSansSerifRect);
sl@0: 				//this value is not compared since the rasterizer may resize/reposition fonts
sl@0: 				
sl@0: 				//compare Hindi
sl@0: 				TRect hindiLinkedRect  (hindiLinked.iX,hindiLinked.iY,
sl@0: 						hindiLinked.iX+compareHindi.iBounds.Width(),
sl@0: 						hindiLinked.iY+compareHindi.iBounds.Height());
sl@0: 				TRect hindiHindiRect  (hindiHindiFont.iX,hindiHindiFont.iY,
sl@0: 						hindiHindiFont.iX+compareHindi.iBounds.Width(),
sl@0: 						hindiHindiFont.iY+compareHindi.iBounds.Height());
sl@0: 				val=iDev->RectCompare(hindiLinkedRect, *iDev,hindiHindiRect);
sl@0: 				//do not call TEST(val) since size/position may be slightly different
sl@0: 				iDev->ReleaseFont(font);
sl@0: 				}
sl@0: 			CleanupStack::PopAndDestroy(2, store);
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:    @SYMTestCaseID			GRAPHICS-FNTSTORE-LINKEDFONTS-0101
sl@0: 
sl@0:    @SYMPREQ					PREQ2146
sl@0: 
sl@0:    @SYMREQ					REQ10924, REQ10925, REQ10926
sl@0: 
sl@0:    @SYMTestCaseDesc			To test PREQ2146 linked fonts with bitmap fonts.  Bitmap fonts are not  
sl@0:    							supported so an error needs to be returned on registration.
sl@0: 
sl@0:    @SYMTestPriority			Critical
sl@0: 
sl@0:    @SYMTestStatus			Implemented
sl@0: 
sl@0:    @SYMTestActions			(1) Create a linked typeface elements, with one of them from a bitmap font
sl@0:    								try registering, and KErrNotSupported error should be returned
sl@0: 
sl@0:    @SYMTestExpectedResults	(1) - registering a bitmap font returns KErrNotSupported.
sl@0: */
sl@0: void CTLinkedFonts2::TestBitmapFontsL()
sl@0: 	{
sl@0: 	INFO_PRINTF1(_L("LinkedFonts2::TestBitmapFontsL"));
sl@0: 
sl@0: 	CFbsTypefaceStore* store = CFbsTypefaceStore::NewL(iDev);
sl@0: 	CleanupStack::PushL(store);
sl@0: 	
sl@0: 	// Create typeface to be linked
sl@0: 	_LIT(KLinkedTypefaceTT, "DejaVu Sans Condensed");
sl@0: 	_LIT(KLinkedTypeFace1, "LinkedFont1"); //this is a bitmap font
sl@0: 
sl@0: 	CLinkedTypefaceSpecification *typefaceSpec;
sl@0: 	_LIT(KLinkedTypefaceBitmap, "LinkedTypefaceBitmap");
sl@0: 		
sl@0: 	typefaceSpec = CLinkedTypefaceSpecification::NewLC(KLinkedTypefaceBitmap);
sl@0: 	
sl@0: 	CLinkedTypefaceGroup* group1 = CLinkedTypefaceGroup::NewLC(1);
sl@0: 	typefaceSpec->AddLinkedTypefaceGroupL(*group1);
sl@0: 	CleanupStack::Pop();
sl@0: 	
sl@0: 	CLinkedTypefaceGroup* group2 = CLinkedTypefaceGroup::NewLC(2);
sl@0: 	typefaceSpec->AddLinkedTypefaceGroupL(*group2);
sl@0: 	CleanupStack::Pop();
sl@0: 	
sl@0: 	// Add first typeface
sl@0: 	CLinkedTypefaceElementSpec *elementSpec1;
sl@0: 	elementSpec1 = CLinkedTypefaceElementSpec::NewLC(KLinkedTypefaceTT, 2);
sl@0: 		
sl@0: 	CLinkedTypefaceElementSpec *elementSpec2;
sl@0: 	elementSpec2 = CLinkedTypefaceElementSpec::NewLC(KLinkedTypeFace1, 1);
sl@0: 	elementSpec2->SetCanonical(ETrue);
sl@0: 		
sl@0: 	typefaceSpec->AddTypefaceAtBackL(*elementSpec1);
sl@0: 	typefaceSpec->AddTypefaceAtBackL(*elementSpec2);
sl@0: 	CleanupStack::Pop(2, elementSpec1);
sl@0: 		
sl@0: 	TEST(typefaceSpec->TypefaceCount() == 2);
sl@0: 	TEST(typefaceSpec->Name() == KLinkedTypefaceBitmap);
sl@0: 
sl@0: 	// Now try regstering the linked typeface
sl@0: 	TRAPD(ret, typefaceSpec->RegisterLinkedTypefaceL(*store));
sl@0: 	TEST(ret == KErrNotSupported);
sl@0: 	CleanupStack::PopAndDestroy(2, store);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:    @SYMTestCaseID			GRAPHICS-FNTSTORE-LINKEDFONTS-0109
sl@0: 
sl@0:    @SYMPREQ					PREQ2146
sl@0: 
sl@0:    @SYMREQ					REQ10924, REQ10925, REQ10926
sl@0: 
sl@0:    @SYMTestCaseDesc			To test PREQ2146 linked fonts updates to the TOpenFontCharMetrics class.  
sl@0:    
sl@0:    @SYMTestPriority			Critical
sl@0: 
sl@0:    @SYMTestStatus			Implemented
sl@0: 
sl@0:    @SYMTestActions			(1) Create a TOpenFontCharMetrics object.
sl@0:    							(2) Check that nothing is set
sl@0:    							(3) Set a small positive baseline
sl@0:    							(4) Check that the baseline is as set and the glyph type is still not set
sl@0:    							(5) Set a large positive baseline
sl@0:    							(6)	Check that the baseline is as set and the glyph type is still not set
sl@0: 							(7) Set a large negative baseline
sl@0: 							(8) Check that the baseline is as set and the glyph type is still not set
sl@0: 							(9) Set the glyph type.
sl@0: 							(10) Check that the baseline is as set and the glyph type is as set
sl@0: 							(11) Set the baseline to a again to various values
sl@0: 							(12) Check that the baseline is as set and the glyph type has not changed
sl@0: 
sl@0:    	@SYMTestExpectedResults	(2) the default values are 0 for baseline and EGlyphBitmapTypeNotDefined for glyph type
sl@0:    							(4)(6)(8)(10)(12) The values are are set, and setting the baseline does 
sl@0:    							not alter the glyph type and vice-versa.
sl@0: */
sl@0: void CTLinkedFonts2::TestTOpenFontMetrics()
sl@0: 	{
sl@0: 	TOpenFontMetrics metrics;
sl@0: 	
sl@0: 	TInt len = metrics.BaselineCorrection();
sl@0: 	TEST(len==0);
sl@0: 	
sl@0: 	metrics.SetBaselineCorrection(22);
sl@0: 	len = metrics.BaselineCorrection();
sl@0: 	TEST(len==22);
sl@0: 	
sl@0: 	metrics.SetBaselineCorrection(444);
sl@0: 	len = metrics.BaselineCorrection();
sl@0: 	TEST(len==444);
sl@0: 	
sl@0: 	metrics.SetBaselineCorrection(-333);
sl@0: 	len = metrics.BaselineCorrection();
sl@0: 	TEST(len==-333);
sl@0: 	
sl@0: 	metrics.SetBaselineCorrection(444);
sl@0: 	len = metrics.BaselineCorrection();
sl@0: 	TEST(len==444);
sl@0: 	
sl@0: 	metrics.SetBaselineCorrection(-1);
sl@0: 	len = metrics.BaselineCorrection();
sl@0: 	TEST(len==-1);
sl@0: 
sl@0: 	}
sl@0: 
sl@0: void CTLinkedFonts2::TestLinkedRegistrationAndFetchL()
sl@0: 	{
sl@0: 	INFO_PRINTF1(_L("CTLinkedFonts2::TestLinkedRegistrationAndFetchL"));
sl@0: 	CFbsTypefaceStore* store = CFbsTypefaceStore::NewL(iDev);
sl@0: 	CleanupStack::PushL(store);
sl@0: 	
sl@0: 	//Create and register a dummy linked typeface to register.
sl@0: 	_LIT(KFetchTypefaceName, "FetchFont");
sl@0: 	CLinkedTypefaceSpecification* typefaceSpec = CLinkedTypefaceSpecification::NewLC(KFetchTypefaceName);
sl@0: 
sl@0: 	CLinkedTypefaceGroup* group1 = CLinkedTypefaceGroup::NewLC(1);
sl@0: 	group1->SetBoldnessPercentage(20);
sl@0: 	group1->SetItalicAngle(10);
sl@0: 	group1->SetBaselineShift(CLinkedTypefaceGroup::EBaselineShift);
sl@0: 	group1->SetScalingOption(CLinkedTypefaceGroup::EScalingDown);
sl@0: 	
sl@0: 	typefaceSpec->AddLinkedTypefaceGroupL(*group1);
sl@0: 	CleanupStack::Pop(group1);
sl@0: 	
sl@0: 	CLinkedTypefaceGroup* group2 = CLinkedTypefaceGroup::NewLC(2);
sl@0: 	group2->SetBoldnessPercentage(21);
sl@0: 	group2->SetItalicAngle(11);
sl@0: 	group2->SetBaselineShift(CLinkedTypefaceGroup::ENoBaselineShift);
sl@0: 	group2->SetScalingOption(CLinkedTypefaceGroup::EScalingUp);
sl@0: 	
sl@0: 	typefaceSpec->AddLinkedTypefaceGroupL(*group2);
sl@0: 	CleanupStack::Pop(group2);
sl@0: 	
sl@0: 	_LIT(KElement1Name, "DejaVu Sans Condensed");
sl@0: 	CLinkedTypefaceElementSpec* element1 = CLinkedTypefaceElementSpec::NewLC(KElement1Name, 1);
sl@0: 	element1->SetCanonical(ETrue);
sl@0: 	typefaceSpec->AddTypefaceAtBackL(*element1);
sl@0: 	CleanupStack::Pop(element1);
sl@0: 	
sl@0: 	_LIT(KElement2Name, "Chandas");
sl@0: 	CLinkedTypefaceElementSpec* element2 = CLinkedTypefaceElementSpec::NewLC(KElement2Name, 2);
sl@0: 	typefaceSpec->AddTypefaceAtBackL(*element2);
sl@0: 	CleanupStack::Pop(element2);
sl@0: 	
sl@0: 	TRAPD(ret, typefaceSpec->RegisterLinkedTypefaceL(*store));
sl@0: 	if (ret == KErrNotSupported)
sl@0: 		{
sl@0: 		INFO_PRINTF1(_L("No Rasterizer is present that supports the extended Font Linking interface. This test case has been skipped."));
sl@0: 		CleanupStack::PopAndDestroy(2,store);
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TEST(ret == KErrNone);
sl@0: 		
sl@0: 		CLinkedTypefaceSpecification* fetchSpec = CLinkedTypefaceSpecification::NewLC(KFetchTypefaceName);
sl@0: 		TRAP(ret, fetchSpec->FetchLinkedTypefaceSpecificationL(*store));
sl@0: 		TEST(ret == KErrNone);
sl@0: 		
sl@0: 		//Compare Groups. Ordering isn't important so can get group by id rather than index.
sl@0: 		TEST(typefaceSpec->GroupCount() == fetchSpec->GroupCount());
sl@0: 		CLinkedTypefaceGroup* groupf = fetchSpec->GroupById(1);
sl@0: 		TEST(CompareGroups(group1,groupf));
sl@0: 		
sl@0: 		groupf = fetchSpec->GroupById(2);
sl@0: 		TEST(CompareGroups(group2,groupf));
sl@0: 			
sl@0: 		//Check elements match 
sl@0: 		TEST(typefaceSpec->TypefaceCount() == fetchSpec->TypefaceCount());
sl@0: 		
sl@0: 		CLinkedTypefaceElementSpec* elementf = fetchSpec->Typeface(0);
sl@0: 		TEST(CompareElementSpecs(elementf, element1));
sl@0: 		elementf = fetchSpec->Typeface(1);
sl@0: 		TEST(CompareElementSpecs(elementf, element2));
sl@0: 			
sl@0: 		CleanupStack::PopAndDestroy(3,store);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0:    @SYMTestCaseID			GRAPHICS-FNTSTORE-LINKEDFONTS-0110
sl@0: 
sl@0:    @SYMDEF					DEF137360
sl@0: 
sl@0:    @SYMTestCaseDesc			Ensure that font full names are used to build a linked font  
sl@0:    
sl@0:    @SYMTestPriority			Critical
sl@0: 
sl@0:    @SYMTestStatus			Implemented
sl@0: 
sl@0:    @SYMTestActions			Attempt to register a linked font using a font full name rather than a family
sl@0: 						    name. DejaVu Sans Condensed is both a family name and a full name. DejaVu Sans Mono Bold is full name only.
sl@0: 
sl@0:    	@SYMTestExpectedResults	Registration of the linked font will be sucessful.
sl@0: 							Failing with KErrNotFound means either the test font is not available or there is a regression.
sl@0: */
sl@0: void CTLinkedFonts2::TestFontNameUsage()
sl@0: 	{
sl@0: 	CFbsTypefaceStore* store = CFbsTypefaceStore::NewL(NULL);
sl@0: 	CleanupStack::PushL(store);
sl@0: 	
sl@0: 	CLinkedTypefaceSpecification* nameSpec = CLinkedTypefaceSpecification::NewLC(_L("FullNameTest"));
sl@0: 	
sl@0: 	CLinkedTypefaceGroup* group = CLinkedTypefaceGroup::NewLC(1);
sl@0: 	nameSpec->AddLinkedTypefaceGroupL(*group);
sl@0: 	CleanupStack::Pop(group);
sl@0: 	
sl@0: 	//Use a font whose name doesn't match a family name
sl@0: 	CLinkedTypefaceElementSpec* element1 = CLinkedTypefaceElementSpec::NewLC(_L("DejaVu Sans Mono Bold"), 1);
sl@0: 	element1->SetCanonical(ETrue);
sl@0: 	nameSpec->AddTypefaceAtBackL(*element1);
sl@0: 	CleanupStack::Pop(element1);
sl@0: 	
sl@0: 	CLinkedTypefaceElementSpec* element2 = CLinkedTypefaceElementSpec::NewLC(_L("Chandas"), 1);
sl@0: 	nameSpec->AddTypefaceAtBackL(*element2);
sl@0: 	CleanupStack::Pop(element2);
sl@0: 	
sl@0: 	TRAPD(ret, store->RegisterLinkedTypeface(*nameSpec));
sl@0: 	
sl@0: 	TEST(ret == KErrNone);
sl@0: 	
sl@0: 	CleanupStack::PopAndDestroy(2, store);
sl@0: 	}
sl@0: 
sl@0: TBool CTLinkedFonts2::CompareElementSpecs(CLinkedTypefaceElementSpec* aSpec1, CLinkedTypefaceElementSpec* aSpec2)
sl@0: 	{
sl@0: 	if ( (aSpec1 == NULL ) && (aSpec2 == NULL) )
sl@0: 		return ETrue;
sl@0: 	if ( (aSpec1 == NULL) || (aSpec2 == NULL) )
sl@0: 		return EFalse;
sl@0: 	if (aSpec1->ElementName().Compare(aSpec2->ElementName()) != 0)
sl@0: 		return EFalse;
sl@0: 	if (aSpec1->Canonical() != aSpec2->Canonical())
sl@0: 		return EFalse;
sl@0: 	if (aSpec1->GroupId() != aSpec2->GroupId())
sl@0: 		return EFalse;
sl@0: 	
sl@0: 	return ETrue;
sl@0: 	}
sl@0: 
sl@0: TBool CTLinkedFonts2::CompareElementSpecs(COpenFontLinkedTypefaceElementSpec* aSpec1, COpenFontLinkedTypefaceElementSpec* aSpec2)
sl@0: 	{
sl@0: 	if ( (aSpec1 == NULL ) && (aSpec2 == NULL) )
sl@0: 		return ETrue;
sl@0: 	if ( (aSpec1 == NULL) || (aSpec2 == NULL) )
sl@0: 		return EFalse;
sl@0: 	if (aSpec1->ElementName().Compare(aSpec2->ElementName()) != 0)
sl@0: 		return EFalse;
sl@0: 	if (aSpec1->Canonical() != aSpec2->Canonical())
sl@0: 		return EFalse;
sl@0: 	if (aSpec1->GroupId() != aSpec2->GroupId())
sl@0: 		return EFalse;
sl@0: 	
sl@0: 	return ETrue;
sl@0: 	}
sl@0: /**
sl@0: Compare two linked typeface groups; the first varable should be a locally created group and the second one fetched from the
sl@0: rasterizer. If the local group has thresholds / metrics set to -1 ("best guess by rasterizer") then the differences between the
sl@0: values are ignored.
sl@0:  */
sl@0: TBool CTLinkedFonts2::CompareGroups(CLinkedTypefaceGroup* aLocalGroup, CLinkedTypefaceGroup* aFetchedGroup)
sl@0: 	{
sl@0: 	if ( (aLocalGroup == NULL) && (aFetchedGroup == NULL) )
sl@0: 		return ETrue;
sl@0: 	if ( (aLocalGroup == NULL) || (aFetchedGroup == NULL) )
sl@0: 		{
sl@0: 		INFO_PRINTF1(_L("One of the specified groups is NULL"));
sl@0: 		return EFalse;
sl@0: 		}
sl@0: 	
sl@0: 	if (aLocalGroup->BaselineShift() != aFetchedGroup->BaselineShift())
sl@0: 		return EFalse;
sl@0: 	
sl@0: 	/*if (aLocalGroup->BoldnessPercentage() != -1)
sl@0: 		{
sl@0: 		if (aLocalGroup->BoldnessPercentage() != aFetchedGroup->BoldnessPercentage())
sl@0: 			{
sl@0: 			INFO_PRINTF1(_L("Fail below caused by non-matching boldness percentages"));
sl@0: 			return EFalse;
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 	if (aLocalGroup->ItalicAngle() != -1)
sl@0: 		{
sl@0: 		if (aLocalGroup->ItalicAngle() != aFetchedGroup->ItalicAngle())
sl@0: 			{
sl@0: 			INFO_PRINTF1(_L("Fail below caused by non-matching italic angles"));
sl@0: 			return EFalse;
sl@0: 			}
sl@0: 		}
sl@0: 	*/
sl@0: 	if (aLocalGroup->ScalingOption() != aFetchedGroup->ScalingOption())
sl@0: 		return EFalse;
sl@0: 	if (aLocalGroup->GroupId() != aFetchedGroup->GroupId())
sl@0: 		return EFalse;
sl@0: 	
sl@0: 	return ETrue;
sl@0: 	}
sl@0: 
sl@0: __CONSTRUCT_STEP__(LinkedFonts2)