fontservices/freetypefontrasteriser/test/testharness.cpp
changeset 0 1fb32624e06b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fontservices/freetypefontrasteriser/test/testharness.cpp	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,518 @@
+/*
+* 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);
+	}
+