First public contribution.
1 // Copyright (c) 1995-2010 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
20 #include <ecom/ecom.h>
21 #include <graphics/bitmapuid.h>
23 #include "BackGroundCompression.h"
24 #include "BitwiseBitmap.inl"
25 #include "bitmapconst.h"
26 #include <graphics/openfontconstants.h>
27 #include <graphics/openfontrasterizer.h>
28 #include <graphics/gdi/glyphsample.h>
29 #include "glyphatlas.h"
30 #include "FbsMessage.H"
32 // Local utility functions
33 void ListImplementationsWithRetry(TUid& aInterfaceUid, RImplInfoPtrArray &aImplementationArray, TBool aRomOnly);
37 iDefaultLanguageForMetrics(ELangNone)
45 iConIx->Remove(iBitmapCon);
46 iConIx->Remove(iFontCon);
48 // there are no bitmap objects left, so the background compression queue must be empty
49 delete iBackgroundCompression;
54 __RHEAP_MARKEND(iHeap);
58 iLargeBitmapChunk.Close();
60 #ifdef SYMBIAN_DEBUG_FBS_LOCKHEAP
63 iFontNameAlias.ResetAndDestroy();
64 iBitmapObjectIndex.Reset();
66 REComSession::FinalClose();
69 CFbTop* CFbTop::NewL()
71 CFbTop* pT=new(ELeave) CFbTop;
72 CleanupStack::PushL(pT);
78 void CFbTop::ConstructL()
81 HAL::Get(HALData::EMemoryRAM, maxmem);
83 TInt maxHeapSize = Min(maxmem, KFbServSharedHeapMaxSize);
85 TChunkHeapCreateInfo sharedHeapCreateInfo(KFBSERVInitialHeapSize, maxHeapSize);
86 sharedHeapCreateInfo.SetCreateChunk(&KFBSERVSharedChunkName);
87 sharedHeapCreateInfo.SetSingleThread(EFalse);
88 sharedHeapCreateInfo.SetAlignment(0);
89 sharedHeapCreateInfo.SetGrowBy(KMinHeapGrowBy * KFBSERVHeapGrowByMultiplier);
91 if(KFbServWritableDataPagingMode == EFbsWdpPageBitmapDataAndSharedHeapChunksOnly)
93 //Request that the shared heap chunk is paged.
94 sharedHeapCreateInfo.SetPaging(TChunkHeapCreateInfo::EPaged);
98 //Use the creating process's paging attributes.
99 sharedHeapCreateInfo.SetPaging(TChunkHeapCreateInfo::EUnspecified);
102 iHeap = UserHeap::ChunkHeap(sharedHeapCreateInfo);
104 User::LeaveIfError(iChunk.OpenGlobal(KFBSERVSharedChunkName,ETrue));
105 TInt virtualSize = CChunkPile::VirtualSize();
107 TChunkCreateInfo createInfo;
108 createInfo.SetDisconnected(0, 0, virtualSize);
109 createInfo.SetGlobal(KFBSERVLargeChunkName);
110 createInfo.SetOwner(EOwnerProcess);
111 createInfo.SetClearByte(0xff); // clear to white on creation
113 if(KFbServWritableDataPagingMode == EFbsWdpPageBitmapDataChunkOnly ||
114 KFbServWritableDataPagingMode == EFbsWdpPageBitmapDataAndSharedHeapChunksOnly)
116 //Request that large bitmap chunk is paged.
117 createInfo.SetPaging(TChunkCreateInfo::EPaged);
121 //Use the creating process's paging attributes.
122 createInfo.SetPaging(TChunkCreateInfo::EUnspecified);
125 User::LeaveIfError(iLargeBitmapChunk.Create(createInfo));
127 iConIx=CObjectConIx::NewL();
128 iBitmapCon=iConIx->CreateL();
129 iFontCon=iConIx->CreateL();
130 User::LeaveIfError(iFilesys.Connect());
131 #ifdef SYMBIAN_DEBUG_FBS_LOCKHEAP
132 User::LeaveIfError(iDebugMutex.CreateGlobal(KFBSERVDebugMutexName));
134 iPile = CChunkPile::NewL(iLargeBitmapChunk);
135 iFontStore=CFontStore::NewL(iHeap);
136 //Constructing a cache to store the stream ids of the bitmaps from a mbm file.
137 //The cache here will store maximum 30 bitmaps before & maximum 30 after the
138 //current loaded bitmap.These values are chosen as to optimize the boottime performance
139 //as we notice during the boottime logs,sequential loading of bitmaps never exceed 30 bitmaps.
140 // The cache will also store maximum 5 mbm files. This number must be as low as possible
141 // while trying to minimize flushing of the cache due to mbm file switching.
142 iMBMCache=new (ELeave) CFbTopStreamIdCache(30,30,5);
144 LoadOpenFontLibraries();
145 iFontStore->LoadFontsAtStartupL();
146 LoadShaperFactories();
147 TRAP_IGNORE(iGlyphAtlas = CGlyphAtlas::NewL(KFbServGlyphAtlasCacheLimit);)
151 RDebug::Printf("FBSERV failed to initialize Glyph Atlas");
155 // start a new thread for background compression after all the other objects have been created
156 iBackgroundCompression = CFbsBackgroundCompression::NewL(*this);
163 Load all ECOM implemented rasterizer DLLs.
166 void CFbTop::LoadOpenFontLibraries()
168 RImplInfoPtrArray implementationArray;
169 TUid uid = {KUidOpenFontRasterizerPlunginInterface};
171 // get implementation list
172 ListImplementationsWithRetry(uid, implementationArray, EFalse);
174 const TInt availCount = implementationArray.Count();
175 for (TInt count=0; count < availCount; ++count)
177 const CImplementationInformation* info = implementationArray[count];
178 // Create & install a rasterizer
179 // ignore Leaves, as any necessary cleanup will have already been done through the cleanup stack
180 TRAP_IGNORE(SafeInstallOfRasterizerL(info->ImplementationUid()));
184 implementationArray.ResetAndDestroy();
189 Load all ECOM implemented shaper factory DLLs.
191 void CFbTop::LoadShaperFactories()
193 RImplInfoPtrArray implementationArray;
194 TUid uid = {KUidShaperFactoryPlunginInterface};
196 // get implementation list
197 ListImplementationsWithRetry(uid, implementationArray, ETrue);
199 const TInt availCount = implementationArray.Count();
200 for (TInt count=0;count<availCount;++count)
202 const CImplementationInformation* info = implementationArray[count];
203 // Create & install a shaper factory
204 // ignore Leaves, as any necessary cleanup will have already been done through the cleanup stack
205 TRAP_IGNORE(SafeInstallOfShaperFactoryL(info->ImplementationUid()));
209 implementationArray.ResetAndDestroy();
213 void ListImplementationsWithRetry(TUid& aInterfaceUid, RImplInfoPtrArray &aImplementationArray, TBool aRomOnly)
215 // Making sure that no race situation arises between FBserv and Ecom
216 // If ECom is not ready, give it another chance and try again. if it still doesn't work
217 // after the third try, then it just carries on quietly and fails...
218 for (TInt ecomnotready =0; ecomnotready <3; ecomnotready++)
220 TInt ecomError = KErrNone;
223 TEComResolverParams resParams;
224 TRAP(ecomError, REComSession::ListImplementationsL(aInterfaceUid, resParams, KRomOnlyResolverUid, aImplementationArray));
227 { // default resolver
228 TRAP(ecomError, REComSession::ListImplementationsL(aInterfaceUid, aImplementationArray));
242 // utility methods to transfer ownership, or destroy object on failure
243 void CFbTop::SafeInstallOfRasterizerL(TUid aInterfaceImplUid)
245 COpenFontRasterizer* rasterizer = COpenFontRasterizer::NewL(aInterfaceImplUid);
246 CleanupStack::PushL(rasterizer);
247 // Install it in the font store.
248 iFontStore->InstallRasterizerL(rasterizer);
249 CleanupStack::Pop(rasterizer);
253 void CFbTop::SafeInstallOfShaperFactoryL(TUid aInterfaceImplUid)
255 CShaperFactory* shaperFactory = CShaperFactory::NewL(aInterfaceImplUid);
256 CleanupStack::PushL(shaperFactory);
257 // Install it in the font store.
258 iFontStore->InstallShaperFactoryL(shaperFactory);
259 CleanupStack::Pop(shaperFactory);
263 Gets the nearest matching font for a given font specification. If the named font cannot be found
264 font aliases are checked.
266 @param aFontObjPtr On success this contains the font object that is the closest match.
267 @param aMessage The font request message.
268 @param aFontSpec The font spec to match.
269 @param aMaxHeight The maximum height of the font to match.
270 @return KErrNone if successful, KErrNotFound if the font is not found, or one of the other System Error codes.
272 TInt CFbTop::GetNearestFont(
273 CFontObject*& aFontObjPtr,
274 TFbsMessage aMessage,
275 const TFontSpec& aFontSpec,
279 User::Heap().Check();
284 TFontSpec fontSpec(aFontSpec);
286 // Check if the font typeface is empty and if so use the system default font if it is set
287 if (fontSpec.iTypeface.iName.Length() == 0 && iSystemDefaultFontTypefaceName.Length() != 0)
289 fontSpec.iTypeface.iName = iSystemDefaultFontTypefaceName;
292 if (GlyphSample::EScriptDefault == fontSpec.ScriptTypeForMetrics())
294 fontSpec.SetScriptTypeForMetrics(iDefaultLanguageForMetrics);
297 // Find the requested font
298 TBool familyNameExistsInTypefaceStore = iFontStore->HaveTypefaceFamilyName(fontSpec.iTypeface.iName);
300 // If the font is not found try finding an alias font
301 if (!familyNameExistsInTypefaceStore)
303 TInt aliasIndex = FindFontNameAlias(fontSpec.iTypeface.iName);
304 //KErrNotFound is the only error which can be returned
305 if (aliasIndex != KErrNotFound)
307 fontSpec.iTypeface.iName = *iFontNameAlias[aliasIndex + 1];
312 TInt ret = GetNearestNonAliasedFont(font, aMessage, fontSpec, aMaxHeight);
319 return GetFontObjectFromFont(aFontObjPtr, font);
323 Gets the nearest matching loaded font for a given font specification.
325 @param aFont On success this contains the font object that is the closest match.
326 @param aMessage The font request message.
327 @param aFontSpec The font spec to match.
328 @param aMaxHeight The maximum height of the font to match.
329 @return KErrNone if successful, KErrNotFound if the font is not found, or one of the other System Error codes.
331 TInt CFbTop::GetNearestNonAliasedFont(CFont*& aFont, TFbsMessage aMessage, const TFontSpec& aFontSpec, TInt aMaxHeight)
333 TInt ret = KErrNotSupported;
336 case EFbsMessGetNearestFontToDesignHeightInTwips:
338 ret = iFontStore->GetNearestFontToDesignHeightInTwips(aFont, aFontSpec);
341 case EFbsMessGetNearestFontToDesignHeightInPixels:
343 ret = iFontStore->GetNearestFontToDesignHeightInPixels(aFont, aFontSpec);
346 case EFbsMessGetNearestFontToMaxHeightInTwips:
348 ret = iFontStore->GetNearestFontToMaxHeightInTwips(aFont, aFontSpec, aMaxHeight);
351 case EFbsMessGetNearestFontToMaxHeightInPixels:
353 ret = iFontStore->GetNearestFontToMaxHeightInPixels(aFont, aFontSpec, aMaxHeight);
360 TInt CFbTop::GetFontObjectFromFont(CFontObject*& aFontObjPtr, CFont* aFont)
362 // First, check if a CFontObject exists for this CFont.
363 // If so, increment its reference count and return it.
364 for (TInt ii = iFontCon->Count() - 1; ii >= 0; --ii)
366 CFontObject* fontObjPtr = reinterpret_cast<CFontObject*>((*iFontCon)[ii]);
367 if (fontObjPtr->iAddressPointer == reinterpret_cast<CBitmapFont*>(aFont))
369 aFontObjPtr = fontObjPtr;
370 // The CFontObject instance keeps the reference count of the CBitmapFont,
371 // not the font store. There is only one CFontObject instance
372 // per CBitmapFont, so to keep the reference count at 1 in the fontstore
373 // call ReleaseFont().
374 iFontStore->ReleaseFont(aFont);
375 return fontObjPtr->Open();
379 // Existing FontObject not found, so create new one.
380 CFontObject* fontObjPtr = new CFontObject(iFontStore, iGlyphAtlas);
383 iFontStore->ReleaseFont(aFont);
387 fontObjPtr->iAddressPointer = reinterpret_cast<CBitmapFont*>(aFont);
388 fontObjPtr->iHeightInTwips = ((aFont->HeightInPixels() * iFontStore->iKPixelHeightInTwips) + 667) / 1000;
389 TRAPD(ret, iFontCon->AddL(fontObjPtr));
395 { // transfer ownership
396 aFontObjPtr = fontObjPtr;
402 /** Create a Bitmap Font, from a UID and Algorithmic drawing Style see CFontStore::GetFontById()
405 TInt CFbTop::GetFontById(CFontObject*& aFontObjPtr,TUid aUid,const TAlgStyle& aAlgStyle)
408 User::Heap().Check();
412 CBitmapFont* font=NULL;
413 TInt ret=iFontStore->GetFontById((CFont*&)font,aUid,(TAlgStyle&)aAlgStyle);
418 return GetFontObjectFromFont(aFontObjPtr, font);
422 /** Create a bitmap with the given size, display mode and UID.
424 @param aSize Size of the bitmap in pixels.
425 @param aDispMode Display mode of the bitmap.
426 @param aUid The UID to use for bitmap creation. This can be:
427 - KUidCFbsBitmapCreation for standard bitmaps.
428 - The application UID for hardware bitmaps.
429 - The data type UID for extended bitmaps.
430 @param aReplacement If ETrue the bitmap is being created as a replacement
431 for a bitmap being made dirty by a resize or compress operation.
432 @param aDataSize If different from zero, it indicates that the bitmap to create
433 is an extended bitmap and specifies the size in bytes of the bitmap.
434 If equal to zero, it indicates that the bitmap to create is a standard
435 bitmap or a hardware bitmap, depending on the value of aUid, and the size
436 in bytes is calculated from the size in pixels and the display mode.
439 CBitmapObject* CFbTop::CreateBitmapL(const TSize& aSize, TDisplayMode aDispMode, TUid aUid, TBool aReplacement, TInt aDataSize)
442 User::Heap().Check();
445 CBitwiseBitmap* bmp=(CBitwiseBitmap*)iHeap->AllocL(sizeof(CBitwiseBitmap) + sizeof(CBitwiseBitmap::TExtra));
446 new(bmp) CBitwiseBitmap(iHeap,iPile);
447 CleanupDeletePushL(bmp); // CBitwiseBitmap is not derived from CBase!
450 User::LeaveIfError(bmp->Construct(aSize, aDispMode, aUid));
452 User::LeaveIfError(bmp->ConstructExtended(aSize, aDispMode, aUid, aDataSize));
453 // bmp popped out of the clean-up stack by NewL
454 CBitmapObject* bmpObj = CBitmapObject::NewL(*this, bmp, aReplacement);
457 bmp->Extra()->iSerialNumber = iNextAvailableSerialNumber++;
463 CBitmapObject* CFbTop::LoadBitmapL(const TDesC& aFilename, TInt32 aId, TUint aFileOffset, RFile* aFile, TInt aSessionHandle)
465 CBitwiseBitmap* bmp=DoLoadBitmapLC(aFilename, aId, aFileOffset, aFile, aSessionHandle);
466 // bmp popped out of the clean-up stack by NewL
467 CBitmapObject* bmpObj = CBitmapObject::NewL(*this, bmp, EFalse);
474 CBitwiseBitmap* CFbTop::DoLoadBitmapLC(const TDesC& aFilename, TInt32 aId, TUint aFileOffset, RFile* aFile, TInt aSessionHandle)
477 User::Heap().Check();
480 CBitwiseBitmap* bmp=(CBitwiseBitmap*)iHeap->AllocL(sizeof(CBitwiseBitmap) + sizeof(CBitwiseBitmap::TExtra));
481 new(bmp) CBitwiseBitmap(iHeap,iPile);
482 bmp->Extra()->iSerialNumber = iNextAvailableSerialNumber++;
483 CleanupDeletePushL(bmp); // CBitwiseBitmap is not derived from CBase!
487 // In this case file should be in z: drive
488 // so load the bitmap from the mbm cache
489 TStreamId streamid(0);
490 streamid=iMBMCache->GetStreamIdL(iFilesys,aFilename,aId,aFileOffset,aSessionHandle);
491 bmp->ConstructL(iMBMCache->MruFileStore(),streamid);
495 //only use the cache when it is Rom File which is read only because when using
496 //the cache the file store is always opened as read access until it is replaced by
497 //another different file, Trying to write it(RAM file) will cause access violation
498 //and therefore we have to split the implementation into two parts one for ROM
500 if (aFilename.Left(2).CompareF(KZDrive))
502 // File is not in ROFS
503 bmp->ConstructL(*aFile,aId,aFileOffset);
508 TStreamId streamid(0);
509 streamid=iMBMCache->GetStreamIdL(*aFile,aFilename,aId,aFileOffset,aSessionHandle);
511 bmp->ConstructL(iMBMCache->MruFileStore(),streamid);
518 /* Similar to LoadBitmap.
519 This function only performs a load the first time it is called for a
520 particular bitmap. Subsequent calls increment a reference counting object.
522 Upon return, aBmpObjPtr points to an object containing a pointer to the loaded bitmap.
524 CSharedBitmapObject* CFbTop::ShareBitmapL(TDes& aFilename, TInt32 aId, TUint aFileOffset, RFile* aFile, TInt aSessionHandle)
527 if (aFilename.Left(2).CompareF(KZDrive))// instead of Compare, CompareF is used to perform folding prior to Compare which is safe with Unicode.
529 // file is not in z: drive so it should not be null.
530 __ASSERT_DEBUG(aFile != NULL, User::Panic(KFBSERVPanicCategory, KErrBadHandle));
531 // File is not in ROM so ModTime is needed to identify it
532 User::LeaveIfError(aFile->Modified(modtime));
535 // Creation of the key is performed here so that it can potentially be
536 // reused in both object lookup and object creation
537 HBufC* key = CSharedBitmapObject::KeyLC(aFilename, aId, modtime);
539 // Calculation of the hash value is performed here so that it can
540 // potentially be reused in both object lookup and object insert.
541 const TUint hash = iSharedBitmapObjectHashMap.Hash(*key);
543 CSharedBitmapObject* bmpObj = iSharedBitmapObjectHashMap.Lookup(*key, hash);
547 // Bitmap already in memory
548 CleanupStack::PopAndDestroy(key); // key will not be needed
549 User::LeaveIfError(bmpObj->Open()); // increase reference count
553 // Bitmap not in memory
554 CBitwiseBitmap* bmp = DoLoadBitmapLC(aFilename, aId, aFileOffset, aFile, aSessionHandle);
555 // bmp and key popped out of the clean-up stack by NewL
556 bmpObj = CSharedBitmapObject::NewL(*this, bmp, key, hash);
562 TInt CFbTop::GetCleanBitmap(CBitmapObject*& aBmpObjPtr)
564 while (aBmpObjPtr->CleanBitmap() != NULL)
566 aBmpObjPtr = aBmpObjPtr->CleanBitmap();
568 if (aBmpObjPtr->IsInCompressionQueue())
573 CBitmapObject* CFbTop::FindBitmap(TInt aHandle)
575 TInt index = iBitmapObjectIndex.FindInOrder(aHandle, CBitmapObject::Compare);
576 if (index != KErrNotFound)
577 return iBitmapObjectIndex[index];
581 TBool CFbTop::ValidFontHandle(TInt aHandle)
583 TInt limit=iFontCon->Count();
584 for(TInt count=0;count<limit;count++)
585 if(aHandle==(TInt)((*iFontCon)[count]))
590 CFontStore* CFbTop::FontStore() const
595 RHeap* CFbTop::Heap() const
600 CChunkPile* CFbTop::Pile() const
605 TInt CFbTop::HeapBase() const
607 return(TInt(iChunk.Base()));
610 void CFbTop::SetFontNameAliasL(const RMessage2& aMessage)
612 const TInt aliasNameLength = aMessage.Int1();
613 if (aliasNameLength <= 0)
614 return; // No alias name to set
616 if(aliasNameLength * sizeof(TText) * 2 >= KMaxTInt)
618 aMessage.Panic(KFBSERVPanicCategory,KErrArgument);
622 HBufC* aliasName = HBufC::NewMaxLC(aliasNameLength);
623 TPtr aliasNamePtr(aliasName->Des());
624 aMessage.ReadL(0,aliasNamePtr);
626 const TInt aliasIndex = FindFontNameAlias(*aliasName);
628 const TInt fontNameLength = aMessage.Int3();
630 if (fontNameLength > 0)
631 { // Set or change an alias
632 HBufC* fontName = HBufC::NewMaxLC(fontNameLength);
633 TPtr fontNamePtr(fontName->Des());
634 aMessage.ReadL(2,fontNamePtr);
636 if (aliasIndex != KErrNotFound)
637 { // Change an existing alias
638 delete iFontNameAlias[aliasIndex + 1];
639 iFontNameAlias[aliasIndex + 1] = fontName;
641 CleanupStack::Pop(); // fontName
642 CleanupStack::PopAndDestroy(); // aliasName
646 User::LeaveIfError(iFontNameAlias.Append(aliasName));
647 TInt ret = iFontNameAlias.Append(fontName);
650 iFontNameAlias.Remove(iFontNameAlias.Count() - 1);
654 CleanupStack::Pop(); // fontName
655 CleanupStack::Pop(); // aliasName
659 { // No fontName so delete the alias
660 CleanupStack::PopAndDestroy(); // aliasName
661 if (aliasIndex != KErrNotFound)
663 delete iFontNameAlias[aliasIndex];
664 iFontNameAlias.Remove(aliasIndex);
665 delete iFontNameAlias[aliasIndex];
666 iFontNameAlias.Remove(aliasIndex);
671 TInt CFbTop::FindFontNameAlias(const TDesC& aAlias)
673 const TInt fontNameAliasCount = iFontNameAlias.Count();
675 for (TInt index = 0; index < fontNameAliasCount; index += 2)
677 if ((*iFontNameAlias[index]).CompareF(aAlias)==0)
686 void CFbTop::SetDefaultLanguageForMetrics(const RMessage2& aMessage)
688 iDefaultLanguageForMetrics = static_cast<TLanguage>(aMessage.Int0());
691 void CFbTop::CloseFileStores(TInt aSessionHandle)
693 iMBMCache->CloseFileStores(aSessionHandle);
696 void CFbTop::SetSystemDefaultTypefaceName(const TDesC& aFontTypefaceName)
698 iSystemDefaultFontTypefaceName = aFontTypefaceName;
701 TInt CFbTop::GetAllBitmapHandles(const RMessage2& aMessage) const
703 TPckgBuf<TInt> handleBuffer; // Use this buffer to store the bitmap handles to write to the message buffer
704 const TInt numBitmaps = iBitmapObjectIndex.Count();
706 for (TInt count=0; count<numBitmaps; ++count)
708 handleBuffer() = iBitmapObjectIndex[count]->Handle();
709 ret = aMessage.Write(0, handleBuffer, KNumBytesPerBitmapHandle * count);
716 void CFbTop::AddClientHelper(TFbClientHelper& aHelper)
718 iClientHelpers.AddLast(aHelper);
721 void CFbTop::NotifyDirtyBitmap(CBitmapObject& aBmpObj, CFbClient* aClient)
723 TDblQueIter<TFbClientHelper> iterator(iClientHelpers);
724 TFbClientHelper* helper;
725 while ((helper = iterator++) != NULL)
727 if (aClient != &helper->iClient)
728 helper->iClient.NotifyDirtyBitmap(aBmpObj);
732 TInt CFbTop::BitmapConUniqueID() const
734 return iBitmapCon->UniqueID();
737 TInt CFbTop::FontConUniqueID() const
739 return iFontCon->UniqueID();
742 CGlyphAtlas* CFbTop::GlyphAtlas() const