--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/AknBitmapMirrorUtils.cpp Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,462 @@
+/*
+* Copyright (c) 2003 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 "AknBitmapMirrorUtils.h"
+#include <bitdev.h>
+
+enum
+ {
+ EAknNoMirroring = 0,
+ EAknVerticalMirroring,
+ EAknHorizontalMirroring
+ };
+
+void AknBitmapMirrorUtils::LoadHorizontalMirroredBitmapL(CFbsBitmap* aBitmap, const TDesC& aFileName,TInt32 aId)
+ {
+ LoadPartialBitmapL(aBitmap, aFileName,aId, KWholeBitmapRect, ETrue);
+ }
+
+void AknBitmapMirrorUtils::LoadPartialBitmapL(CFbsBitmap* aBitmap, const TDesC& aFileName,TInt32 aId, TRect aRect, TBool aMirrorHorizontally)
+ {
+ CFbsBitmap* destinationBitmap = aBitmap;
+ User::LeaveIfNull(destinationBitmap);
+
+ CFbsBitmap* sourceBitmap = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(sourceBitmap);
+ User::LeaveIfError(sourceBitmap->Load(aFileName, aId, ETrue));
+ TSize sourceBitmapSize = sourceBitmap->SizeInPixels();
+
+ TRect sourceRect = TRect(aRect);
+ if (sourceRect == KWholeBitmapRect)
+ {
+ sourceRect.iTl.iX = 0;
+ sourceRect.iTl.iY = 0;
+ sourceRect.iBr.iX = sourceBitmapSize.iWidth;
+ sourceRect.iBr.iY = sourceBitmapSize.iHeight;
+ }
+
+ TSize destinationBitmapSize(sourceRect.Width(), sourceRect.Height());
+ User::LeaveIfError(destinationBitmap->Create(destinationBitmapSize, sourceBitmap->DisplayMode()));
+
+ CFbsBitmapDevice* destinationDevice = CFbsBitmapDevice::NewL( destinationBitmap );
+ CleanupStack::PushL(destinationDevice);
+
+ CFbsBitGc* destinationGc;
+ User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) );
+
+ if (aMirrorHorizontally)
+ {
+ TRect sourceBitmapBlittingRect( sourceRect.iTl.iX,sourceRect.iTl.iY,sourceRect.iTl.iX + 1,sourceRect.iBr.iY );
+
+ for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- )
+ {
+ destinationGc->BitBlt( TPoint(xPos,0), sourceBitmap, sourceBitmapBlittingRect );
+ sourceBitmapBlittingRect.iTl.iX++;
+ sourceBitmapBlittingRect.iBr.iX++;
+ }
+ }
+ else
+ {
+ destinationGc->BitBlt( TPoint(0,0), sourceBitmap, sourceRect );
+ }
+
+ delete destinationGc;
+ CleanupStack::PopAndDestroy(2); // sourceBitmap, destinationDevice
+ }
+
+CFbsBitmap* AknBitmapMirrorUtils::HorizontallyMirrorBitmapL( CFbsBitmap* aBitmap )
+ {
+ return PartialBitmapL( aBitmap, KWholeBitmapRect, ETrue );
+ }
+
+CFbsBitmap* AknBitmapMirrorUtils::PartialBitmapL( CFbsBitmap* aBitmap, TRect aRect, TBool aMirrorHorizontally )
+ {
+ User::LeaveIfNull(aBitmap);
+ CFbsBitmap* tmpBitmap = NULL;
+ TSize sourceBitmapSize = aBitmap->SizeInPixels();
+
+ TRect sourceRect = TRect(aRect);
+ if ( sourceRect == KWholeBitmapRect )
+ {
+ sourceRect.iTl.iX = 0;
+ sourceRect.iTl.iY = 0;
+ sourceRect.iBr.iX = sourceBitmapSize.iWidth;
+ sourceRect.iBr.iY = sourceBitmapSize.iHeight;
+ if (aMirrorHorizontally)
+ tmpBitmap = CreateBitmapOptimizedL(aBitmap, EAknHorizontalMirroring);
+ else
+ tmpBitmap = CreateBitmapOptimizedL(aBitmap, EAknNoMirroring);
+ }
+ else
+ {
+ // Check rect sanity
+ if ( sourceRect.iBr.iX > sourceBitmapSize.iWidth || sourceRect.iBr.iX <= 0 )
+ {
+ sourceRect.iBr.iX = sourceBitmapSize.iWidth;
+ }
+ if ( sourceRect.iBr.iY > sourceBitmapSize.iHeight || sourceRect.iBr.iY <= 0 )
+ {
+ sourceRect.iBr.iY = sourceBitmapSize.iHeight;
+ }
+ if ( sourceRect.iTl.iX >= sourceBitmapSize.iWidth || sourceRect.iTl.iX < 0)
+ {
+ sourceRect.iTl.iX = 0;
+ }
+ if ( sourceRect.iTl.iY >= sourceBitmapSize.iHeight || sourceRect.iTl.iY < 0)
+ {
+ sourceRect.iTl.iY = 0;
+ }
+ TSize destinationBitmapSize = TSize( sourceRect.Width(), sourceRect.Height() );
+
+ // get a copy of wanted rect of source bitmap to tmpBitmap
+ tmpBitmap = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL( tmpBitmap );
+
+ User::LeaveIfError( tmpBitmap->Create( destinationBitmapSize, aBitmap->DisplayMode() ) );
+
+ CFbsBitmapDevice* destinationDevice = CFbsBitmapDevice::NewL( tmpBitmap );
+ CleanupStack::PushL( destinationDevice );
+
+ CFbsBitGc* destinationGc;
+ User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) );
+
+ if ( aMirrorHorizontally )
+ {
+ TRect sourceBitmapBlittingRect( sourceRect.iTl.iX, sourceRect.iTl.iY,
+ sourceRect.iTl.iX + 1, sourceRect.iBr.iY );
+
+ for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- )
+ {
+ destinationGc->BitBlt( TPoint(xPos,0), aBitmap, sourceBitmapBlittingRect );
+ sourceBitmapBlittingRect.iTl.iX++;
+ sourceBitmapBlittingRect.iBr.iX++;
+ }
+ }
+ else
+ {
+ destinationGc->BitBlt( TPoint(0,0), aBitmap, sourceRect );
+ }
+
+ delete destinationGc;
+ CleanupStack::PopAndDestroy(); // destinationDevice
+ CleanupStack::Pop(); // tmpBitmap
+ }
+
+ return tmpBitmap;
+ }
+
+CFbsBitmap* AknBitmapMirrorUtils::CreateMirroredBitmapL(CFbsBitmap* aSourceBitmap, TBool aVerticalMirror, TBool aHorizontalMirror)
+ {
+ CFbsBitmap* verticalMirroredBitmap = NULL;
+ CFbsBitmap* horizontalMirroredBitmap = NULL;
+
+ if (aVerticalMirror)
+ {
+ verticalMirroredBitmap = CreateBitmapOptimizedL(aSourceBitmap, EAknVerticalMirroring);
+ }
+
+ if (aHorizontalMirror)
+ {
+ if (verticalMirroredBitmap)
+ {
+ CleanupStack::PushL(verticalMirroredBitmap);
+ horizontalMirroredBitmap = CreateBitmapOptimizedL(verticalMirroredBitmap, EAknHorizontalMirroring);
+ CleanupStack::PopAndDestroy(); // verticalMirroredBitmap
+ verticalMirroredBitmap = NULL;
+ }
+ else
+ {
+ horizontalMirroredBitmap = CreateBitmapOptimizedL(aSourceBitmap, EAknHorizontalMirroring);
+ }
+ }
+
+
+ if (!aHorizontalMirror && !aVerticalMirror)
+ {
+ verticalMirroredBitmap = CreateBitmapOptimizedL(aSourceBitmap, EAknNoMirroring);
+ }
+
+ if (verticalMirroredBitmap)
+ {
+ return verticalMirroredBitmap;
+ }
+ else
+ {
+ return horizontalMirroredBitmap;
+ }
+
+
+ }
+
+
+CFbsBitmap* AknBitmapMirrorUtils::CreateBitmapL(CFbsBitmap* aSourceBitmap, TInt aMirrorDirection)
+ {
+ User::LeaveIfNull(aSourceBitmap);
+ CFbsBitmap* destinationBitmap = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(destinationBitmap);
+
+ TSize sourceBitmapSize = aSourceBitmap->SizeInPixels();
+ TRect sourceRect = TRect(TPoint(0,0), sourceBitmapSize);
+ TSize destinationBitmapSize(sourceRect.Width(), sourceRect.Height());
+
+ User::LeaveIfError(destinationBitmap->Create(destinationBitmapSize, aSourceBitmap->DisplayMode()));
+
+ CFbsBitmapDevice* destinationDevice = CFbsBitmapDevice::NewL( destinationBitmap );
+ CleanupStack::PushL(destinationDevice);
+
+ CFbsBitGc* destinationGc;
+ User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) );
+
+ switch (aMirrorDirection)
+ {
+ case EAknVerticalMirroring:
+ {
+ TRect sourceBitmapBlittingRect( sourceRect.iTl.iX,sourceRect.iTl.iY,sourceRect.iBr.iX,sourceRect.iTl.iY + 1 );
+ for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- )
+ {
+ destinationGc->BitBlt( TPoint(0,yPos), aSourceBitmap, sourceBitmapBlittingRect );
+ sourceBitmapBlittingRect.iTl.iY++;
+ sourceBitmapBlittingRect.iBr.iY++;
+ }
+ break;
+ }
+
+ case EAknHorizontalMirroring:
+ {
+ TRect sourceBitmapBlittingRect( sourceRect.iTl.iX,sourceRect.iTl.iY,sourceRect.iTl.iX + 1,sourceRect.iBr.iY );
+ for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- )
+ {
+ destinationGc->BitBlt( TPoint(xPos,0), aSourceBitmap, sourceBitmapBlittingRect );
+ sourceBitmapBlittingRect.iTl.iX++;
+ sourceBitmapBlittingRect.iBr.iX++;
+ }
+ break;
+ }
+
+ default:
+ {
+ destinationGc->BitBlt( TPoint(0,0), aSourceBitmap, sourceRect );
+ break;
+ }
+ }
+
+ delete destinationGc;
+ CleanupStack::Pop(2); // destinationBitmap, destinationDevice
+ delete destinationDevice;
+
+ return destinationBitmap;
+ }
+
+CFbsBitmap* AknBitmapMirrorUtils::CreateBitmapOptimizedL(CFbsBitmap* aSourceBitmap, TInt aMirrorDirection)
+ {
+ // Check if displaymode is optimized, fallback to non-optimized version if not.
+ TBool fallback = ETrue;
+ TDisplayMode displayMode = aSourceBitmap->DisplayMode();
+ switch( displayMode )
+ {
+ case EGray256:
+ case EColor256:
+ case EColor4K:
+ case EColor64K:
+ fallback = EFalse;
+ break;
+ default:
+ fallback = ETrue;
+ }
+
+ // Check if mirroring mode is supported, fallback to non-optimized version if not.
+ if ((aMirrorDirection != EAknVerticalMirroring) && (aMirrorDirection != EAknHorizontalMirroring))
+ {
+ fallback = ETrue;
+ }
+
+ if( fallback )
+ return CreateBitmapL(aSourceBitmap, aMirrorDirection);
+
+ // Prepare destination bitmap
+ User::LeaveIfNull(aSourceBitmap);
+ CFbsBitmap* destinationBitmap = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(destinationBitmap);
+
+ TSize sourceBitmapSize = aSourceBitmap->SizeInPixels();
+ TRect sourceRect = TRect(TPoint(0,0), sourceBitmapSize);
+ TSize destinationBitmapSize(sourceRect.Width(), sourceRect.Height());
+
+ User::LeaveIfError(destinationBitmap->Create(destinationBitmapSize, aSourceBitmap->DisplayMode()));
+
+ // Check source, if rom bitmap or compressed then create uncompressed ram bitmap
+ TBool srcTemporary = EFalse;
+ if( aSourceBitmap->IsRomBitmap() )
+ {
+ srcTemporary = ETrue;
+ }
+
+ // Heap lock for FBServ large chunk to prevent background
+ // compression of aSrcBitmap after if IsCompressedInRAM returns EFalse
+ aSourceBitmap->LockHeapLC( ETrue ); // fbsheaplock
+ TBool fbsHeapLock = ETrue;
+
+ if( aSourceBitmap->IsCompressedInRAM() )
+ {
+ srcTemporary = ETrue;
+ }
+ if( aSourceBitmap->ExtendedBitmapType() != KNullUid )
+ {
+ srcTemporary = ETrue;
+ }
+
+ CFbsBitmap* realSource = aSourceBitmap;
+ if( srcTemporary )
+ {
+ CleanupStack::PopAndDestroy(); // fbsheaplock
+ fbsHeapLock = EFalse;
+
+ realSource = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL( realSource );
+ User::LeaveIfError( realSource->Create( sourceBitmapSize, aSourceBitmap->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), aSourceBitmap );
+ CleanupStack::PopAndDestroy(2); // dev, gc
+ }
+
+ // Heap lock for FBServ large chunk is only needed with large bitmaps.
+ if (!fbsHeapLock)
+ {
+ if ( realSource->IsLargeBitmap() || destinationBitmap->IsLargeBitmap() )
+ {
+ destinationBitmap->LockHeapLC( ETrue ); // fbsheaplock
+ }
+ else
+ {
+ CleanupStack::PushL( (TAny*)NULL );
+ }
+ }
+
+ TUint32* srcAddress = realSource->DataAddress();
+ TUint32* trgAddress = destinationBitmap->DataAddress();
+
+ if ( displayMode == EColor4K || displayMode == EColor64K )
+ {
+ TInt srcScanLen16 = CFbsBitmap::ScanLineLength(sourceBitmapSize.iWidth, displayMode) / 2;
+ TInt trgScanLen16 = CFbsBitmap::ScanLineLength(destinationBitmapSize.iWidth, displayMode) / 2;
+ TInt srcScanLen32 = CFbsBitmap::ScanLineLength(sourceBitmapSize.iWidth, displayMode) / 4;
+ TInt trgScanLen32 = CFbsBitmap::ScanLineLength(destinationBitmapSize.iWidth, displayMode) / 4;
+
+ switch (aMirrorDirection)
+ {
+ case EAknVerticalMirroring:
+ {
+ TUint32* trgAddress32 = trgAddress;
+ TUint32* srcAddress32 = srcAddress;
+ TInt trgPos = 0;
+ for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- )
+ {
+ srcAddress32 = srcAddress + srcScanLen32*yPos;
+ trgAddress32 = trgAddress + trgScanLen32*trgPos;
+ memcpy(trgAddress32, srcAddress32, srcScanLen32*4);
+ trgPos++;
+ }
+ break;
+ }
+ case EAknHorizontalMirroring:
+ {
+ TUint16* trgAddress16 = reinterpret_cast<TUint16*>(trgAddress);
+ TUint16* srcAddress16 = reinterpret_cast<TUint16*>(srcAddress);
+ TInt xTrgPos = 0;
+ for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- )
+ {
+ xTrgPos = 0;
+ for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- )
+ {
+ trgAddress16[xTrgPos] = srcAddress16[xPos];
+ xTrgPos++;
+ }
+ srcAddress16 += srcScanLen16;
+ trgAddress16 += trgScanLen16;
+ }
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ else if( (displayMode==EGray256) || (displayMode==EColor256) )
+ {
+ TInt srcScanLen8 = CFbsBitmap::ScanLineLength(sourceBitmapSize.iWidth, displayMode);
+ TInt trgScanLen8 = CFbsBitmap::ScanLineLength(destinationBitmapSize.iWidth, displayMode);
+ TInt srcScanLen32 = CFbsBitmap::ScanLineLength(sourceBitmapSize.iWidth, displayMode) / 4;
+ TInt trgScanLen32 = CFbsBitmap::ScanLineLength(destinationBitmapSize.iWidth, displayMode) / 4;
+
+ switch (aMirrorDirection)
+ {
+ case EAknVerticalMirroring:
+ {
+ TUint32* trgAddress32 = trgAddress;
+ TUint32* srcAddress32 = srcAddress;
+ TInt trgPos = 0;
+ for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- )
+ {
+ srcAddress32 = srcAddress + srcScanLen32*yPos;
+ trgAddress32 = trgAddress + trgScanLen32*trgPos;
+ memcpy(trgAddress32, srcAddress32, srcScanLen32*4);
+ trgPos++;
+ }
+ break;
+ }
+ case EAknHorizontalMirroring:
+ {
+ TUint8* trgAddress8 = reinterpret_cast<TUint8*>(trgAddress);
+ TUint8* srcAddress8 = reinterpret_cast<TUint8*>(srcAddress);
+ TInt xTrgPos = 0;
+ for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- )
+ {
+ xTrgPos = 0;
+ for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- )
+ {
+ trgAddress8[xTrgPos] = srcAddress8[xPos];
+ xTrgPos++;
+ }
+ srcAddress8 += srcScanLen8;
+ trgAddress8 += trgScanLen8;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); // fbsheaplock
+
+ if( srcTemporary )
+ {
+ CleanupStack::PopAndDestroy(); // realSource
+ }
+
+ CleanupStack::Pop(); // destinationBitmap
+ return destinationBitmap;
+ }