fontservices/textshaperplugin/test/CreateTestData/T_SHAP_createTestData.cpp
changeset 0 1fb32624e06b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fontservices/textshaperplugin/test/CreateTestData/T_SHAP_createTestData.cpp	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,504 @@
+/*
+* 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: 
+* Creates test data files that are used by TC_SHAP_shapeText.cpp test. 
+* This tool uses the Unicode test input text defined in inputData.h and
+* shapes the text by calling the IcuLayoutEngine API ShapeText().
+* The result, along with the input text is stored in the test data files with 
+* extensions .dat
+* First, the reference input data is stored in the data files in the following format, seperated by a delimiter - | :
+* Length (of the input data string)	Font typeface name | Font file name | Starting offset in the input string | End offset in the input string | Input text string
+* Then the result of the shaping is stored in data files in the following format:
+* Output glyph count	Output glyphs	Glyph X and Y coordinates	Glyph advances	Glyph indices	Output character count
+* The TC_SHAP_shape_Text test is programmed to read in files in this format, and this format only.
+* This tool needs to be run, and new test data files need to be created everytime the 
+* IcuLayoutEngine shaping rules are changed/edited/appended.
+* IN ORDER TO CREATE NEW TEST DATA FILES USING THIS UTILITY, YOU WILL NEED TO:
+* 1. Add a new TInputData entry in inputData.txt
+* 2. Delete any old data files in %EPOCROOT%epoc32\winscw\c\
+* 3. Run the test.
+* IN ORDER TO GET THE TC_SHAP_shapeText TEST FILE TO USE THIS NEW DATA, YOU WILL NEED TO:
+* 1. Add your new test file in perforce to:
+* IcuLayoutEngine/test/testdata/...
+* They will have been added to %EPOCROOT%epoc32\winscw\c
+* 2. Update the bld.inf file for IcuLayoutEngine to export this file to z:\test\data\...
+* 3. Update the .cpp file by adding the a new literal at the top of the file with the new filename to be used.
+* 4. Update the TC_SHAP_shapeText.iby file in IcuLayoutEngine/test to include the new file.
+* THIS TOOL SHOULD ONLY BE RUN BY SOMEONE WHO KNOWS WHAT HE/SHE IS DOING!!
+*
+*/
+
+
+#include <e32def.h>
+#include <e32test.h>
+#include <e32std.h>
+#include <f32file.h>
+#include <fntstore.h>
+#include <s32file.h>
+
+#include <graphics/openfontrasterizer.h>
+#include <graphics/openfontconstants.h>
+#include <graphics/shapeimpl.h>
+#include "inputData.h"
+
+const TUint32 KDevanagariScriptCode = 0x64657661;
+const TUint32 KKannadaScriptCode = 0x6B6E6461;
+const TUint32 KHindiLanguageCode = 0x48494E20;
+const TUint32 KKannadaLanguageCode = 0x4B414E20;
+const TUint32 KGujaratiScriptCode = 0x67756A72;
+const TUint32 KGujaratiLanguageCode = 0x47554A20;
+const TUint32 KBengaliScriptCode = 0x62656E67;
+const TUint32 KBengaliLanguageCode = 0x42454E20;
+const TUint32 KTamilScriptCode = 0x74616D6C;
+const TUint32 KTamilLanguageCode = 0x54414D20;
+const TUint32 KTeluguScriptCode = 0x74656C75;
+const TUint32 KTeluguLanguageCode = 0x54454C20;
+const TUint32 KGurmukhiScriptCode = 0x67757275;
+const TUint32 KGurmukhiLanguageCode = 0;
+const TUint32 KMalayalamScriptCode = 0x6d6c796d;
+const TUint32 KMalayalamLanguageCode = 0x4d4c5220;
+
+
+_LIT16(KDelimiter, "|");
+
+//RTest Macros etc
+static RTest TheTest(_L("T_SHAP_createTestData"));
+static void Check(TInt aValue, TInt aLine)
+	{
+	if(!aValue)
+		{
+		TheTest(EFalse, aLine);
+		}
+	}
+
+static  void Check(TInt aValue, TInt aExpected, TInt aLine)
+	{
+	if(aValue != aExpected)
+		{
+		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
+		TheTest(EFalse, aLine);
+		}
+	}
+
+#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)	
+#define TEST(arg) ::Check((arg), __LINE__)
+
+/* 
+Used for cleanup of RImplInfoArray implementationArray below 
+This method is stolen from FbsTop.cpp
+*/
+LOCAL_C void ResetAndDestroyRImplInfoPtrArray(TAny* aPtr)
+	{
+	RImplInfoPtrArray* array = reinterpret_cast <RImplInfoPtrArray*> (aPtr);
+	array->ResetAndDestroy();
+	}
+	
+/*
+Load all ECOM implemented rasterizer DLLs. 
+This method is stolen from CFbTop::LoadOpenFontLibraries()
+*/
+LOCAL_C void LoadOpenFontLibraries(CFontStore* aFontStore)
+	{
+
+	RImplInfoPtrArray implementationArray;
+	TCleanupItem cleanup(ResetAndDestroyRImplInfoPtrArray, &implementationArray);
+	CleanupStack::PushL(cleanup);
+	TInt error;
+	TInt ecomerror;
+	TInt ecomnotready;
+	TUid uid = {KUidOpenFontRasterizerPlunginInterface};
+
+	// Making sure that no race situation arises
+	// If ECom is not ready, give it another chance and try again. if it still doesn't work 
+	// after the third try, then it just carries on quietly and fails... 
+	for (ecomnotready =0; ecomnotready <3; ecomnotready++)
+		{
+		TRAP(ecomerror,REComSession::ListImplementationsL(uid,implementationArray));
+		if (!ecomerror)
+			{
+			break;
+			}
+		else
+			{
+			ecomerror = 0; 	
+			User::After(0);
+			}
+		}
+
+	const TInt availCount = implementationArray.Count();
+	for (TInt count=0;count<availCount;++count)
+		{
+		const CImplementationInformation* info = implementationArray[count];
+		TUid rasterizerUid = info->ImplementationUid();
+ 		// Create a rasterizer
+ 		COpenFontRasterizer* rasterizer=0;
+ 		TRAP(error,rasterizer = COpenFontRasterizer::NewL(rasterizerUid));
+ 		if (!error)
+   			{
+   			// Install it in the font store.
+   			TRAP(error,aFontStore->InstallRasterizerL(rasterizer));
+   			if (error)
+   				delete rasterizer;
+   			}
+		}
+	CleanupStack::PopAndDestroy(&implementationArray); 	
+
+	}
+	
+LOCAL_C void WriteInputData(RWriteStream& aStream, const TInputData& aInputData)
+	{
+	//output the input data to the file
+	TPtrC input = aInputData.TextInput();
+	TInt length = input.Length();
+	TInt start = aInputData.iStart;
+	if (start < 0)
+		start += length;
+	TInt end = aInputData.iEnd;
+	if (end <= 0)
+		end += length;
+
+	aStream.WriteInt16L(length);
+
+	aStream.WriteL(aInputData.TypeFaceName());
+	aStream.WriteL(KDelimiter);
+
+	aStream.WriteL(aInputData.FontFilename());
+	aStream.WriteL(KDelimiter);
+	
+	aStream.WriteInt16L(start);
+	aStream.WriteL(KDelimiter);
+	aStream.WriteInt16L(end);
+	aStream.WriteL(KDelimiter);
+
+	aStream.WriteL(input);
+	aStream.WriteL(KDelimiter);
+	}
+
+static void WriteOutputData(RWriteStream& aStream, const TInputData& aInputData, 
+							TUint32 aScript, TUint32 aLanguage)
+	{
+	//SHAPE THE TEXT
+
+	TPtrC input = aInputData.TextInput();
+	TInt length = input.Length();
+	TInt start = aInputData.iStart;
+	if (start < 0)
+		start += length;
+	TInt end = aInputData.iEnd;
+	if (end <= 0)
+		end += length;
+
+	//set up font store and install rasterizer(s)
+	CFontStore* fontStore = CFontStore::NewL(&User::Heap());
+	fontStore->iKPixelWidthInTwips = 11860;
+	fontStore->iKPixelHeightInTwips = 11860;
+	CleanupStack::PushL(fontStore);
+	LoadOpenFontLibraries(fontStore);
+
+	//add required font file
+	TRAPD( err, fontStore->AddFileL(aInputData.FontFilename()) );
+	TEST(err==KErrNone);
+	
+	CBitmapFont* font;
+	TFontSpec fontSpec(aInputData.TypeFaceName(), 12);
+	fontStore->GetNearestFontToDesignHeightInPixels((CFont*&)font, fontSpec);
+	CleanupStack::PushL(font);
+
+	CShaper* theShaper = NULL;
+	CShaperFactory* shaperFactory = NULL;
+
+	RImplInfoPtrArray implementationArray;
+	TCleanupItem cleanup(ResetAndDestroyRImplInfoPtrArray, &implementationArray);
+	CleanupStack::PushL(cleanup);
+	TInt error;
+	TInt ecomerror;
+	TInt ecomnotready;
+	TUid uid = {KUidShaperFactoryPlunginInterface};
+
+	// Making sure that no race situation arises between FBserv and Ecom
+	// If ECom is not ready, give it another chance and try again. if it still doesn't work 
+	// after the third try, then it just carries on quietly and fails... 
+	for (ecomnotready =0; ecomnotready <3; ecomnotready++)
+		{
+       		TRAP(ecomerror,REComSession::ListImplementationsL(uid,implementationArray));
+		if (!ecomerror)
+			{
+			break;
+			}
+		else
+			{
+			ecomerror = 0; 	
+			User::After(0);
+			}
+		}
+
+	const TInt availCount = implementationArray.Count();
+	for (TInt count=0;count<availCount;++count)
+		{
+		const CImplementationInformation* info = implementationArray[count];
+		TUid shaperFactoryUid = info->ImplementationUid();
+ 		// Create a shaper factory
+ 		//CShaperFactory* shaperFactory = 0;
+ 		TRAP(error,shaperFactory = CShaperFactory::NewL(shaperFactoryUid));
+   		TEST2(error, KErrNone);
+   			// Create a shaper
+   		TRAPD(err, theShaper = shaperFactory->NewShaperL(font, aScript, aLanguage, &User::Heap()));
+   		TEST2(err, KErrNone);
+    	}
+	CleanupStack::PopAndDestroy(&implementationArray); 	
+
+	CleanupStack::PushL(shaperFactory);
+	CleanupStack::PushL(theShaper);
+
+	// create the data to be shaped
+	// this uses testData, defined in testData.h
+	CShaper::TInput shaperInput;
+	shaperInput.iText = &input;
+	shaperInput.iStart = start;
+	shaperInput.iEnd = end;
+
+	TShapeHeader* output = NULL;
+	err = theShaper->ShapeText(output, shaperInput, &User::Heap());
+	TEST2(err,KErrNone);
+	CleanupStack::PushL(output);
+	
+	
+	//AND FILL THE FILE UP WITH THE RESULTS
+	
+	//first the glyph count
+	aStream.WriteInt16L(output->iGlyphCount);
+	TInt glyphCount(output->iGlyphCount);
+	TInt i;
+	
+	//then the Glyphs
+	TUint32* shapePtr32 = (reinterpret_cast<TUint32*>(&output->iBuffer[0]));
+	for(i=0; i <glyphCount; i++)
+		{
+		aStream.WriteInt32L(*shapePtr32);
+		shapePtr32++;
+		}
+	
+	//then the X and Y positions
+	TUint16* shapePtr16 = (reinterpret_cast<TUint16*>(shapePtr32));
+	for(i=0; i<glyphCount*2; i++)
+		{
+		aStream.WriteInt16L(*shapePtr16);
+		shapePtr16++;		
+		}
+	
+  	//then the advance
+  	aStream.WriteInt16L(*shapePtr16);
+	shapePtr16++;		
+  	aStream.WriteInt16L(*shapePtr16);
+	shapePtr16++;		
+ 	
+	//then the indices
+	for(i=0; i<glyphCount; i++)
+		{
+		aStream.WriteInt16L(*shapePtr16);
+		shapePtr16++;		
+		}	
+	
+	//then the character count
+	aStream.WriteInt16L(output->iCharacterCount);
+
+	CleanupStack::PopAndDestroy(output);
+	CleanupStack::PopAndDestroy(theShaper);
+	CleanupStack::PopAndDestroy(shaperFactory);
+	REComSession::FinalClose();
+
+	CleanupStack::Pop(font);  
+	fontStore->ReleaseFont(font);
+	CleanupStack::PopAndDestroy(fontStore);
+
+	//close the ecom session opened by LoadOpenFontLibraries()
+	REComSession::FinalClose();
+	}
+
+static void MainL()
+	{
+	RFs fs;
+	RFile file;
+	RFileBuf buf;
+
+	// Create the Devanagari test data files
+	const TInt numberOfTests
+		= sizeof(TNR_Dev_OTInputData)/sizeof(TNR_Dev_OTInputData[0]);
+	for (TInt i = 0; i != numberOfTests; ++i)
+		{
+		const TInputData& data = TNR_Dev_OTInputData[i];
+		User::LeaveIfError(fs.Connect());
+		CleanupClosePushL(fs);
+		// note this uses RFile::Create so that users of this utility cannot accidentally write over
+		// files created before. If this test fails, you need to ensure that the file specified by 
+		// KFileName is correct, and if so delete it before running this utility.
+		TEST2(file.Create(fs, data.OutputFilename(), EFileWrite), KErrNone);
+				
+		CleanupClosePushL(buf);
+		buf.Attach(file);
+		RWriteStream stream(&buf);
+
+		//write to the stream
+		WriteInputData(stream, data);
+		WriteOutputData(stream, data, KDevanagariScriptCode, KHindiLanguageCode);
+
+		CleanupStack::PopAndDestroy(2);	//buf, fs
+		}
+	
+	// Create the Kannada test data files
+	const TInt numberOfKanTests = sizeof(Kannada_InputData)/sizeof(Kannada_InputData[0]);
+	for (TInt i = 0; i != numberOfKanTests; i++)
+		{
+		const TInputData& kan_data = Kannada_InputData[i];
+		User::LeaveIfError(fs.Connect());
+		CleanupClosePushL(fs);
+		TEST2(file.Create(fs, kan_data.OutputFilename(), EFileWrite), KErrNone);
+		CleanupClosePushL(buf);
+		buf.Attach(file);
+		RWriteStream stream(&buf);
+			
+		WriteInputData(stream, kan_data);
+		WriteOutputData(stream, kan_data, KKannadaScriptCode, KKannadaLanguageCode);
+		
+		CleanupStack::PopAndDestroy(2);
+		}
+
+	
+	// Create the Gujarati test data files
+	const TInt numberOfGujTests = sizeof(Gujarati_InputData)/sizeof(Gujarati_InputData[0]);
+	for (TInt i = 0; i != numberOfGujTests; i++)
+		{
+		const TInputData& kan_data = Gujarati_InputData[i];
+		User::LeaveIfError(fs.Connect());
+		CleanupClosePushL(fs);
+		TEST2(file.Create(fs, kan_data.OutputFilename(), EFileWrite), KErrNone);
+		CleanupClosePushL(buf);
+		buf.Attach(file);
+		RWriteStream stream(&buf);
+			
+		WriteInputData(stream, kan_data);
+		WriteOutputData(stream, kan_data, KGujaratiScriptCode, KGujaratiLanguageCode);
+		
+		CleanupStack::PopAndDestroy(2);
+		}
+	
+	
+	// Create the Bengali test data files
+	const TInt numberOfBenTests = sizeof(Bengali_InputData)/sizeof(Bengali_InputData[0]);
+	for (TInt i = 0; i != numberOfBenTests; i++)
+		{
+		const TInputData& ben_data = Bengali_InputData[i];
+		User::LeaveIfError(fs.Connect());
+		CleanupClosePushL(fs);
+		TEST2(file.Create(fs, ben_data.OutputFilename(), EFileWrite), KErrNone);
+		CleanupClosePushL(buf);
+		buf.Attach(file);
+		RWriteStream stream(&buf);
+			
+		WriteInputData(stream, ben_data);
+		WriteOutputData(stream, ben_data, KBengaliScriptCode, KBengaliLanguageCode);
+		
+		CleanupStack::PopAndDestroy(2);
+		}
+	
+	// Create the Tamil test data files
+	const TInt numberOfTamTests = sizeof(Tamil_InputData)/sizeof(Tamil_InputData[0]);
+	for (TInt i = 0; i != numberOfTamTests; i++)
+		{
+		const TInputData& tam_data = Tamil_InputData[i];
+		User::LeaveIfError(fs.Connect());
+		CleanupClosePushL(fs);
+		TEST2(file.Create(fs, tam_data.OutputFilename(), EFileWrite), KErrNone);
+		CleanupClosePushL(buf);
+		buf.Attach(file);
+		RWriteStream stream(&buf);
+			
+		WriteInputData(stream, tam_data);
+		WriteOutputData(stream, tam_data, KTamilScriptCode, KTamilLanguageCode);
+		
+		CleanupStack::PopAndDestroy(2);
+		}
+	
+	// Create the Telugu test data files
+	const TInt numberOfTelTests = sizeof(Telugu_InputData)/sizeof(Telugu_InputData[0]);
+	for (TInt i = 0; i != numberOfTelTests; i++)
+		{
+		const TInputData& tel_data = Telugu_InputData[i];
+		User::LeaveIfError(fs.Connect());
+		CleanupClosePushL(fs);
+		TEST2(file.Create(fs, tel_data.OutputFilename(), EFileWrite), KErrNone);
+		CleanupClosePushL(buf);
+		buf.Attach(file);
+		RWriteStream stream(&buf);
+			
+		WriteInputData(stream, tel_data);
+		WriteOutputData(stream, tel_data, KTeluguScriptCode, KTeluguLanguageCode);
+		
+		CleanupStack::PopAndDestroy(2);
+		}
+	
+	// Create the Gurmukhi test data files
+	const TInt numberOfGurTests = sizeof(Gurmukhi_InputData)/sizeof(Gurmukhi_InputData[0]);
+	for (TInt i = 0; i != numberOfGurTests; i++)
+		{
+		const TInputData& tel_data = Gurmukhi_InputData[i];
+		User::LeaveIfError(fs.Connect());
+		CleanupClosePushL(fs);
+		TEST2(file.Create(fs, tel_data.OutputFilename(), EFileWrite), KErrNone);
+		CleanupClosePushL(buf);
+		buf.Attach(file);
+		RWriteStream stream(&buf);
+			
+		WriteInputData(stream, tel_data);
+		WriteOutputData(stream, tel_data, KGurmukhiScriptCode, KGurmukhiLanguageCode);
+		
+		CleanupStack::PopAndDestroy(2);
+		}
+	
+	// 	Create the Malayalam test data files
+	const TInt numberOfMalaTests = sizeof(Malayalam_InputData)/sizeof(Malayalam_InputData[0]);
+	for (TInt i = 0; i != numberOfMalaTests; i++)
+		{
+		const TInputData& tel_data = Malayalam_InputData[i];
+		User::LeaveIfError(fs.Connect());
+		CleanupClosePushL(fs);
+		TEST2(file.Create(fs, tel_data.OutputFilename(), EFileWrite), KErrNone);
+		CleanupClosePushL(buf);
+		buf.Attach(file);
+		RWriteStream stream(&buf);
+			
+		WriteInputData(stream, tel_data);
+		WriteOutputData(stream, tel_data, KMalayalamScriptCode, KMalayalamLanguageCode);
+		
+		CleanupStack::PopAndDestroy(2);
+		}
+	}
+
+TInt E32Main()
+	{
+	__UHEAP_MARK;
+		
+	CTrapCleanup* cleanup = CTrapCleanup::New();
+	if(!cleanup)
+		return KErrNoMemory;
+	
+	TRAPD(err, MainL());
+	TEST2(err, KErrNone);
+	
+	delete cleanup;
+	__UHEAP_MARKEND;
+
+	return KErrNone;
+	}
+