imaging/imagingfws/src/pluginextensionmanager.cpp
changeset 0 5752a19fdefe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imaging/imagingfws/src/pluginextensionmanager.cpp	Wed Aug 25 12:29:52 2010 +0300
@@ -0,0 +1,770 @@
+// Copyright (c) 2007-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 <icl/imageconversionextension.h>
+#include <icl/imagecodec.h>
+#include <icl/imagedata.h>
+#include "ImageClientMain.h"
+#include "fwextconstants.h"
+#include "pluginextensionmanager.h"
+#include "ImageProcessorPriv.h"
+
+const TUint KAllOperationCapabilities = TImageConvOperation::ERotation90DegreesClockwise |
+										TImageConvOperation::ERotation180DegreesClockwise |
+										TImageConvOperation::ERotation270DegreesClockwise |
+										TImageConvOperation::EMirrorHorizontalAxis |
+										TImageConvOperation::EMirrorVerticalAxis;
+
+const TUint KImageCornerCount = 4;
+const TUint8 KImageTLCoord = 0x00;
+const TUint8 KImageTRCoord = 0x10;
+const TUint8 KImageBLCoord = 0x01;
+const TUint8 KImageBRCoord = 0x11;
+
+/**
+Generic extension container for codec plugin use.
+*/
+EXPORT_C CPluginExtensionManager* CPluginExtensionManager::NewL(MReadCodecExtension* aReadCodec)
+	{
+	return new (ELeave) CPluginExtensionManager(aReadCodec);
+	}
+
+CPluginExtensionManager::CPluginExtensionManager(MReadCodecExtension* aReadCodec)
+:iReadCodec(aReadCodec)
+	{
+	}
+
+EXPORT_C CPluginExtensionManager::~CPluginExtensionManager()
+	{
+	delete iOperationExtension;
+	delete iScalerExtension;
+	}
+
+EXPORT_C void CPluginExtensionManager::ResetCodecExtension(MReadCodecExtension* aReadCodec)
+	{
+	iReadCodec = aReadCodec;
+	}
+
+EXPORT_C TInt CPluginExtensionManager::ConvertScalingCoeffToReductionFactor(TInt aScalingCoeff)
+	{
+	return aScalingCoeff == 1 ? 0 : -(aScalingCoeff+1);
+	}
+
+EXPORT_C void CPluginExtensionManager::GetExtensionL(TUid aExtUid, MImageConvExtension*& aExtPtr)
+	{
+	switch(aExtUid.iUid)
+		{
+		case KUidImageConvExtOperationValue:
+			{
+			if(!iOperationExtension)
+				{
+				iOperationExtension = COperationExtension::NewL();
+				aExtPtr = iOperationExtension;
+				}
+			else 
+				{
+				aExtPtr = iOperationExtension;
+				//this extension might have been created for auto rotation before so reset the reference count
+				if (!iOperationExtension->iRefCount) 
+					{
+					iOperationExtension->iRefCount = 1;
+					}
+				}
+			break;
+			}
+		case KUidImageConvExtScalerValue:
+			{
+			if(!iScalerExtension)
+				{
+				iScalerExtension = CScalerExtension::NewL();
+				aExtPtr = iScalerExtension;
+				}
+			else 
+				{
+				aExtPtr = iScalerExtension;
+				}
+			break;
+			}
+		default:
+			{
+			User::Leave(KErrNotSupported);
+			}
+		}
+	}
+
+EXPORT_C void CPluginExtensionManager::CreateExtensionForAutoRotateL() 
+	{
+	if(!iOperationExtension)
+		{
+		iOperationExtension = COperationExtension::NewL();
+		iOperationExtension->iRefCount = 0;// this extension is not referenced as no high level API icl extension is created
+		}
+	}
+
+/*
+Called by the plugin with the size of the original image
+*/
+EXPORT_C TInt CPluginExtensionManager::GetDestinationSize(TSize& aOriginalSize)
+	{
+	TSize destinationSize = aOriginalSize;
+	TInt err = KErrNone;
+	
+	if(!iClippingRect.IsEmpty())
+		{
+		// Check for validity, as client may have switched main<->thumb
+		TRect clipRect(iClippingRect);
+		clipRect.Intersection(aOriginalSize);
+		if(clipRect == iClippingRect)
+			{
+			// Clipping rect set and valid
+			destinationSize = iClippingRect.Size();
+			}
+		else
+			{
+			err = KErrArgument;
+			return err;
+			}
+		}
+	
+	if(iOperationExtension && iOperationExtension->DimensionsSwapped())
+		{
+		// switch orientation
+		destinationSize.SetSize(destinationSize.iHeight, destinationSize.iWidth);
+		}
+
+	if(iScalerExtension)
+		{
+		if(iScalerExtension->ScaleCmd() != CScalerExtension::EScalerExtFullSize)
+			{
+			TInt scalingCoeff = 1; // full size
+			err = GetScalingCoefficient(scalingCoeff, &destinationSize);
+			if(err != KErrNone)
+				{
+				return err;
+				}
+
+			ASSERT(iReadCodec);
+			err = iReadCodec->GetReducedSize(destinationSize, scalingCoeff, destinationSize);
+			if(err != KErrNone)
+				{
+				return err;
+				}
+			}
+		}
+
+	aOriginalSize = destinationSize;
+	return err;
+	}
+
+/*
+Validate the clipping rectangle.
+*/
+EXPORT_C void CPluginExtensionManager::SetClippingRectL(const TRect* aClipRect, const RPointerArray<TFrameInfo>& aFrameInfo)
+	{
+	if(!aClipRect)
+		{
+		//reset and return
+		iClippingRect.SetRect(0,0,0,0);
+		return;
+		}
+
+	if(aClipRect->IsEmpty() || !aClipRect->IsNormalized())
+		{
+		User::Leave(KErrArgument);
+		}
+
+	// Check if this crop rect falls within at least one frame.
+	for(TInt i = 0; i < aFrameInfo.Count(); i++)
+		{
+		const TFrameInfo& frame = *aFrameInfo[i];
+
+		TRect clipTest(*aClipRect);
+		clipTest.Intersection(frame.iFrameCoordsInPixels);
+		if(clipTest == *aClipRect) // clipping rect within/same as the image rect
+			{
+			iClippingRect = *aClipRect;
+			return;
+			}
+		}
+	User::Leave(KErrArgument);
+	}
+
+/*
+Has the clipping rectangle extension been set?
+*/
+EXPORT_C TBool CPluginExtensionManager::ClippingRectExtensionRequested() const
+	{
+	if(!iClippingRect.IsEmpty())
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+
+/*
+Has the scaler extension been set?
+*/
+EXPORT_C TBool CPluginExtensionManager::ScalerExtensionRequested() const
+	{
+	if (iScalerExtension)
+		{
+		return (iScalerExtension->ScaleCmd() != CScalerExtension::EScalerExtFullSize);
+		}
+
+ 	return EFalse;
+	}
+
+/*
+Has the operation extension been set?
+*/
+EXPORT_C TBool CPluginExtensionManager::OperationExtensionRequested() const
+	{
+	if(iOperationExtension && iOperationExtension->HasBeenSet())
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+/*
+Return the clipping rectangle (may or may not have been set by client).
+*/
+EXPORT_C TRect CPluginExtensionManager::ClippingRect()
+	{
+	return iClippingRect;
+	}
+
+/*
+Returns the scaling coefficient set by the client.  If the scaling coefficient
+has been set directly by the client (i.e. calling
+TImageConvScaler::SetScalingL(TInt aScalingCoeff, ...) then this function will
+return that.  If the client has set scaling using the desired size (i.e.
+calling TImageConvScaler::SetScalingL(TSize& aDesiredSize, ...) then this function
+will calculate the appropriate scaling coefficient.
+
+@param	aScalingCoeff 		The scaling coefficient to be returned.
+@param	aOriginalSize		A pointer to the original size of the image.  Default is NULL.
+@return KErrNone 			If the call was successful.
+@return KErrArgument		If the aOriginalSize argument is NULL when
+							SetScaling() has been set with a desired size.
+@return KErrNotSupported	If client has not requested a scaling operation or the plugin
+							is not capable of scaling to the set size.
+@return						One of the system wide error codes.
+
+@see TImageConvScaler::SetScalingL(TInt aScalingCoeff, TImageConvScaler::TScalerQuality aScalingQuality)
+@see TImageConvScaler::SetScalingL(const TSize& aDesiredSize, TImageConvScaler::TScalerQuality aQuality, TBool aLockAspectRatio)
+@see TScalerCaps
+*/
+EXPORT_C TInt CPluginExtensionManager::GetScalingCoefficient(TInt& aScalingCoeff, const TSize* aOriginalSize) const
+	{
+	if(iScalerExtension)
+		{
+		switch(iScalerExtension->ScaleCmd())
+			{
+			case CScalerExtension::EScalerExtFullSize:
+				{
+				aScalingCoeff = 1; // Full size
+				return KErrNone;
+				}
+			case CScalerExtension::EScalerExtUseScalingCoeff:
+				{
+				return iScalerExtension->GetScalingCoefficient(aScalingCoeff);
+				}
+			case CScalerExtension::EScalerExtUseDesiredSize:
+				{
+				// desired size has been set so we need to validate the
+				// aOriginalSize arg, which can be NULL
+				if(aOriginalSize == NULL)
+					{
+					return KErrArgument;
+					}
+
+				TSize reducedSize;
+				TInt err = iScalerExtension->GetDesiredSize(reducedSize);
+				if(err != KErrNone)
+					{
+					return err;
+					}
+
+				ASSERT(iReadCodec);
+				aScalingCoeff = iReadCodec->ScalingCoefficient(*aOriginalSize, reducedSize);
+				if(!iScalerExtension->ScalingCoefficientSupported(aScalingCoeff))
+					{
+					return KErrNotSupported;
+					}
+				return KErrNone;
+				}
+			default:
+				{
+				Panic(EInvalidFwExtensionCall);
+				}
+			}
+		}
+	return KErrNotSupported;
+	}
+
+/*
+Get the desired scaler size set by client.
+*/
+EXPORT_C TInt CPluginExtensionManager::GetScalerDesiredSize(TSize& aDesiredSize) const
+	{
+	if(iScalerExtension)
+		{
+		return iScalerExtension->GetDesiredSize(aDesiredSize);
+		}
+	return KErrNotSupported;
+	}
+
+/*
+Get the scaler quality setting set by client.
+*/
+EXPORT_C TInt CPluginExtensionManager::GetScalerQuality(TImageConvScaler::TScalerQuality& aQuality) const
+	{
+	if(iScalerExtension)
+		{
+		return iScalerExtension->GetScalerQuality(aQuality);
+		}
+	return KErrNotSupported;
+	}
+
+/*
+Has the client requested that scaling, when using the desired size, is to
+maintain the aspect ratio.
+*/
+EXPORT_C TBool CPluginExtensionManager::ScalerMaintainAspectRatio() const
+	{
+	if(iScalerExtension)
+		{
+		return iScalerExtension->LockAspectRatioSet();
+		}
+	return EFalse;
+	}
+
+/*
+Passes the data that has been set in the extensions by the client, to the image processor.
+
+@param aImageProcessor	A pointer to the CImageProcessorExtension that is to have the extension data
+						passed to it.
+@leave					A range of system wide error codes.
+*/
+EXPORT_C void CPluginExtensionManager::TransferExtensionDataL(CImageProcessorExtension* aImageProcessor)
+	{
+	ASSERT(aImageProcessor);
+
+	if(!iClippingRect.IsEmpty())
+		{
+		aImageProcessor->SetClippingRect(iClippingRect);
+		}
+
+	if(iScalerExtension)
+		{
+		switch(iScalerExtension->ScaleCmd())
+			{
+			case CScalerExtension::EScalerExtFullSize:
+				{
+				TInt scalingCoeff = 1; // assume full size
+				aImageProcessor->SetScaling(scalingCoeff);
+				break;
+				}
+			case CScalerExtension::EScalerExtUseScalingCoeff:
+				{
+				TInt scalingCoeff = 1; // assume full size
+				User::LeaveIfError(iScalerExtension->GetScalingCoefficient(scalingCoeff));
+				aImageProcessor->SetScaling(scalingCoeff);
+				break;
+				}
+			case CScalerExtension::EScalerExtUseDesiredSize:
+				{
+				TSize desiredSize;
+				User::LeaveIfError(iScalerExtension->GetDesiredSize(desiredSize));
+				aImageProcessor->SetScaling(desiredSize);
+				break;
+				}
+			default:
+				{
+				Panic(EInvalidFwExtensionCall);
+				}
+			}
+		}
+
+	aImageProcessor->SetOperation(Operation());
+	}
+
+/**
+Gets the operations that have been set in the operation extension.  This is in the
+form of TTransformOptions and so the caller can determine the overall orientation.
+
+@return TTransformOptions	The orientation of the image.
+
+@see TTransformOptions
+@see MImageConvOperation::AddOperationL
+*/
+EXPORT_C TTransformOptions CPluginExtensionManager::Operation() const
+	{
+	if(iOperationExtension)
+		{
+		return iOperationExtension->Operation();
+		}
+	return EDecodeNormal;
+	}
+
+/**
+Gets the operations that have been set in the operation extension. If the auto rotation flag 
+is set the auto rotation operations are inserted before other operations. 
+This is in the form of TTransformOptions and so the caller can determine the overall orientation.
+
+@param aAutoRotationFlag	An auto rotation flag to define auto rotation operations required.
+
+@return TTransformOptions	The orientation of the image.
+
+@see TTransformOptions
+@see MImageConvOperation::AddOperationL
+*/
+EXPORT_C TTransformOptions CPluginExtensionManager::OperationL(TUint16 aAutoRotationFlag) const
+	{
+	if(iOperationExtension)
+		{
+		switch (aAutoRotationFlag)
+			{
+			case 1:
+				break;
+		
+			case 2:
+				iOperationExtension->InsertOperationL(TImageConvOperation::EMirrorHorizontalAxis, 0);
+				break;
+
+			case 3:
+				iOperationExtension->InsertOperationL(TImageConvOperation::ERotation180DegreesClockwise, 0);
+				break;
+			
+			case 4:
+				iOperationExtension->InsertOperationL(TImageConvOperation::EMirrorVerticalAxis, 0);
+				break;
+			
+			case 5:
+				iOperationExtension->InsertOperationL(TImageConvOperation::EMirrorVerticalAxis, 0);
+				iOperationExtension->InsertOperationL(TImageConvOperation::ERotation90DegreesClockwise, 0);
+				break;
+			
+			case 6:
+				iOperationExtension->InsertOperationL(TImageConvOperation::ERotation90DegreesClockwise, 0);
+				break;
+			
+			case 7:
+				iOperationExtension->InsertOperationL(TImageConvOperation::EMirrorHorizontalAxis , 0);
+				iOperationExtension->InsertOperationL(TImageConvOperation::ERotation90DegreesClockwise, 0);
+				break;
+			
+			case 8:
+				iOperationExtension->InsertOperationL(TImageConvOperation::ERotation270DegreesClockwise, 0);
+				break;
+			}
+		}
+		
+	return iOperationExtension->Operation();
+	}
+
+/**
+Based on the client-provided operations, have the dimensions of the image been
+swapped?
+*/
+EXPORT_C TBool CPluginExtensionManager::DimensionsSwapped() const
+	{
+	return (iOperationExtension && iOperationExtension->DimensionsSwapped());
+	}
+
+/**
+Generic plugin codec operation extension
+*/
+COperationExtension* COperationExtension::NewL()
+	{
+	return new (ELeave) COperationExtension();
+	}
+
+COperationExtension::COperationExtension()
+:iRefCount(1), iCapabilities(KAllOperationCapabilities)
+	{
+	}
+
+COperationExtension::~COperationExtension()
+	{
+	ASSERT(iRefCount == 0);
+	iOperationStack.Close();
+	}
+
+TUid COperationExtension::Uid() const
+	{
+	return KICLOperationUid;
+	}
+
+void COperationExtension::IncrementRef()
+	{
+	iRefCount++;
+	}
+
+void COperationExtension::Release()
+	{
+	iRefCount--;
+	}
+
+TUint COperationExtension::Capabilities() const
+	{
+	return iCapabilities;
+	}
+
+void COperationExtension::AddOperationL(TImageConvOperation::TOperation aOperation)
+	{
+	iOperationStack.AppendL(aOperation);
+	}
+
+void COperationExtension::InsertOperationL(TImageConvOperation::TOperation aOperation, TInt aPos)
+	{
+	iOperationStack.InsertL(aOperation, aPos);
+	}
+
+void COperationExtension::ClearOperationStack()
+	{
+	iOperationStack.Reset();
+	}
+
+TBool COperationExtension::HasBeenSet()
+	{
+	return iOperationStack.Count() > 0;
+	}
+
+/**
+Based on the client-provided operations, have the dimensions of the image been
+swapped?
+*/
+TBool COperationExtension::DimensionsSwapped() const
+	{
+	TBool rotate = EFalse;
+	for(TInt i = 0; i < iOperationStack.Count(); i++)
+		{
+		if(iOperationStack[i] == TImageConvOperation::ERotation90DegreesClockwise ||
+			iOperationStack[i] == TImageConvOperation::ERotation270DegreesClockwise)
+			{
+			rotate = !rotate;
+			}
+		}
+	return rotate;
+	}
+
+TTransformOptions COperationExtension::Operation() const
+	{
+	TUint8 imageCornerCoord[KImageCornerCount];
+	imageCornerCoord[0] = KImageTLCoord;
+	imageCornerCoord[1] = KImageTRCoord;
+	imageCornerCoord[2] = KImageBLCoord;
+	imageCornerCoord[3] = KImageBRCoord;
+
+	for(TInt i = 0; i < iOperationStack.Count(); i++)
+		{
+		switch(iOperationStack[i])
+			{
+			case TImageConvOperation::ERotation90DegreesClockwise:
+				{
+				TUint8 tempVal = imageCornerCoord[0];
+				imageCornerCoord[0] = imageCornerCoord[2];
+				imageCornerCoord[2] = imageCornerCoord[3];
+				imageCornerCoord[3] = imageCornerCoord[1];
+				imageCornerCoord[1] = tempVal;
+
+				break;
+				}
+			case TImageConvOperation::ERotation180DegreesClockwise:
+				{
+				TUint8 tempVal = imageCornerCoord[0];
+				imageCornerCoord[0] = imageCornerCoord[3];
+				imageCornerCoord[3] = tempVal;
+				tempVal = imageCornerCoord[1];
+				imageCornerCoord[1] = imageCornerCoord[2];
+				imageCornerCoord[2] = tempVal;
+
+				break;
+				}
+			case TImageConvOperation::ERotation270DegreesClockwise:
+				{
+				TUint8 tempVal = imageCornerCoord[0];
+				imageCornerCoord[0] = imageCornerCoord[1];
+				imageCornerCoord[1] = imageCornerCoord[3];
+				imageCornerCoord[3] = imageCornerCoord[2];
+				imageCornerCoord[2] = tempVal;
+
+				break;
+				}
+			case TImageConvOperation::EMirrorHorizontalAxis:
+				{
+				TUint8 tempVal = imageCornerCoord[0];
+				imageCornerCoord[0] = imageCornerCoord[2];
+				imageCornerCoord[2] = tempVal;
+				tempVal = imageCornerCoord[1];
+				imageCornerCoord[1] = imageCornerCoord[3];
+				imageCornerCoord[3] = tempVal;
+
+				break;
+				}
+			case TImageConvOperation::EMirrorVerticalAxis:
+				{
+				TUint8 tempVal = imageCornerCoord[0];
+				imageCornerCoord[0] = imageCornerCoord[1];
+				imageCornerCoord[1] = tempVal;
+				tempVal = imageCornerCoord[2];
+				imageCornerCoord[2] = imageCornerCoord[3];
+				imageCornerCoord[3] = tempVal;
+
+				break;
+				}
+			default:
+				{
+				Panic(EInvalidFwExtensionCall);
+				}
+			}
+		}
+	return *(reinterpret_cast<TTransformOptions*>(&imageCornerCoord));
+	}
+
+/**
+Generic plugin codec scaler extension
+*/
+CScalerExtension* CScalerExtension::NewL()
+	{
+	return new (ELeave) CScalerExtension();
+	}
+
+CScalerExtension::CScalerExtension()
+:iRefCount(1), iCommand(CScalerExtension::EScalerExtFullSize),
+iScalingCoefficient(1), iQuality(TImageConvScaler::EMediumQuality),
+iLockAspectRatio(ETrue)
+	{
+	}
+
+CScalerExtension::~CScalerExtension()
+	{
+	ASSERT(iRefCount == 0);
+	}
+
+TUid CScalerExtension::Uid() const
+	{
+	return KICLScalerUid;
+	}
+
+void CScalerExtension::IncrementRef()
+	{
+	iRefCount++;
+	}
+
+void CScalerExtension::Release()
+	{
+	iRefCount--;
+	}
+
+void CScalerExtension::GetCapabilities(TScalerCaps& aCaps) const
+	{
+	aCaps = TScalerCaps();
+	}
+
+void CScalerExtension::SetScalingL(const TSize& aDesiredSize, TImageConvScaler::TScalerQuality aQuality, TBool aLockAspectRatio)
+	{
+	if(aDesiredSize.iWidth <= 0 || aDesiredSize.iHeight <= 0)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	if(!aLockAspectRatio && iCapabilities.MustPreserveAspectRatio())
+		{
+		User::Leave(KErrNotSupported);
+		}
+
+	// reset scaling coeff to full size
+	iScalingCoefficient = 1;
+
+	iCommand = CScalerExtension::EScalerExtUseDesiredSize;
+	iDesiredSize = aDesiredSize;
+	iQuality = aQuality;
+	}
+
+void CScalerExtension::SetScalingL(TInt aScalingCoeff, TImageConvScaler::TScalerQuality aScalingQuality)
+	{
+	if(!ScalingCoefficientSupported(aScalingCoeff))
+		{
+		User::Leave(KErrNotSupported);
+		}
+
+	// reset desired size
+	iDesiredSize.SetSize(0,0);
+
+	// check if reset to full size
+	if(aScalingCoeff == -1 || aScalingCoeff == 1)
+		{
+		iCommand = CScalerExtension::EScalerExtFullSize;
+		}
+	else
+		{
+		iCommand = CScalerExtension::EScalerExtUseScalingCoeff;
+		}
+	iScalingCoefficient = aScalingCoeff;
+	iQuality = aScalingQuality;
+	}
+
+CScalerExtension::TScalerCmd CScalerExtension::ScaleCmd() const
+	{
+	return iCommand;
+	}
+
+TInt CScalerExtension::GetScalingCoefficient(TInt& aScalingCoeff) const
+	{
+	if(iCommand == CScalerExtension::EScalerExtUseScalingCoeff)
+		{
+		aScalingCoeff = iScalingCoefficient;
+		return KErrNone;
+		}
+	return KErrNotSupported;
+	}
+
+TInt CScalerExtension::GetDesiredSize(TSize& aDesiredSize) const
+	{
+	if(iCommand == CScalerExtension::EScalerExtUseDesiredSize)
+		{
+		aDesiredSize = iDesiredSize;
+		return KErrNone;
+		}
+	return KErrNotSupported;
+	}
+
+// Checks if a given scaling coefficient is supported.
+TBool CScalerExtension::ScalingCoefficientSupported(TInt aScalingCoeff) const
+	{
+	if(aScalingCoeff > iCapabilities.MaxUpscaleLimit() ||
+		aScalingCoeff < iCapabilities.MaxDownscaleLimit() ||
+		aScalingCoeff == 0)
+		{
+		return EFalse;
+		}
+	return ETrue;
+	}
+
+TInt CScalerExtension::GetScalerQuality(TImageConvScaler::TScalerQuality& aQuality) const
+	{
+	aQuality = iQuality;
+	return KErrNone;
+	}
+
+TBool CScalerExtension::LockAspectRatioSet() const
+	{
+	return iLockAspectRatio;
+	}
+