diff -r f966699dea19 -r ff572dfe6d86 idlehomescreen/widgetmanager/src/wmimageconverter.cpp --- a/idlehomescreen/widgetmanager/src/wmimageconverter.cpp Fri Feb 19 22:42:37 2010 +0200 +++ b/idlehomescreen/widgetmanager/src/wmimageconverter.cpp Fri Mar 12 15:41:49 2010 +0200 @@ -200,12 +200,11 @@ { CFbsBitmap* bitmap = NULL; CFbsBitmap* mask = NULL; - + + if ( aUid.iUid >= KWidgetUidLowerBound && aUid.iUid < KWidgetUidUpperBound ) { - // AknsUtils::CreateAppIconLC panics incase of WRT - RApaLsSession lsSession; User::LeaveIfError( lsSession.Connect() ); CleanupClosePushL( lsSession ); @@ -214,42 +213,53 @@ CArrayFixFlat* sizeArray = new (ELeave) CArrayFixFlat( KAppSizeArraySize ); CleanupStack::PushL( sizeArray ); + User::LeaveIfError( lsSession.GetAppIconSizes( aUid, *sizeArray ) ); - TSize size; + + // there should be atleast one size available + if ( sizeArray->Count() == 0 ){ User::Leave( KErrNotReady ); }; + + TSize size(0,0); for( TInt i=0; i < sizeArray->Count(); i++ ) { - size = (*sizeArray)[i]; - if ( size == iSize ) - { - break; - } + TSize s = (*sizeArray)[i]; + if ( size.iWidth < s.iWidth || size.iHeight < s.iHeight ) + { size = s; } + if ( size == iSize ) { break; } } + CApaMaskedBitmap* maskedBmp = CApaMaskedBitmap::NewLC(); User::LeaveIfError( lsSession.GetAppIcon( aUid, size, *maskedBmp ) ); - iBitmap = static_cast( maskedBmp ); // ownership transfered - iMask = new ( ELeave ) CFbsBitmap; - User::LeaveIfError( iMask->Create( - maskedBmp->Mask()->SizeInPixels(), - maskedBmp->Mask()->DisplayMode() ) ); - // duplicate mask, origional is owned by maskedBmp - iMask->Duplicate( maskedBmp->Mask()->Handle() ); - CleanupStack::Pop( maskedBmp ); - maskedBmp = NULL; - CleanupStack::PopAndDestroy(sizeArray); + // handle bitmap + iBitmap = new ( ELeave ) CFbsBitmap; + User::LeaveIfError( iBitmap->Create( + maskedBmp->SizeInPixels(), + maskedBmp->DisplayMode() ) ); + + // scale bitmap + ScaleBitmapL( iSize, iBitmap, maskedBmp ); + + // handle mask + if ( maskedBmp->Mask() ) + { + iMask = new ( ELeave ) CFbsBitmap; + User::LeaveIfError( iMask->Create( + maskedBmp->Mask()->SizeInPixels(), + maskedBmp->Mask()->DisplayMode() ) ); + + // scale mask + ScaleBitmapL( iSize, iMask, maskedBmp->Mask() ); + } + + // cleanup + CleanupStack::PopAndDestroy( maskedBmp ); + CleanupStack::PopAndDestroy( sizeArray ); CleanupStack::PopAndDestroy( &lsSession ); - - // scale or notify - if ( size == iSize ) - { - iState = EIdle; - iObserver->NotifyCompletion( KErrNone ); - } - else - { - iScaleNeeded = ETrue; - ScaleBitmap( iSize.iWidth, iSize.iHeight ); - } + + // notify + iState = EIdle; + iObserver->NotifyCompletion( KErrNone ); } else if ( aUid.iUid != KNullUid.iUid ) { @@ -398,7 +408,7 @@ iMask = new (ELeave) CFbsBitmap(); iMask->Create( size, EGray256 ); - + if ( size != iSize ) { iScaleNeeded = ETrue; @@ -933,6 +943,283 @@ } // --------------------------------------------------------------------------- +// CWmImageConverter::DoesScaleBitmapUseFallBack +// --------------------------------------------------------------------------- +// +TBool CWmImageConverter::DoesScaleBitmapUseFallBack( CFbsBitmap* aSrcBitmap ) + { + if ( !aSrcBitmap ) + { + return EFalse; + } + + TDisplayMode displayMode = aSrcBitmap->DisplayMode(); + TBool fallbackOnly = EFalse; + + switch ( displayMode ) + { + case EGray2: + case EGray4: + case EGray16: + case EColor16: + case EColor16M: + case ERgb: + case EColor16MA: + fallbackOnly = ETrue; + break; + case EGray256: + case EColor4K: + case EColor64K: + case EColor256: + case EColor16MU: + // These are the supported modes + break; + default: + fallbackOnly = ETrue; + } + + return fallbackOnly; + } + + +// --------------------------------------------------------------------------- +// CWmImageConverter::ScaleBitmapL +// --------------------------------------------------------------------------- +// +void CWmImageConverter::ScaleBitmapL( + const TSize& aSize, + CFbsBitmap* aTrgBitmap, + CFbsBitmap* aSrcBitmap ) + { + if ( !aSrcBitmap ) User::Leave( KErrArgument ); + if ( !aTrgBitmap ) User::Leave( KErrArgument ); + if ( aSrcBitmap->DisplayMode() != aTrgBitmap->DisplayMode() ) + { + User::Leave( KErrArgument ); + } + + TRect targetRect( aSize ); + + // calculate aspect ratio + TInt srcHeight = aSrcBitmap->SizeInPixels().iHeight; + TInt srcWidth = aSrcBitmap->SizeInPixels().iWidth; + TReal scaleRatio( 1 ); //no scale as defaul + + //If any dimension is 0, then we do not bother to scale + if ( targetRect.Width() > 0 && targetRect.Height() > 0 ) + { + TReal xRatio = ( ( TReal )srcWidth / ( TReal )targetRect.Width() ); + TReal yRatio = ( ( TReal )srcHeight / ( TReal )targetRect.Height() ); + //Find out appropriate scaling factor + xRatio > yRatio ? ( scaleRatio = xRatio ) : ( scaleRatio = yRatio ); + } + + //Scale the size for target bitmap + targetRect.SetHeight( srcHeight / scaleRatio ); + targetRect.SetWidth( srcWidth / scaleRatio ); + + TSize trgBitmapSize = aTrgBitmap->SizeInPixels(); + + // calculate the valid drawing area + TRect drawRect = targetRect; + drawRect.Intersection( TRect( TPoint( 0, 0 ), trgBitmapSize ) ); + + if( drawRect.IsEmpty() || + aSrcBitmap->SizeInPixels().iHeight <= 0 || + aSrcBitmap->SizeInPixels().iWidth <= 0 ) + { + User::Leave( KErrArgument ); + } + + TSize srcSize = aSrcBitmap->SizeInPixels(); + + TBool srcTemporary = EFalse; + if ( aSrcBitmap->IsRomBitmap() ) + { + srcTemporary = ETrue; + } + + TDisplayMode displayMode = aSrcBitmap->DisplayMode(); + TBool fallbackOnly = DoesScaleBitmapUseFallBack( aSrcBitmap ); + + if ( fallbackOnly ) + { + CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( aTrgBitmap ); + CleanupStack::PushL( dev ); + CFbsBitGc* gc = NULL; + User::LeaveIfError( dev->CreateContext( gc ) ); + CleanupStack::PushL( gc ); + + // write alpha information if it exists + if ( aSrcBitmap->DisplayMode() == EColor16MA ) + { + gc->SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha ); + } + + // targetRect is used because DrawBitmap handles clipping automatically + gc->DrawBitmap( targetRect, aSrcBitmap ); + CleanupStack::PopAndDestroy( 2 ); // dev, gc + return; + } + + // Heap lock for FBServ large chunk to prevent background + // compression of aSrcBitmap after if IsCompressedInRAM returns EFalse + aSrcBitmap->LockHeapLC( ETrue ); // fbsheaplock + TBool fbsHeapLock = ETrue; + if ( aSrcBitmap->IsCompressedInRAM() ) + { + srcTemporary = ETrue; + } + + CFbsBitmap* realSource = aSrcBitmap; + if ( srcTemporary ) + { + CleanupStack::PopAndDestroy(); // fbsheaplock + fbsHeapLock = EFalse; + + realSource = new ( ELeave ) CFbsBitmap(); + CleanupStack::PushL( realSource ); + User::LeaveIfError( + realSource->Create( srcSize, aSrcBitmap->DisplayMode() ) ); + CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( realSource ); + CleanupStack::PushL( dev ); + CFbsBitGc* gc = NULL; + User::LeaveIfError( dev->CreateContext( gc ) ); + CleanupStack::PushL( gc ); + gc->BitBlt( TPoint( 0, 0 ), aSrcBitmap ); + CleanupStack::PopAndDestroy( 2 ); // dev, gc + } + + if ( !fbsHeapLock ) + { + // Heap lock for FBServ large chunk is only needed with large bitmaps. + if ( realSource->IsLargeBitmap() || aTrgBitmap->IsLargeBitmap() ) + { + aTrgBitmap->LockHeapLC( ETrue ); // fbsheaplock + } + else + { + CleanupStack::PushL( ( TAny* )NULL ); + } + } + + TUint32* srcAddress = realSource->DataAddress(); + TUint32* trgAddress = aTrgBitmap->DataAddress(); + + const TInt xSkip = ( srcSize.iWidth << 8 ) / targetRect.Width(); + const TInt ySkip = ( srcSize.iHeight << 8 ) / targetRect.Height(); + + const TInt drawWidth = drawRect.Width(); + const TInt drawHeight = drawRect.Height(); + + TRect offsetRect( targetRect.iTl, drawRect.iTl ); + const TInt yPosOffset = ySkip * offsetRect.Height(); + const TInt xPosOffset = xSkip * offsetRect.Width(); + + if ( ( displayMode == EGray256 ) || ( displayMode == EColor256 ) ) + { + TInt srcScanLen8 = CFbsBitmap::ScanLineLength( + srcSize.iWidth, displayMode ); + TInt trgScanLen8 = CFbsBitmap::ScanLineLength( + trgBitmapSize.iWidth, displayMode ); + + TUint8* trgAddress8 = reinterpret_cast< TUint8* >( trgAddress ); + + TInt yPos = yPosOffset; + // skip left and top margins in the beginning + trgAddress8 += trgScanLen8 * drawRect.iTl.iY + drawRect.iTl.iX; + + for ( TInt y = 0; y < drawHeight; y++ ) + { + TUint8* srcAddress8 = reinterpret_cast< TUint8* >( srcAddress ) + + ( srcScanLen8 * ( yPos >> 8 ) ); + + TInt xPos = xPosOffset; + for ( TInt x = 0; x < drawWidth; x++ ) + { + *( trgAddress8++ ) = srcAddress8[xPos >> 8]; + xPos += xSkip; + } + + yPos += ySkip; + + trgAddress8 += trgScanLen8 - drawWidth; + } + } + else if ( displayMode == EColor4K || displayMode == EColor64K ) + { + TInt srcScanLen16 = CFbsBitmap::ScanLineLength( + srcSize.iWidth, displayMode ) /2; + TInt trgScanLen16 = CFbsBitmap::ScanLineLength( + trgBitmapSize.iWidth, displayMode ) /2; + + TUint16* trgAddress16 = reinterpret_cast< TUint16* >( trgAddress ); + + TInt yPos = yPosOffset; + // skip left and top margins in the beginning + trgAddress16 += trgScanLen16 * drawRect.iTl.iY + drawRect.iTl.iX; + + for ( TInt y = 0; y < drawHeight; y++ ) + { + TUint16* srcAddress16 = reinterpret_cast< TUint16* >( srcAddress ) + + ( srcScanLen16 * ( yPos >> 8 ) ); + + TInt xPos = xPosOffset; + for ( TInt x = 0; x < drawWidth; x++ ) + { + *( trgAddress16++ ) = srcAddress16[xPos >> 8]; + xPos += xSkip; + } + + yPos += ySkip; + + trgAddress16 += trgScanLen16 - drawWidth; + } + } + else if ( displayMode == EColor16MU ) + { + TInt srcScanLen32 = CFbsBitmap::ScanLineLength( + srcSize.iWidth, displayMode ) /4; + TInt trgScanLen32 = CFbsBitmap::ScanLineLength( + trgBitmapSize.iWidth, displayMode ) /4; + + TUint32* trgAddress32 = reinterpret_cast< TUint32* >( trgAddress ); + + TInt yPos = yPosOffset; + // skip left and top margins in the beginning + trgAddress32 += trgScanLen32 * drawRect.iTl.iY + drawRect.iTl.iX; + + for ( TInt y = 0; y < drawHeight; y++ ) + { + TUint32* srcAddress32 = reinterpret_cast< TUint32* >( srcAddress ) + + ( srcScanLen32 * ( yPos >> 8 ) ); + + TInt xPos = xPosOffset; + for ( TInt x = 0; x < drawWidth; x++ ) + { + *( trgAddress32++ ) = srcAddress32[xPos >> 8]; + xPos += xSkip; + } + + yPos += ySkip; + + trgAddress32 += trgScanLen32 - drawWidth; + } + } + else + { + User::Leave( KErrUnknown ); + } + + CleanupStack::PopAndDestroy(); // fbsheaplock + + if ( srcTemporary ) + { + CleanupStack::PopAndDestroy(); // realSource + } + } + +// --------------------------------------------------------------------------- // CWmImageConverter::Finished // --------------------------------------------------------------------------- //