fontservices/freetypefontrasteriser/test/testharness.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 17:01:26 +0300
branchRCL_3
changeset 16 748ec5531811
parent 0 1fb32624e06b
permissions -rw-r--r--
Revision: 201021 Kit: 201035

/*
* Copyright (c) 2008-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 "testharness.h"
#include <bitdev.h>
#include <fntstore.h>
#include <fbs.h>
#include <test/testexecutestepbase.h>
#include <graphics/fbsdefs.h>

CTestHarness::CTestHarness(CTestStep* aStep) :
		iStep(aStep)
	{
	iStep -> INFO_PRINTF1(iStep -> TestStepName());
	}

CTestHarness* CTestHarness::NewL(CTestStep* aStep)
	{
	CTestHarness* t = new (ELeave)CTestHarness (aStep);
	CleanupStack::PushL(t);
	t->ConstructL();
	CleanupStack::Pop();
	return t;
	}

void CTestHarness::ConstructL()
	{
	User::LeaveIfError(FbsStartup());
	
	RFbsSession::Connect();
	iFbs = RFbsSession::GetSession();
	if (iFbs == NULL)
		User::Leave(KErrGeneral);

	TRAPD(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EColor16M));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EColor16MA));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EColor16MU));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EColor64K));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EColor4K));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EColor256));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EColor16));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EGray256));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EGray16));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EGray4));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EGray2));
	if (error == KErrNotSupported)
		TRAP(error, iDev = CFbsScreenDevice::NewL(_L("scdv"),EColor16MAP));
	
	if(error == KErrNone)
		{
		iDev->ChangeScreenDevice(NULL);
		iDev->SetAutoUpdate(ETrue);
		iDev->CreateContext(iGc);

		TFontSpec fs(_L("DejaVu Sans Condensed"),16);
		error = iDev->GetNearestFontToDesignHeightInPixels((CFont*&)iStandardFont,fs);
		if (error)
			User::Panic(_L("Could not create 16-pixel DejaVu Sans Condensed"),error);
		}
	}

CTestHarness::~CTestHarness()
	{
	if (iStandardFont)
		iDev->ReleaseFont(iStandardFont);
	delete iGc;
	delete iDev;
	RFbsSession::Disconnect();
	}

void CTestHarness::PerformTests()
	{
	iStep->INFO_PRINTF1(_L("Test started"));
	
	TInt typefaces = iDev->NumTypefaces();
	for (int typeface = 0; typeface < typefaces; typeface++)
		{
		TestFont(typeface);
		}
		
	iStep->INFO_PRINTF1(_L("Test ended"));
	}
	
void CTestHarness::TestFont(TInt aTypeface)
	{
	TTypefaceSupport support;
	iDev->TypefaceSupport(support,aTypeface);
	
	TBuf<50> testInfo;
	testInfo.Append(_L("Testing typeface: "));
	testInfo.Append(support.iTypeface.iName);
	iStep->INFO_PRINTF1(testInfo);
	
	const TInt pointsizes = 9;
	static TInt pointsize[pointsizes] = { 8, 10, 12, 14, 16, 20, 24, 48, 200 };
	TInt i = 0;
	for (i = 0; i < (pointsizes-2); i++)
		{
		TestFontDisplayAtSize(support, pointsize[i], i & 1);
		}
		
	TestFontMetricsDiagram(support, pointsize[i], i & 1);
	i++;
	
	TestFontHugeCharacters(support, pointsize[i], i & 1);
	}
	
void CTestHarness::TestFontDisplayAtSize(TTypefaceSupport& aSupport, TInt aPointSize, TBool aItalic)
	{
	TBuf<50> testInfo;
	testInfo.Append(_L("Testing font size: "));
	TBuf<10> num;
	num.Num(aPointSize);
	testInfo.Append(num);
	iStep->INFO_PRINTF1(testInfo);
	
	TFontSpec fs;

	fs.iTypeface = aSupport.iTypeface;
	fs.iHeight = aPointSize * 20;
	if (aItalic)
		{
		fs.iFontStyle.SetPosture(EPostureItalic);
		}
	iTestFont = NULL;
	TInt error = iDev->GetNearestFontToDesignHeightInTwips((CFont*&)iTestFont,fs);
	if (error)
		User::Panic(_L("Could not create font"),error);
	if (!iTestFont->IsOpenFont())
		{
		iDev->ReleaseFont(iTestFont);
		iTestFont = NULL;
		return;
		}
	PrintMetrics();
	DisplayFont();
	iDev->ReleaseFont(iTestFont);
	}

void CTestHarness::TestFontMetricsDiagram(TTypefaceSupport& aSupport, TInt aPointSize, TBool aItalic)
	{
	TBuf<50> testInfo;
	testInfo.Append(_L("Testing font metrics: "));
	TBuf<10> num;
	num.Num(aPointSize);
	testInfo.Append(num);
	iStep->INFO_PRINTF1(testInfo);
	
	TFontSpec fs;
	fs.iTypeface = aSupport.iTypeface;
	fs.iHeight = aPointSize * 20;
	if (aItalic)
		{
		fs.iFontStyle.SetPosture(EPostureItalic);
		}
	iTestFont = NULL;
	TInt error = iDev->GetNearestFontToDesignHeightInTwips((CFont*&)iTestFont,fs);
	if (error)
		User::Panic(_L("Could not create font"),error);
	if (!iTestFont->IsOpenFont())
		{
		iDev->ReleaseFont(iTestFont);
		iTestFont = NULL;
		return;
		}
	PrintMetrics();
	DrawMetricsDiagram();
	iDev->ReleaseFont(iTestFont);
	}
	
void CTestHarness::TestFontHugeCharacters(TTypefaceSupport& aSupport, TInt aPointSize, TBool aItalic)
	{
	TBuf<50> testInfo;
	testInfo.Append(_L("Testing huge characters: "));
	TBuf<10> num;
	num.Num(aPointSize);
	testInfo.Append(num);
	iStep->INFO_PRINTF1(testInfo);
	
	TFontSpec fs;
	fs.iTypeface = aSupport.iTypeface;
	fs.iHeight = aPointSize * 20;
	if (aItalic)
		fs.iFontStyle.SetPosture(EPostureItalic);
	iTestFont = NULL;
	TInt error = iDev->GetNearestFontToDesignHeightInTwips((CFont*&)iTestFont,fs);
	if (error)
		User::Panic(_L("Could not create font"),error);
	if (!iTestFont->IsOpenFont())
		{
		iDev->ReleaseFont(iTestFont);
		iTestFont = NULL;
		return;
		}
	PrintMetrics();
	DrawHugeCharacters();
	iDev->ReleaseFont(iTestFont);
	}
	
static void Hellenize(TDes16& text)
	{
	static const TUint16* roman = (TUint16*)(L"ABGDEZJQIKLMNXOPRVSTUFHCW");
	
	for (int i = 0; i < text.Length(); i++)
		for (int j = 0; j < 25; j++)
			if (roman[j] == text[i])
				{
				text[i] = (TUint16)(0x391 + j);
				break;
				}
			else if (roman[j] + 32 == text[i])
				{
				text[i] = (TUint16)(0x3B1 + j);
				break;
				}
	}

void CTestHarness::PrintMetrics(TBool isClear)
	{
	if(isClear)
		{
		Clear();	
		}
	
	UseFont(iStandardFont);
	TFontSpec fs = iTestFont->FontSpecInTwips();
	TOpenFontMetrics metrics;
	iTestFont->GetFontMetrics(metrics);
	TOpenFontFaceAttrib attrib;
	iTestFont->GetFaceAttrib(attrib);
	TPtrC name = attrib.LocalFullName();
	iBuffer.Format(_L("%S %dpt size=%d ascent=%d descent=%d maxheight=%d maxdepth=%d maxwidth=%d"),
				  &name,(fs.iHeight + 10) / 20,metrics.Size(),metrics.Ascent(),metrics.Descent(),
				  metrics.MaxHeight(),metrics.MaxDepth(),metrics.MaxWidth());
	Print(iBuffer);
	}

void CTestHarness::DisplayFont()
	{
	UseFont(iStandardFont);
	TOpenFontFaceAttrib attrib;
	iTestFont->GetFaceAttrib(attrib);
	iBuffer.SetLength(0);
	if (attrib.HasLatin())
		iBuffer.Append(_L("Latin, "));			  
	if (attrib.HasGreek())
		iBuffer.Append(_L("Greek, "));			  
	if (attrib.HasCyrillic())
		iBuffer.Append(_L("Cyrillic, "));			  
	if (attrib.HasKana())
		iBuffer.Append(_L("Kana (Japanese syllabaries), "));
	if (attrib.HasHangul())
		iBuffer.Append(_L("Hangul (Korean writing system), "));
	if (attrib.HasCJK())
		iBuffer.Append(_L("CJK (Chinese, Japanese & Korean ideographs), "));
	if (iBuffer.Length() == 0)
		iBuffer.Append(_L("(character sets unknown)"));
	else
		iBuffer.SetLength(iBuffer.Length() - 2);
	Print(iBuffer);

	UseFont(iTestFont);

	// Benchmark the rasterization of Ascii printable characters.
	const int count = 126 - 33 + 1;
	iBuffer.SetLength(count);
	int i;
	for (i = 0; i < count; i++)
		iBuffer[i] = (TText)(i + 33);
	TTime start, end;
	start.HomeTime();
	iTestFont->RawTextWidthInPixels(iBuffer);
	end.HomeTime();
	TTimeIntervalMicroSeconds time64 = end.MicroSecondsFrom(start);
	int time = I64INT(time64.Int64());

	start.HomeTime();
	for (i = 0; i < 100; i++)
		iTestFont->RawTextWidthInPixels(iBuffer);
	end.HomeTime();
	time64 = end.MicroSecondsFrom(start);
	int overhead = I64INT(time64.Int64()) / 100;
	time -= overhead;
	if (time <= 0)
		time = 1;

	iBuffer.Format(_L("%d characters rasterized per second"),
				  count * 1000000 / time);
	Print(iBuffer);
	iBuffer.UpperCase();
	Print(iBuffer);
	iBuffer = _L("sm\xf6rg\xe5sbord soup\xe7on na\xefvet\xe9");
	Print(iBuffer);
	iBuffer.UpperCase();
	Print(iBuffer);

	if (attrib.HasGreek())
		{
		iBuffer = _L("agjwmetrjsewv mjdeiv eisitw");
		Hellenize(iBuffer);
		Print(iBuffer);
		iBuffer.UpperCase();
		Print(iBuffer);
		}
	if (attrib.HasCyrillic())
		{
		iBuffer.SetLength(32);
		for (int i = 0; i < 32; i++)
			iBuffer[i] = (TText)(0x430 + i);
		Print(iBuffer);
		iBuffer.UpperCase();
		Print(iBuffer);
		}
	if (attrib.HasKana())
		{
		iBuffer.SetLength(32);
		int i;
		for (i = 0; i < 32; i++)
			iBuffer[i] = (TText)(0x3041 + i);
		Print(iBuffer);
		for (i = 0; i < iBuffer.Length(); i++)
			iBuffer[i] = (TText)User::Fold(iBuffer[i],TChar::EFoldKana);	// fold to katakana
		Print(iBuffer);
		}
	if (attrib.HasHangul())
		{
		iBuffer.SetLength(32);
		for (int i = 0; i < 32; i++)
			iBuffer[i] = (TText)(0x3131 + i);
		Print(iBuffer);
		}

	// Display characters from 4e00 that are found in all 6 encodings given in the Unicode table.
	if (attrib.HasCJK())
		{
		iBuffer.SetLength(15);
		iBuffer[0] = 0x4e00;
		iBuffer[1] = 0x4e01;
		iBuffer[2] = 0x4e03;
		iBuffer[3] = 0x4e07;
		iBuffer[4] = 0x4e08;
		iBuffer[5] = 0x4e09;
		iBuffer[6] = 0x4e0a;
		iBuffer[7] = 0x4e0b;
		iBuffer[8] = 0x4e0d;
		iBuffer[9] = 0x4e11;
		iBuffer[10] = 0x4e14;
		iBuffer[11] = 0x4e15;
		iBuffer[12] = 0x4e16;
		iBuffer[13] = 0x4e18;
		iBuffer[14] = 0x4e19;
		Print(iBuffer);
		}

	iGc->DiscardFont();
	}

void CTestHarness::DrawCharMetrics(TPoint& aPos,TInt aCode)
	{
	TOpenFontCharMetrics metrics;
	const TUint8* bytes;
	TSize size;
	iTestFont->GetCharacterData(aCode,metrics,bytes,size);
	TRect r;
	r.iTl = aPos;
	r.iTl.iX += metrics.HorizBearingX();
	r.iTl.iY += iBaseLine;
	r.iTl.iY -= metrics.HorizBearingY();
	r.iBr = r.iTl + TSize(metrics.Width(),metrics.Height());
	iGc->DrawRect(r);
	aPos.iX += metrics.HorizAdvance();
	}

void CTestHarness::DrawMetricsDiagram()
	{
	UseFont(iTestFont);
	iBuffer = _L("Dig my crazy metrics!");
	iPrintPos.iX += 8;
	TPoint pos = iPrintPos;
	Print(iBuffer);
	TPoint baseline_start = pos;
	baseline_start.iY += iBaseLine;
	for (int i = 0; i < iBuffer.Length(); i++)
		DrawCharMetrics(pos,iBuffer[i]);
	TPoint baseline_end = pos;
	baseline_end.iY += iBaseLine;
	iGc->DrawLine(baseline_start,baseline_end);
	iGc->DiscardFont();
	//iTest.Getch();
	}

void CTestHarness::DrawHugeCharacters()
	{
	UseFont(iTestFont);
	iBuffer = _L("ABC123");
	TOpenFontCharMetrics metrics;
	const TUint8* bytes;
	TSize size;
	iTestFont->GetCharacterData('A',metrics,bytes,size);
	iBaseLine = metrics.HorizBearingY();;
	Print(iBuffer);
	iGc->DiscardFont();
	//iTest.Getch();
	}

void CTestHarness::Clear()
	{
	TRect r(iDev->SizeInPixels());
	iGc->Clear(r);
	iPrintPos = TPoint(0,0);
	}

void CTestHarness::Print(const TDesC& aText)
	{
	TPoint p = iPrintPos;
	p.iY += iBaseLine;
	iGc->DrawText(aText,p);
	iPrintPos.iX = 0;
	iPrintPos.iY += iLineHeight;
	}

void CTestHarness::UseFont(CFbsFont* aFont)
	{
	iGc->UseFont(aFont);
	TOpenFontMetrics metrics;
	aFont->GetFontMetrics(metrics);
	iBaseLine = metrics.MaxHeight();
	iLineHeight = metrics.MaxHeight() + metrics.MaxDepth();
	}

/*
@SYMTestCaseID GRAPHICS-FREETYPE-0001
@SYMTestCaseDesc Supplementary characters rasterization Test
@SYMTestPriority High
@SYMTestActions  This test checks that the free type rasterizer rasterizes supplementary characters 
properly.
It prints the descriptor containing supplementary characters with 2 Fonts. One font does not support
supplementary characters and the other does.
@SYMTestExpectedResults This step should be executed without error and the user should be able to see the 
above descriptor is displayed as a square with the first font and in the correct shape with the other font.
@SYMDEF DEF120018 Security issue in FreeType rasterizer! Supplementary characters rendered as BMP
*/
void CTestHarness::SurrogateRasterizedTestsL()
	{
	// The literal descriptor consisting of common letter 'A' and Supplementary character 0x20000
	// which is represented by surrogate pair 0xD840 0xDC00
	_LIT16(KSurrogatePairCode, "A\xD840\xDC00");
	
	// Testing Fonts: DejaVu Sans Condensed does not support Supplementary character.
	// Test2 only supports letter "A" and Supplementary character 0x20000
	TFontSpec fsDejaVuSans(_L("DejaVu Sans Condensed"), 16 * 20);
	TFontSpec fsTest2(_L("Test2"), 16 * 20);
	
	Clear();

	// Prints test descriptor with font SwissA
	iTestFont = NULL;
	TInt error = iDev->GetNearestFontToDesignHeightInTwips((CFont*&)iTestFont,fsDejaVuSans);
	iStep->TESTL(KErrNone == error);
	
	if (!iTestFont->IsOpenFont())
		{
		iDev->ReleaseFont(iTestFont);
		iTestFont = NULL;
		User::Leave(KErrGeneral);
		}
	PrintMetrics(EFalse);
	
	UseFont(iTestFont);
	Print(KSurrogatePairCode);
	iDev->ReleaseFont(iTestFont);

	// Prints test descriptor with font Test2
	iTestFont = NULL;
	error = iDev->GetNearestFontToDesignHeightInTwips((CFont*&)iTestFont,fsTest2);
	iStep->TESTL(KErrNone == error);
	
	if (!iTestFont->IsOpenFont())
		{
		iDev->ReleaseFont(iTestFont);
		iTestFont = NULL;
		User::Leave(KErrGeneral);
		}
	PrintMetrics(EFalse);

	UseFont(iTestFont);
	Print(KSurrogatePairCode);
	iDev->ReleaseFont(iTestFont);
	iTestFont = NULL;
	
//	User::After(10000000);
	}