--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/imagingplugins/bitmaptransform/src/refplugin/BitmapRotationPlugin.cpp Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,584 @@
+// Copyright (c) 2001-2009 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 "BitmapTransformsPlugin.h"
+#include "BitmapConverter.h"
+#include <bitmtrans/bitmtranspanic.h>
+
+const TInt KLinesPerCall = 10;
+
+/**
+The function NewL constructs a CBitmapRotatorPlugin
+
+@returns CBitmapRotatorPlugin*
+
+
+*/
+
+MBitmapRotatorPlugin* CBitmapRotatorPlugin::NewL()
+ {
+ CBitmapRotatorPlugin* self = new(ELeave) CBitmapRotatorPlugin();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Constructor for this class. Adds itself to <code>CActiveScheduler</code>.
+The priority of this active object is CActive::EPriorityIdle
+
+*/
+
+CBitmapRotatorPlugin::CBitmapRotatorPlugin()
+ : CActive(CActive::EPriorityIdle), iScanlineDes(NULL,0)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+
+/**
+Performs second phase of contruction
+*
+*/
+
+void CBitmapRotatorPlugin::ConstructL()
+ {
+ }
+
+/**
+*
+* Default destructor for this class.
+*
+*/
+
+CBitmapRotatorPlugin::~CBitmapRotatorPlugin()
+ {
+ Cancel();
+ Cleanup();
+
+ // should have been deleted by cleanup
+ ASSERT(iScanlineBuffer==NULL);
+ ASSERT(iTempBitmap==NULL);
+ ASSERT(iDevice==NULL);
+ ASSERT(iGc==NULL);
+ }
+
+
+/**
+This function performs deallocation of memory allocated by the class
+
+*/
+
+void CBitmapRotatorPlugin::Cleanup()
+ {
+ delete [] iScanlineBuffer; iScanlineBuffer = NULL;
+ delete iTempBitmap; iTempBitmap = NULL;
+ delete iGc; iGc = NULL;
+ delete iDevice; iDevice = NULL;
+ delete iScanlineBitmap; iScanlineBitmap = NULL;
+#if defined(ROTATION_PROFILING)
+ TUint fcTaken=User::FastCounter() - iStartedAtFc;
+ RDebug::Print(_L("BmpRotator: FC time taken %d"),fcTaken);
+#endif //
+ }
+
+// MBitmapRotatorPlugin::Cancel() calls CActive::Cancel()
+void CBitmapRotatorPlugin::Cancel()
+ {
+ CActive::Cancel();
+ }
+
+/**
+The function Rotate schedules a rotate/mirror operation on a bitmap supplied in the
+aSrcBitmap whose output overwrites aSrcBitmap.
+Preconditions:
+aRequestStatus is not a NULL pointer
+aSrcBitmap is a fully constructed bitmap of unknown size including zero dimension
+aAngle is a member of the enumeration TRotationAngle
+
+@param "aRequestStatus"
+ is a pointer to the completion status of the asynchronous operation.
+@param "CFbsBitmap& aBitmap"
+ is a reference to a CFbsBitmap. This bitmap should have been created
+ and is also an output
+@param "TRotationAngle aAngle"
+ aAngle is a member of the enumeration TRotationAngle and specifies the rotation mirror operation
+
+@panic This function panics with TBitmapTransformsMain::ENoSourceBitmap when the aSrcBitmap has not been constructed
+ie its handle is 0
+
+Sucess Guarantee
+aSrcBitmap contains the rotated bitmap
+aRequestStatus points to the value KErrorNone
+
+*/
+
+void CBitmapRotatorPlugin::Rotate(TRequestStatus* aRequestStatus, CFbsBitmap& aBitmap, TRotationAngle aAngle)
+ {
+ // [ panic if aRequestStatus is NULL ]
+ __ASSERT_ALWAYS( (aRequestStatus != NULL), Panic( EBadArgumentScale ) );
+
+ //[ panic if the src has not been created]
+ __ASSERT_ALWAYS( (aBitmap.Handle() != 0), Panic( ENoSourceBitmap ) );
+
+ //[ assert the angle is ok ]
+ __ASSERT_ALWAYS( ( aAngle >= CBitmapRotator::ERotation90DegreesClockwise ) &&
+ ( aAngle <= CBitmapRotator::EMirrorVerticalAxis ), Panic(EBadArgumentRotate) );
+
+ ASSERT(iTempBitmap==NULL);
+
+ iRotateStatus = aRequestStatus;
+ *iRotateStatus = KRequestPending;
+
+ if(aBitmap.ExtendedBitmapType()!=KNullUid)
+ {
+ RequestComplete(KErrNotSupported);
+ return;
+ }
+
+ iTempBitmap = new CFbsBitmap;
+ if (!iTempBitmap)
+ {
+ RequestComplete(KErrNoMemory);
+ return;
+ }
+ Rotate(aRequestStatus, aBitmap, *iTempBitmap, aAngle);
+ }
+
+ /**
+The Rotate function schedules a rotate/mirror operation on a bitmap supplied in the srcBitmap and
+produces the output in the tgtBitmap.
+The CBitmapRotatorPlugin is an active object and as such provides asynchronous operations
+
+Preconditions:
+aRequestStatus is not a NULL pointer
+aSrcBitmap is a fully constructed bitmap of unknown size including zero dimension and
+of type EColor16M
+aTgtBitmap is a fully constructed bitmap of unknown size including zero dimension
+and is of type EColor16M
+aAngle is a member of the enumeration TRotationAngle
+
+Sucess Guarantee:
+aTgtBitmap contains the rotated bitmap
+aRequestStatus points to the value KErrNone
+
+Minimal Guarantee:
+The bitmap supplied in aSrcBitmap is unaltered
+
+
+@param "TRequestStatus* aRequestStatus"
+ a pointer to the completion status of the asynchronous operation.
+@param "CFbsBitmap& aSrcBitmap"
+ This bitmap should have been created and be of type EColor16M
+@param "CFbsBitmap& aTgtBitmap"
+ This bitmap should have been created and be of type EColor16M
+@param "TRotationAngle aAngle"
+ is a member of the enumeration TRotationAngle and specifies the rotation mirror operation
+
+
+@panic This function panics with TBitmapTransformsMain::ENoSourceBitmap when the aSrcBitmap has not been constructed
+ i.e. its handle is zero
+
+
+*/
+
+void CBitmapRotatorPlugin::Rotate(TRequestStatus* aRequestStatus, CFbsBitmap& aSrcBitmap, CFbsBitmap& aTgtBitmap, TRotationAngle aAngle)
+ {
+ // [ panic if aRequestStatus is NULL ]
+ __ASSERT_ALWAYS( (aRequestStatus != NULL), Panic( EBadArgumentScale ) );
+
+ //[ panic if the src has not been created]
+ __ASSERT_ALWAYS( (aSrcBitmap.Handle() != 0), Panic( ENoSourceBitmap ) );
+
+ //[ assert the angle is ok ]
+ __ASSERT_ALWAYS( ( aAngle >= CBitmapRotator::ERotation90DegreesClockwise ) &&
+ ( aAngle <= CBitmapRotator::EMirrorVerticalAxis ), Panic(EBadArgumentRotate) );
+
+ //[ we do not need to ensure a tgt has been created]
+#if defined(ROTATION_PROFILING)
+ iStartedAtFc = User::FastCounter();
+#endif // ROTATION_PROFILING
+ // Initialize member variables
+ iSrcBitmap = &aSrcBitmap;
+ iTgtBitmap = &aTgtBitmap;
+ iAngle = aAngle;
+ iCurOffset = 0;
+ iBitmapSize = iSrcBitmap->SizeInPixels();
+ iDisplayMode = iSrcBitmap->DisplayMode();
+ iRotateStatus = aRequestStatus;
+ *iRotateStatus = KRequestPending;
+
+ if(aSrcBitmap.ExtendedBitmapType()!=KNullUid)
+ {
+ RequestComplete(KErrNotSupported);
+ return;
+ }
+
+ if(aTgtBitmap.Handle()!=0 && aTgtBitmap.ExtendedBitmapType()!=KNullUid)
+ {
+ RequestComplete(KErrNotSupported);
+ return;
+ }
+
+ TSize newSize;
+ if ((aAngle == CBitmapRotator::ERotation90DegreesClockwise) || (aAngle == CBitmapRotator::ERotation270DegreesClockwise))
+ {
+ newSize.SetSize(iBitmapSize.iHeight, iBitmapSize.iWidth); // Swap width and height
+ }
+ else
+ {
+ newSize.SetSize(iBitmapSize.iWidth, iBitmapSize.iHeight);
+ }
+ TInt err = iTgtBitmap->Create(newSize, iDisplayMode);
+
+ TBool bmpDeviceNeeded=EFalse;
+ if (iSrcBitmap->DisplayMode()==EColor16M || iSrcBitmap->DisplayMode()==EColor16MU ||
+ iSrcBitmap->DisplayMode()==EColor16MA ||
+ iSrcBitmap->DisplayMode()==EColor256 || iSrcBitmap->DisplayMode()==EGray256 ||
+ iSrcBitmap->DisplayMode()==EColor64K )
+ {
+ iScanlineDisplayMode = iSrcBitmap->DisplayMode();
+ }
+ else
+ {
+ // we can't cope with that color mode, then use the highest one for intermediate buffer
+ bmpDeviceNeeded = ETrue;
+ iScanlineDisplayMode= EColor16MA;
+ }
+ iPixelSizeInBytes = TDisplayModeUtils::NumDisplayModeBitsPerPixel(iScanlineDisplayMode) / 8;
+
+ TInt scanlineLength=iSrcBitmap->ScanLineLength(newSize.iWidth, iScanlineDisplayMode);
+ scanlineLength=Align4(scanlineLength);
+ if (err == KErrNone)
+ {
+ ASSERT(iScanlineBuffer==NULL);
+ iScanlineBuffer = new TUint32 [ scanlineLength ];
+ if(!iScanlineBuffer)
+ {
+ err = KErrNoMemory;
+ }
+ }
+ if (err != KErrNone)
+ {
+ Cleanup();
+ RequestComplete(err);
+ return;
+ }
+ iRows = newSize.iHeight;
+
+ TPtr8 scanlineDes(reinterpret_cast<TText8*>(iScanlineBuffer),scanlineLength,scanlineLength); // Use a temporary to avoid compiler warnings
+ iScanlineDes.Set(scanlineDes);
+
+ ASSERT(iDevice==NULL);
+ if (bmpDeviceNeeded)
+ {
+ iScanlineBitmap = new CFbsBitmap();
+ err= (iScanlineBitmap? iScanlineBitmap->Create(TSize(iTgtBitmap->SizeInPixels().iWidth, 1), iScanlineDisplayMode)
+ : KErrNoMemory);
+ if (err==KErrNone)
+ {
+ TRAP(err, iDevice = CFbsBitmapDevice::NewL(iTgtBitmap));
+ }
+ if (err == KErrNone)
+ {
+ err = iDevice->CreateContext(iGc);
+ }
+ }
+
+ if (err != KErrNone)
+ {
+ Cleanup();
+ RequestComplete(err);
+ return;
+ }
+
+ // Start the active object
+ SelfComplete(KErrNone);
+ }
+
+/**
+This function is called by the Active Scheduler
+to perform the rotate operation
+
+*/
+
+void CBitmapRotatorPlugin::DoRotate()
+ {
+ TInt linesLeftPerCall = KLinesPerCall;
+ while ((linesLeftPerCall > 0) && (iCurOffset < iRows))
+ {
+ switch (iAngle)
+ {
+ // Rotation of 90 degrees
+ case CBitmapRotator::ERotation90DegreesClockwise:
+ {
+ iSrcBitmap->GetVerticalScanLine(iScanlineDes, iCurOffset, iScanlineDisplayMode);
+ FlipScanLine(iScanlineDes, iTgtBitmap->SizeInPixels().iWidth);
+ PutScanline(iCurOffset);
+ break;
+ }
+
+ // Rotation of 180 degrees
+ case CBitmapRotator::ERotation180DegreesClockwise:
+ {
+ iSrcBitmap->GetScanLine(iScanlineDes,TPoint(0, iCurOffset), iBitmapSize.iWidth, iScanlineDisplayMode);
+ FlipScanLine(iScanlineDes, iBitmapSize.iWidth);
+ PutScanline(iBitmapSize.iHeight - 1 - iCurOffset);
+ break;
+ }
+
+ // Rotation of 270 degrees
+ case CBitmapRotator::ERotation270DegreesClockwise:
+ {
+ iSrcBitmap->GetVerticalScanLine(iScanlineDes, iCurOffset, iScanlineDisplayMode);
+ PutScanline(iBitmapSize.iWidth - 1 - iCurOffset);
+ break;
+ }
+
+ // Flip about the vertical Axis
+ case CBitmapRotator::EMirrorVerticalAxis:
+ {
+ iSrcBitmap->GetScanLine(iScanlineDes,TPoint(0,iCurOffset),iBitmapSize.iWidth,iScanlineDisplayMode);
+ FlipScanLine(iScanlineDes, iBitmapSize.iWidth);
+ PutScanline(iCurOffset);
+ break;
+ }
+
+ // Flip about the horizontal axis
+ case CBitmapRotator::EMirrorHorizontalAxis:
+ {
+ iSrcBitmap->GetScanLine(iScanlineDes,TPoint(0,iCurOffset),iBitmapSize.iWidth,iScanlineDisplayMode);
+ PutScanline(iBitmapSize.iHeight-1-iCurOffset);
+ break;
+ }
+
+ default:
+ {
+ ASSERT( EFalse );
+ }
+ }
+
+ iCurOffset++;
+ linesLeftPerCall--;
+ }
+
+ if (iCurOffset == iRows)
+ {
+ TInt duplicateErr = KErrNone;
+ if (iTempBitmap)
+ {
+ duplicateErr = iSrcBitmap->Duplicate(iTgtBitmap->Handle());
+ }
+ Cleanup();
+ RequestComplete(duplicateErr);
+ }
+ else
+ {
+ // Start the active object
+ SelfComplete(KErrNone);
+ }
+ }
+
+/**
+Handles an active object’s request completion event.
+The function is called by the active scheduler
+when a request completion event occurs,
+
+*/
+
+void CBitmapRotatorPlugin::RunL()
+ {
+ DoRotate();
+ }
+
+/**
+Implements cancellation of an outstanding request.
+This function is called as part of the active object’s Cancel().
+It must call the appropriate cancel function offered by the active object’s asynchronous service provider.
+The asynchronous service provider’s cancel is expected to act immediately.
+
+*/
+
+void CBitmapRotatorPlugin::DoCancel()
+ {
+ Cleanup();
+ RequestComplete(KErrCancel);
+ }
+
+/**
+Signals to the current thread that the asynchronous request
+associated with the request status is complete.
+@param aReason is a TInt and is the completion code of this request.
+
+*/
+
+void CBitmapRotatorPlugin::RequestComplete(TInt aReason)
+ {
+ ASSERT(iRotateStatus);
+ TRequestStatus* status = iRotateStatus;
+ User::RequestComplete(status, aReason);
+ }
+
+/**
+This function activates the active object and
+signals completion of the current asynchronous operation
+
+*/
+
+void CBitmapRotatorPlugin::SelfComplete(TInt aReason)
+ {
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, aReason);
+ }
+
+/**
+ template function that can be used for swapping of memory locations
+ of particular pointer type
+ @param ptr1 - pointer to value1
+ @param ptr2 - pointer to value2
+*/
+template <class T>
+inline void SwapPixels(T* ptr1, T* ptr2)
+ {
+ T temp = *ptr1;
+ *ptr1 = *ptr2;
+ *ptr2 = temp;
+ }
+
+/**
+ template function that can be used for mirroring of linear
+ memory location of a particular scalar type
+ @param aScanLinePtr location address
+ @param aWidth width of location in elements, not bytes
+*/
+template <class T>
+inline void FlipLine(TUint8* aScanLinePtr, TInt aWidth)
+ {
+ T* startPixelPtr = reinterpret_cast<T*>(aScanLinePtr);
+ T* endPixelPtr = startPixelPtr + aWidth - 1;
+ if (aWidth&1)
+ {
+ SwapPixels(startPixelPtr++, endPixelPtr--);
+ }
+ if(aWidth&3)
+ {
+ while (startPixelPtr < endPixelPtr)
+ {
+ SwapPixels(startPixelPtr++, endPixelPtr--);
+ }
+ }
+ else
+ {
+ while (startPixelPtr < endPixelPtr)
+ {
+ SwapPixels(startPixelPtr++, endPixelPtr--);
+ SwapPixels(startPixelPtr++, endPixelPtr--);
+ }
+ }
+ }
+
+/**
+This function flips a scan line buffer of width aWidth
+PreConditions:
+aWidth >= 0 && aWidth is the length of the buffer
+aDes is a reference to a buffer of rgb pixels
+Postcondition:
+The contents of the buffer have flipped about the buffers centre
+
+@param TDes8 aDes
+ reference to a buffer of rgb pixels of lenth aWidth
+@param Tint aWidth
+ is the width of the buffer
+
+*/
+void CBitmapRotatorPlugin::FlipScanLine(TDes8& aDes, TInt aWidth)
+ {
+ //[ assert consistency between descriptor length and width ]
+ ASSERT( (aDes.Length() == (iPixelSizeInBytes * aWidth) ));
+
+ TUint8* const scanLinePtr=const_cast<TUint8*>(aDes.Ptr());
+
+ switch (iPixelSizeInBytes)
+ {
+ case 4:
+ {
+ FlipLine<TUint32>(scanLinePtr, aWidth);
+ }
+ break;
+ case 3:
+ {
+ TUint8* startPixelPtr = scanLinePtr;
+ TUint8* endPixelPtr = startPixelPtr + (aWidth - 1)*iPixelSizeInBytes;
+ while (startPixelPtr < endPixelPtr)
+ {
+ TUint8 temp0 = startPixelPtr[0];
+ TUint8 temp1 = startPixelPtr[1];
+ TUint8 temp2 = startPixelPtr[2];
+ startPixelPtr[0] = endPixelPtr[0];
+ startPixelPtr[1] = endPixelPtr[1];
+ startPixelPtr[2] = endPixelPtr[2];
+ endPixelPtr[0] = temp0;
+ endPixelPtr[1] = temp1;
+ endPixelPtr[2] = temp2;
+ startPixelPtr += iPixelSizeInBytes;
+ endPixelPtr -= iPixelSizeInBytes;
+ }
+ }
+ break;
+ case 2:
+ {
+ FlipLine<TUint16>(scanLinePtr, aWidth);
+ }
+ break;
+ case 1:
+ {
+ FlipLine<TUint8>(scanLinePtr, aWidth);
+ }
+ break;
+
+ default:
+ ASSERT(EFalse);
+ }
+ }
+
+void CBitmapRotatorPlugin::PutScanline(TInt aYPos)
+ {
+ if (iScanlineBitmap)
+ {
+ iScanlineBitmap->SetScanLine(iScanlineDes, 0);
+ iGc->BitBlt(TPoint(0, aYPos), iScanlineBitmap);
+ }
+ else
+ {
+ iTgtBitmap->SetScanLine(iScanlineDes, aYPos);
+ }
+ }
+
+/*
+*
+* CustomCommand
+* @param aUid
+* @param aParam
+* @return 'TInt' an error code indicating success or failure of the
+* command
+*
+*/
+TInt CBitmapRotatorPlugin::CustomCommand(TUid /*aUid*/, TAny* /*aParam*/)
+ {
+ TInt status = KErrNotSupported;
+ return status;
+ }