os/textandloc/fontservices/textshaperplugin/test/CreateTestData/T_SHAP_createTestData.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/fontservices/textshaperplugin/test/CreateTestData/T_SHAP_createTestData.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,504 @@
1.4 +/*
1.5 +* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +* Creates test data files that are used by TC_SHAP_shapeText.cpp test.
1.19 +* This tool uses the Unicode test input text defined in inputData.h and
1.20 +* shapes the text by calling the IcuLayoutEngine API ShapeText().
1.21 +* The result, along with the input text is stored in the test data files with
1.22 +* extensions .dat
1.23 +* First, the reference input data is stored in the data files in the following format, seperated by a delimiter - | :
1.24 +* 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
1.25 +* Then the result of the shaping is stored in data files in the following format:
1.26 +* Output glyph count Output glyphs Glyph X and Y coordinates Glyph advances Glyph indices Output character count
1.27 +* The TC_SHAP_shape_Text test is programmed to read in files in this format, and this format only.
1.28 +* This tool needs to be run, and new test data files need to be created everytime the
1.29 +* IcuLayoutEngine shaping rules are changed/edited/appended.
1.30 +* IN ORDER TO CREATE NEW TEST DATA FILES USING THIS UTILITY, YOU WILL NEED TO:
1.31 +* 1. Add a new TInputData entry in inputData.txt
1.32 +* 2. Delete any old data files in %EPOCROOT%epoc32\winscw\c\
1.33 +* 3. Run the test.
1.34 +* IN ORDER TO GET THE TC_SHAP_shapeText TEST FILE TO USE THIS NEW DATA, YOU WILL NEED TO:
1.35 +* 1. Add your new test file in perforce to:
1.36 +* IcuLayoutEngine/test/testdata/...
1.37 +* They will have been added to %EPOCROOT%epoc32\winscw\c
1.38 +* 2. Update the bld.inf file for IcuLayoutEngine to export this file to z:\test\data\...
1.39 +* 3. Update the .cpp file by adding the a new literal at the top of the file with the new filename to be used.
1.40 +* 4. Update the TC_SHAP_shapeText.iby file in IcuLayoutEngine/test to include the new file.
1.41 +* THIS TOOL SHOULD ONLY BE RUN BY SOMEONE WHO KNOWS WHAT HE/SHE IS DOING!!
1.42 +*
1.43 +*/
1.44 +
1.45 +
1.46 +#include <e32def.h>
1.47 +#include <e32test.h>
1.48 +#include <e32std.h>
1.49 +#include <f32file.h>
1.50 +#include <fntstore.h>
1.51 +#include <s32file.h>
1.52 +
1.53 +#include <graphics/openfontrasterizer.h>
1.54 +#include <graphics/openfontconstants.h>
1.55 +#include <graphics/shapeimpl.h>
1.56 +#include "inputData.h"
1.57 +
1.58 +const TUint32 KDevanagariScriptCode = 0x64657661;
1.59 +const TUint32 KKannadaScriptCode = 0x6B6E6461;
1.60 +const TUint32 KHindiLanguageCode = 0x48494E20;
1.61 +const TUint32 KKannadaLanguageCode = 0x4B414E20;
1.62 +const TUint32 KGujaratiScriptCode = 0x67756A72;
1.63 +const TUint32 KGujaratiLanguageCode = 0x47554A20;
1.64 +const TUint32 KBengaliScriptCode = 0x62656E67;
1.65 +const TUint32 KBengaliLanguageCode = 0x42454E20;
1.66 +const TUint32 KTamilScriptCode = 0x74616D6C;
1.67 +const TUint32 KTamilLanguageCode = 0x54414D20;
1.68 +const TUint32 KTeluguScriptCode = 0x74656C75;
1.69 +const TUint32 KTeluguLanguageCode = 0x54454C20;
1.70 +const TUint32 KGurmukhiScriptCode = 0x67757275;
1.71 +const TUint32 KGurmukhiLanguageCode = 0;
1.72 +const TUint32 KMalayalamScriptCode = 0x6d6c796d;
1.73 +const TUint32 KMalayalamLanguageCode = 0x4d4c5220;
1.74 +
1.75 +
1.76 +_LIT16(KDelimiter, "|");
1.77 +
1.78 +//RTest Macros etc
1.79 +static RTest TheTest(_L("T_SHAP_createTestData"));
1.80 +static void Check(TInt aValue, TInt aLine)
1.81 + {
1.82 + if(!aValue)
1.83 + {
1.84 + TheTest(EFalse, aLine);
1.85 + }
1.86 + }
1.87 +
1.88 +static void Check(TInt aValue, TInt aExpected, TInt aLine)
1.89 + {
1.90 + if(aValue != aExpected)
1.91 + {
1.92 + RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
1.93 + TheTest(EFalse, aLine);
1.94 + }
1.95 + }
1.96 +
1.97 +#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
1.98 +#define TEST(arg) ::Check((arg), __LINE__)
1.99 +
1.100 +/*
1.101 +Used for cleanup of RImplInfoArray implementationArray below
1.102 +This method is stolen from FbsTop.cpp
1.103 +*/
1.104 +LOCAL_C void ResetAndDestroyRImplInfoPtrArray(TAny* aPtr)
1.105 + {
1.106 + RImplInfoPtrArray* array = reinterpret_cast <RImplInfoPtrArray*> (aPtr);
1.107 + array->ResetAndDestroy();
1.108 + }
1.109 +
1.110 +/*
1.111 +Load all ECOM implemented rasterizer DLLs.
1.112 +This method is stolen from CFbTop::LoadOpenFontLibraries()
1.113 +*/
1.114 +LOCAL_C void LoadOpenFontLibraries(CFontStore* aFontStore)
1.115 + {
1.116 +
1.117 + RImplInfoPtrArray implementationArray;
1.118 + TCleanupItem cleanup(ResetAndDestroyRImplInfoPtrArray, &implementationArray);
1.119 + CleanupStack::PushL(cleanup);
1.120 + TInt error;
1.121 + TInt ecomerror;
1.122 + TInt ecomnotready;
1.123 + TUid uid = {KUidOpenFontRasterizerPlunginInterface};
1.124 +
1.125 + // Making sure that no race situation arises
1.126 + // If ECom is not ready, give it another chance and try again. if it still doesn't work
1.127 + // after the third try, then it just carries on quietly and fails...
1.128 + for (ecomnotready =0; ecomnotready <3; ecomnotready++)
1.129 + {
1.130 + TRAP(ecomerror,REComSession::ListImplementationsL(uid,implementationArray));
1.131 + if (!ecomerror)
1.132 + {
1.133 + break;
1.134 + }
1.135 + else
1.136 + {
1.137 + ecomerror = 0;
1.138 + User::After(0);
1.139 + }
1.140 + }
1.141 +
1.142 + const TInt availCount = implementationArray.Count();
1.143 + for (TInt count=0;count<availCount;++count)
1.144 + {
1.145 + const CImplementationInformation* info = implementationArray[count];
1.146 + TUid rasterizerUid = info->ImplementationUid();
1.147 + // Create a rasterizer
1.148 + COpenFontRasterizer* rasterizer=0;
1.149 + TRAP(error,rasterizer = COpenFontRasterizer::NewL(rasterizerUid));
1.150 + if (!error)
1.151 + {
1.152 + // Install it in the font store.
1.153 + TRAP(error,aFontStore->InstallRasterizerL(rasterizer));
1.154 + if (error)
1.155 + delete rasterizer;
1.156 + }
1.157 + }
1.158 + CleanupStack::PopAndDestroy(&implementationArray);
1.159 +
1.160 + }
1.161 +
1.162 +LOCAL_C void WriteInputData(RWriteStream& aStream, const TInputData& aInputData)
1.163 + {
1.164 + //output the input data to the file
1.165 + TPtrC input = aInputData.TextInput();
1.166 + TInt length = input.Length();
1.167 + TInt start = aInputData.iStart;
1.168 + if (start < 0)
1.169 + start += length;
1.170 + TInt end = aInputData.iEnd;
1.171 + if (end <= 0)
1.172 + end += length;
1.173 +
1.174 + aStream.WriteInt16L(length);
1.175 +
1.176 + aStream.WriteL(aInputData.TypeFaceName());
1.177 + aStream.WriteL(KDelimiter);
1.178 +
1.179 + aStream.WriteL(aInputData.FontFilename());
1.180 + aStream.WriteL(KDelimiter);
1.181 +
1.182 + aStream.WriteInt16L(start);
1.183 + aStream.WriteL(KDelimiter);
1.184 + aStream.WriteInt16L(end);
1.185 + aStream.WriteL(KDelimiter);
1.186 +
1.187 + aStream.WriteL(input);
1.188 + aStream.WriteL(KDelimiter);
1.189 + }
1.190 +
1.191 +static void WriteOutputData(RWriteStream& aStream, const TInputData& aInputData,
1.192 + TUint32 aScript, TUint32 aLanguage)
1.193 + {
1.194 + //SHAPE THE TEXT
1.195 +
1.196 + TPtrC input = aInputData.TextInput();
1.197 + TInt length = input.Length();
1.198 + TInt start = aInputData.iStart;
1.199 + if (start < 0)
1.200 + start += length;
1.201 + TInt end = aInputData.iEnd;
1.202 + if (end <= 0)
1.203 + end += length;
1.204 +
1.205 + //set up font store and install rasterizer(s)
1.206 + CFontStore* fontStore = CFontStore::NewL(&User::Heap());
1.207 + fontStore->iKPixelWidthInTwips = 11860;
1.208 + fontStore->iKPixelHeightInTwips = 11860;
1.209 + CleanupStack::PushL(fontStore);
1.210 + LoadOpenFontLibraries(fontStore);
1.211 +
1.212 + //add required font file
1.213 + TRAPD( err, fontStore->AddFileL(aInputData.FontFilename()) );
1.214 + TEST(err==KErrNone);
1.215 +
1.216 + CBitmapFont* font;
1.217 + TFontSpec fontSpec(aInputData.TypeFaceName(), 12);
1.218 + fontStore->GetNearestFontToDesignHeightInPixels((CFont*&)font, fontSpec);
1.219 + CleanupStack::PushL(font);
1.220 +
1.221 + CShaper* theShaper = NULL;
1.222 + CShaperFactory* shaperFactory = NULL;
1.223 +
1.224 + RImplInfoPtrArray implementationArray;
1.225 + TCleanupItem cleanup(ResetAndDestroyRImplInfoPtrArray, &implementationArray);
1.226 + CleanupStack::PushL(cleanup);
1.227 + TInt error;
1.228 + TInt ecomerror;
1.229 + TInt ecomnotready;
1.230 + TUid uid = {KUidShaperFactoryPlunginInterface};
1.231 +
1.232 + // Making sure that no race situation arises between FBserv and Ecom
1.233 + // If ECom is not ready, give it another chance and try again. if it still doesn't work
1.234 + // after the third try, then it just carries on quietly and fails...
1.235 + for (ecomnotready =0; ecomnotready <3; ecomnotready++)
1.236 + {
1.237 + TRAP(ecomerror,REComSession::ListImplementationsL(uid,implementationArray));
1.238 + if (!ecomerror)
1.239 + {
1.240 + break;
1.241 + }
1.242 + else
1.243 + {
1.244 + ecomerror = 0;
1.245 + User::After(0);
1.246 + }
1.247 + }
1.248 +
1.249 + const TInt availCount = implementationArray.Count();
1.250 + for (TInt count=0;count<availCount;++count)
1.251 + {
1.252 + const CImplementationInformation* info = implementationArray[count];
1.253 + TUid shaperFactoryUid = info->ImplementationUid();
1.254 + // Create a shaper factory
1.255 + //CShaperFactory* shaperFactory = 0;
1.256 + TRAP(error,shaperFactory = CShaperFactory::NewL(shaperFactoryUid));
1.257 + TEST2(error, KErrNone);
1.258 + // Create a shaper
1.259 + TRAPD(err, theShaper = shaperFactory->NewShaperL(font, aScript, aLanguage, &User::Heap()));
1.260 + TEST2(err, KErrNone);
1.261 + }
1.262 + CleanupStack::PopAndDestroy(&implementationArray);
1.263 +
1.264 + CleanupStack::PushL(shaperFactory);
1.265 + CleanupStack::PushL(theShaper);
1.266 +
1.267 + // create the data to be shaped
1.268 + // this uses testData, defined in testData.h
1.269 + CShaper::TInput shaperInput;
1.270 + shaperInput.iText = &input;
1.271 + shaperInput.iStart = start;
1.272 + shaperInput.iEnd = end;
1.273 +
1.274 + TShapeHeader* output = NULL;
1.275 + err = theShaper->ShapeText(output, shaperInput, &User::Heap());
1.276 + TEST2(err,KErrNone);
1.277 + CleanupStack::PushL(output);
1.278 +
1.279 +
1.280 + //AND FILL THE FILE UP WITH THE RESULTS
1.281 +
1.282 + //first the glyph count
1.283 + aStream.WriteInt16L(output->iGlyphCount);
1.284 + TInt glyphCount(output->iGlyphCount);
1.285 + TInt i;
1.286 +
1.287 + //then the Glyphs
1.288 + TUint32* shapePtr32 = (reinterpret_cast<TUint32*>(&output->iBuffer[0]));
1.289 + for(i=0; i <glyphCount; i++)
1.290 + {
1.291 + aStream.WriteInt32L(*shapePtr32);
1.292 + shapePtr32++;
1.293 + }
1.294 +
1.295 + //then the X and Y positions
1.296 + TUint16* shapePtr16 = (reinterpret_cast<TUint16*>(shapePtr32));
1.297 + for(i=0; i<glyphCount*2; i++)
1.298 + {
1.299 + aStream.WriteInt16L(*shapePtr16);
1.300 + shapePtr16++;
1.301 + }
1.302 +
1.303 + //then the advance
1.304 + aStream.WriteInt16L(*shapePtr16);
1.305 + shapePtr16++;
1.306 + aStream.WriteInt16L(*shapePtr16);
1.307 + shapePtr16++;
1.308 +
1.309 + //then the indices
1.310 + for(i=0; i<glyphCount; i++)
1.311 + {
1.312 + aStream.WriteInt16L(*shapePtr16);
1.313 + shapePtr16++;
1.314 + }
1.315 +
1.316 + //then the character count
1.317 + aStream.WriteInt16L(output->iCharacterCount);
1.318 +
1.319 + CleanupStack::PopAndDestroy(output);
1.320 + CleanupStack::PopAndDestroy(theShaper);
1.321 + CleanupStack::PopAndDestroy(shaperFactory);
1.322 + REComSession::FinalClose();
1.323 +
1.324 + CleanupStack::Pop(font);
1.325 + fontStore->ReleaseFont(font);
1.326 + CleanupStack::PopAndDestroy(fontStore);
1.327 +
1.328 + //close the ecom session opened by LoadOpenFontLibraries()
1.329 + REComSession::FinalClose();
1.330 + }
1.331 +
1.332 +static void MainL()
1.333 + {
1.334 + RFs fs;
1.335 + RFile file;
1.336 + RFileBuf buf;
1.337 +
1.338 + // Create the Devanagari test data files
1.339 + const TInt numberOfTests
1.340 + = sizeof(TNR_Dev_OTInputData)/sizeof(TNR_Dev_OTInputData[0]);
1.341 + for (TInt i = 0; i != numberOfTests; ++i)
1.342 + {
1.343 + const TInputData& data = TNR_Dev_OTInputData[i];
1.344 + User::LeaveIfError(fs.Connect());
1.345 + CleanupClosePushL(fs);
1.346 + // note this uses RFile::Create so that users of this utility cannot accidentally write over
1.347 + // files created before. If this test fails, you need to ensure that the file specified by
1.348 + // KFileName is correct, and if so delete it before running this utility.
1.349 + TEST2(file.Create(fs, data.OutputFilename(), EFileWrite), KErrNone);
1.350 +
1.351 + CleanupClosePushL(buf);
1.352 + buf.Attach(file);
1.353 + RWriteStream stream(&buf);
1.354 +
1.355 + //write to the stream
1.356 + WriteInputData(stream, data);
1.357 + WriteOutputData(stream, data, KDevanagariScriptCode, KHindiLanguageCode);
1.358 +
1.359 + CleanupStack::PopAndDestroy(2); //buf, fs
1.360 + }
1.361 +
1.362 + // Create the Kannada test data files
1.363 + const TInt numberOfKanTests = sizeof(Kannada_InputData)/sizeof(Kannada_InputData[0]);
1.364 + for (TInt i = 0; i != numberOfKanTests; i++)
1.365 + {
1.366 + const TInputData& kan_data = Kannada_InputData[i];
1.367 + User::LeaveIfError(fs.Connect());
1.368 + CleanupClosePushL(fs);
1.369 + TEST2(file.Create(fs, kan_data.OutputFilename(), EFileWrite), KErrNone);
1.370 + CleanupClosePushL(buf);
1.371 + buf.Attach(file);
1.372 + RWriteStream stream(&buf);
1.373 +
1.374 + WriteInputData(stream, kan_data);
1.375 + WriteOutputData(stream, kan_data, KKannadaScriptCode, KKannadaLanguageCode);
1.376 +
1.377 + CleanupStack::PopAndDestroy(2);
1.378 + }
1.379 +
1.380 +
1.381 + // Create the Gujarati test data files
1.382 + const TInt numberOfGujTests = sizeof(Gujarati_InputData)/sizeof(Gujarati_InputData[0]);
1.383 + for (TInt i = 0; i != numberOfGujTests; i++)
1.384 + {
1.385 + const TInputData& kan_data = Gujarati_InputData[i];
1.386 + User::LeaveIfError(fs.Connect());
1.387 + CleanupClosePushL(fs);
1.388 + TEST2(file.Create(fs, kan_data.OutputFilename(), EFileWrite), KErrNone);
1.389 + CleanupClosePushL(buf);
1.390 + buf.Attach(file);
1.391 + RWriteStream stream(&buf);
1.392 +
1.393 + WriteInputData(stream, kan_data);
1.394 + WriteOutputData(stream, kan_data, KGujaratiScriptCode, KGujaratiLanguageCode);
1.395 +
1.396 + CleanupStack::PopAndDestroy(2);
1.397 + }
1.398 +
1.399 +
1.400 + // Create the Bengali test data files
1.401 + const TInt numberOfBenTests = sizeof(Bengali_InputData)/sizeof(Bengali_InputData[0]);
1.402 + for (TInt i = 0; i != numberOfBenTests; i++)
1.403 + {
1.404 + const TInputData& ben_data = Bengali_InputData[i];
1.405 + User::LeaveIfError(fs.Connect());
1.406 + CleanupClosePushL(fs);
1.407 + TEST2(file.Create(fs, ben_data.OutputFilename(), EFileWrite), KErrNone);
1.408 + CleanupClosePushL(buf);
1.409 + buf.Attach(file);
1.410 + RWriteStream stream(&buf);
1.411 +
1.412 + WriteInputData(stream, ben_data);
1.413 + WriteOutputData(stream, ben_data, KBengaliScriptCode, KBengaliLanguageCode);
1.414 +
1.415 + CleanupStack::PopAndDestroy(2);
1.416 + }
1.417 +
1.418 + // Create the Tamil test data files
1.419 + const TInt numberOfTamTests = sizeof(Tamil_InputData)/sizeof(Tamil_InputData[0]);
1.420 + for (TInt i = 0; i != numberOfTamTests; i++)
1.421 + {
1.422 + const TInputData& tam_data = Tamil_InputData[i];
1.423 + User::LeaveIfError(fs.Connect());
1.424 + CleanupClosePushL(fs);
1.425 + TEST2(file.Create(fs, tam_data.OutputFilename(), EFileWrite), KErrNone);
1.426 + CleanupClosePushL(buf);
1.427 + buf.Attach(file);
1.428 + RWriteStream stream(&buf);
1.429 +
1.430 + WriteInputData(stream, tam_data);
1.431 + WriteOutputData(stream, tam_data, KTamilScriptCode, KTamilLanguageCode);
1.432 +
1.433 + CleanupStack::PopAndDestroy(2);
1.434 + }
1.435 +
1.436 + // Create the Telugu test data files
1.437 + const TInt numberOfTelTests = sizeof(Telugu_InputData)/sizeof(Telugu_InputData[0]);
1.438 + for (TInt i = 0; i != numberOfTelTests; i++)
1.439 + {
1.440 + const TInputData& tel_data = Telugu_InputData[i];
1.441 + User::LeaveIfError(fs.Connect());
1.442 + CleanupClosePushL(fs);
1.443 + TEST2(file.Create(fs, tel_data.OutputFilename(), EFileWrite), KErrNone);
1.444 + CleanupClosePushL(buf);
1.445 + buf.Attach(file);
1.446 + RWriteStream stream(&buf);
1.447 +
1.448 + WriteInputData(stream, tel_data);
1.449 + WriteOutputData(stream, tel_data, KTeluguScriptCode, KTeluguLanguageCode);
1.450 +
1.451 + CleanupStack::PopAndDestroy(2);
1.452 + }
1.453 +
1.454 + // Create the Gurmukhi test data files
1.455 + const TInt numberOfGurTests = sizeof(Gurmukhi_InputData)/sizeof(Gurmukhi_InputData[0]);
1.456 + for (TInt i = 0; i != numberOfGurTests; i++)
1.457 + {
1.458 + const TInputData& tel_data = Gurmukhi_InputData[i];
1.459 + User::LeaveIfError(fs.Connect());
1.460 + CleanupClosePushL(fs);
1.461 + TEST2(file.Create(fs, tel_data.OutputFilename(), EFileWrite), KErrNone);
1.462 + CleanupClosePushL(buf);
1.463 + buf.Attach(file);
1.464 + RWriteStream stream(&buf);
1.465 +
1.466 + WriteInputData(stream, tel_data);
1.467 + WriteOutputData(stream, tel_data, KGurmukhiScriptCode, KGurmukhiLanguageCode);
1.468 +
1.469 + CleanupStack::PopAndDestroy(2);
1.470 + }
1.471 +
1.472 + // Create the Malayalam test data files
1.473 + const TInt numberOfMalaTests = sizeof(Malayalam_InputData)/sizeof(Malayalam_InputData[0]);
1.474 + for (TInt i = 0; i != numberOfMalaTests; i++)
1.475 + {
1.476 + const TInputData& tel_data = Malayalam_InputData[i];
1.477 + User::LeaveIfError(fs.Connect());
1.478 + CleanupClosePushL(fs);
1.479 + TEST2(file.Create(fs, tel_data.OutputFilename(), EFileWrite), KErrNone);
1.480 + CleanupClosePushL(buf);
1.481 + buf.Attach(file);
1.482 + RWriteStream stream(&buf);
1.483 +
1.484 + WriteInputData(stream, tel_data);
1.485 + WriteOutputData(stream, tel_data, KMalayalamScriptCode, KMalayalamLanguageCode);
1.486 +
1.487 + CleanupStack::PopAndDestroy(2);
1.488 + }
1.489 + }
1.490 +
1.491 +TInt E32Main()
1.492 + {
1.493 + __UHEAP_MARK;
1.494 +
1.495 + CTrapCleanup* cleanup = CTrapCleanup::New();
1.496 + if(!cleanup)
1.497 + return KErrNoMemory;
1.498 +
1.499 + TRAPD(err, MainL());
1.500 + TEST2(err, KErrNone);
1.501 +
1.502 + delete cleanup;
1.503 + __UHEAP_MARKEND;
1.504 +
1.505 + return KErrNone;
1.506 + }
1.507 +