uifw/AvKon/src/AknBitmapMirrorUtils.cpp
changeset 0 2f259fa3e83a
--- /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;   
+    }