diff -r 57c618273d5c -r bbf46f59e123 fbs/fontandbitmapserver/sfbs/FBSCLI.CPP --- a/fbs/fontandbitmapserver/sfbs/FBSCLI.CPP Thu Aug 19 11:11:18 2010 +0300 +++ b/fbs/fontandbitmapserver/sfbs/FBSCLI.CPP Tue Aug 31 16:31:06 2010 +0300 @@ -16,11 +16,13 @@ #include #include #include -#include "fbsmessage.h" +#include +#include "FbsMessage.H" #include "SERVER.H" #include "BackGroundCompression.h" #include #include +#include "glyphatlas.h" #include "OstTraceDefinitions.h" #include "fbstrace.h" #ifdef OST_TRACE_COMPILER_IN_USE @@ -28,6 +30,12 @@ #endif +/** +Bitwise mask that sets the MSB to indicate to a font rasterizer +that a code is a glyphcode and not a character code +*/ +const TUint32 KTreatAsGlyphCodeFlag = 1UL << 31; + /** Helper function for converting a pointer to an offset from the passed heap base. Use OffsetToPointer() to convert the returned offset back to a useable pointer. @@ -39,11 +47,12 @@ */ LOCAL_C TInt PointerToOffset(const TAny* aAny, TInt aHeapBase) { + TInt offset = 0; if (aAny && aHeapBase) { - return reinterpret_cast(aAny) - aHeapBase; + offset = reinterpret_cast(aAny) - aHeapBase; } - return 0; + return offset; } /** Helper function for converting an offset (that was calculated using @@ -64,9 +73,6 @@ CFbClient::CFbClient(RHeap* aHeap): CSession2(), - iConnectionHandle(0), - iIx(NULL), - iResourceCount(0), iHeap(aHeap) #ifdef _DEBUG ,iOwnHeapFailNumber(-1), @@ -77,14 +83,24 @@ CFbClient* CFbClient::NewL(RHeap* aHeap) { - CFbClient* c = new(ELeave) CFbClient(aHeap); - c->iOpenFontGlyphData = TOpenFontGlyphData::New(aHeap,4 * 1024); - if (!c->iOpenFontGlyphData) + CFbClient* self = new (ELeave) CFbClient(aHeap); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); // self; + return self; + } + +/** +Two-phase constructor. +@leave KErrNoMemory if TOpenFontGlyphData construction failed. +*/ +void CFbClient::ConstructL() + { + iOpenFontGlyphData = TOpenFontGlyphData::New(iHeap, 4 * 1024); + if (!iOpenFontGlyphData) { - delete c; User::Leave(KErrNoMemory); } - return c; } CFbClient::~CFbClient() @@ -101,30 +117,40 @@ } if (font_store) + { font_store->DeleteSessionCache(iSessionHandle); + font_store->CleanupCacheOnFbsSessionTermination(iSessionHandle); + + // If the font store doesn't exist, neither will the shared heap owned by FBSERV. + iHeap->Free(iOpenFontGlyphData); + } - // If the font store doesn't exist, neither will the shared heap owned by FBSERV. - if (font_store) - iHeap->Free(iOpenFontGlyphData); - - // delete fonts hold by the client + // delete fonts held by the client delete iIx; - // delete font files hold by the client - if (iFontFileIndex) - { - TInt count = iFontFileIndex->Count(); - for (TInt index = 0;index < count; index++) - { - if (font_store) - font_store->RemoveFile(iFontFileIndex->At(0).iUid); - iFontFileIndex->Delete(0); - } - delete iFontFileIndex; - } + // delete font files held by the client + if (iFontFileIndex) + { + TInt count = iFontFileIndex->Count(); + for (TInt index = 0;index < count; index++) + { + if (font_store) + { + font_store->RemoveFile(iFontFileIndex->At(0).iUid); + } + iFontFileIndex->Delete(0); + } + delete iFontFileIndex; + } - // Close the buffer used to hold the text thats needs shaping. + // Close the buffer used to hold the text that needs shaping. iTextToShape.Close(); + + for (TInt i = iGlyphImagesInTransit.Count() - 1; i >= 0; --i) + { + iGlyphImagesInTransit[i].Close(); + } + iGlyphImagesInTransit.Close(); } void CFbClient::Init(TUint aConnectionHandle) @@ -147,9 +173,13 @@ { CFontBitmapServer* server = FontBitmapServer(); if (server) + { return server->TopLevelStore(); + } else + { return NULL; + } } void CFbClient::CopyFontInfo(CFontObject* aFontObjPtr,TInt aHandle,TFontInfo& aFontInfo) @@ -162,6 +192,7 @@ void CFbClient::ServiceL(const RMessage2& aMessage) { + #ifdef _DEBUG TBool resetOwnHeap=EFalse; TBool resetSharedHeap=EFalse; @@ -193,6 +224,14 @@ __RHEAP_MARK(iHeap); } #endif + //Call close on RSgImage handles being used to share glyph data with clients. + //The glyph images are held open to prevent the GlyphAtlas from closing them + //before a client can use them. + for (TInt i = iGlyphImagesInTransit.Count() - 1; i >= 0; --i) + { + iGlyphImagesInTransit[i].Close(); + iGlyphImagesInTransit.Remove(i); + } switch(aMessage.Function()) { @@ -251,6 +290,7 @@ case EFbsMessFetchLinkedTypeface: case EFbsMessRegisterLinkedTypeface: case EFbsMessUpdateLinkedTypeface: + #ifdef _DEBUG FontBitmapServer()->ProcMessage(aMessage,iSessionHandle,iRet); #else @@ -275,9 +315,15 @@ case EFbsMessSetTwipsHeight: case EFbsMessGetTwipsHeight: case EFbsSetSystemDefaultTypefaceName: + case EFbsMessGetFontTable: + case EFbsMessReleaseFontTable: + case EFbsMessGetGlyphOutline: + case EFbsMessReleaseGlyphOutline: #if (_DEBUG) case EFbsMessSetDuplicateFail: #endif + case EFbsMessGetGlyphs: + case EFbsMessGetGlyphMetrics: ProcFontMessage(aMessage); break; // bitmap messages @@ -306,6 +352,31 @@ aMessage.Complete(KErrNone); #endif break; +// Glyph Atlas messages (debug-only) + case EFbsMessAtlasFontCount: + case EFbsMessAtlasGlyphCount: +#ifdef _DEBUG + ProcAtlasMessage(aMessage); +#else + aMessage.Complete(KErrNotSupported); +#endif + break; + case EFbsMessOogmNotification: + + aMessage.Complete( HandleMesgOogmStatus( aMessage ) ); + break; + case EFbsMessGetGlyphCacheMetrics: + + HandleMesgGlyphCacheMetrics( aMessage ); + break; + +//No-op message + case EFbsMessNoOp: +#ifdef _DEBUG + iRet = KErrNone; +#endif + aMessage.Complete(KErrNone); + break; default: aMessage.Panic(KFBSERVPanicCategory,KErrArgument); break; @@ -373,7 +444,9 @@ { #if _DEBUG if (iFontDuplicateToFail) + { return KErrNoMemory; //return with this error since this error is possible + } #endif CFontObject* fontptr = (CFontObject*) aMessage.Int0(); if(!TopLevelStore()->ValidFontHandle((TInt)fontptr)) @@ -381,7 +454,7 @@ return KErrUnknown; } - TPckgBuf foninfo; + TPckgBuf fontinfo; TInt localhandle = 0; TInt ret = fontptr->Open(); if (ret != KErrNone) @@ -394,9 +467,9 @@ fontptr->Close(); return ret; } - CopyFontInfo(fontptr,localhandle,foninfo()); + CopyFontInfo(fontptr,localhandle,fontinfo()); fontptr->iHeightInTwips = ((fontptr->iAddressPointer->HeightInPixels() * fontptr->iFontStore->iKPixelHeightInTwips) + 667) / 1000; - ret = aMessage.Write(1, foninfo); + ret = aMessage.Write(1, fontinfo); if(ret != KErrNone) { iIx->Remove(localhandle); @@ -424,14 +497,14 @@ TInt pckgMaxHeight; TPckgBuf info; - const TFbsMessage fbsMessage = static_cast(aMessage.Function()); + const TFbsMessage fbsMessage = static_cast(aMessage.Function()); TInt ret = aMessage.Read(0, pckgFontSpec); TFontSpec& fontSpec = pckgFontSpec(); if (ret == KErrNone ) { TInt length = fontSpec.iTypeface.iName.Length(); - if(length < 0 || length > TOpenFontFaceAttribBase::ENameLength) + if((length < 0) || (length > TOpenFontFaceAttribBase::ENameLength)) { aPanicRequired = ETrue; return KErrArgument; @@ -647,6 +720,183 @@ return EFalse; } +/** Handler for EFbsMessGetGlyphs message. +Reads a batch of up to KMaxGlyphBatchSize glyph codes, and on success returns +the corresponding TGlyphImageInfo objects. + @param aMessage input parameters + @param aPanicRequired flag that is set if a client panic is required + @return KErrNone if successful, otherwise any system-wide error code. + */ +TInt CFbClient::HandleMesgGetGlyphs(const RMessage2& aMessage, TBool& aPanicRequired) + { + CFbTop* fbtop = TopLevelStore(); + // Previously requested glyphs were closed in ServiceL() + CGlyphAtlas* glyphAtlas = fbtop->GlyphAtlas(); + if (!glyphAtlas) + { + return KErrNotSupported; + } + CFontObject* fontptr = static_cast(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID())); + if(!fontptr) + { + aPanicRequired = ETrue; + return KErrBadHandle; + } + + TUint glyphCodes[KMaxGlyphBatchSize]; + TGlyphImageInfo glyphImageInfo[KMaxGlyphBatchSize]; + TPckg glyphBatchPckg(glyphCodes); + + TInt err = aMessage.Read(1, glyphBatchPckg); + if (err != KErrNone) + { + aPanicRequired = ETrue; + return err; + } + TInt glyphCodesCount = glyphBatchPckg.Length() / sizeof(TUint); + if (glyphCodesCount > KMaxGlyphBatchSize) + { + aPanicRequired = ETrue; + return KErrOverflow; + } + + TInt glyphsProcessed = 0; + CBitmapFont* font = fontptr->iAddressPointer; + for (; (glyphsProcessed < glyphCodesCount); ++glyphsProcessed) + { + TUint32 glyphCode = glyphCodes[glyphsProcessed]; + err = glyphAtlas->GetGlyph(*font, glyphCode, glyphImageInfo[glyphsProcessed]); + // Search for glyph in glyph atlas + if (KErrNone != err) + { + const TUint8* bitmapData = NULL; + TOpenFontCharMetrics metrics; + // search for glyph in font glyph cache and session cache. + if (!font->GetCharacterData(iSessionHandle, glyphCode | KTreatAsGlyphCodeFlag, metrics, bitmapData)) + { + // Rasterize the glyph + if(!font->Rasterize(iSessionHandle, glyphCode | KTreatAsGlyphCodeFlag, iOpenFontGlyphData)) + { + err = KErrNoMemory; + break; + } + metrics = *(iOpenFontGlyphData->Metrics()); + bitmapData = iOpenFontGlyphData->BitmapPointer(); + } + CGlyphAtlas::TAddGlyphArgs args(bitmapData, glyphCode, metrics); + err = glyphAtlas->AddGlyph(*font, args, glyphImageInfo[glyphsProcessed]); + } + if ((err == KErrNone) && (glyphImageInfo[glyphsProcessed].iImageId != KSgNullDrawableId)) + { + // To prevent other threads closing the glyph image in the glyph atlas + // before client has had chance to open the drawable id, open a local + // handle to the glyph image for the session, which will be closed either + // next time a request is made or when EFbsMessCloseGlyphs is handled. + RSgImage glyphImage; + err = glyphImage.Open(glyphImageInfo[glyphsProcessed].iImageId); + if (err == KErrNone) + { + err = iGlyphImagesInTransit.Append(glyphImage); + } + } + // If an error occurred during this iteration, abort now before the glyphsProcessed + // counter is incremented, which would give one too many processed glyphs. + if (KErrNone != err) + { + break; + } + } + + // Even if there was an error, if at least one glyph was processed successfully + // send that back to the client, and reset the error code. + if (glyphsProcessed > 0) + { + TPckg glyphImageInfoPckg(glyphImageInfo); + glyphImageInfoPckg.SetLength(glyphsProcessed * sizeof(TGlyphImageInfo)); + err = aMessage.Write(2, glyphImageInfoPckg); + if (err != KErrNone) + { + aPanicRequired = ETrue; + return err; + } + } + else + { + // No glyphs being returned, so an error code must be returned. + __ASSERT_DEBUG(err != KErrNone, User::Panic(KFBSERVPanicCategory, err)); + } + return err; + } + +/** +Handler for EFbsMessGetGlyphMetrics message. +Reads an array of glyph codes, and returns the offset from the heap base for the +corresponding metrics object. +@pre The glyph codes have already been searched client-side in the font glyph + cache and the session cache. +@param aMessage input parameters +@param aPanicRequired flag that is set if a client panic is required +@return KErrNone if successful, otherwise any system-wide error code. + */ +TInt CFbClient::HandleMesgGetGlyphMetrics(const RMessage2& aMessage, TBool& aPanicRequired) + { + CFbTop* fbtop = TopLevelStore(); + CFontObject* fontptr = static_cast(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID())); + if(!fontptr) + { + aPanicRequired = ETrue; + return KErrBadHandle; + } + + TInt err = KErrNone; + TUint glyphCodes[KMaxMetricsBatchSize]; + TPckg glyphBatchPckg(glyphCodes); + err = aMessage.Read(1, glyphBatchPckg); + if (err != KErrNone) + { + aPanicRequired = ETrue; + return err; + } + + TInt numGlyphCodes = glyphBatchPckg.Length() / sizeof(TUint); + if (numGlyphCodes > KMaxMetricsBatchSize) + { + aPanicRequired = ETrue; + return KErrOverflow; + } + + CBitmapFont* font = fontptr->iAddressPointer; + const TInt heapbase = fbtop->HeapBase(); + + TInt glyphProcessed; + TInt glyphMetricsOffsets[KMaxMetricsBatchSize]; + for (glyphProcessed = 0; (glyphProcessed < numGlyphCodes) && (err == KErrNone); ++glyphProcessed) + { + if (font->Rasterize(iSessionHandle, glyphCodes[glyphProcessed] | KTreatAsGlyphCodeFlag, iOpenFontGlyphData)) + { + // Convert all pointers to be passed back to the client to offsets from + // the heap base so that they can be recreated client side relative to the + // client's heap base + glyphMetricsOffsets[glyphProcessed] = PointerToOffset(iOpenFontGlyphData->Metrics(), heapbase); + } + else + { + err = KErrNoMemory; + } + } + + if (err == KErrNone) + { + TPckg glyphMetricsOffsetsPckg(glyphMetricsOffsets); + glyphMetricsOffsetsPckg.SetLength(glyphProcessed * sizeof(TInt)); + err = aMessage.Write(2, glyphMetricsOffsetsPckg); + if (err != KErrNone) + { + aPanicRequired = ETrue; + } + } + return err; + } /** Handler for EFbsMessFaceAttrib message @param aMessage Input and output parameters @@ -664,21 +914,21 @@ } CBitmapFont* bitmapFont = fontptr->iAddressPointer; + TInt ret = EFalse; TPckgBuf package; if ( (bitmapFont != NULL) && (bitmapFont->GetFaceAttrib(package())) ) { - TInt ret = aMessage.Write(1,package); + ret = aMessage.Write(1,package); if (ret == KErrNone) { - return ETrue; + ret = ETrue; } else { aPanicRequired = ETrue; - return ret; } } - return EFalse; + return ret; } @@ -720,7 +970,6 @@ { TInt error = KErrNone; TShapeHeader* shape = 0; - TPckgBuf sp; if (aMessage.GetDesLength(2) != sizeof(TShapeMessageParameters)) { aPanicRequired = ETrue; @@ -734,7 +983,6 @@ aPanicRequired = ETrue; return KErrArgument; } - CBitmapFont* bitmapFont = fontptr->iAddressPointer; TInt inputTextLength = aMessage.GetDesLength(1); if (inputTextLength < 0) @@ -747,7 +995,9 @@ { iTextToShape.Zero(); if (iTextToShape.MaxLength() < inputTextLength) + { error = iTextToShape.ReAlloc(inputTextLength); + } } if (error == KErrNone) { @@ -757,12 +1007,14 @@ aPanicRequired = ETrue; return error; } + TPckgBuf sp; error = aMessage.Read(2, sp); if (error != KErrNone) { aPanicRequired = ETrue; return error; } + CBitmapFont* bitmapFont = fontptr->iAddressPointer; TRAP(error, shape = bitmapFont->ShapeTextL(iTextToShape, iSessionHandle, sp()) ); if (error == KErrNone) { @@ -801,10 +1053,225 @@ return KErrNone; } +TInt CFbClient::HandleMesgReleaseGlyphOutline(const RMessage2& aMessage, TBool& aPanicRequired) + { + TInt ret = KErrNone; + CFbTop* fbtop = TopLevelStore(); + TPckgBuf params; + ret = aMessage.Read(0, params); + if (KErrNone != ret) + { + aPanicRequired = ETrue; + return ret; + } + CFontObject* fontptr = static_cast(iIx->At(params().iHandle, fbtop->FontConUniqueID())); + if(!fontptr) + { + aPanicRequired = ETrue; + return KErrArgument; + } + CBitmapFont* bitmapFont = fontptr->iAddressPointer; + + TInt count = params().iCount; + TUint *glyphCodes = (TUint *)User::Alloc(count * sizeof(TUint)); + if (NULL == glyphCodes) + { + return KErrNoMemory; + } + // copy the glyph codes out of the IPC buffer... + TPtr8 ptr((TUint8 *)glyphCodes, count * sizeof(TUint), count * sizeof(TUint)); + ret = aMessage.Read(1, ptr); + + if (KErrNone == ret) + { + bitmapFont->ReleaseGlyphOutlines(count, glyphCodes, + params().iHinted, iSessionHandle); + } + else + { + aPanicRequired = ETrue; + } + + User::Free(glyphCodes); + return ret; + } + +TInt CFbClient::HandleMesgGetGlyphOutline(const RMessage2& aMessage, TBool& aPanicRequired) + { + TInt ret = KErrNone; + CFbTop* fbtop = TopLevelStore(); + TPckgBuf params; + ret = aMessage.Read(0, params); + if (KErrNone != ret) + { + aPanicRequired = ETrue; + return ret; + } + CFontObject* fontptr = static_cast(iIx->At(params().iHandle, fbtop->FontConUniqueID())); + if(!fontptr) + { + aPanicRequired = ETrue; + return KErrArgument; + } + CBitmapFont* bitmapFont = fontptr->iAddressPointer; + + TInt count = params().iCount; + TUint* glyphCodes = (TUint *)User::Alloc(count * sizeof(TUint)); + if (NULL == glyphCodes) + { + return KErrNoMemory; + } + // copy the glyph codes out of the IPC buffer... + TPtr8 ptr((TUint8 *)glyphCodes, count * sizeof(TUint), count * sizeof(TUint)); + ret = aMessage.Read(1, ptr); + if (KErrNone != ret) + { + User::Free(glyphCodes); + aPanicRequired = ETrue; + return ret; + } + + TOffsetLen* offsetLens = + (TOffsetLen *)User::Alloc(count * sizeof(TOffsetLen)); + if (NULL == offsetLens) + { + User::Free(glyphCodes); + return KErrNoMemory; + } + + TInt len = 0; + TAny* outline = NULL; + for (TInt i = 0; i < count; ++i) + { + bitmapFont->GetGlyphOutline(glyphCodes[i], + params().iHinted, outline, len, iSessionHandle); + + offsetLens[i].iLen = len; + offsetLens[i].iOffset = PointerToOffset((outline), fbtop->HeapBase()); + } + TPtr8 pkg2((TUint8 *)offsetLens, count * sizeof(TOffsetLen), + count * sizeof(TOffsetLen)); + ret = aMessage.Write(2, pkg2); + if (KErrNone != ret) + { + aPanicRequired = ETrue; + } + + User::Free(glyphCodes); + User::Free(offsetLens); + return ret; + } + +TInt CFbClient::HandleMesgReleaseFontTable(const RMessage2& aMessage, TBool& aPanicRequired) + { + CFbTop* fbtop = TopLevelStore(); + CFontObject* fontptr = static_cast(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID())); + if(!fontptr) + { + aPanicRequired = ETrue; + return KErrArgument; + } + CBitmapFont* bitmapFont = fontptr->iAddressPointer; + + TUint32 tag = aMessage.Int1(); + + bitmapFont->ReleaseFontTable(tag, iSessionHandle); + + return KErrNone; + } + +TInt CFbClient::HandleMesgGetFontTable(const RMessage2& aMessage, TBool& aPanicRequired) + { + TInt ret = KErrNone; + CFbTop* fbtop = TopLevelStore(); + CFontObject* fontptr = static_cast(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID())); + if(!fontptr) + { + aPanicRequired = ETrue; + return KErrArgument; + } + CBitmapFont* bitmapFont = fontptr->iAddressPointer; + + TInt len = 0; + TAny* tablePtr = NULL; + ret = bitmapFont->GetFontTable((TUint32)aMessage.Int1(), tablePtr, len, iSessionHandle); + + if (KErrNone == ret) + { + TPckgBuf params; + params().iLen = len; + params().iOffset = PointerToOffset(tablePtr, fbtop->HeapBase()); + ret = aMessage.Write(2, params); + aPanicRequired = (KErrNone != ret); + } + + return ret; + } + + +/** + Called in response to the GoomMonitor framework's call into FbsOogmPlugin. + We wish to either free some GPU memory, or reinstate its normal usage. + +@param aMessage The IPC message. +@return KErrNone If the value contained in the TFbsOogmMessage enumeration member is meaningful and the glyph atlas is present. + KErrNotSupported if there is no glyph atlas. + KErrUnknown if the value contained in the TFbsOogmMessage enumeration member is not meaningful. + */ +TInt CFbClient::HandleMesgOogmStatus( const RMessage2& aMessage ) + { + TInt ret = KErrNone; + CGlyphAtlas* glyphAtlas = TopLevelStore()->GlyphAtlas(); + + if ( NULL == glyphAtlas ) + { + return KErrNotSupported; + } + + + TPckgBuf oogmMessage; + aMessage.Read( 0, oogmMessage ); + + switch( oogmMessage().iOogmNotification ) + { + case TFbsOogmMessage::EFbsOogmNoAction: + break; + + case TFbsOogmMessage::EFbsOogmLowNotification: + { + glyphAtlas->ReleaseGpuMemory( oogmMessage().iBytesToFree, oogmMessage().iFlags ); + } + break; + + case TFbsOogmMessage::EFbsOogmOkayNotification: + { + glyphAtlas->InstateGpuMemory( oogmMessage().iFlags ); + } + break; + + default: + ret = KErrUnknown; + break; + } + + return ret; + } + + +void CFbClient::HandleMesgGlyphCacheMetrics( const RMessage2& aMessage ) + { + CGlyphAtlas* glyphAtlas = TopLevelStore()->GlyphAtlas(); + TPckgBuf metrics; + + glyphAtlas->GetGlyphCacheMetrics( metrics() ); + + aMessage.Complete( aMessage.Write(0, metrics) ); + } + void CFbClient::ProcFontMessage(const RMessage2& aMessage) { - TInt ret = KErrUnknown; + TInt ret = KErrNone; TBool panicRequired = EFalse; switch(aMessage.Function()) @@ -911,9 +1378,40 @@ break; } + case EFbsMessGetFontTable: + { + ret = HandleMesgGetFontTable(aMessage, panicRequired); + break; + } + case EFbsMessGetGlyphOutline: + { + ret = HandleMesgGetGlyphOutline(aMessage, panicRequired); + break; + } + case EFbsMessReleaseGlyphOutline: + { + ret = HandleMesgReleaseGlyphOutline(aMessage, panicRequired); + break; + } + case EFbsMessReleaseFontTable: + { + ret = HandleMesgReleaseFontTable(aMessage, panicRequired); + break; + } + case EFbsMessGetGlyphs: + { + ret = HandleMesgGetGlyphs(aMessage, panicRequired); + break; + } + case EFbsMessGetGlyphMetrics: + { + ret = HandleMesgGetGlyphMetrics(aMessage, panicRequired); + break; + } #ifdef _DEBUG case EFbsMessSetDuplicateFail: + { TInt argument =aMessage.Int0(); if (argument) { @@ -925,7 +1423,10 @@ } ret=KErrNone; break; + } #endif + default: + ret = KErrUnknown; } // either have a result or an error code to panic the client with @@ -949,7 +1450,7 @@ { CBitmapObject* bmpptr=NULL; TInt localhandle=0; - TInt ret=KErrUnknown; + TInt ret = KErrNone; switch(aMessage.Function()) { case EFbsMessBitmapCreate: @@ -1115,14 +1616,18 @@ } ret = fbtop->GetCleanBitmap(bmpptr); if (ret != KErrNone) + { break; + } TSize newsize(aMessage.Int1(),aMessage.Int2()); const TBool compressedInRam = bmpptr->Address()->IsCompressedInRAM(); //It must be set before the resizing is done. const TDisplayMode dispMode = bmpptr->Address()->DisplayMode(); CBitmapObject* newbmpptr = NULL; TRAP(ret, newbmpptr = fbtop->CreateBitmapL(newsize, dispMode, KUidCFbsBitmapCreation, ETrue)); if (ret != KErrNone) + { break; + } ret = newbmpptr->Address()->CopyData(*bmpptr->Address()); if (ret != KErrNone) { @@ -1157,7 +1662,9 @@ } bmpptr->SetCleanBitmap(newbmpptr); if (bmpptr->AccessCount() >= 2) + { fbtop->NotifyDirtyBitmap(*bmpptr, this); + } iIx->Remove(localhandle); TPckgBuf handlebuffer; handlebuffer().iHandle = newlocalhandle; @@ -1186,7 +1693,9 @@ TopLevelStore()->GetCleanBitmap(bmpptr); ret = bmpptr->Open(); if (ret != KErrNone) + { break; + } TPckgBuf handlebuffer; TRAP(ret,localhandle=iIx->AddL(bmpptr)); if(ret!=KErrNone) @@ -1220,13 +1729,17 @@ } ret = fbtop->GetCleanBitmap(bmpptr); if (ret != KErrNone) + { break; + } const TSize size = bmpptr->Address()->SizeInPixels(); const TDisplayMode dispMode = bmpptr->Address()->DisplayMode(); CBitmapObject* newbmpptr = NULL; TRAP(ret, newbmpptr = fbtop->CreateBitmapL(size, dispMode, KUidCFbsBitmapCreation, ETrue)); if (ret != KErrNone) + { break; + } ret = newbmpptr->Address()->CopyData(*bmpptr->Address()); if (ret != KErrNone) { @@ -1254,7 +1767,9 @@ } bmpptr->SetCleanBitmap(newbmpptr); if (bmpptr->AccessCount() >= 2) + { fbtop->NotifyDirtyBitmap(*bmpptr, this); + } iIx->Remove(localhandle); TPckgBuf handlebuffer; handlebuffer().iHandle = newlocalhandle; @@ -1286,7 +1801,9 @@ if (ret != KErrNone) { if (!async) + { ret = KErrNone; + } break; } ret = bmpptr->Address()->CheckBackgroundCompressData(); @@ -1294,10 +1811,14 @@ { ret = fbtop->BackgroundCompression()->AddToCompressionQueue(bmpptr, scheme, async ? &aMessage : NULL); if (ret == KErrNone && async) + { return; // do not complete the client's request - that will be done by the background compression thread + } } if (KErrAlreadyExists == ret) + { ret = KErrNone; + } break; } case EFbsMessBitmapClean: @@ -1312,10 +1833,14 @@ } ret = fbtop->GetCleanBitmap(bmpptr); if (ret != KErrNone) + { break; + } ret = bmpptr->Open(); if (ret != KErrNone) + { break; + } TInt cleanlocalhandle = 0; TRAP(ret, cleanlocalhandle = iIx->AddL(bmpptr)); if (ret != KErrNone) @@ -1366,17 +1891,19 @@ iHelper->iMessage = aMessage; return; // do not complete the client's request yet - that will be done when a bitmap becomes dirty } - ret = KErrNone; iHelper->iDirty = EFalse; } break; case EFbsMessBitmapCancelNotifyDirty: { if (iHelper != NULL && !iHelper->iMessage.IsNull()) + { iHelper->iMessage.Complete(KErrCancel); - ret = KErrNone; + } } break; + default: + ret = KErrUnknown; } if(!aMessage.IsNull()) @@ -1452,7 +1979,9 @@ if (iHelper) { if (!iHelper->iMessage.IsNull()) + { iHelper->iMessage.Complete(KErrDisconnected); + } iHelper->Deque(); delete iHelper; iHelper = NULL; @@ -1514,7 +2043,58 @@ break; case EFbsMessHeap: ret=(TInt)iHeap; - break; + break; + default: + ret = KErrUnknown; + } + aMessage.Complete(ret); + iRet=ret; + } + +/** +Processes messages associated with the Glyph Atlas. +@param aMessage The message used to perform IPC to the client. + */ +void CFbClient::ProcAtlasMessage(const RMessage2 &aMessage) + { + TInt ret = KErrNone; + CFbTop* fbtop = TopLevelStore(); + CGlyphAtlas* glyphAtlas = fbtop->GlyphAtlas(); + if (!glyphAtlas) + { + ret = KErrNotSupported; + } + else + { + switch(aMessage.Function()) + { + case EFbsMessAtlasFontCount: + ret = glyphAtlas->FontCount(); + break; + case EFbsMessAtlasGlyphCount: + { + TInt fontHandle = aMessage.Int0(); + if (fontHandle != 0) + { + if (fbtop->ValidFontHandle(fontHandle)) + { + CFontObject* fontptr = reinterpret_cast(fontHandle); + ret = glyphAtlas->GlyphCount(static_cast(*(fontptr->iAddressPointer))); + } + else + { + ret = KErrNotFound; + } + } + else + { + ret = glyphAtlas->GlyphCount(); + } + } + break; + default: + ret = KErrUnknown; + } } aMessage.Complete(ret); iRet=ret;