--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fontservices/fontstore/src/FNTBODY.CPP Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,565 @@
+/*
+* Copyright (c) 1996-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 <s32file.h>
+#include <fntstore.h>
+#include "FNTBODY.H"
+#include <graphics/openfontconstants.h>
+
+CFontStoreFile::CFontStoreFile()
+ : iCollectionUid(KNullUid),
+ iUsageCount(1),
+ iFileStore(NULL),
+ iFileAddress(0),
+ iDataStreamId(KNullStreamId)
+ {
+ }
+
+void CFontStoreFile::ConstructL(const TParse& aParse,RFs& aFs)
+ {
+ TInt drive;
+ User::LeaveIfError(RFs::CharToDrive(aParse.Drive()[0], drive));
+ TDriveInfo driveinfo;
+ User::LeaveIfError(aFs.Drive(driveinfo, drive));
+ RFile file;
+
+ // store the filename
+ iFullName = aParse.FullName().AllocL();
+ User::LeaveIfError(file.Open(aFs, *iFullName, EFileStream | EFileRead | EFileShareReadersOnly));
+
+ // check to see if the fonts are stored on ROM. Note that NAND != rom so font files in NAND devices
+ // must be handled as if they were in RAM. A NULL pointer returned by IsFileInRom means its RAM
+
+ if (aFs.IsFileInRom(*iFullName)!=NULL)
+ {
+ // fonts are stored on a XIP (execute in place) device
+ TInt ret = file.Seek(ESeekAddress, iFileAddress);
+
+ if (ret != KErrNone)
+ {
+ file.Close();
+ User::Leave(ret);
+ }
+ }
+
+ // convert RFile into a CDirectFileStore
+ CDirectFileStore* fileStore = CDirectFileStore::FromLC(file);
+
+ if (fileStore->Type()[1] != TUid::Uid(KFontStoreFileUidVal))
+ User::Leave(KErrNotSupported);
+ TStreamId headerid = fileStore->Root();
+ RStoreReadStream stream;
+ stream.OpenLC(*fileStore, headerid);
+ TInt fnttranversion = stream.ReadInt32L();
+ // This works for version 42 (with new metrics) and for earlier versions
+ // which will synthesize the required metrics. It may have to be changed
+ // if the version number is incremented again.
+ if (fnttranversion < (KFnttranVersion - 1) && fnttranversion != KFnttran7650Version)
+ User::Leave(KErrNotSupported);
+ iFontVersion = fnttranversion;
+ stream >> iCollectionUid;
+ iKPixelAspectRatio = stream.ReadInt32L();
+ stream >> iDataStreamId;
+ CleanupStack::PopAndDestroy(&stream); // close root stream
+ // ensure font data stream can be opened
+ stream.OpenLC(*fileStore, iDataStreamId);
+ CleanupStack::PopAndDestroy(&stream); // close font stream
+ // transfer ownership of fileStore
+ CleanupStack::Pop(fileStore);
+ iFileStore = fileStore;
+ }
+
+CFontStoreFile* CFontStoreFile::NewL(const TParse& aParse, RFs& aFs)
+ {
+ CFontStoreFile* fontstorefile = new(ELeave) CFontStoreFile;
+ CleanupStack::PushL(fontstorefile);
+ fontstorefile->ConstructL(aParse, aFs);
+ CleanupStack::Pop();
+ return fontstorefile;
+ }
+
+CFontStoreFile::~CFontStoreFile()
+ {
+ delete iFullName;
+ iFullName = NULL;
+ delete iFileStore;
+ iFileStore = NULL;
+ }
+
+TBitmapCodeSection::TBitmapCodeSection()
+ : TCodeSection(),
+ iCharacterData(),
+ iBitmapData()
+ {
+ }
+
+//This method is called from CFontBitmap::InternalizeL.
+//We have to read stream IDs from the stream, not offsets.
+//Obviously the method is called once per life time of
+//CFontBitmap instance.
+void TBitmapCodeSection::InternalizeL(RReadStream &aStream)
+ {
+ iStart = aStream.ReadUint16L();
+ iEnd = aStream.ReadUint16L();
+ aStream >> iCharacterData.iOffsetsId;
+ aStream >> iBitmapData.iBitmapId;
+ }
+
+//This method is called from CFontBitmap::RestoreComponentsL -
+//if the CFontBitmap instance is in RAM and CFontBitmap::iComponentsRestored is EFalse.
+//We use here stream IDs, not offsets.
+//If the memory allocation for the offsets doesn't fail - aAllocMemCounter is incremented
+//After calling of TBitmapCodeSection::InternalizeOffsetsL character metrics streamID is no more valid -
+//we have valid character metrics offset into RAM memory.
+void TBitmapCodeSection::InternalizeOffsetsL(const CStreamStore& aStreamStore, RHeap* aHeap, TInt& aAllocMemCounter)
+ {
+ RStoreReadStream stream;
+ stream.OpenLC(aStreamStore, iCharacterData.iOffsetsId);
+
+ TInt size = stream.ReadInt32L();
+ TBitmapFontCharacterOffset* characterOffsetsList = (TBitmapFontCharacterOffset*)aHeap->AllocL(sizeof(TBitmapFontCharacterOffset) * size);
+ aAllocMemCounter++;
+ iCharacterData.iCharacterOffsetsListOffset = TInt(characterOffsetsList) - TInt(this);
+ TBitmapFontCharacterOffset* pEnd = characterOffsetsList + size;
+ for (TBitmapFontCharacterOffset* p = characterOffsetsList; p < pEnd; p++)
+ {
+ p->InternalizeL(stream);
+ }
+
+ CleanupStack::PopAndDestroy();
+ }
+
+//This method is called from CFontBitmap::RestoreComponentsL -
+//if the CFontBitmap instance is in RAM and CFontBitmap::iComponentsRestored is EFalse.
+//We use here stream IDs, not offsets.
+//If the memory allocation for the bitmap doesn't fail - aAllocMemCounter is incremented
+//After calling of TBitmapCodeSection::InternalizeBitmapL bitmap streamID is no more valid -
+//we have valid bitmap offset into RAM memory.
+void TBitmapCodeSection::InternalizeBitmapL(const CStreamStore& aStreamStore, RHeap* aHeap, TInt& aAllocMemCounter)
+ {
+ RStoreReadStream stream;
+ stream.OpenLC(aStreamStore, iBitmapData.iBitmapId);
+
+ TInt size = stream.ReadInt32L();
+ TUint8* bitmap = (TUint8*)aHeap->AllocL(size);
+ aAllocMemCounter++;
+ iBitmapData.iBitmapOffset = TInt(bitmap) - TInt(this);
+ stream.ReadL(bitmap, size);
+
+ CleanupStack::PopAndDestroy();
+ }
+
+//This method is called from CFontBitmap::InternalizeL if the
+//CFontBitmap instance is in ROM.
+//We use here stream IDs to calculate offsets.
+//After calling of TBitmapCodeSection::FixUpComponents streamIDs are no more valid -
+//we have valid offsets into ROM memory.
+//Obviously the method is called once per life time of
+//CFontBitmap instance.
+void TBitmapCodeSection::FixUpComponents(TInt aFileAddress)
+ {
+ TBitmapFontCharacterOffset* characterOffsetsList = (TBitmapFontCharacterOffset*) (aFileAddress + sizeof(TInt) + iCharacterData.iOffsetsId);
+ iCharacterData.iCharacterOffsetsListOffset = TInt(characterOffsetsList);
+ TUint8* bitmap = (TUint8*) (aFileAddress + sizeof(TInt) + iBitmapData.iBitmapId);
+ iBitmapData.iBitmapOffset = TInt(bitmap);
+ }
+
+//This method is caled from CFontBitmap::DeleteComponents(),
+//only if the CFontBitmap instance is in RAM.
+void TBitmapCodeSection::DeleteOffsets(RHeap* aHeap)
+ {
+ TBitmapFontCharacterOffset* charactersOffsetsList = CharacterOffsetsList(ETrue);
+ if(TUint32(this) != TUint32(charactersOffsetsList))
+ {
+ aHeap->Free(charactersOffsetsList);
+ }
+ }
+
+//This method is caled from CFontBitmap::DeleteComponents(),
+//only if the CFontBitmap instance is in RAM.
+void TBitmapCodeSection::DeleteBitmap(RHeap* aHeap)
+ {
+ TUint8* bitmap = Bitmap(ETrue);
+ if(TUint32(this) != TUint32(bitmap))
+ {
+ aHeap->Free(bitmap);
+ }
+ }
+
+TBitmapFontCharacterOffset* TBitmapCodeSection::CharacterOffsetsList(TBool aIsInRAM) const
+ {
+ return reinterpret_cast <TBitmapFontCharacterOffset*>
+ (iCharacterData.iCharacterOffsetsListOffset + (aIsInRAM ? TInt(this) : 0));
+ }
+
+TUint8* TBitmapCodeSection::Bitmap(TBool aIsInRAM) const
+ {
+ return reinterpret_cast <TUint8*>
+ (iBitmapData.iBitmapOffset + (aIsInRAM ? TInt(this) : 0));
+ }
+
+TCharacterMetricsTable::TCharacterMetricsTable(RHeap* aHeap)
+ : iHeap(aHeap),
+ iMetricsStartId(KNullStreamId),
+ iCharacterMetricsStartPtr(0),
+ iNumberOfMetrics(0)
+ {}
+
+void TCharacterMetricsTable::InternalizeL(RReadStream& aStream)
+ {
+ iMetricsStartId = aStream.ReadInt32L();
+ iNumberOfMetrics = aStream.ReadInt32L();
+ }
+
+void TCharacterMetricsTable::InternalizeMetricsL(RReadStream& aStream)
+ {
+ aStream.ReadInt32L(); // size
+ TBitmapFontCharacterMetrics* charactermetricslist = static_cast<TBitmapFontCharacterMetrics*>(iHeap->AllocL(sizeof(TBitmapFontCharacterMetrics) * iNumberOfMetrics));
+
+ iCharacterMetricsStartPtr = TInt(charactermetricslist); // Ptr to location on the heap ('cos the file is not in ROM)
+ TBitmapFontCharacterMetrics* pEnd = charactermetricslist + iNumberOfMetrics;
+ for (TBitmapFontCharacterMetrics* p = charactermetricslist; p < pEnd; p++)
+ {
+ p->InternalizeL(aStream);
+ }
+ }
+
+void TCharacterMetricsTable::RestoreL(const CStreamStore& aStreamStore)
+ {
+ if (iCharacterMetricsStartPtr == 0)
+ { // We haven't already read it in from RAM file
+ RStoreReadStream stream;
+ stream.OpenLC(aStreamStore, iMetricsStartId);
+ InternalizeMetricsL(stream);
+ CleanupStack::PopAndDestroy();
+ }
+ }
+
+void TCharacterMetricsTable::FixUp(TInt aFileAddress)
+ {
+ TBitmapFontCharacterMetrics* charactermetricslist = reinterpret_cast<TBitmapFontCharacterMetrics*>(aFileAddress + sizeof(TInt) + iMetricsStartId.Value());
+ iCharacterMetricsStartPtr = TInt(charactermetricslist); // Ptr to location in a ROM file
+ iMetricsStartId = KNullStreamId;
+ }
+
+void TCharacterMetricsTable::Delete()
+ { // This routine is only called if the font file is in RAM, not ROM, and therefore the metrics have been stashed on the heap
+ if (iCharacterMetricsStartPtr)
+ {
+ iHeap->Free(reinterpret_cast<TAny*>(iCharacterMetricsStartPtr));
+ iCharacterMetricsStartPtr = 0;
+ }
+ }
+
+const TBitmapFontCharacterMetrics* TCharacterMetricsTable::Metric(TInt aIndex) const
+ {
+ __ASSERT_DEBUG((aIndex >= 0) && (aIndex <= iNumberOfMetrics), Panic(EFntMetricsIndexOutOfBounds));
+ // Sometimes the start ptr is to a metrics heap item and sometimes it points into a ROM file
+ return reinterpret_cast<const TBitmapFontCharacterMetrics*>(iCharacterMetricsStartPtr + (aIndex * sizeof(TBitmapFontCharacterMetrics)));
+ }
+
+TInt TCharacterMetricsTable::NumberOfMetrics() const
+ {
+ return iNumberOfMetrics;
+ }
+
+CFontBitmap::CFontBitmap(RHeap* aHeap, CFontStoreFile* aFontStoreFile)
+ : iHeap(aHeap),
+ iFontStoreFileOffset(0),
+ iUid(KNullUid),
+ iPosture(0),
+ iStrokeWeight(0),
+ iIsProportional(0),
+ iIsInRAM(!aFontStoreFile->iFileAddress),
+ iUsageCount(1),
+ iCellHeightInPixels(0),
+ iAscentInPixels(0),
+ iMaxCharWidthInPixels(0),
+ iMaxNormalCharWidthInPixels(0),
+ iBitmapEncoding(0),
+ iNumCodeSections(0),
+ iCodeSectionListOffset(0),
+ iCharacterMetricsTable(aHeap),
+ iComponentsRestored(EFalse),
+ iAllocMemCounter_Offsets(0),
+ iAllocMemCounter_Bitmaps(0),
+ iFontCapitalAscent(0),
+ iFontMaxAscent(0),
+ iFontStandardDescent(0),
+ iFontMaxDescent(0),
+ iFontLineGap(0)
+ {
+ iFontStoreFileOffset = TInt(aFontStoreFile) - TInt(this);
+ }
+
+void CFontBitmap::InternalizeL(RReadStream &aStream, TInt aFontVersion)
+ {
+ aStream >> iUid;
+ iPosture = aStream.ReadInt8L();
+ iStrokeWeight = aStream.ReadInt8L();
+ iIsProportional = aStream.ReadInt8L();
+ iCellHeightInPixels = aStream.ReadInt8L();
+ iAscentInPixels = aStream.ReadInt8L();
+ iMaxCharWidthInPixels = aStream.ReadInt8L();
+ iMaxNormalCharWidthInPixels = aStream.ReadInt8L();
+ if ( aFontVersion >= KFnttranVersion )
+ { // read the new metrics in
+ iFontCapitalAscent = aStream.ReadInt8L();
+ iFontMaxAscent = aStream.ReadInt8L();
+ iFontStandardDescent = aStream.ReadInt8L();
+ iFontMaxDescent = aStream.ReadInt8L();
+ iFontLineGap = aStream.ReadInt8L();
+ }
+ else // synthesize the extra metrics (data compatibility with third party bitmap fonts for old phones)
+ {
+ iFontMaxAscent = iFontCapitalAscent = iAscentInPixels;
+ iFontMaxDescent = iFontStandardDescent = iCellHeightInPixels - iAscentInPixels;
+ iFontLineGap = ( ( iCellHeightInPixels * 12 ) + 5) / 10; // 1.2 times design height
+ }
+ iBitmapEncoding = aStream.ReadInt32L();
+ iCharacterMetricsTable.InternalizeL(aStream);
+ const TBool fixup = FontStoreFile()->iFileAddress;
+ if (fixup)
+ {
+ iCharacterMetricsTable.FixUp(FontStoreFile()->iFileAddress);
+ }
+ iNumCodeSections = aStream.ReadInt32L();
+ TBitmapCodeSection* codesectionlist = (TBitmapCodeSection*)User::LeaveIfNull(iHeap->AllocL(iNumCodeSections * sizeof(TBitmapCodeSection)));
+ iCodeSectionListOffset = TInt(codesectionlist) - TInt(this);
+ for (TInt i = 0; i < iNumCodeSections; i++)
+ {
+ new(codesectionlist + i) TBitmapCodeSection;
+ codesectionlist[i].InternalizeL(aStream);
+ if (fixup)
+ codesectionlist[i].FixUpComponents(FontStoreFile()->iFileAddress);
+ }
+ }
+
+void CFontBitmap::UseL()
+ {
+ // Note object is created with a Usage Count of 1.
+ // So incrementing to 2 normally indicates the first external reference.
+ iUsageCount++;
+ if (iUsageCount == 2)
+ {
+ RestoreComponentsL();
+ }
+ }
+
+void CFontBitmap::Release()
+ {
+ iUsageCount--;
+ if (!iUsageCount)
+ { // object and all its users have closed
+ delete this;
+ }
+ }
+
+/*
+Get the metrics for a given character.
+Return aBytes as null if the character aCode doesn't exist in the font.
+*/
+TBitmapFontCharacterMetrics CFontBitmap::CharacterMetrics(TInt aCode, const TUint8*& aBytes) const
+ {
+ const TBitmapCodeSection* matchSection = NULL;
+ const TBitmapCodeSection* const lastSection = CodeSectionList() + iNumCodeSections - 1;
+
+ TBitmapFontCharacterOffset offset;
+ aBytes = NULL;
+
+ TBitmapFontCharacterMetrics metrics;
+ const TBitmapCodeSection* startSearchBand = CodeSectionList();
+ TInt numCodeSectionsRemaining = iNumCodeSections;
+ while (numCodeSectionsRemaining >= 1)
+ {
+ TInt halfNumCodeSectionsRemaining = numCodeSectionsRemaining/2;
+ const TBitmapCodeSection* centralSearchBand = startSearchBand+halfNumCodeSectionsRemaining;
+ if ((aCode >= centralSearchBand->iStart) && (aCode <= centralSearchBand->iEnd))
+ {
+ matchSection = centralSearchBand;
+ break;
+ }
+ else if ((aCode < centralSearchBand->iStart) || (centralSearchBand == lastSection))
+ numCodeSectionsRemaining = halfNumCodeSectionsRemaining;
+ else
+ {
+ startSearchBand = centralSearchBand + 1;
+ numCodeSectionsRemaining -= halfNumCodeSectionsRemaining + 1;
+ }
+ }
+
+ if (matchSection)
+ {
+ offset =* ((matchSection->CharacterOffsetsList(iIsInRAM)) + (aCode-matchSection->iStart));
+
+ // Fill characters within code section.
+ // Recursive call ensures that a valid metric is always returned.
+ if (offset.iBitmapOffset == KFillCharacterOffset)
+ {
+ return CharacterMetrics(KReplacementCharacter, aBytes);
+ }
+
+ aBytes = matchSection->Bitmap(iIsInRAM) + offset.iBitmapOffset;
+
+ // retrieve metric index from encoded 1 or 2 bytes
+ TInt index = 0;
+ TUint8 byte1 = (TUint8)*aBytes;
+ const TInt switchMask = 0x1;
+ const TBool oneByteIndex =! (byte1 & switchMask);
+ byte1 = TUint8(byte1 >> 1);
+ if (oneByteIndex)
+ {
+ index = byte1;
+ aBytes += 1;
+ }
+ else
+ {
+ const TUint8 byte2 = (TUint8)(*(aBytes + 1));
+ index = byte1 + (byte2 * 128);
+ aBytes += 2;
+ }
+ // Copy metric from table
+ metrics =* iCharacterMetricsTable.Metric(index);
+ }
+ return metrics;
+ }
+
+void CFontBitmap::operator delete(TAny *aThis)
+ {
+ if (((CFontBitmap *)aThis)->iHeap)
+ {
+ ((CFontBitmap *)aThis)->iHeap->Free(aThis);
+ }
+ }
+
+void CFontBitmap::SetPosture(TFontPosture aPosture)
+ {
+ iPosture = (TInt8)aPosture;
+ }
+
+TFontPosture CFontBitmap::Posture() const
+ {
+ return (TFontPosture)iPosture; // iPosture is always smaller than TFontPosture
+ }
+
+void CFontBitmap::SetStrokeWeight(TFontStrokeWeight aStrokeWeight)
+ {
+ iStrokeWeight = (TInt8)aStrokeWeight;
+ }
+
+TFontStrokeWeight CFontBitmap::StrokeWeight() const
+ {
+ return (TFontStrokeWeight)iStrokeWeight;
+ }
+
+void CFontBitmap::SetIsProportional(TBool aIsProportional)
+ {
+ iIsProportional = (TInt8)aIsProportional;
+ }
+
+TBool CFontBitmap::IsProportional() const
+ {
+ return iIsProportional;
+ }
+
+CFontStoreFile* CFontBitmap::FontStoreFile() const
+ {
+ TInt fsf = TInt(this) + iFontStoreFileOffset;
+ return (CFontStoreFile*)fsf;
+ }
+
+CFontBitmap::~CFontBitmap()
+ {
+ DeleteComponents();
+ TBitmapCodeSection* codeSectionList = CodeSectionList();
+ if(TUint32(this) != TUint32(codeSectionList))
+ {
+ iHeap->Free(codeSectionList);
+ }
+ iCodeSectionListOffset = 0;
+ }
+
+//We have to count how many offsets and bitmaps are allocated successfully because if
+//some of codesection's Internalize..L fails we have to deallocate the right amount of
+//data.
+void CFontBitmap::RestoreComponentsL()
+ {
+ if (iIsInRAM)
+ {
+ if(!iComponentsRestored)
+ {
+ iAllocMemCounter_Offsets = 0;
+ iAllocMemCounter_Bitmaps = 0;
+ CStreamStore& store =* FontStoreFile()->iFileStore;
+ for (TInt i = 0; i < iNumCodeSections; i++)
+ {
+ CodeSectionList()[i].InternalizeOffsetsL(store, iHeap, iAllocMemCounter_Offsets);
+ CodeSectionList()[i].InternalizeBitmapL(store, iHeap, iAllocMemCounter_Bitmaps);
+ }
+ iCharacterMetricsTable.RestoreL(store);
+ }
+ iComponentsRestored = ETrue;
+ }
+ }
+
+void CFontBitmap::DeleteComponents()
+ {
+ if (iIsInRAM)
+ {
+ TInt i;
+ for (i = 0; i < iAllocMemCounter_Offsets; i++)
+ {
+ CodeSectionList()[i].DeleteOffsets(iHeap);
+ }
+ for (i = 0; i < iAllocMemCounter_Bitmaps; i++)
+ {
+ CodeSectionList()[i].DeleteBitmap(iHeap);
+ }
+ iCharacterMetricsTable.Delete();
+ }
+ iAllocMemCounter_Offsets = 0;
+ iAllocMemCounter_Bitmaps = 0;
+ iComponentsRestored = EFalse;
+ }
+
+TBitmapCodeSection* CFontBitmap::CodeSectionList() const
+ {
+ TInt bcs = TInt(this) + iCodeSectionListOffset;
+ return (TBitmapCodeSection*)bcs;
+ }
+
+TTypefaceFontBitmap::TTypefaceFontBitmap()
+ : iTypeface(NULL),
+ iFontBitmap(NULL),
+ iHeightFactor(1),
+ iWidthFactor(1)
+ {
+ }
+
+TTypefaceFontBitmap::TTypefaceFontBitmap(TTypeface* aTypeface,CFontBitmap* aFontBitmap)
+ : iTypeface(aTypeface),
+ iFontBitmap(aFontBitmap),
+ iHeightFactor(1),
+ iWidthFactor(1)
+ {
+ }
+
+TInt TTypefaceFontBitmap::HeightInPixels() const
+ {
+ return iFontBitmap->iCellHeightInPixels * iHeightFactor;
+ }