aknlayoutcompiler/src/LayCdl2InstO.cpp
changeset 0 f58d6ec98e88
child 1 b700e12870ca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aknlayoutcompiler/src/LayCdl2InstO.cpp	Thu Dec 17 09:14:18 2009 +0200
@@ -0,0 +1,898 @@
+/*
+* Copyright (c) 2002-2004 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:  
+*
+*/
+
+
+
+// disable "identifier was truncated to '255' characters in the browser information" warning
+#pragma warning (disable:4786)
+
+#include "LayCdl2InstO.h"
+#include "LayoutCompilerErr.h"
+#include "LayoutParse.h"
+#include "CppWriter.h"
+#include "Lay2Cdl.h"
+#include "CodeGenConsts.h"
+#include <fstream>
+#include <algorithm>
+#include <iostream>
+using namespace std;
+using namespace CdlCompilerToolkit;
+
+#define AKNLAYOUT_DEFINE_BYTECODE(name,byte) const char name = char(byte);
+#include "AknLayoutByteCodes.h"
+
+
+extern string KMultiLine("Multiline_");
+typedef LayoutProcessArgsErr<LayoutCdlInstanceOpt> LayoutCdlInstanceOptArgsErr;
+
+
+/**
+*  gTheFuncs
+*  This is a collection of all SImplFunc objects that a layout instance needs, initialised
+*  so that there are up to four integer parameters per API type.
+*/
+CAllFuncs gTheFuncs(4);
+
+const string KDefinitionNotSet("Layout definition not found");
+
+
+CAllFuncs::CAllFuncs(int aMaxParams)
+	{
+	for (int ii=0; ii<=aMaxParams; ii++)
+		{
+		for (int jj=0; jj<2; jj++)
+			{
+			bool useParent = (jj == 1);
+			AddLineFunc(SImplFunc::EWindowLine, ii, useParent, KTypeWindowLineLayout, "WindowLine");
+			AddLineFunc(SImplFunc::ETextLine, ii, useParent, KTypeTextLineLayout, "TextLine");
+			AddLineFunc(SImplFunc::EMultilineTextLine, ii, useParent, KTypeMultiLineTextLayout, "MultiLineTextLine");
+			AddTableFunc(SImplFunc::EWindowTable, ii, useParent, KTypeWindowLineLayout, "WindowTable");
+			AddTableFunc(SImplFunc::ETextTable, ii, useParent, KTypeTextLineLayout, "TextTable");
+			}
+		}
+	SImplFunc limits(
+		SImplFunc::ETableLimits, 0, false,
+		KTypeLayoutTableLimits + " Limits() { return AknLayoutDecode::TableLimits(KDataLookup); }",
+		"&Limits");
+	push_back(limits);
+	}
+
+void CAllFuncs::AddLineFunc(SImplFunc::TFuncType aType, int aParams, bool aParent, const string& aReturn, const string& aFuncName)
+	{
+	// create a function of this form:
+	//TAknWindowLineLayout WindowTable$NUM$PARENT($PARAMS_TYPES_AND_NAMES)
+	//	{
+	//	return AknLayoutDecode::WindowLine$NUM$PARENT(&KImplData, $PARAM_NAMES);
+	//  }
+	string funcName = aFuncName + CdlTkUtil::IntToString(aParams) + (aParent ? "t" : "f");
+	string defn = aReturn + " " + funcName + "(";
+	string body = string(") { return AknLayoutDecode::") + funcName + "(&KImplData";
+
+	if (aParent)
+		{
+		defn += KTypeRect + " " + KParamParentRect;
+		body += ", " + KParamParentRect;
+		}
+
+	for (int ii=0; ii<aParams; ii++)
+		{
+		if (aParent || ii>0)
+			defn += ",";
+		defn += string(KTypeInt + " aParam") + CdlTkUtil::IntToString(ii);
+		body += string(", aParam") + CdlTkUtil::IntToString(ii);
+		}
+
+	defn += body + "); }";
+
+	string ptrRef = string("&") + funcName;
+
+	SImplFunc func(aType, aParams, aParent, defn, ptrRef);
+	push_back(func);
+	}
+
+void CAllFuncs::AddTableFunc(SImplFunc::TFuncType aType, int aParams, bool aParent, const string& aReturn, const string& aFuncName)
+	{
+	//Create a function of this form:
+	//TAknWindowLineLayout WindowTable$NUM$PARENT(TInt aLineIndex, $PARAMS_TYPES_AND_NAMES) 
+	//	{
+	//	return AknLayoutDecode::WindowTable$NUM$PARENT(&KImplData, aLineIndex, $PARAM_NAMES); 
+	//  }
+
+	string funcName = aFuncName + CdlTkUtil::IntToString(aParams) + (aParent ? "t" : "f");
+	string defn = aReturn + " " + funcName + "(" + KTypeInt + " " + KParamLineIndex;
+	string body = string(") { return AknLayoutDecode::") + funcName + "(&KImplData, " + KParamLineIndex;
+
+	if (aParent)
+		{
+		defn += ", " + KTypeRect + " " + KParamParentRect;
+		body += ", " + KParamParentRect;
+		}
+
+	for (int ii=0; ii<aParams; ii++)
+		{
+		defn += string(", " + KTypeInt + " aParam") + CdlTkUtil::IntToString(ii);
+		body += string(", aParam") + CdlTkUtil::IntToString(ii);
+		}
+
+	defn += body + "); }";
+
+	string ptrRef = string("&") + funcName;
+
+	SImplFunc func(aType, aParams, aParent, defn, ptrRef);
+	push_back(func);
+	}
+
+
+class CLayoutInstOptImpl
+	{
+public:
+	CLayoutInstOptImpl(TLayoutLine* aLine, CCdlTkImplementation* aImpl);
+	TLayoutLine* iLine;
+	CCdlTkImplementation* iImpl;
+	int iByteCodeIndex;
+	string iComment;
+	vector<char> iBytes;
+	};
+
+CLayoutInstOptImpl::CLayoutInstOptImpl(TLayoutLine* aLine, CCdlTkImplementation* aImpl)
+: iLine(aLine), iImpl(aImpl)
+	{
+	}
+
+
+class CLayoutInstOpt
+	{
+public:
+	CLayoutInstOpt(LayoutCdlInstanceOpt& aInstances, auto_ptr<TLayout>& aLayout, const string& aInstName);
+	~CLayoutInstOpt();
+
+	void Process();
+	void WriteInstance();
+
+	CCdlTkInstance& Inst() { return *iInstance; }
+
+private:
+	void ProcessTable(TLayoutTable& aTable);
+	void ProcessLine(TLayoutLine& aLine);
+	void ProcessLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl);
+	void ProcessMultiLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl);
+
+	void SetSimilarLineData(CLayoutInstOptImpl& aImpl, CLayoutInstOptImpl& aSimilar);
+	void SetNewLineData(CLayoutInstOptImpl& aImpl);
+	bool HasApi(const string& aName);
+	CCdlTkImplementation& FindImp(const string& aName);
+	void SetLineFunc(CLayoutInstOptImpl& aImpl);
+
+	void CountApiParams(CCdlTkImplementation& aApi, int& aParams, bool& aParent);
+	SImplFunc& AddImplFunc(SImplFunc::TFuncType aType, int iParams, bool aParent);
+
+	void SetExtraCpp();
+
+	void AddTableToInstance(TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub, int aTableNum);
+	void AddTableLimitsImpl(const string& aApiName, TLayoutTable::TLayoutSubTable& aSubTable);
+	void AddTableImpl(const string& aApiName, TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub);
+
+	void EncodeValue(vector<char>& aBytes, string aValue);
+
+	void MirrorParamName(string& aParamName);
+
+private:
+	LayoutCdlInstanceOpt& iInstances;
+	TLayout* iLayout;
+	string iName;
+	CCdlTkInterface& iInterface;
+	CCdlTkInstance* iInstance;
+	CLayoutInstOptImpls iImpls;
+	typedef vector<SImplFunc*> CImplFuncs;
+	CImplFuncs iFuncs;
+	};
+
+CLayoutInstOpt::CLayoutInstOpt(LayoutCdlInstanceOpt& aInstances, auto_ptr<TLayout>& aLayout, const string& aInstName)
+: iInstances(aInstances), iName(aInstName), iInterface(iInstances.Interface())
+	{
+	iLayout = aLayout.get();
+	aLayout.release();
+
+	iInstance = new CCdlTkInstance(iInterface);
+	iInstance->SetName(aInstName);
+
+	// Initially set definitions that will not compile in the resulting code.
+	// This will alert the programmer to missing layout data.
+	CCdlTkImplementations& impl = iInstance->Impl();
+	for (CCdlTkImplementations::iterator pImpl = impl.begin(); pImpl != impl.end(); ++pImpl)
+		(*pImpl)->SetDefinition(KDefinitionNotSet);
+	}
+
+CLayoutInstOpt::~CLayoutInstOpt()
+	{
+	delete iLayout;
+	delete iInstance;
+	for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
+		delete *pImpl;
+	}
+
+void CLayoutInstOpt::Process()
+	{
+	for (TLayout::iterator pTab = iLayout->begin(); pTab != iLayout->end(); ++pTab)
+		ProcessTable(**pTab);
+	SetExtraCpp();
+	}
+
+void CLayoutInstOpt::WriteInstance()
+	{
+	CCdlTkWriteInstance writer(*iInstance);
+	writer.Process();
+	}
+
+void CLayoutInstOpt::ProcessTable(TLayoutTable& aTable)
+	{
+	for (TLayoutTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
+		ProcessLine(**pLine);
+
+	int tableNum = 0;
+	for (TLayoutTable::TLayoutSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub)
+		{
+		TLayoutTable::TLayoutSubTable& sub = **pSub;
+		AddTableToInstance(aTable, sub, tableNum);
+		tableNum++;
+		}
+	}
+
+void CLayoutInstOpt::ProcessLine(TLayoutLine& aLine)
+	{
+	string apiName = LayoutToCdl::LineApiName(aLine);
+	if (!HasApi(apiName))
+		return;
+
+	ProcessLineApi(aLine, FindImp(apiName));
+
+	string multilineApiName = KFuncMultiline + apiName;
+	if (aLine.iTable->iType == TLayoutTable::ETextTable &&
+		aLine["B"].size() > 1 &&
+		HasApi(multilineApiName))
+		ProcessMultiLineApi(aLine, FindImp(multilineApiName));
+	}
+
+void CLayoutInstOpt::ProcessLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl)
+	{
+	CLayoutInstOptImpl* newImpl = new CLayoutInstOptImpl(&aLine, &aImpl);
+	iImpls.push_back(newImpl);
+
+	// always set the new line data
+	SetNewLineData(*newImpl);
+
+	// if we can find the new line data in the aggregated data, point to that instead
+	int foundIndex = iInstances.FindSimilarBytes(newImpl);
+	if(foundIndex >= 0)
+		{
+		newImpl->iByteCodeIndex = foundIndex;
+		newImpl->iBytes.clear();
+		}
+
+	SetLineFunc(*newImpl);
+	iInstances.AddImpl(newImpl);
+	newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString(newImpl->iByteCodeIndex) + ",\t// " + LayoutToCdl::LineApiName(aLine));
+	}
+
+void CLayoutInstOpt::ProcessMultiLineApi(TLayoutLine& aLine, CCdlTkImplementation& aImpl)
+	{
+	CLayoutInstOptImpl* newImpl = new CLayoutInstOptImpl(&aLine, &aImpl);
+	iImpls.push_back(newImpl);
+
+	CCdlTkImplementation& textImpl = FindImp(LayoutToCdl::LineApiName(aLine));
+
+	// locate the position of the "aIndex_B" paramters in the text API parameter list
+	// and the position of the "aNumberOfLinesShown" parameter in the multiline API
+	// parmeter list. This is all the info needed to implement multiline APIs in terms
+	// of the corresponding text API
+	int bPos = 4, lPos = 0;
+	const CCdlTkApiParams& mParams = aImpl.Api().AsFunc().Params();
+	const CCdlTkApiParams& tParams = textImpl.Api().AsFunc().Params();
+	CCdlTkApiParams::const_iterator pMParam = mParams.begin(); 
+	CCdlTkApiParams::const_iterator pTParam = tParams.begin();
+	int ii=0;
+	while (pMParam != mParams.end() || pTParam != tParams.end())
+		{
+		if (pTParam != tParams.end())
+			{
+			if (pTParam->Name() == KParamNameB)
+				bPos = ii;
+			++pTParam;
+			}
+		if (pMParam != mParams.end())
+			{
+			if (pMParam->Name() == KParamNameNumberOfLinesShown)
+				lPos = ii;
+			++pMParam;
+			}
+		ii++;
+		}
+
+	SetLineFunc(*newImpl);
+	iInstances.AddImpl(newImpl);
+	newImpl->iImpl->SetDefinition(CdlTkUtil::ShortToHexString((bPos<<8)|lPos) + ",\t// " + aImpl.Name());
+	}
+
+
+void CLayoutInstOpt::SetSimilarLineData(CLayoutInstOptImpl& aImpl, CLayoutInstOptImpl& aSimilar)
+	{
+	aImpl.iByteCodeIndex = aSimilar.iByteCodeIndex;
+	}
+
+void CLayoutInstOpt::SetNewLineData(CLayoutInstOptImpl& aImpl)
+	{
+	TLayoutLine& line = *aImpl.iLine;
+
+	// set comment
+	aImpl.iComment = string("for ") + LayoutToCdl::LineApiName(line);
+
+	const string* outputOrder = KWindowOutputOrder;
+	int outputSize = KWindowOutputOrderSize;
+	if (line.iTable->iType == TLayoutTable::ETextTable)
+		{
+		outputOrder = KTextOutputOrder;
+		outputSize = KTextOutputOrderSize;
+		}
+
+	// encode parameters
+	const CCdlTkApiParams& params = aImpl.iImpl->Api().AsFunc().Params();
+	for (CCdlTkApiParams::const_iterator pParam = params.begin(); pParam != params.end(); ++pParam)
+		{
+		const CCdlTkApiParam& param = *pParam;
+		if (param.Type() == KTypeInt)	// is it a cell index parameter
+			{
+			string paramName = param.Name();
+			if (line.iIsMirroredHorizontally)
+				MirrorParamName(paramName);
+			char cells = 0;		// bit field for cells that this parameter applies to
+			char maxVal = 0;
+			char nextCell = 1;	// bit flag for the next cell
+			for (int ii=0; ii<outputSize; ii++)
+				{
+				TValues& values = line[outputOrder[ii]];
+				if (values.iNeedsIndex && values.ParamName() == paramName)
+					{
+					if (maxVal == 0)
+						maxVal = values.size();
+					else if (maxVal != values.size())
+						throw CdlTkAssert(string("param range mismatch ") + line.Name() + " " + param.Name());
+					cells |= nextCell;
+					}
+				nextCell = nextCell << 1;
+				}
+			aImpl.iBytes.push_back(cells);
+			aImpl.iBytes.push_back(maxVal);
+			}
+		}
+
+	// encode data
+	for (int ii=0; ii<outputSize; ii++)
+		{
+		TValues& values = line[outputOrder[ii]];
+		for (TValues::iterator pVal = values.begin(); pVal != values.end(); ++pVal)
+			EncodeValue(aImpl.iBytes, *pVal);
+		}
+	}
+
+void CLayoutInstOpt::CountApiParams(CCdlTkImplementation& aApi, int& aParams, bool& aParent)
+	{
+	aParams = 0;
+	aParent = false;
+	const CCdlTkApiParams& params = aApi.Api().AsFunc().Params();
+	for (CCdlTkApiParams::const_iterator pParam = params.begin(); pParam != params.end(); ++pParam)
+		{
+		if (pParam->Type() == KTypeInt) // is it a cell index parameter
+			aParams++;
+		else
+			aParent = true;
+		}
+	}
+
+void CLayoutInstOpt::SetLineFunc(CLayoutInstOptImpl& aImpl)
+	{
+	int nParams;
+	bool hasParent;
+	CountApiParams(*aImpl.iImpl, nParams, hasParent);
+
+	SImplFunc::TFuncType type = SImplFunc::EWindowLine;
+	if (aImpl.iLine->iTable->iType == TLayoutTable::ETextTable)
+		{
+		type = SImplFunc::ETextLine;
+		string name = aImpl.iImpl->Name();
+		if (name.size() > KFuncMultiline.size() && name.substr(0,KFuncMultiline.size()) == KFuncMultiline)
+			type = SImplFunc::EMultilineTextLine;
+		}
+
+	SImplFunc& func = AddImplFunc(type, nParams, hasParent);
+	aImpl.iImpl->SetPointerReference(func.iPtrRef);
+	}
+
+CCdlTkImplementation& CLayoutInstOpt::FindImp(const string& aName)
+	{
+	CCdlTkImplementation* impl = iInstance->Impl().Find(aName);
+	if (!impl)
+		throw NotFoundErr(aName + " in interface " + iInterface.FileName());
+	return *impl;
+	}
+
+bool CLayoutInstOpt::HasApi(const string& aName)
+	{
+	return iInterface.ApiList().Find(aName) != 0;
+	}
+
+SImplFunc& CLayoutInstOpt::AddImplFunc(SImplFunc::TFuncType aType, int aParams, bool aParent)
+	{
+	for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc)
+		{
+		SImplFunc& func = **pFunc;
+		if (func.iType == aType && func.iParams == aParams && func.iParent == aParent)
+			return func;
+		}
+
+	int count = gTheFuncs.size();
+	for (int ii=0; ii<count; ii++)
+		{
+		SImplFunc* func = &gTheFuncs[ii];
+		if (func->iType == aType && func->iParams == aParams && func->iParent == aParent)
+			{
+			iFuncs.push_back(func);
+			return *func;
+			}
+		}
+
+	throw NotFoundErr("implementation function");
+	return gTheFuncs[0];
+	}
+
+// The following strings and the SetExtraCpp() function build the gross structure of
+// the C++ customisation instance.
+// So far, the implementations are actually just 16-bit values, typically indexes into
+// the data lookup table. These need to be turned into an array by adding declarations
+// and brackets to the first and last implementations. Extra support functions are also
+// added.
+extern string KExtraCpp = "\
+#include \"aknlayout2decode.h\"\n\
+namespace $INTERFACE_NS { extern const TUint8 KByteCodedData[]; }\n";
+
+extern string KInitialCpp ="\
+extern const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize];\n\
+const SImplData KImplData = { KDataLookup, $INTERFACE_NS::KByteCodedData };\n\
+\n\
+$FUNCTIONS\
+\n\
+const TUint16 KDataLookup[$INTERFACE_NS::E_TApiId_TableSize] =\n\
+\t{\n";
+
+void CLayoutInstOpt::SetExtraCpp()
+	{
+	// The "extra cpp" field is written to the top of the cpp file.
+	iInstance->SetExtraCpp(CdlTkUtil::Replace("$INTERFACE_NS", iInterface.NamespaceName(), KExtraCpp));
+
+	// add headers & fwd declarations
+	string init = CdlTkUtil::Replace("$INTERFACE_NS", iInterface.NamespaceName(), KInitialCpp);
+
+	// add decode functions
+	string functions;
+	for (CImplFuncs::iterator pFunc = iFuncs.begin(); pFunc != iFuncs.end(); ++pFunc)
+		{
+		CdlTkUtil::AppendString(functions, (*pFunc)->iDefn);
+		CdlTkUtil::AppendString(functions, "\n");
+		}
+	init = CdlTkUtil::Replace("$FUNCTIONS", functions, init);
+	CCdlTkImplementation& first = **(iInstance->Impl().begin());
+	first.SetDefinition(init + first.Definition());
+
+	// add end of data table
+	CCdlTkImplementation& last = **(iInstance->Impl().end() - 1);
+	last.SetDefinition(last.Definition() + "\n};");
+	}
+
+void CLayoutInstOpt::AddTableToInstance(TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub, int aTableNum)
+	{
+	string tableName = LayoutToCdl::TableApiName(aTable, aSub, aTableNum);
+	if (HasApi(tableName))
+		{
+		AddTableLimitsImpl(tableName + KFuncLimitsSuffix, aSub);
+		AddTableImpl(tableName, aTable, aSub);
+		}
+	}
+
+void CLayoutInstOpt::AddTableLimitsImpl(const string& aApiName, TLayoutTable::TLayoutSubTable& aSubTable)
+	{
+	// code up table limits as a pair of byte values, the first byte is the first table
+	// index, the second is the last table index.
+	CCdlTkImplementation& impl = FindImp(aApiName);
+	int first = (*aSubTable.begin()) & 0xff;
+	int last = (*aSubTable.rbegin()) & 0xff;
+	impl.SetDefinition(CdlTkUtil::ShortToHexString((first<<8)|last) + ",");
+	impl.SetPointerReference(AddImplFunc(SImplFunc::ETableLimits, 0, false).iPtrRef);
+	}
+
+void CLayoutInstOpt::AddTableImpl(const string& aApiName, TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSub)
+	{
+	CCdlTkImplementation& impl = FindImp(aApiName);
+
+	int nParams;
+	bool hasParent;
+	CountApiParams(impl, nParams, hasParent);
+	nParams--;	// don't count the aLineIndex param
+	SImplFunc::TFuncType type = SImplFunc::EWindowTable;
+	if (aTable.iType == TLayoutTable::ETextTable)
+		type = SImplFunc::ETextTable;
+
+	SImplFunc& func = AddImplFunc(type, nParams, hasParent);
+
+	impl.SetDefinition(string("(TUint16)") + iInterface.NamespaceName() + "::EApiId_" + LayoutToCdl::LineApiName(*aTable[0]) + ",");
+	impl.SetPointerReference(func.iPtrRef);
+	}
+
+struct SIdToInt
+	{
+	int iInt;
+	char* iStr;
+	};
+
+#include <avkon.hrh>
+const int KScalableFontIdOffset(0x1000);
+extern SIdToInt gIdToIntTable[] =
+	{
+		{ ELayoutAlignLeft, "ELayoutAlignLeft" },
+		{ ELayoutAlignRight, "ELayoutAlignRight" },
+		{ ELayoutAlignCenter, "ELayoutAlignCenter" },
+		{ ELayoutAlignBidi, "ELayoutAlignBidi" },
+		{ ELatinBold19, "ELatinBold19" },
+		{ ELatinBold17, "ELatinBold17" },
+		{ ELatinBold13, "ELatinBold13" },
+		{ ELatinBold12, "ELatinBold12" },
+		{ ELatinPlain12, "ELatinPlain12" },
+		{ ELatinClock14, "ELatinClock14" },
+		{ EApacPlain12, "EApacPlain12" },	
+		{ EApacPlain16, "EApacPlain16" },
+		{ ENumberPlain5, "ENumberPlain5" },
+		{ ELatinBold16, "ELatinBold16" },
+
+		{ ELatinBold19+KScalableFontIdOffset, "ELatinBold19_Scaled" },
+		{ ELatinBold17+KScalableFontIdOffset, "ELatinBold17_Scaled" },
+		{ ELatinBold13+KScalableFontIdOffset, "ELatinBold13_Scaled" },
+		{ ELatinBold12+KScalableFontIdOffset, "ELatinBold12_Scaled" },
+		{ ELatinPlain12+KScalableFontIdOffset, "ELatinPlain12_Scaled" },
+		{ ELatinClock14+KScalableFontIdOffset, "ELatinClock14_Scaled" },
+		{ EApacPlain12+KScalableFontIdOffset, "EApacPlain12_Scaled" },	
+		{ EApacPlain16+KScalableFontIdOffset, "EApacPlain16_Scaled" },
+		{ ENumberPlain5+KScalableFontIdOffset, "ENumberPlain5_Scaled" },
+		{ ELatinBold16+KScalableFontIdOffset, "ELatinBold16_Scaled" },
+
+		{ 100, "qfn_latin_plain_17" },		// fonts that appear in app laf
+		{ ECalcBold21, "ECalcBold21" },
+		{ ECalcOperBold21, "ECalcOperBold21" },
+		{ ECalcOperBold13, "ECalcOperBold13" },
+		{ 100, "gfn_latin_bold_13" },
+		{ 100, "gfn_latin_plain_12" },
+		{ 100, "qfn_clock_plain_5" },
+
+		{ 100, "qfn_latin_plain_17_Scaled" },
+		{ ECalcBold21+KScalableFontIdOffset, "ECalcBold21_Scaled" },
+		{ ECalcOperBold21+KScalableFontIdOffset, "ECalcOperBold21_Scaled" },
+		{ ECalcOperBold13+KScalableFontIdOffset, "ECalcOperBold13_Scaled" },
+		{ 100, "gfn_latin_bold_13_Scaled" },
+		{ 100, "gfn_latin_plain_12_Scaled" },
+		{ 100, "qfn_clock_plain_5_Scaled" }
+
+	};
+extern const int gIdToIntTableCount = sizeof(gIdToIntTable)/sizeof(SIdToInt);
+
+extern void TranslateValue(string& aValue)
+	{
+	int count = gIdToIntTableCount;
+	for (int ii=0; ii<count; ii++)
+		{
+		SIdToInt& trans = gIdToIntTable[ii];
+		if (aValue == trans.iStr)
+			{
+			aValue = CdlTkUtil::IntToString(trans.iInt);
+			return;
+			}
+		}
+	}
+
+void CLayoutInstOpt::EncodeValue(vector<char>& aBytes, string aValue)
+	{
+	int pos;
+	TranslateValue(aValue);
+
+	if (aValue == "")
+		{
+		aBytes.push_back(KByteEmpty);
+		}
+	else if ((pos = aValue.find('p')) != string::npos)
+		{
+		if (pos != 0)
+			throw CdlTkAssert(string("arithmetic parser not good enough : ") + aValue);
+		int val = CdlTkUtil::ParseInt(aValue.substr(1));
+		if (-128 <= val && val <= 127)
+			{
+			aBytes.push_back(KByteP1);
+			aBytes.push_back(val);
+			}
+		else
+			{
+			aBytes.push_back(KByteP2);
+			aBytes.push_back((val & 0xff00) >> 8);
+			aBytes.push_back(val);
+			}
+		}
+	else
+		{
+		int val = CdlTkUtil::ParseInt(aValue);
+		if (0 <= val && val <= KMaxSingleByteValue)
+			{
+			aBytes.push_back(val);
+			}
+		else
+			{
+			aBytes.push_back(KByteWord);
+			aBytes.push_back((val & 0xff00) >> 8);
+			aBytes.push_back(val);
+			}
+		}
+	}
+
+void CLayoutInstOpt::MirrorParamName(string& aParamName)
+	{
+	if (aParamName == KParamNameL)
+		aParamName = KParamNameR;
+	else if (aParamName == KParamNameR)
+		aParamName = KParamNameL;
+	}
+
+
+
+//
+// CInstanceList
+//
+
+void CInstanceList::ProcessOptions(vector<string>& aArgs)
+	{
+	bool instanceFileOk = false;
+	iLoaded = false;
+	string instFile;
+	for(vector<string>::iterator pArg = aArgs.begin(); pArg != aArgs.end(); ++pArg)
+		{
+		string& arg = *pArg;
+		if (arg.size() >= 2 && arg.substr(0,2) == "-i")
+			{
+			instFile = arg.substr(2);
+			aArgs.erase(pArg);
+			instanceFileOk = true;
+			break;
+			}
+		}
+	if(!instanceFileOk)
+		throw LayoutCdlInstanceOptArgsErr();
+	ifstream in;
+	CdlTkUtil::OpenInput(in, instFile);
+	iLoaded = true;
+	string line;
+	while (!in.eof())
+		{
+		getline(in, line);
+		iInstances.insert(line);
+		}
+	in.close();
+	}
+
+bool CInstanceList::IsInstanceOk(const string& aInstance) const
+	{
+	return (!iLoaded || iInstances.find(aInstance) != iInstances.end());
+	}
+
+
+//
+// LayoutCdlInstanceOpt
+//
+
+int LayoutCdlInstanceOpt::Process(vector<string>& args)
+	{
+	CInstanceList instList;
+	instList.ProcessOptions(args);
+
+	int extraArgs = args.size() - 5;
+	if (extraArgs < 0 || extraArgs%2 == 1)
+		throw LayoutCdlInstanceOptArgsErr();
+
+	string cdlName = args[2];
+	CCdlTkCdlFileParser parser(cdlName);
+	auto_ptr<CCdlTkInterface> iface(parser.LoadAndParse(true));
+
+	LayoutCdlInstanceOpt process(*iface);
+
+	TLayout* base = NULL;
+	for (int arg = 3; arg < args.size(); arg += 2)
+		{
+		string layoutName = args[arg];
+		string instName = args[arg+1];
+		if (!instList.IsInstanceOk(instName))
+			continue;
+
+		auto_ptr<TLayParseLayout> layoutParse = TLayParseLayout::Parse(layoutName);
+		auto_ptr<TLayout> layout(layoutParse.get());
+		layoutParse.release();
+		if (base)
+			{
+			auto_ptr<TLayout> newLayout(new TLayout(*base));
+			newLayout->Merge(TLayout::KMergeModeVariant, *layout);
+			layout = newLayout;
+			}
+		else
+			{
+			base = layout.get();
+			}
+		process.AddLayout(layout, instName);
+		}
+
+	if (base)
+		{
+		process.Process();
+		process.WriteInstances();
+		}
+
+	return 0;
+	}
+
+void LayoutCdlInstanceOpt::ShowHelp(ostream& stream)
+	{
+	stream << "LayCdl2InstO [-i<instanceList>] <cdlName> (<layoutName> <instanceName>)+ " << endl;
+	stream << "  Creates optimised CDL instances containing the layout data." << endl;
+	stream << "  All layout instances must conform to the CDL interface." << endl;
+	stream << "  If more than one layout is supplies, subsequent ones are treated as" << endl;
+	stream << "  variants of the first." << endl;
+	stream << "  If -i<instanceList> is specified, then only instances whose name" << endl;
+	stream << "  appears in the file <instanceList> will be processed" << endl;
+	}
+
+LayoutCdlInstanceOpt::LayoutCdlInstanceOpt(CCdlTkInterface& aInterface)
+: iInterface(aInterface), iByteCodeIndex(0)
+	{
+	}
+
+LayoutCdlInstanceOpt::~LayoutCdlInstanceOpt()
+	{
+	for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout)
+		delete *pLayout;
+	}
+
+void LayoutCdlInstanceOpt::AddLayout(auto_ptr<TLayout>& aLayout, const string& aInstName)
+	{
+	auto_ptr<CLayoutInstOpt> p(new CLayoutInstOpt(*this, aLayout, aInstName));
+	iLayouts.push_back(p.get());
+	p.release();
+	}
+
+void LayoutCdlInstanceOpt::Process()
+	{
+	for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout)
+		(*pLayout)->Process();
+	ProcessCommonImpl();
+	}
+
+void LayoutCdlInstanceOpt::WriteInstances()
+	{
+	for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout)
+		(*pLayout)->WriteInstance();
+	}
+
+CCdlTkInterface& LayoutCdlInstanceOpt::Interface()
+	{
+	return iInterface;
+	}
+
+const string KCommonImplStart = "\
+#include \"aknlayout2decode.h\"\n\
+namespace $NAMESPACENAME { extern TUint8 const KByteCodedData[] = {\n";
+
+const string KCommonImplImpl = "\
+// $INDEX $COMMENT\n\
+$BYTES\n";
+
+void LayoutCdlInstanceOpt::ProcessCommonImpl()
+	{
+	string bytecode = CdlTkUtil::Replace("$NAMESPACENAME", iInterface.NamespaceName(), KCommonImplStart);
+
+	for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
+		{
+		vector<char>& bytes = (*pImpl)->iBytes;
+		if (bytes.size())
+			{
+			string byteString;
+			for (vector<char>::iterator pChar = bytes.begin(); pChar != bytes.end(); ++pChar)
+				{
+				CdlTkUtil::AppendString(byteString, CdlTkUtil::CharToHexString(*pChar));
+				CdlTkUtil::AppendString(byteString, ",");
+				}
+
+			CdlTkUtil::CReplaceSet implSet;
+			implSet.Add("$INDEX", CdlTkUtil::ShortToHexString((*pImpl)->iByteCodeIndex));
+			implSet.Add("$COMMENT", (*pImpl)->iComment);
+			implSet.Add("$BYTES", byteString);
+			CdlTkUtil::AppendString(bytecode, CdlTkUtil::MultiReplace(implSet, KCommonImplImpl));
+			}
+		}
+	CdlTkUtil::AppendString(bytecode, "};\n}");
+
+	CCdlTkInstance& firstInst = iLayouts[0]->Inst();
+	firstInst.SetExtraCpp(bytecode);
+	}
+
+LayoutCdlInstanceOpt::CLayouts& LayoutCdlInstanceOpt::Layouts()
+	{
+	return iLayouts;
+	}
+
+CLayoutInstOptImpl* LayoutCdlInstanceOpt::FindSimilarImpl(TLayoutLine& aLine)
+	{
+	for (CLayoutInstOptImpls::iterator pImpl = iImpls.begin(); pImpl != iImpls.end(); ++pImpl)
+		{
+		CLayoutInstOptImpl* impl = *pImpl;
+		if (LinesAreEqual(*impl->iLine, aLine))
+			{
+			return impl;
+			}
+		}
+	return NULL;
+	}
+
+int LayoutCdlInstanceOpt::FindSimilarBytes(CLayoutInstOptImpl* aImpl)
+	{
+	int index = -1;
+	vector<char>::iterator found = std::search(
+		iBytesAggregated.begin(), 
+		iBytesAggregated.end(), 
+		aImpl->iBytes.begin(), 
+		aImpl->iBytes.end());
+	if(found != iBytesAggregated.end())
+		{
+		index = std::distance(iBytesAggregated.begin(), found);
+		}
+	return index;
+	}
+
+void LayoutCdlInstanceOpt::AddImpl(CLayoutInstOptImpl* aImpl)
+	{
+	iImpls.push_back(aImpl);
+	int bytesAdded = aImpl->iBytes.size();
+	if (bytesAdded)
+		{
+		aImpl->iByteCodeIndex = iByteCodeIndex;
+		iByteCodeIndex += bytesAdded;
+		iBytesAggregated.insert(
+			iBytesAggregated.end(), 
+			aImpl->iBytes.begin(), 
+			aImpl->iBytes.end());
+		}
+	}
+
+bool LayoutCdlInstanceOpt::LinesAreEqual(TLayoutLine& aLine1, TLayoutLine& aLine2)
+	{
+	TLayoutLine::iterator pValues1 = aLine1.begin();
+	TLayoutLine::iterator pValues2 = aLine2.begin();
+	for (; pValues1 != aLine1.end() && pValues2 != aLine2.end(); ++pValues1, ++pValues2)
+		{
+		if (TLayoutTable::IsValueColumn(pValues1->first) && *pValues1 != *pValues2)
+			return false;
+		}
+	return true;
+	}