--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imaging/imagingfws/src/Test/TImageViewer/TImageViewer.cpp Wed Aug 25 12:29:52 2010 +0300
@@ -0,0 +1,2946 @@
+// Copyright (c) 1997-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 <barsread.h>
+#include <bidi.h>
+#include <eikenv.h>
+#include <techview/eikchlst.h>
+#include <techview/eikinfo.h>
+#include <techview/eikmenup.h>
+#include <e32math.h>
+#include <badesca.h>
+#include <techview/eikon.rsg>
+#include <eikpriv.rsg>
+#include <techview/eiktxlbx.h>
+#include <techview/eikmfne.h>
+#include <techview/eiktxlbm.h>
+#include <iclexif.h>
+
+#include <icl/icl_uids.hrh>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <icl/icl_uids_const.hrh>
+#include <icl/icl_uids_def.hrh>
+#endif
+#include "TImageViewer.h"
+
+const TInt KVideoMinZoomFactor = -3;
+const TInt KVideoMaxZoomFactor = 0;
+
+const TInt KDefaultStreamDelay = 1000000; // 1s. Used when streaming non-animated
+const TInt KDefaultFolderDelay = 2000000; // 2s. Used when playing a folder
+
+const TInt KButtonMoveIncr = 16;
+const TInt KScaleFactor = 10;
+
+const TInt KInfoBufferSize = 1024;
+
+_LIT(KDefPath, "C:\\");
+const TInt KShortestPossiblePath=4;
+
+// #define __USE_PURE_SCALING // fine scaling scales to 1/2, 1/4 and 1/8 - check non-universal scaling
+
+#define __CLEAR_BITMAPS_FIRST // for debugging purposes, get TImageViewer to clear bitmaps prior to
+ // decode conversion. Really the codecs should do this, but...
+
+inline TBool IsMngImage(const CImageDecoder* aDecoder)
+ {
+ TUid type, subtype;
+ aDecoder->ImageType(0, type, subtype);
+ return (type.iUid==KMngMimeTypeUidValue);
+ }
+
+inline TBool HasMoreMngFrames(const CImageDecoder* aDecoder)
+ {
+ const TFrameInfo& info=aDecoder->FrameInfo(0);
+ return (info.iFlags & TFrameInfo::EMngMoreFramesToDecode);
+ }
+
+CPluginInfoArray* CPluginInfoArray::NewL()
+ {
+ CPluginInfoArray* self = new (ELeave) CPluginInfoArray;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CPluginInfoArray::ConstructL()
+ {
+ RefreshPluginListL();
+ }
+
+CPluginInfoArray::CPluginInfoArray()
+ {
+ }
+
+void CPluginInfoArray::Reset()
+ {
+ iPluginArray.ResetAndDestroy();
+ }
+
+void CPluginInfoArray::RefreshPluginListL()
+ {
+ Reset();
+ CImageEncoder::GetImageTypesL(iPluginArray);
+ }
+
+CPluginInfoArray::~CPluginInfoArray()
+ {
+ Reset();
+ }
+
+TInt CPluginInfoArray::MdcaCount() const
+ {
+ return iPluginArray.Count();
+ }
+
+TPtrC CPluginInfoArray::MdcaPoint(TInt aIndex) const
+ {
+ return iPluginArray[aIndex]->Description();
+ }
+
+TUid CPluginInfoArray::ImageType(TInt aIndex)
+ {
+ return iPluginArray[aIndex]->ImageType();
+ }
+
+TUid CPluginInfoArray::SubType(TInt aIndex)
+ {
+ return iPluginArray[aIndex]->SubType();
+ }
+
+// CFrameInfoDialog
+class CFrameInfoDialog : public CEikDialog
+ {
+public:
+ CFrameInfoDialog(const TDesC& aPropertiesText, const TDesC& aImageCommentText, const TDesC& aFrameCommentText);
+
+protected:
+ void PreLayoutDynInitL();
+
+private:
+ const TDesC& iPropertiesText;
+ const TDesC& iImageCommentText;
+ const TDesC& iFrameCommentText;
+ };
+
+CFrameInfoDialog::CFrameInfoDialog(const TDesC& aPropertiesText, const TDesC& aImageCommentText, const TDesC& aFrameCommentText)
+ : iPropertiesText(aPropertiesText), iImageCommentText(aImageCommentText), iFrameCommentText(aFrameCommentText)
+ {
+ }
+
+void CFrameInfoDialog::PreLayoutDynInitL()
+ {
+ // Grab each Edwin and set the text.
+ CEikEdwin* page = STATIC_CAST(CEikEdwin*, Control(EFramePropertiesPage));
+ page->SetTextL(&iPropertiesText);
+
+ page = STATIC_CAST(CEikEdwin*, Control(EImageCommentsPage));
+ page->SetTextL(&iImageCommentText);
+
+ page = STATIC_CAST(CEikEdwin*, Control(EFrameCommentsPage));
+ page->SetTextL(&iFrameCommentText);
+ }
+
+//
+// CVideoWalker
+//
+
+class CVideoWalker : public CActive
+ {
+public:
+ static CVideoWalker* NewL(CVideoAppUi* aAppUi);
+ ~CVideoWalker();
+ TRequestStatus& ActiveStatus();
+ void SelfComplete(TInt aError);
+protected:
+ CVideoWalker(CVideoAppUi* aAppUi);
+ // from CActive
+ void RunL();
+ void DoCancel();
+protected:
+ CVideoAppUi* const iAppUi; // not owned
+ };
+
+
+//
+// CVideoAppUi
+//
+
+CVideoAppUi::CVideoAppUi():
+ iStreamBuffer(NULL,0,0)
+ {
+ iDecoderOptions = (CImageDecoder::EAllowGeneratedMask | CImageDecoder::EPreferFastDecode);
+ }
+
+void CVideoAppUi::ConstructL()
+ {
+ CEikAppUi::ConstructL();
+
+ iAppView = CVideoAppView::NewL(ClientRect());
+
+ ::new(&iFrame) CWsBitmap(iEikonEnv->WsSession());
+ ::new(&iMask) CWsBitmap(iEikonEnv->WsSession());
+
+ iRotator = CBitmapRotator::NewL();
+ iScaler = CBitmapScaler::NewL();
+
+ iBackgroundColor = KRgbWhite.Color16();
+
+ iAppView->SetBackgroundColor(TRgb::Color16(iBackgroundColor), ENoDrawNow);
+
+ iWalker = CVideoWalker::NewL(this);
+ User::LeaveIfError(iTimer.CreateLocal());
+ iStreamGen = CVideoWalker::NewL(this);
+ User::LeaveIfError(iStreamTimer.CreateLocal());
+
+ // Note iStreamSeed deliberated left as 0 to give consistent behaviour
+
+ iSaveInfo.iImageTypeUid = KImageTypeJPGUid;
+ iSaveInfo.iBpp = 6;
+ iSaveInfo.iColor = ETrue;
+ iSaveInfo.iQualityFactor = 40;
+ iSaveInfo.iSampling = 2;
+
+ iUseNativeDisplayMode = ETrue;
+
+ iScalingCoefficient = 1; // Full size
+ }
+
+CVideoAppUi::~CVideoAppUi()
+ {
+ Cancel();
+
+ iFrame.Reset();
+ iMask.Reset();
+ if (iAppView)
+ {
+ RemoveFromStack(iAppView);
+ delete iAppView;
+ }
+ delete iFrameImageData;
+ delete iLoadUtil;
+ delete iSaveUtil;
+ delete iRotator;
+ delete iScaler;
+ delete iWalker;
+ iTimer.Close();
+ iStreamTimer.Close();
+ delete iStreamGen;
+ User::Free(REINTERPRET_CAST(TAny*,CONST_CAST(TUint8*, iStreamBuffer.Ptr())));
+ delete iDir;
+ iOperations.Close();
+ }
+
+void CVideoAppUi::Cancel()
+ {
+ if (iWalker)
+ iWalker->Cancel(); // if active will callback on DoCancel()
+ if (iStreamGen)
+ iStreamGen->Cancel();
+ iState = EIdle;
+ }
+
+TKeyResponse CVideoAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
+ {
+ TKeyResponse ret = EKeyWasConsumed;
+
+ if (aType!=EEventKey)
+ return ret;
+
+ TUint code = aKeyEvent.iCode;
+
+ switch (code)
+ {
+ case EKeyLeftArrow:
+ case EKeyRightArrow:
+ case EKeyUpArrow:
+ case EKeyDownArrow:
+ {
+ if ( aKeyEvent.iModifiers & EModifierShift )
+ {
+ // update crop region
+ UpdateClippingRect(code);
+ }
+ else
+ {
+ TPoint moveBy;
+ switch (code)
+ {
+ case EKeyLeftArrow:
+ moveBy.SetXY(KButtonMoveIncr,0);
+ break;
+ case EKeyRightArrow:
+ moveBy.SetXY(-KButtonMoveIncr,0);
+ break;
+ case EKeyUpArrow:
+ moveBy.SetXY(0,KButtonMoveIncr);
+ break;
+ case EKeyDownArrow:
+ moveBy.SetXY(0,-KButtonMoveIncr);
+ break;
+ }
+ iAppView->MoveBy(moveBy);
+ }
+ }
+ break;
+ case EKeyEscape:
+ Cancel();
+ ASSERT(iState==EIdle);
+ iEikonEnv->BusyMsgCancel();
+ iEikonEnv->InfoMsg(_L("Cancelled"));
+ break;
+ default:
+ ret = EKeyWasNotConsumed;
+ break;
+ }
+ return ret;
+ }
+
+void CVideoAppUi::HandleCommandL(TInt aCommand)
+ {
+ switch (aCommand)
+ {
+ case EVideoCmdOpenFile:
+ OpenFileL(EFileTypeUnknown);
+ break;
+ case EVideoCmdOpenOtaFile:
+ OpenFileL(EFileTypeOta);
+ break;
+ case EVideoCmdOpenWbmpFile:
+ OpenFileL(EFileTypeWbmp);
+ break;
+ case EVideoCmdOpenFolder:
+ OpenFolderL();
+ break;
+ case EVideoCmdSaveAs:
+ SaveAsL();
+ break;
+ case EVideoCmdMask:
+ iDisableMask = ! iDisableMask;
+ if (iDisableMask)
+ {
+ iEikonEnv->InfoMsg(_L("Mask reset"));
+ }
+ else
+ {
+ iEikonEnv->InfoMsg(_L("Mask enabled"));
+ }
+ if (iMask.Handle() && iDisableMask)
+ {
+ iMask.Reset();
+ }
+ else if (iMask.Handle()==0 && !iDisableMask)
+ {
+ User::LeaveIfError(iMask.Create(TSize(0,0),EGray256));
+ }
+ break;
+ case EVideoCmdZoomIn:
+ iZoomFactor++;
+ if (iZoomFactor > KVideoMaxZoomFactor)
+ iZoomFactor = KVideoMinZoomFactor;
+ if ( iUseExtensions )
+ {
+ iScalingCoefficient = iZoomFactor - 1;
+ }
+ LoadFileL();
+ break;
+ case EVideoCmdZoomOut:
+ iZoomFactor--;
+ if (iZoomFactor < KVideoMinZoomFactor)
+ iZoomFactor = KVideoMaxZoomFactor;
+ if ( iUseExtensions )
+ {
+ iScalingCoefficient = iZoomFactor - 1;
+ }
+ LoadFileL();
+ break;
+ case EVideoCmdFineZoomIn:
+ ZoomFrameL(ETrue);
+ break;
+ case EVideoCmdFineZoomOut:
+ ZoomFrameL(EFalse);
+ break;
+ case EVideoCmdDisplayMode:
+ DisplayModeL();
+ break;
+ case EVideoCmdBackgroundColor:
+ BackgroundColorL();
+ break;
+ case EVideoCmdPlay:
+ if (iState == EPlaying || iState == ELoading)
+ iEikonEnv->InfoMsg(_L("Busy..."));
+ else
+ PlayClipL();
+ break;
+ case EVideoCmdStream:
+ StreamPlayL(EFileTypeUnknown);
+ break;
+ case EVideoCmdOtaStream:
+ StreamPlayL(EFileTypeOta);
+ break;
+ case EVideoCmdWbmpStream:
+ StreamPlayL(EFileTypeWbmp);
+ break;
+ case EVideoCmdDecoderOptions:
+ DecoderOptionsL();
+ break;
+ case EVideoCmdExtension:
+ ExtensionOptionsL();
+ break;
+ case EVideoCmdUseExtensions:
+ iUseExtensions = !iUseExtensions;
+ break;
+ case EVideoCmdRefresh:
+ LoadFileL();
+ break;
+ case EVideoCmdExtractFrame:
+ ExtractFrameL();
+ break;
+ case EVideoCmdExtractStreamedFrame:
+ StreamPlayL(EFileTypeUnknown, ETrue);
+ break;
+ case EVideoCmdFrameInfo:
+ FrameInfoL();
+ break;
+ case EVideoCmdRotateClockwise:
+ FrameRotateL(ETrue);
+ break;
+ case EVideoCmdRotateAntiClockwise:
+ FrameRotateL(EFalse);
+ break;
+ case EVideoCmdMirrorHorizontalAxis:
+ FrameMirrorL(ETrue);
+ break;
+ case EVideoCmdMirrorVerticalAxis:
+ FrameMirrorL(EFalse);
+ break;
+ case EEikCmdExit:
+ Exit();
+ break;
+ default:
+ iEikonEnv->InfoMsg(R_VIDEO_UNKNOWN);
+ break;
+ }
+ }
+
+TBool CVideoAppUi::ProcessCommandParametersL(TApaCommand aCommand,TFileName& aDocumentName,const TDesC8& aTail)
+ {
+ switch (aCommand)
+ {
+ case EApaCommandOpen:
+ iLoadFileName = aDocumentName;
+ break;
+ case EApaCommandCreate:
+ case EApaCommandRun:
+ break;
+ case EApaCommandBackground:
+ default:
+ break;
+ }
+
+ return CEikAppUi::ProcessCommandParametersL(aCommand,aDocumentName,aTail);
+ }
+
+void CVideoAppUi::OpenFileL(TFileType aFileType)
+ {
+ if (iLoadFileName.Length() < KShortestPossiblePath)
+ iLoadFileName = KDefPath;
+
+ Cancel();
+ delete iLoadUtil; iLoadUtil = NULL;
+
+ TInt title;
+ switch (aFileType)
+ {
+ default:
+ title = 0;
+ break;
+ case EFileTypeWbmp:
+ title = R_VIDEO_OPEN_WBMP;
+ break;
+ case EFileTypeOta:
+ title = R_VIDEO_OPEN_OTA;
+ break;
+ }
+ CEikDialog* dialog = new(ELeave) CEikFileOpenDialog(&iLoadFileName, title);
+ if (!dialog->ExecuteLD(R_EIK_DIALOG_FILE_OPEN))
+ return;
+
+ iLastFileType = aFileType;
+ iOpeningFolder = EFalse;
+ LoadFileL();
+ }
+
+void CVideoAppUi::OpenFolderL()
+ {
+ Cancel();
+
+ if (iLoadFileName.Length() < KShortestPossiblePath)
+ iLoadFileName = KDefPath;
+
+ TFileName folderName = iLoadFileName;
+
+ CEikDialog* dialog = new(ELeave) CEikFileOpenDialog(&folderName, R_VIDEO_SELECT_FOLDER);
+ if (!dialog->ExecuteLD(R_EIK_DIALOG_FILE_OPEN))
+ return;
+
+ iLastFileType = EFileTypeUnknown;
+ iOpeningFolder = ETrue;
+ LoadFolderL(folderName);
+ }
+
+void CVideoAppUi::DecoderOptionsL()
+ {
+ CEikDialog* dialog = new(ELeave) CDecoderOptionsDialog(iDecoderOptions);
+ dialog->ExecuteLD(R_VIDEO_DECODER_OPTIONS_DIALOG);
+ }
+
+void CVideoAppUi::ExtensionOptionsL()
+ {
+ CEikDialog* dialog = new(ELeave) CExtensionOptionsDialog(iClippingRect,
+ iOperations,
+ iScalingCoefficient,
+ iScalingQuality,
+ iLockAspectRatio);
+ TInt buttonPressed = dialog->ExecuteLD(R_VIDEO_DECODER_EXTENSION_DIALOG);
+ if ( buttonPressed == EEikBidOk && iLoadUtil )
+ {
+ // re-convert the image e.g. if clipping rect has changed
+ LoadFileL();
+ }
+ }
+
+void CVideoAppUi::LoadFileL()
+ {
+ Cancel();
+ if ( !iLoadUtil )
+ {
+ if (iLoadFileName.Length() < KShortestPossiblePath)
+ return;
+
+ TUid format;
+ switch (iLastFileType)
+ {
+ case EFileTypeOta:
+ format = KImageTypeOTAUid;
+ break;
+ case EFileTypeWbmp:
+ format = KImageTypeWBMPUid;
+ break;
+ default:
+ format = KNullUid;
+ }
+
+ TRAPD(error,iLoadUtil = CImageDecoder::FileNewL(iCoeEnv->FsSession(), iLoadFileName, CImageDecoder::TOptions(iDecoderOptions), format));
+ if (error!=KErrNone)
+ {
+ iEikonEnv->HandleError(error);
+ iAppView->Reset(EDrawNow); // ensure we redraw whole screen - replace previous cross if required
+ return;
+ }
+ }
+
+ HandleNewlyOpenedImageL();
+
+ StartFrameOpen(EPlaying);
+ }
+
+void CVideoAppUi::LoadFolderL(const TDesC& aDirName)
+ {
+ delete iDir; iDir = NULL;
+
+ TParsePtrC parse(aDirName);
+ iDirName = parse.DriveAndPath();
+
+ iEikonEnv->FsSession().GetDir(iDirName, 0, 0, iDir);
+
+ if (iDir->Count()==0)
+ {
+ iEikonEnv->InfoMsg(R_VIDEO_EMPTY_FOLDER);
+ return;
+ }
+
+ iDirIndex = 0;
+ OpenNextFolderEntry();
+ }
+
+void CVideoAppUi::OpenNextFolderEntry()
+ {
+ if (iDirIndex >= iDir->Count())
+ {
+ // end of processing - so stop
+ iEikonEnv->BusyMsgCancel();
+ Cancel();
+ iState = EIdle;
+ return;
+ }
+
+ const TEntry& entry = (*iDir)[iDirIndex];
+ iLoadFileName.Copy(iDirName);
+ iLoadFileName.Append(entry.iName);
+
+ delete iLoadUtil;
+ iLoadUtil = NULL;
+ TRAPD(error, LoadFileL());
+
+ if (error==KErrNone)
+ iEikonEnv->InfoMsg(entry.iName);
+ else
+ {
+ TBuf<64> errorMsg;
+ errorMsg.Format(_L("%S - error %d"), &entry.iName, error);
+ iEikonEnv->InfoMsg(errorMsg);
+ LoadFolderWait();
+ }
+ }
+
+void CVideoAppUi::DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane)
+ {
+ if(aResourceId==R_VIDEO_CLIP_MENU)
+ {
+ if (iLoadUtil==NULL || iState!=EIdle) // nothing open or we are busy
+ aMenuPane->SetItemDimmed(EVideoCmdPlay,ETrue);
+ }
+ else if (aResourceId==R_VIDEO_OPERATE_MENU)
+ {
+ if (iLoadUtil==NULL || iState!=EIdle || iUseExtensions)
+ {
+ // nothing open or we are busy
+ aMenuPane->SetItemDimmed(EVideoCmdRotateClockwise,ETrue);
+ aMenuPane->SetItemDimmed(EVideoCmdRotateAntiClockwise,ETrue);
+ aMenuPane->SetItemDimmed(EVideoCmdMirrorHorizontalAxis,ETrue);
+ aMenuPane->SetItemDimmed(EVideoCmdMirrorVerticalAxis,ETrue);
+ }
+ }
+ else if (aResourceId==R_VIDEO_ZOOM_MENU)
+ {
+ if (iLoadUtil==NULL || iState!=EIdle || iUseExtensions)
+ {
+ aMenuPane->SetItemDimmed(EVideoCmdZoomIn,ETrue);
+ aMenuPane->SetItemDimmed(EVideoCmdZoomOut,ETrue);
+ }
+ }
+ else if ( aResourceId==R_VIDEO_VIEW_MENU )
+ {
+ aMenuPane->SetItemButtonState(EVideoCmdUseExtensions,(iUseExtensions) ? EEikMenuItemSymbolOn : 0);
+ }
+ }
+
+TBool CVideoAppUi::CheckHotKeyNotDimmedL(TInt aCommandId)
+ {
+ TInt result = ETrue;
+ switch (aCommandId)
+ {
+ case EVideoCmdPlay:
+ case EVideoCmdRotateClockwise:
+ case EVideoCmdRotateAntiClockwise:
+ case EVideoCmdFineZoomIn:
+ case EVideoCmdFineZoomOut:
+ case EVideoCmdMirrorHorizontalAxis:
+ case EVideoCmdMirrorVerticalAxis:
+ if (iLoadUtil==NULL || iState!=EIdle || iUseExtensions)
+ result = EFalse;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ return result;
+ }
+
+void CVideoAppUi::LoadFolderWait()
+ {
+ ASSERT(!iWalker->IsActive()); // if we get here, should not be doing anything
+
+ iTimer.After(iWalker->ActiveStatus(), KDefaultFolderDelay);
+ iState = EFolderWait;
+ }
+
+void CVideoAppUi::HandleNewlyOpenedImageL()
+ {
+ ASSERT(iLoadUtil); // should have already been opened
+
+ TFrameInfo frameInfo = iLoadUtil->FrameInfo(0);
+
+ // jf 3/12/01. Assume frame 0 gives the main image characteristics
+ iOverallSize = frameInfo.iOverallSizeInPixels;
+ if (iOverallSize.iWidth==0 || iOverallSize.iHeight==0)
+ {
+ iOverallSize = frameInfo.iFrameCoordsInPixels.Size();
+ if (iOverallSize.iWidth==0 || iOverallSize.iHeight==0)
+ {
+ iEikonEnv->InfoMsg(_L("Invalid image dimensions."));
+ User::Leave(KErrCorrupt);
+ }
+ }
+
+ iAnimating = (frameInfo.iDelay != TTimeIntervalMicroSeconds(0) || IsMngImage(iLoadUtil));
+
+ iFrameNumber = 0;
+
+ iTime.HomeTime();
+ }
+
+void CVideoAppUi::ExtractFrameL()
+ {
+ if (iLoadFileName.Length() < KShortestPossiblePath)
+ return;
+
+ ASSERT(iLoadUtil);
+
+ Cancel();
+
+ TInt frameCount = iLoadUtil->FrameCount();
+
+ if (iFrameNumber >= frameCount)
+ iFrameNumber = 0;
+
+ CEikDialog* dialog = new(ELeave) CVideoCurrentFrameDialog(iFrameNumber,frameCount);
+ if (!dialog->ExecuteLD(R_VIDEO_FRAME_DIALOG))
+ return;
+
+ StartFrameOpen(ELoading);
+ }
+
+void CVideoAppUi::StartFrameOpen(TState aNextState, TBool aSizeFrame)
+ {
+ TRAPD(error, DoStartFrameOpenL(aSizeFrame));
+ if (error!=KErrNone)
+ iWalker->SelfComplete(error);
+ iState = aNextState; // what ever happens we go to next state, and will handle any error there
+ }
+
+void CVideoAppUi::DoStartFrameOpenL(TBool aSizeFrame)
+ {
+ ASSERT(iLoadUtil); // should be true by now
+ ASSERT(!iWalker->IsActive()); // we are going to use it
+
+ ASSERT(iFrameNumber>=0 && iFrameNumber<iLoadUtil->FrameCount());
+
+ // Set up extensions
+ if ( iClippingRect.IsEmpty() )
+ {
+ TRAPD(err, iLoadUtil->SetClippingRectL(NULL));
+ // Plugin may not support the call at all
+ if(err != KErrNone && err != KErrNotSupported)
+ {
+ User::Leave(err);
+ }
+ }
+ else
+ {
+ TRAPD(err,iLoadUtil->SetClippingRectL((iUseExtensions) ? &iClippingRect : NULL ));
+ // Plugin may not support the call at all
+ if(err == KErrNotSupported)
+ {
+ iEikonEnv->InfoMsg(_L("Clipping Not Supported using this codec."));
+ }
+ }
+
+ TImageConvScaler* scaler = NULL;
+ TRAPD(err,scaler = iLoadUtil->ScalerL());
+ if ( err == KErrNone )
+ {
+ scaler->SetScalingL( (iUseExtensions) ? iScalingCoefficient : -1 , iScalingQuality);
+ }
+ else if ( iScalingCoefficient != -1 && err == KErrNotSupported )
+ {
+ iEikonEnv->InfoMsg(_L("Scaler extension Not Supported using this codec."));
+ }
+
+
+ if ( iOperations.Count() )
+ {
+ TImageConvOperation* operation = NULL;
+ TRAPD(err,operation = iLoadUtil->OperationL());
+ if ( err == KErrNone )
+ {
+ operation->ClearOperationStack();
+
+ if ( iUseExtensions)
+ {
+ for ( TInt i = 0; i < iOperations.Count(); i++)
+ {
+ operation->AddOperationL(static_cast<TImageConvOperation::TOperation>(iOperations[i]));
+ }
+ }
+ }
+ else if ( err == KErrNotSupported )
+ {
+ iEikonEnv->InfoMsg(_L("Operations Not Supported using this codec."));
+ }
+ }
+
+ if (aSizeFrame)
+ {
+ TFrameInfo frameInfo = iLoadUtil->FrameInfo(iFrameNumber);
+
+ if (iFrame.Handle() == 0) // Only create the bitmap if we haven't done it already.
+ {
+ if ( !iUseNativeDisplayMode && (frameInfo.iFlags & TFrameInfo::ECanDither) )
+ User::LeaveIfError(iFrame.Create(TSize(0,0),iAppView->DisplayMode()));
+ else
+ User::LeaveIfError(iFrame.Create(TSize(0,0),frameInfo.iFrameDisplayMode));
+ }
+
+ // with 16MA and 16MAP we don't use the mask anymore, this since the introduction
+ // with CR894 & CR1111 of alpha channel support in PNG decoding
+
+ if (frameInfo.iFlags & TFrameInfo::ETransparencyPossible && !iDisableMask
+ && iAppView->DisplayMode() != EColor16MA && iAppView->DisplayMode() != EColor16MAP )
+ {
+ if (iMask.Handle() == 0)
+ User::LeaveIfError(iMask.Create(TSize(0,0),EGray256));
+ }
+ else
+ {
+ if (iMask.Handle())
+ iMask.Reset();
+ }
+
+
+ SetFrameSizeAndPosL(frameInfo.iFrameCoordsInPixels,frameInfo.iOverallSizeInPixels);
+ }
+
+ ASSERT(iDisableMask && iMask.Handle()==0 || !iDisableMask); // iDisableMask -> iMask.Handle()==0
+ ASSERT(iMask.Handle()==0 || iFrame.SizeInPixels()==iMask.SizeInPixels()); // if mask must be same size
+
+ // DEF090667: T: SetDisplayMode causes another file to be opened with wrong size
+ if(iFrameNumber == 0)
+ {
+ iAppView->Reset(ENoDrawNow);
+ }
+
+ if (iMask.Handle())
+ iLoadUtil->Convert(&(iWalker->ActiveStatus()),iFrame,iMask,iFrameNumber);
+ else
+ iLoadUtil->Convert(&(iWalker->ActiveStatus()),iFrame,iFrameNumber);
+
+ iViewResized = EFalse;
+ }
+
+TBool CVideoAppUi::ExtensionIsSetup()
+ {
+ return ( ( !iClippingRect.IsEmpty() ) || Abs(iScalingCoefficient) > 1 || iOperations.Count() );
+ }
+
+void CVideoAppUi::PlayClipL()
+ {
+ iFrameNumber = 0;
+ iTime.HomeTime();
+
+ StartFrameOpen(EPlaying);
+ }
+
+void CVideoAppUi::SaveAsL()
+ {
+ if (iSaveFileName.Length() < KShortestPossiblePath)
+ iSaveFileName = KDefPath;
+
+ Cancel();
+
+ CEikDialog* dialog = new(ELeave) CVideoSaveAsDialog(&iSaveFileName,iSaveInfo,iEncodeOperations,iCreateThumbnail,iSaveAsEXIF);
+ if (!dialog->ExecuteLD(R_VIDEO_FILE_SAVEAS_DIALOG))
+ return;
+ iEikonEnv->FsSession().Delete(iSaveFileName);
+
+ delete iFrameImageData; iFrameImageData = NULL;
+
+ const TUid imageType = iSaveInfo.iImageTypeUid;
+ TImageDataBlock *imageData = NULL;
+ TFrameDataBlock *frameData = NULL;
+
+ if(imageType == KImageTypeBMPUid)
+ {
+ imageData = new (ELeave) TBmpImageData;
+ TBmpImageData* data = STATIC_CAST(TBmpImageData*, imageData);
+ switch (iSaveInfo.iBpp)
+ {
+ case 0: data->iBitsPerPixel = 1; break;
+ case 2: data->iBitsPerPixel = 4; break;
+ case 3: data->iBitsPerPixel = 8; break;
+ case 6: data->iBitsPerPixel = 24; break;
+ default: ASSERT(EFalse); break;
+ }
+ }
+ else if(imageType == KImageTypeGIFUid)
+ {// gif does not have encoding options
+ }
+ else if(imageType == KImageTypeJPGUid)
+ {
+ imageData = new (ELeave) TJpegImageData;
+ TJpegImageData* data = STATIC_CAST(TJpegImageData*, imageData);
+ if (!iSaveInfo.iColor)
+ data->iSampleScheme = TJpegImageData::EMonochrome;
+ else
+ data->iSampleScheme = TJpegImageData::TColorSampling(3 - iSaveInfo.iSampling);
+ data->iQualityFactor = iSaveInfo.iQualityFactor;
+ }
+ else if(imageType == KImageTypeMBMUid)
+ {
+ frameData = new (ELeave) TMbmEncodeData;
+ TMbmEncodeData* data = STATIC_CAST(TMbmEncodeData*, frameData);
+ switch (iSaveInfo.iBpp)
+ {
+ case 0: data->iDisplayMode = EGray2; break;
+ case 1: data->iDisplayMode = EGray4; break;
+ case 2: data->iDisplayMode = iSaveInfo.iColor ? EColor16 : EGray16; break;
+ case 3: data->iDisplayMode = iSaveInfo.iColor ? EColor256 : EGray256; break;
+ case 4: data->iDisplayMode = EColor4K; break;
+ case 5: data->iDisplayMode = EColor64K; break;
+ case 6: data->iDisplayMode = EColor16M; break;
+ case 7: data->iDisplayMode = EColor16MU; break;
+ default: ASSERT(EFalse); break;
+ }
+ }
+ else if(imageType == KImageTypePNGUid)
+ {
+ frameData = new (ELeave) TPngEncodeData;
+ TPngEncodeData* data = STATIC_CAST(TPngEncodeData*, frameData);
+ // bpp
+ switch (iSaveInfo.iBpp)
+ {
+ case 0: data->iBitsPerPixel = 1; break; // 1 bpp
+ case 1: data->iBitsPerPixel = 2; break; // 2 bpp
+ case 2: data->iBitsPerPixel = 4; break; // 4 bpp
+ case 3: data->iBitsPerPixel = 8; break; // 8 bpp
+ case 6: data->iBitsPerPixel = 24; break; // 24 bpp
+ default: ASSERT(EFalse); break; // unsupported bit depth
+ }
+ // colour or grayscale?
+ data->iColor = iSaveInfo.iColor;
+ // compression level
+ switch (iSaveInfo.iCompression)
+ {
+ case 0:
+ data->iLevel = TPngEncodeData::EDefaultCompression;
+ break;
+ case 1:
+ data->iLevel = TPngEncodeData::ENoCompression;
+ break;
+ case 2:
+ data->iLevel = TPngEncodeData::EBestSpeed;
+ break;
+ case 3:
+ data->iLevel = TPngEncodeData::EBestCompression;
+ break;
+ default: // unsupported compression
+ ASSERT(EFalse);
+ break;
+ }
+ }
+ else
+ {
+ //custom encoder
+ }
+
+ if (frameData)
+ CleanupStack::PushL(frameData);
+
+ if (imageData)
+ CleanupStack::PushL(imageData);
+
+ delete iSaveUtil; iSaveUtil = NULL;
+ if ( iSaveAsEXIF && (imageType == KImageTypeJPGUid) )
+ {
+ iSaveUtil = CJPEGExifEncoder::FileNewL(iCoeEnv->FsSession(), iSaveFileName, CImageEncoder::EOptionNone, imageType);
+ // force creation of metadata - this will cause save as EXIF rather than JFIF
+ MExifMetadataWriter* metaData=static_cast<CJPEGExifEncoder*>(iSaveUtil)->ExifMetadata();
+ }
+ else
+ {
+ iSaveUtil = CImageEncoder::FileNewL(iCoeEnv->FsSession(), iSaveFileName, CImageEncoder::EOptionNone, imageType);
+ }
+
+
+ ASSERT(iFrameImageData==NULL); // deleted above
+ if (imageData)
+ {
+ iFrameImageData = CFrameImageData::NewL();
+
+ User::LeaveIfError(iFrameImageData->AppendImageData(imageData));
+ CleanupStack::Pop(); // imageData - ownership now passed to iFrameImageData
+ }
+
+ if (frameData)
+ {
+ if (iFrameImageData == NULL)
+ iFrameImageData = CFrameImageData::NewL();
+
+ User::LeaveIfError(iFrameImageData->AppendFrameData(frameData));
+ CleanupStack::Pop(); // frameData - ownership now passed to iFrameImageData
+ }
+
+ if (iCreateThumbnail)
+ {
+ iSaveUtil->SetThumbnail(iCreateThumbnail);
+ }
+
+ if ( iEncodeOperations.Count() )
+ {
+ TImageConvOperation* operation = NULL;
+ TRAPD(err, operation = iSaveUtil->OperationL());
+ if ( err == KErrNone )
+ {
+ operation->ClearOperationStack();
+
+ for ( TInt i = 0; i < iEncodeOperations.Count(); i++)
+ {
+ operation->AddOperationL(static_cast<TImageConvOperation::TOperation>(iEncodeOperations[i]));
+ }
+ }
+ }
+
+ StartFrameSave();
+ }
+
+void CVideoAppUi::DisplayModeL()
+ {
+ Cancel();
+ TDisplayMode displayMode = iAppView->DisplayMode();
+ CEikDialog* dialog = new(ELeave) CVideoDisplayModeDialog(displayMode,iUseNativeDisplayMode);
+ if (dialog->ExecuteLD(R_VIDEO_DISPLAY_MODE_DIALOG))
+ {
+ if ( iUseNativeDisplayMode && iLoadUtil )
+ {
+ TFrameInfo frameInfo = iLoadUtil->FrameInfo(0);
+ displayMode = frameInfo.iFrameDisplayMode;
+ }
+
+ iAppView->SetDisplayModeL(displayMode, &iFrame);
+ }
+ }
+
+void CVideoAppUi::BackgroundColorL()
+ {
+ Cancel();
+ TInt backgroundColor = iBackgroundColor;
+ TBool override = iOverrideBackgroundColor;
+ CEikDialog* dialog = new(ELeave) CVideoBackgroundColorDialog(backgroundColor, override);
+ if (dialog->ExecuteLD(R_VIDEO_BACKGROUND_COLOR_DIALOG))
+ {
+ iBackgroundColor = backgroundColor;
+ iOverrideBackgroundColor = override;
+ if (iOverrideBackgroundColor)
+ {
+ iAppView->SetBackgroundColor(TRgb::Color16(iBackgroundColor), ENoDrawNow);
+ iAppView->Clear(ENoDrawNow);
+ //redraw without reloading
+ if (iMask.Handle()==0)
+ iAppView->DrawImage(&iFrame, iOffset, EDrawNow);
+ else
+ iAppView->DrawImage(&iFrame, &iMask, iOffset, EDrawNow);
+ }
+ }
+ }
+
+void CVideoAppUi::StreamPlayL(TFileType aFileType, TBool aMultiFrameStreaming)
+ {
+ Cancel();
+ iLastFileType = aFileType;
+ iMultiFrameStreaming = aMultiFrameStreaming;
+
+ if (iLoadFileName.Length() < 4)
+ iLoadFileName = KDefPath;
+ CEikDialog* dialog = new(ELeave) CEikFileOpenDialog(&iLoadFileName);
+ if (!dialog->ExecuteLD(R_EIK_DIALOG_FILE_OPEN))
+ return;
+
+ delete iLoadUtil; iLoadUtil = NULL;
+
+ User::Free(REINTERPRET_CAST(TAny*,CONST_CAST(TUint8*, iStreamBuffer.Ptr())));
+ iStreamBuffer.Set(NULL, 0, 0);
+
+ RFile file;
+ User::LeaveIfError(file.Open(iEikonEnv->FsSession(), iLoadFileName, EFileShareReadersOnly|EFileStream|EFileRead));
+ CleanupClosePushL(file);
+ TInt fileSize;
+ User::LeaveIfError(file.Size(fileSize));
+ iStreamBuffer.Set(STATIC_CAST(TUint8 *, User::AllocL(fileSize)), 0, fileSize);
+ User::LeaveIfError(file.Read(iStreamBuffer));
+ CleanupStack::PopAndDestroy(); // file
+
+ iEikonEnv->BusyMsgL(_L("Busy..."));
+
+ // NB. State machine assumes no leaves after this point
+
+ ASSERT(!iStreamGen->IsActive()); // no async behav should be going on at this point
+ ASSERT(!iWalker->IsActive());
+
+ // initialize the buffer
+ iStreamBuffer.SetLength(0); // data is in buffer, and we increase length to simulate data arriving
+ User::LeaveIfError(ExtendStreamBuffer());
+
+ iState = EStreamOpening;
+ }
+
+TInt CVideoAppUi::ExtendStreamBuffer()
+ {
+// ASSERT(iStreamBuffer.Length()<iStreamBuffer.MaxLength()); // assumed we don't call when no more streaming to do
+
+ // We CAN get called when there's no more data if the decoders have failed
+ // to detect end-of-data - e.g. when the input file's header contains a length
+ // greater than the file size - so return KErrUnderflow if this happens
+ ASSERT(iStreamBuffer.Length() <= iStreamBuffer.MaxLength());
+ if (iStreamBuffer.Length() == iStreamBuffer.MaxLength())
+ return KErrUnderflow;
+
+ // 95% change of 128 bytes - else random 1..128
+ TInt chance = Math::Rand(iStreamSeed) % 100;
+ TInt increment;
+ if (chance < 95)
+ increment = 128;
+ else
+ increment = Math::Rand(iStreamSeed) % 127 + 1; // 1 .. 128
+ TInt newSize = Min(iStreamBuffer.Length()+increment, iStreamBuffer.MaxLength());
+ iStreamBuffer.SetLength(newSize);
+
+ // random time is 99% chance between 0 and 1/20s, with remainder between 0 and 5s
+ chance = Math::Rand(iStreamSeed) % 100;
+ TInt waitTime;
+ if (chance>=99)
+ waitTime = Math::Rand(iStreamSeed) % 5000000;
+ else
+ waitTime = Math::Rand(iStreamSeed) % 50000;
+
+ iStreamTimer.After(iStreamGen->ActiveStatus(), waitTime);
+ iSourceHasGrown = ETrue;
+
+#if defined(_DEBUG) && defined(__ENABLE_DEBUG_OUTPUT)
+ RDebug::Print(_L("ExtendingStreamBuffer(%d,%d->%d)"), increment, waitTime, newSize);
+#endif
+
+ return KErrNone;
+ }
+
+void CVideoAppUi::FrameInfoL()
+ {
+ if (iFrame.Handle() == 0)
+ return;
+
+ Cancel();
+
+ const TInt frameCount = iLoadUtil->FrameCount();
+ if(iFrameNumber >= frameCount)
+ iFrameNumber = frameCount-1;
+
+ HBufC* infoBuffer = HBufC::NewLC(KInfoBufferSize);
+ TPtr info(infoBuffer->Des());
+
+ CFrameInfoStrings *frameInfoStrings = iLoadUtil->FrameInfoStringsLC(iFrameNumber);
+ TInt count = frameInfoStrings->Count();
+ TInt index;
+ for (index=0; index<count; index++)
+ {
+ TPtrC frameInfoString = frameInfoStrings->String(index);
+ info.Append(frameInfoString);
+ info.Append(TChar(CEditableText::ELineBreak));
+ }
+
+ HBufC* imageComments = HBufC::NewLC(0);
+ TInt numImageComments = iLoadUtil->NumberOfImageComments();
+ for (index = 0; index<numImageComments; index++)
+ {
+ HBufC* nextComment = iLoadUtil->ImageCommentL(index);
+ CleanupStack::PushL(nextComment);
+
+ TPtr commentTPtr(nextComment->Des());
+ ReplaceNewlinesWithLineBreaks(commentTPtr);
+
+ if (index==0)
+ {
+ // first go through, so should have nothing in comments - just assign
+ ASSERT(imageComments->Length()==0);
+ imageComments = imageComments->ReAllocL(nextComment->Length());
+ *imageComments = *nextComment;
+ }
+ else
+ {
+ // append line break and then new comments
+ imageComments = imageComments->ReAllocL(imageComments->Length() + nextComment->Length() + 1); // 1 for linebreak character
+ TPtr imageCommentsPtr(imageComments->Des());
+ imageCommentsPtr.Append(TChar(CEditableText::ELineBreak));
+ imageCommentsPtr.Append(*nextComment);
+ }
+ CleanupStack::PopAndDestroy(); // nextComment
+ CleanupStack::Pop(); // old imageComments (already deleted by ReAlloc)
+ CleanupStack::PushL(imageComments);
+ }
+
+ HBufC* frameComments = HBufC::NewLC(0);
+ TInt numFrameComments = iLoadUtil->NumberOfFrameComments(iFrameNumber);
+ for (index = 0; index<numFrameComments; index++)
+ {
+ HBufC* nextComment = iLoadUtil->FrameCommentL(iFrameNumber, index);
+ CleanupStack::PushL(nextComment);
+
+ TPtr commentTPtr(nextComment->Des());
+ ReplaceNewlinesWithLineBreaks(commentTPtr);
+
+ if (index==0)
+ {
+ // first go through, so should have nothing in comments - just assign
+ ASSERT(frameComments->Length()==0);
+ frameComments = frameComments->ReAllocL(nextComment->Length());
+ *frameComments = *nextComment;
+ }
+ else
+ {
+ // append line break and then new comments
+ frameComments->ReAllocL(frameComments->Length() + nextComment->Length() + 1); // 1 for linebreak character
+ TPtr frameCommentsPtr(frameComments->Des());
+ frameCommentsPtr.Append(TChar(CEditableText::ELineBreak));
+ frameCommentsPtr.Append(*nextComment);
+ }
+ CleanupStack::PopAndDestroy(); // nextComment
+ CleanupStack::Pop(); // old frameComments (already deleted by ReAlloc)
+ CleanupStack::PushL(frameComments);
+ }
+
+ CEikDialog* dialog = new(ELeave) CFrameInfoDialog(info, *imageComments, *frameComments);
+ dialog->ExecuteLD(R_VIDEO_INFO_DIALOG);
+
+ CleanupStack::PopAndDestroy(4); // frameComments, imageComments, frameInfoStrings + infoBuffer
+ }
+
+void CVideoAppUi::FrameRotateL(TBool aClockwise)
+ {
+ ASSERT(iState == EIdle);
+ CBitmapRotator::TRotationAngle angle = aClockwise ?
+ CBitmapRotator::ERotation90DegreesClockwise :
+ CBitmapRotator::ERotation270DegreesClockwise;
+ if (iMask.Handle() != 0)
+ {
+ iRotateAngle = angle; //keep for second phase
+ iRotator->Rotate(&(iWalker->ActiveStatus()), iMask, angle);
+ iState = ERotatingMask;
+ }
+ else
+ {
+ iRotator->Rotate(&(iWalker->ActiveStatus()), iFrame, angle);
+ iState = ERotating;
+ }
+ iViewResized = EFalse;
+ }
+
+void CVideoAppUi::FrameMirrorL(TBool aHorizontalAxis)
+ {
+ ASSERT(iState == EIdle);
+ CBitmapRotator::TRotationAngle angle = aHorizontalAxis ?
+ CBitmapRotator::EMirrorHorizontalAxis :
+ CBitmapRotator::EMirrorVerticalAxis;
+ if (iMask.Handle() != 0)
+ {
+ iRotateAngle = angle; //keep for second phase
+ iRotator->Rotate(&(iWalker->ActiveStatus()), iMask, angle);
+ iState = ERotatingMask;
+ }
+ else
+ {
+ iRotator->Rotate(&(iWalker->ActiveStatus()), iFrame, angle);
+ iState = ERotating;
+ }
+ iViewResized = EFalse;
+ }
+
+void CVideoAppUi::ZoomFrameL(TBool aZoomIn)
+ {
+ TSize size(iFrame.SizeInPixels());
+ const TSize adjust(size.iWidth / KScaleFactor, size.iHeight / KScaleFactor);
+
+ if (aZoomIn)
+ size += adjust;
+ else
+ size -= adjust;
+
+ Cancel();
+
+ TFrameInfo frameInfo = iLoadUtil->FrameInfo(iFrameNumber);
+
+ if (!(frameInfo.iFlags&TFrameInfo::EFullyScaleable))
+ {
+ if (iMask.Handle()!=0)
+ {
+ iScaleSize = size; // keep for second scale action
+ iScaler->Scale(&(iWalker->ActiveStatus()),iMask,size);
+ iViewResized = EFalse;
+ iState = EScalingMask;
+ }
+ else
+ {
+ iScaler->Scale(&(iWalker->ActiveStatus()),iFrame,size);
+ iViewResized = EFalse;
+ iState = EScaling;
+ }
+ }
+ else
+ {
+ SetFrameSizeAndPosL(frameInfo.iFrameCoordsInPixels,size);
+
+ if (!(frameInfo.iFlags&TFrameInfo::ECanDither))
+ {
+ iFrame.Reset();
+ User::LeaveIfError(iFrame.Create(TSize(0,0),frameInfo.iFrameDisplayMode)); // We will dither later
+ }
+
+#if !defined(__CLEAR_BITMAPS_FIRST)
+ if (iFrame.SizeInPixels() != size)
+#endif
+ {
+ #if defined(__CLEAR_BITMAPS_FIRST)
+ User::LeaveIfError(iFrame.Resize(TSize(0,0)));
+ #endif
+ User::LeaveIfError(iFrame.Resize(size));
+ }
+
+ if (iMask.Handle())
+ {
+ if (iMask.SizeInPixels() != size)
+ User::LeaveIfError(iMask.Resize(size));
+ #if defined(__CLEAR_BITMAPS_FIRST)
+ // set mask to black, so it is opaque and by default nothing is drawn
+ CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(&iMask);
+ CleanupStack::PushL(device);
+ CFbsBitGc* bmGc = CFbsBitGc::NewL();
+ CleanupStack::PushL(bmGc);
+ bmGc->Activate(device);
+ bmGc->SetPenStyle(CGraphicsContext::ENullPen);
+ bmGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ bmGc->SetBrushColor(KRgbBlack);
+ const TRect drawRect(TPoint(0,0), iMask.SizeInPixels());
+ bmGc->DrawRect(drawRect);
+ CleanupStack::PopAndDestroy(2);
+ #endif
+ }
+
+ StartFrameOpen(ELoading, EFalse);
+ }
+ }
+
+void CVideoAppUi::StartFrameSave()
+ {
+ ASSERT(iSaveUtil); // should be true by now
+ ASSERT(iState==EIdle);
+ ASSERT(!iWalker->IsActive()); // we are going to use it
+ iSaveUtil->Convert(&(iWalker->ActiveStatus()),iFrame,iFrameImageData);
+ iState = ESaving;
+ }
+
+void CVideoAppUi::DrawConvertedFrameL()
+ {
+ ASSERT(iDisableMask && iMask.Handle()==0 || !iDisableMask); // iDisableMask -> iMask.Handle()==0
+ ASSERT(iMask.Handle()==0 || iFrame.SizeInPixels()==iMask.SizeInPixels()); // if mask must be same size
+
+ TBool fullRedrawReq = EFalse;
+ if (!iViewResized)
+ {
+ TFrameInfo frameInfo = iLoadUtil->FrameInfo(iFrameNumber);
+ TRgb backgroundColor = iOverrideBackgroundColor ? TRgb::Color16(iBackgroundColor) : frameInfo.iBackgroundColor;
+ fullRedrawReq = iAppView->SetBackgroundColor(backgroundColor, ENoDrawNow);
+ if (iState == EScaling || iState == ERotating)
+ {
+ // size and center based on bitmap, rather than the official image size
+ TBool resized = iAppView->ResizeL(iFrame.SizeInPixels(), ETrue, ENoDrawNow);
+ if (resized)
+ iAppView->Center(ENoDrawNow);
+ fullRedrawReq = fullRedrawReq || resized;
+ }
+ else if (!iAnimating || iFrameNumber==0)
+ {
+ TBool resized = iAppView->ResizeL(iImageDisplaySize, ETrue, ENoDrawNow);
+ // implies Resize
+
+ // PDEF088116: TImageViewer USER 0 with certain animated gifs
+ if(frameInfo.iFlags & TFrameInfo::EUsesFrameSizeInPixels)
+ {
+ if(iFrame.SizeInPixels() != frameInfo.iFrameSizeInPixels)
+ {
+ iFrame.Resize(frameInfo.iFrameSizeInPixels);
+ }
+ }
+ //Resize iFrame to iImageDisplaySize if they are different
+ else if (iFrame.SizeInPixels() != iImageDisplaySize)
+ {
+ iFrame.Resize(iImageDisplaySize);
+ }
+
+ if (resized)
+ iAppView->Center(ENoDrawNow);
+ else if (IsMngImage(iLoadUtil) && (iLastFrameFlags & TFrameInfo::ERestoreToBackground))
+ {
+ iAppView->Clear(EFalse, EDrawNow);
+ }
+ fullRedrawReq = fullRedrawReq || resized;
+ }
+ else if (iFrameNumber > 0 && iLastFrameFlags & TFrameInfo::ERestoreToBackground
+ || iState != EPlaying && iState != EStreamDecoding && iFrameNumber-1!=iPrevFrameNumber)
+ {
+ iAppView->Clear(EFalse, EDrawNow);
+ ASSERT(iAnimating); // should be true given above, avoids complicating below
+ if (iState != EPlaying && iState != EStreamDecoding && iFrameNumber-1!=iPrevFrameNumber)
+ fullRedrawReq = ETrue;
+ // usually will want to redraw _whole_ bitmap area - otherwise we only
+ // redraw that part of the bitmap we DrawImage to
+ // exception is when we are extracting frames in the correct sequence
+ }
+ else if (iAnimating && (iState==EPlaying||iState==EStreamDecoding))
+ {
+ // if animating and playing, should have frame greater than 0 and no restore to background - or will trigger above
+ ASSERT(! (iLastFrameFlags & TFrameInfo::ERestoreToBackground));
+ ASSERT(iFrameNumber>0 && iFrameNumber-1==iPrevFrameNumber);
+ fullRedrawReq = EFalse; // don't redraw full - even if background changed, want to just redraw our bit
+ }
+ iViewResized = ETrue;
+ }
+
+ if (iMask.Handle()==0)
+ iAppView->DrawImage(&iFrame, iOffset, fullRedrawReq?ENoDrawNow:EDrawNow);
+ else
+ iAppView->DrawImage(&iFrame, &iMask, iOffset, fullRedrawReq?ENoDrawNow:EDrawNow);
+
+ if (fullRedrawReq)
+ iAppView->DrawNow();
+ }
+
+void CVideoAppUi::HandleConvertCompleteL()
+ {
+ DrawConvertedFrameL();
+
+ TFrameInfo frameInfo = iLoadUtil->FrameInfo(iFrameNumber);
+
+ iLastFrameFlags = frameInfo.iFlags;
+ iPrevFrameNumber = iFrameNumber;
+
+ if (iAnimating && iState==EPlaying ||
+ iState==EStreamDecoding && (iMultiFrameStreaming||iAnimating))
+ {
+ ASSERT(!iWalker->IsActive()); // we will use it again
+ TBool mustSelfComplete=EFalse;
+ if ((iAnimating && frameInfo.iDelay > TTimeIntervalMicroSeconds(0))||iMultiFrameStreaming)
+ {
+ TTime endTime;
+ endTime.HomeTime();
+
+ TTimeIntervalMicroSeconds timeTaken = endTime.MicroSecondsFrom(iTime);
+ if (frameInfo.iDelay > timeTaken)
+ {
+ TInt64 delay = frameInfo.iDelay.Int64() - timeTaken.Int64();
+ TInt delayPeriod = I64LOW(delay);
+ if (delayPeriod<0)
+ delayPeriod=0; // can get negative if we took longer on the streaming than this
+ iTimer.After(iWalker->ActiveStatus(), delayPeriod);
+ }
+ else if(iMultiFrameStreaming)
+ {
+ TInt delay = KDefaultStreamDelay - I64LOW(timeTaken.Int64());
+ if (delay<0)
+ delay=0; // can get negative if we took longer on the streaming than this
+ iTimer.After(iWalker->ActiveStatus(), delay);
+ }
+ else
+ mustSelfComplete=ETrue;
+ }
+ else
+ mustSelfComplete=ETrue;
+ if (mustSelfComplete)
+ iWalker->SelfComplete(KErrNone);
+ if (iState==EPlaying)
+ iState = EPlayingWait;
+ else
+ {
+ ASSERT(iState==EStreamDecoding);
+ iState = EStreamDecodeWait;
+ }
+ }
+ else if (iOpeningFolder)
+ LoadFolderWait();
+ else
+ {
+ iEikonEnv->BusyMsgCancel();
+ Cancel(); // cancel any background streaming
+ iState = EIdle;
+ }
+ }
+
+void CVideoAppUi::RunL(CVideoWalker* aWalker, TInt aStatus)
+ {
+ ASSERT(aWalker==iWalker || aWalker==iStreamGen); // ones we know about
+
+#if defined(_DEBUG) && defined(__ENABLE_DEBUG_OUTPUT)
+ RDebug::Print(_L("RunL(%x,%d,%d)(%x,%x)"), aWalker, aStatus, iState, iWalker, iStreamGen);
+#endif
+
+ switch (iState)
+ {
+ case EIdle:
+ ASSERT(EFalse); // should not happen
+ break;
+ case ELoading:
+ case EPlaying:
+ case EScaling:
+ case ERotating:
+ {
+ ASSERT(aWalker==iWalker);
+ TInt error = aStatus;
+ if (error==KErrNone)
+ TRAP(error, HandleConvertCompleteL());
+ if (error!=KErrNone)
+ HandleRunError(aWalker, error);
+ }
+ break;
+ case ERotatingMask:
+ {
+ ASSERT(aWalker == iWalker);
+ if (aStatus==KErrNone)
+ {
+ // having done mask, kick off rotate the image itself
+ iRotator->Rotate(&(iWalker->ActiveStatus()), iFrame, iRotateAngle);
+ iState = ERotating;
+ }
+ else
+ {
+ HandleRunError(aWalker, aStatus);
+ }
+ break;
+ }
+ case EScalingMask:
+ {
+ ASSERT(aWalker==iWalker);
+ if (aStatus==KErrNone)
+ {
+ // having done mask, kick off scale of normal
+ iScaler->Scale(&iWalker->ActiveStatus(), iFrame, iScaleSize);
+ iState = EScaling;
+ }
+ else
+ HandleRunError(aWalker, aStatus);
+ }
+ break;
+ case EPlayingWait:
+ {
+ ASSERT(iWalker==aWalker);
+ iTime.HomeTime(); // whatever reset the time here
+ if (aStatus!=KErrNone)
+ HandleRunError(aWalker, aStatus);
+ else if (iFrameNumber < iLoadUtil->FrameCount()-1 || (IsMngImage(iLoadUtil)&&HasMoreMngFrames(iLoadUtil)) )
+ {
+ iFrameNumber += ( IsMngImage(iLoadUtil)==EFalse );
+ StartFrameOpen(EPlaying);
+ }
+ else if (iOpeningFolder)
+ LoadFolderWait();
+ else
+ {
+ ASSERT(!iWalker->IsActive() && !iStreamGen->IsActive()); // should have stopped naturally
+ iEikonEnv->BusyMsgCancel();
+ iState = EIdle;
+ }
+ }
+ break;
+ case ESaving:
+ {
+ ASSERT(iWalker==aWalker);
+ iEikonEnv->BusyMsgCancel();
+ iState = EIdle;
+ if (aStatus!=KErrNone)
+ HandleRunError(aWalker, aStatus);
+ }
+ break;
+ case EStreamOpening:
+ {
+ ASSERT(aWalker==iStreamGen);
+ TInt error = aStatus;
+
+ if (error==KErrNone)
+ {
+ delete iLoadUtil; iLoadUtil = NULL;
+
+ TUid format;
+ switch (iLastFileType)
+ {
+ case EFileTypeOta:
+ format = KImageTypeOTAUid;
+ break;
+ case EFileTypeWbmp:
+ format = KImageTypeWBMPUid;
+ break;
+ default:
+ format = KNullUid;
+ }
+
+ TRAP(error, iLoadUtil = CImageDecoder::DataNewL(iCoeEnv->FsSession(), iStreamBuffer,
+ CImageDecoder::TOptions(iDecoderOptions | CImageDecoder::EOptionAllowZeroFrameOpen), format));
+ }
+
+ if (error==KErrUnderflow)
+ {
+ error = KErrNone; // clear so we don't hit the error handler below
+ if (!iStreamGen->IsActive())
+ error = ExtendStreamBuffer(); // wait for more input. remain in current state
+ }
+ else if (error==KErrNone)
+ {
+ if (iLoadUtil->FrameCount()>0)
+ {
+ TRAP(error,HandleNewlyOpenedImageL());
+ if (error==KErrNone)
+ TRAP(error,StreamOpenFrameIfPosL());
+ }
+ else
+ {
+ // insufficient data, so wait until it comes along
+ if (!iStreamGen->IsActive())
+ error = ExtendStreamBuffer(); // wait for more input. switch to EStreamWaitForFirstFrame
+ iState = EStreamWaitForFirstFrame;
+ }
+ }
+
+ if (error!=KErrNone)
+ HandleRunError(aWalker, error);
+ }
+ break;
+ case EStreamWaitAndContinue:
+#if defined(__BYPASS_CONTINUE_CONVERT)
+ ASSERT(EFalse); // should not happen when bypassing
+#else
+ {
+ ASSERT(aWalker==iStreamGen);
+
+ TInt error = aStatus;
+
+ if (error==KErrNone)
+ {
+ if ((iStreamBuffer.Length()<iStreamBuffer.MaxLength()) && !iStreamGen->IsActive())
+ error = ExtendStreamBuffer(); // "new data has arrived"
+ ASSERT(iSourceHasGrown);
+ ASSERT(iState==EStreamWaitAndContinue);
+ iLoadUtil->ContinueConvert(&(iWalker->ActiveStatus()));
+ iSourceHasGrown = EFalse;
+ iState = EStreamDecoding;
+ }
+
+ if (error!=KErrNone)
+ HandleRunError(aWalker, error);
+ }
+#endif
+ break;
+ case EStreamWaitForFirstFrame:
+ {
+ ASSERT(aWalker==iStreamGen);
+
+ TInt error = aStatus;
+
+ if (error==KErrNone)
+ {
+ ASSERT(!iLoadUtil->IsImageHeaderProcessingComplete()); // should not be reading more than we need to know
+ iLoadUtil->ContinueProcessingHeaderL();
+ if (iLoadUtil->FrameCount()>0)
+ {
+ TRAP(error,HandleNewlyOpenedImageL());
+ if (error==KErrNone)
+ TRAP(error,StreamOpenFrameIfPosL());
+ }
+ else
+ {
+ // insufficient data, so wait until it comes along
+ if (!iStreamGen->IsActive())
+ error = ExtendStreamBuffer(); // wait for more input. stay in same state
+ }
+ }
+
+ if (error!=KErrNone)
+ HandleRunError(aWalker, error);
+ }
+ break;
+ case EStreamWaitForDetails:
+ {
+ ASSERT(aWalker==iStreamGen);
+ TInt error = aStatus;
+
+ if (error==KErrNone)
+ {
+ TRAP(error, StreamOpenFrameIfPosL());
+ }
+ if (error!=KErrNone)
+ HandleRunError(aWalker, error);
+ }
+ break;
+ case EStreamDecoding:
+ {
+ ASSERT(aWalker==iWalker || aWalker==iStreamGen);
+ TInt error = aStatus;
+ if (aWalker==iWalker)
+ {
+ TBool timerActive = iStreamGen->IsActive();
+ if (error==KErrNone)
+ {
+ TRAP(error, HandleConvertCompleteL());
+ }
+ else if (error==KErrUnderflow && (timerActive || iSourceHasGrown))
+ {
+ // draw partial result to the screen if possible, else set error to KErrNone so we don't stop
+ TFrameInfo frameInfo = iLoadUtil->FrameInfo(iFrameNumber);
+ if (!(frameInfo.iFlags & TFrameInfo::EPartialDecodeInvalid))
+ {
+ TRAP(error, DrawConvertedFrameL());
+ }
+ else
+ error = KErrNone;
+
+ if (error==KErrNone)
+ {
+ // wait for more data to arrive before we try again
+ #if defined(__BYPASS_CONTINUE_CONVERT)
+ iState = EStreamWaitForDetails;
+ #else
+ iState = EStreamWaitAndContinue;
+ #endif
+ if(!timerActive)
+ { // final buffer was added after last Convert()/ContinueConvert()
+ ASSERT(iStreamBuffer.Length()==iStreamBuffer.MaxLength());
+ ASSERT(iSourceHasGrown);
+ // force a final decode
+ iStreamTimer.After(iStreamGen->ActiveStatus(),0);
+ }
+ }
+ }
+ }
+ else
+ {
+ ASSERT(aWalker==iStreamGen);
+ if (error==KErrNone && iStreamBuffer.Length()<iStreamBuffer.MaxLength())
+ error = ExtendStreamBuffer(); // data can arrive concurrent with decode
+ }
+ if (error!=KErrNone)
+ HandleRunError(aWalker, error);
+ }
+ break;
+ case EStreamDecodeWait:
+ {
+ ASSERT(aWalker==iWalker || aWalker==iStreamGen);
+ TInt error = aStatus;
+ if (aWalker==iWalker)
+ {
+ iTime.HomeTime(); // whatever reset the time here
+ if (error==KErrNone)
+ {
+ if (iFrameNumber < iLoadUtil->FrameCount()-1 || !iLoadUtil->IsImageHeaderProcessingComplete())
+ {
+ iFrameNumber += 1;
+ TRAP(error,StreamOpenFrameIfPosL());
+ }
+ else
+ {
+ Cancel(); // may be required true, eg if there is data after the frame, other AO may be busy
+ iEikonEnv->BusyMsgCancel();
+ iState = EIdle;
+ }
+ }
+ }
+ else
+ {
+ ASSERT(aWalker==iStreamGen);
+ if (error==KErrNone && iStreamBuffer.Length()<iStreamBuffer.MaxLength())
+ error = ExtendStreamBuffer(); // data can arrive concurrent with wait
+ }
+ if (error!=KErrNone)
+ HandleRunError(aWalker, error);
+ }
+ break;
+ case EFolderWait:
+ iDirIndex++;
+ OpenNextFolderEntry();
+ break;
+ default:
+ ASSERT(EFalse); // unknown state
+ }
+ }
+
+void CVideoAppUi::DoCancel(CVideoWalker *aWalker)
+ {
+ ASSERT(aWalker==iWalker || aWalker==iStreamGen); // only ones we know about
+
+#if defined(_DEBUG) && defined(__ENABLE_DEBUG_OUTPUT)
+ RDebug::Print(_L("DoCancel(%x,%d)(%x,%x)"), aWalker, iState, iWalker, iStreamGen);
+#endif
+
+ if (aWalker==iWalker)
+ {
+ switch (iState)
+ {
+ case ELoading:
+ case EPlaying:
+ case EStreamDecoding:
+ iLoadUtil->Cancel();
+ break;
+ case ESaving:
+ iSaveUtil->Cancel();
+ break;
+ case EScaling:
+ case EScalingMask:
+ iScaler->Cancel();
+ break;
+ case ERotating:
+ case ERotatingMask:
+ iRotator->Cancel();
+ break;
+ case EStreamDecodeWait:
+ case EPlayingWait: // ignore scenario where we self complete - will not get here
+ case EFolderWait:
+ iTimer.Cancel();
+ break;
+ default:
+ ASSERT(EFalse); // unknown state or should not happen
+ }
+ }
+ else
+ {
+ ASSERT(aWalker==iStreamGen);
+ switch (iState)
+ {
+ case EStreamOpening:
+ case EStreamWaitForDetails:
+ case EStreamWaitAndContinue:
+ case EStreamDecoding:
+ case EStreamDecodeWait:
+ case EStreamWaitForFirstFrame:
+ iStreamTimer.Cancel();
+ break;
+ default:
+ ASSERT(EFalse); // unknown state or should not happen
+ }
+ }
+ }
+
+void CVideoAppUi::HandleRunError(CVideoWalker* /*aWalker*/, TInt aError)
+ {
+ Cancel();
+ iEikonEnv->BusyMsgCancel();
+ iEikonEnv->HandleError(aError);
+ ASSERT(iState == EIdle);
+ }
+
+void CVideoAppUi::StreamOpenFrameIfPosL()
+ {
+ if (iFrameNumber >= iLoadUtil->FrameCount())
+ {
+ // Continue processing headers if necessary and only if we are not in the middle of an image conversion.
+ ASSERT(!iLoadUtil->IsImageHeaderProcessingComplete()); // should not be reading more than we need to know
+ iLoadUtil->ContinueProcessingHeaderL();
+ }
+
+ if (iFrameNumber >= iLoadUtil->FrameCount())
+ {
+ if (iLoadUtil->IsImageHeaderProcessingComplete())
+ {
+ Cancel(); // other AO could still be busy if there were bytes after last frame data
+ iEikonEnv->BusyMsgCancel();
+ iState = EIdle;
+ }
+ else
+ {
+ // not yet reached the frame header
+ iState = EStreamWaitForDetails;
+ if (!iStreamGen->IsActive())
+ // this shuld cope with reaching end of stream prematurely :
+ User::LeaveIfError(ExtendStreamBuffer());
+ }
+ }
+ else
+ {
+ if ((iStreamBuffer.Length()<iStreamBuffer.MaxLength()) && !iStreamGen->IsActive())
+ User::LeaveIfError(ExtendStreamBuffer()); // "new data has arrived"
+ ASSERT(iSourceHasGrown);
+ StartFrameOpen(EStreamDecoding);
+ iSourceHasGrown = EFalse;
+ }
+ ASSERT(iState==EIdle||iStreamBuffer.Length()==iStreamBuffer.MaxLength()||iStreamGen->IsActive()); // either we've finished, reached the end or we expect more data
+ }
+
+void CVideoAppUi::SetFrameSizeAndPosL(const TRect& aFrameRect,const TSize& aOverallSize)
+ {
+ TRect zoomedFrame(aFrameRect);
+ TSize zoomedSize(aOverallSize);
+ TSize zoomedOverallSize(iOverallSize); // effectively size on frame 0
+ if (aOverallSize.iWidth == 0 || aOverallSize.iHeight == 0)
+ zoomedSize = aFrameRect.Size();
+
+ if ( iUseExtensions )
+ {
+ // using PREQ1630 extensions
+ TInt err = iLoadUtil->GetDestinationSize(zoomedSize,iFrameNumber);
+ if ( err != KErrNone )
+ {
+ TBuf<256> buf;
+ buf.Format(_L("GetDestinationSize Error %d"),err);
+ iEikonEnv->InfoMsg(buf);
+ }
+
+ User::LeaveIfError(iFrame.Resize(zoomedSize));
+ }
+ else
+ {
+ if (iZoomFactor > 0)
+ {
+ zoomedFrame.iTl.iX <<= iZoomFactor;
+ zoomedFrame.iTl.iY <<= iZoomFactor;
+ zoomedFrame.iBr.iX <<= iZoomFactor;
+ zoomedFrame.iBr.iY <<= iZoomFactor;
+ zoomedSize.iWidth <<= iZoomFactor;
+ zoomedSize.iHeight <<= iZoomFactor;
+ zoomedOverallSize.iWidth <<= iZoomFactor;
+ zoomedOverallSize.iHeight <<= iZoomFactor;
+ }
+ else if (iZoomFactor < 0)
+ {
+ const TInt absZoomFactor = -iZoomFactor;
+#if defined(__USE_PURE_SCALING)
+ const TInt roundingFactor = 0; // set 0 to get pure scaling
+#else
+ const TInt roundingFactor = (1 << absZoomFactor) - 1;
+#endif
+ zoomedFrame.iTl.iX = (zoomedFrame.iTl.iX) >> absZoomFactor;
+ zoomedFrame.iTl.iY = (zoomedFrame.iTl.iY) >> absZoomFactor;
+ // zoomedFrame.iBr.iX = (zoomedFrame.iBr.iX + roundingFactor) >> absZoomFactor;
+ // zoomedFrame.iBr.iY = (zoomedFrame.iBr.iY + roundingFactor) >> absZoomFactor;
+
+ zoomedSize.iWidth = (zoomedSize.iWidth + roundingFactor) >> absZoomFactor;
+ zoomedSize.iHeight = (zoomedSize.iHeight + roundingFactor) >> absZoomFactor;
+
+ zoomedFrame.iBr = zoomedFrame.iTl + zoomedSize;
+
+ zoomedOverallSize.iWidth = (zoomedOverallSize.iWidth + roundingFactor) >> absZoomFactor;
+ zoomedOverallSize.iHeight = (zoomedOverallSize.iHeight + roundingFactor) >> absZoomFactor;
+ }
+
+#if !defined(__CLEAR_BITMAPS_FIRST)
+ if (iFrame.SizeInPixels() != zoomedFrame.Size())
+#endif
+ {
+#if defined(__CLEAR_BITMAPS_FIRST)
+ // resize via 0 so that we clear original
+ User::LeaveIfError(iFrame.Resize(TSize(0,0)));
+#endif
+ User::LeaveIfError(iFrame.Resize(zoomedSize));
+ }
+ }
+
+ if (iMask.Handle())
+ {
+ if (iMask.SizeInPixels() != zoomedFrame.Size())
+ User::LeaveIfError(iMask.Resize(zoomedSize));
+ #if defined(__CLEAR_BITMAPS_FIRST)
+ // set mask to black, so it is opaque and by default nothing is drawn
+ CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(&iMask);
+ CleanupStack::PushL(device);
+ CFbsBitGc* bmGc = CFbsBitGc::NewL();
+ CleanupStack::PushL(bmGc);
+ bmGc->Activate(device);
+ bmGc->SetPenStyle(CGraphicsContext::ENullPen);
+ bmGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ bmGc->SetBrushColor(KRgbBlack);
+ const TRect drawRect(TPoint(0,0), zoomedSize);
+ bmGc->DrawRect(drawRect);
+ CleanupStack::PopAndDestroy(2);
+ #endif
+ }
+
+ iImageDisplaySize = zoomedSize;
+ iOffset = zoomedFrame.iTl;
+
+ ASSERT(iMask.Handle()==0 || iFrame.SizeInPixels()==iMask.SizeInPixels()); // if mask must be same size
+ }
+
+void CVideoAppUi::ReplaceNewlinesWithLineBreaks(TDes& aText)
+ {
+ TInt pos=0;
+
+ for (;;)
+ {
+ if (pos >= aText.Length()) // will occur if last character in comment is new line
+ break;
+ const TPtrC restOfText(aText.Mid(pos));
+ TInt posOfNextNewLine = restOfText.Locate(TChar('\n'));
+ if (posOfNextNewLine<0) // no more new lines in text
+ break;
+ posOfNextNewLine += pos; // position relative to whole descriptor
+ aText[posOfNextNewLine] = CEditableText::ELineBreak;
+ pos = posOfNextNewLine + 1; // next cycle, start at next character
+ }
+ }
+
+// update crop region
+void CVideoAppUi::UpdateClippingRect(TUint code)
+ {
+ TFrameInfo frameInfo;
+ if ( iLoadUtil )
+ {
+ switch (code)
+ {
+ case EKeyLeftArrow:
+ iClippingRect.Move(-Min(iClippingRect.Width(),iClippingRect.iTl.iX),0);
+ break;
+ case EKeyRightArrow:
+ {
+ const TFrameInfo& frameInfo = iLoadUtil->FrameInfo(iFrameNumber);
+ iClippingRect.Move(Min(iClippingRect.Width(),frameInfo.iOverallSizeInPixels.iWidth-iClippingRect.iBr.iX),0);
+ }
+ break;
+ case EKeyUpArrow:
+ iClippingRect.Move(0,-Min(iClippingRect.Height(),iClippingRect.iTl.iY));
+ break;
+ case EKeyDownArrow:
+ {
+ const TFrameInfo& frameInfo = iLoadUtil->FrameInfo(iFrameNumber);
+ iClippingRect.Move(0,Min(iClippingRect.Height(),frameInfo.iOverallSizeInPixels.iHeight-iClippingRect.iBr.iY));
+ }
+ break;
+ }
+ }
+ LoadFileL();
+ }
+//
+// CVideoAppView
+//
+
+CVideoAppView* CVideoAppView::NewL(const TRect& aRect)
+ {
+ CVideoAppView* self = new (ELeave) CVideoAppView;
+ CleanupStack::PushL(self);
+ self->ConstructL(aRect);
+ CleanupStack::Pop();
+ return self;
+ }
+
+CVideoAppView::CVideoAppView():
+ CCoeControl()
+ {}
+
+void CVideoAppView::ConstructL(const TRect& /*aRect*/)
+ {
+ CreateWindowL();
+#if defined(__WINS__)
+ Window().SetRequiredDisplayMode(SystemGc().Device()->DisplayMode());
+#endif
+ iDisplayMode = Window().DisplayMode();
+ EnableDragEvents();
+ SetExtentToWholeScreen();
+
+ iBmBuffer = new (ELeave) CWsBitmap(iCoeEnv->WsSession());
+ ActivateL();
+ }
+
+CVideoAppView::~CVideoAppView()
+ {
+ delete iBmGc;
+ delete iBmDevice;
+ delete iBmBuffer;
+ }
+
+void CVideoAppView::Draw(const TRect& aRect) const
+ {
+ CWindowGc& gc = SystemGc();
+ TRect drawRect=Rect();
+
+ ASSERT(!iBitmapValid || iBmRect.Size() == iBmBuffer->SizeInPixels()); // either bitmap not valid or size of bmrect is same as the buffer
+
+ if (iBitmapValid)
+ {
+ // if the required rect includes some background, then draw it
+ // check is to see if the passed aRect is a pure subset of the bitmap rect
+ TRect intersection(aRect);
+ intersection.Intersection(iBmRect);
+ if (intersection != aRect)
+ {
+ gc.SetPenStyle(CGraphicsContext::ENullPen); // solid background rect
+ gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+ gc.SetBrushColor(KRgbWhite);
+ gc.DrawRect(drawRect);
+ TRect frame(iBmRect); // draw a frame one pixel larger than bitmap
+ frame.Grow(1,1);
+ gc.SetBrushStyle(CGraphicsContext::ENullBrush);
+ gc.SetPenStyle(CGraphicsContext::ESolidPen);
+ gc.DrawRect(frame);
+ }
+ // now if there is some bitmap to be drawn...
+ if (!intersection.IsEmpty())
+ {
+ gc.BitBlt(iBmRect.iTl, iBmBuffer);
+ }
+ }
+ else
+ {
+ gc.Clear();
+ drawRect.Shrink(10,10);
+ gc.DrawRect(drawRect);
+ gc.DrawLine(drawRect.iTl,drawRect.iBr);
+ gc.DrawLine(TPoint(drawRect.iTl.iX,drawRect.iBr.iY),TPoint(drawRect.iBr.iX,drawRect.iTl.iY));
+ }
+ }
+
+void CVideoAppView::Reset(TDrawNow aDrawNow)
+ {
+ iBmBuffer->Reset();
+ iBitmapValid = EFalse;
+ if (aDrawNow!=ENoDrawNow)
+ DrawNow();
+ }
+
+void CVideoAppView::DrawImage(CFbsBitmap* aBitmap, const TPoint& aOffset, TDrawNow aDrawNow)
+ {
+ DrawImage(aBitmap, NULL, aOffset, aDrawNow);
+ }
+
+void CVideoAppView::DrawImage(CFbsBitmap* aBitmap, CFbsBitmap* aMask, const TPoint& aOffset, TDrawNow aDrawNow)
+ {
+ ASSERT(iBitmapValid && iBmBuffer->Handle()); // should only be called when size setup properly
+ ASSERT(aMask==NULL || aBitmap->SizeInPixels()==aMask->SizeInPixels());
+ // if we have a mask, assumed to be the same size as the original
+
+ const TPoint screenOffset = iBmRect.iTl + aOffset; // relative to screen instead of iBmRect
+ const TRect bitmapRect (screenOffset, aBitmap->SizeInPixels()); // the rect for this bitmap
+
+#if defined(_DEBUG)
+ TRect intersection (bitmapRect); // check that this rect is same or smaller than the bitmap
+ ASSERT(iBmRect.Size() == iBmBuffer->SizeInPixels());
+ intersection.Intersection(iBmRect);
+ ASSERT(intersection==bitmapRect);
+#endif
+
+ // first draw to bitmap buffer
+ if (aMask)
+ iBmGc->BitBltMasked(aOffset, aBitmap, TRect(aBitmap->SizeInPixels()), aMask, EFalse);
+ else
+ iBmGc->BitBlt(aOffset, aBitmap);
+
+ // if required, also draw to screen
+ if (aDrawNow!=ENoDrawNow)
+ {
+ ActivateGc();
+ CWindowGc& gc = SystemGc();
+ if (aMask)
+ gc.BitBltMasked(screenOffset, aBitmap, TRect(aBitmap->SizeInPixels()), aMask, EFalse);
+ else
+ gc.BitBlt(screenOffset, aBitmap);
+ DeactivateGc();
+ }
+ }
+
+TBool CVideoAppView::ResizeL(const TSize& aNewSize, TBool aClear, TDrawNow aDrawNow)
+ {
+ //Resize iBmBuffer to iBmRect where iBmBuffer holds the aNewSize.
+ if(iBmRect.Size() != aNewSize)
+ {
+ iBmBuffer->Resize(iBmRect.Size());
+ }
+ ASSERT(!iBitmapValid || iBmRect.Size() == iBmBuffer->SizeInPixels()); // either bitmap not valid or size of bmrect is same as the buffer
+ if (iBitmapValid && aNewSize==iBmRect.Size())
+ {
+ // special cases where we don't actually modify the size
+ if (aDrawNow!=ENoDrawNow)
+ DrawNow();
+ return EFalse;
+ }
+
+ CFbsBitmap* tempBuffer = NULL;
+
+ TBool preserveOrig = !aClear && iBitmapValid;
+
+ if (preserveOrig)
+ {
+ // tempBuffer becomes copy of original
+ tempBuffer = new (ELeave) CWsBitmap(iCoeEnv->WsSession());
+ CleanupStack::PushL(tempBuffer);
+ User::LeaveIfError(tempBuffer->Duplicate(iBmBuffer->Handle()));
+ }
+
+ ResizeBufferL(aNewSize, iDisplayMode);
+ // resize bitmap
+
+ iBitmapValid = ETrue;
+ iBmRect.SetRect(iBmRect.iTl, aNewSize); // rect with same Tl but new size
+ ASSERT(iBmRect.Size() == iBmBuffer->SizeInPixels()); // check resized bitmap OK
+
+ if (preserveOrig)
+ {
+ // draw original back at new size
+ EnsureSizeInTwipsSet(tempBuffer);
+ EnsureSizeInTwipsSet(iBmBuffer);
+ iBmGc->DrawBitmap(TPoint(0,0), tempBuffer);
+ CleanupStack::PopAndDestroy(); // tempBuffer
+ }
+ else
+ Clear(EFalse, ENoDrawNow); // get background correct colour
+
+ if (aDrawNow!=ENoDrawNow)
+ DrawNow();
+
+ return ETrue;
+ }
+
+void CVideoAppView::ResizeBufferL(const TSize& aNewSize, TDisplayMode aDisplayMode)
+ {
+ delete iBmGc; iBmGc = NULL;
+ delete iBmDevice; iBmDevice = NULL;
+ User::LeaveIfError(iBmBuffer->Create(aNewSize, aDisplayMode));
+ iBmDevice = CFbsBitmapDevice::NewL(iBmBuffer);
+ iBmGc = CFbsBitGc::NewL();
+ iBmGc->Activate(iBmDevice);
+ }
+
+void CVideoAppView::EnsureSizeInTwipsSet(CFbsBitmap* aBitmap) const
+ {
+ // ensure the bitmap has twips size set - this allows us to use DrawBitmap
+ // note this does not itself resize the bitmap - size in pixels remains unchanged
+ TSize size = aBitmap->SizeInTwips();
+ ASSERT(size.iWidth==0 && size.iHeight==0 || size.iWidth>0 && size.iHeight>0);
+ // assumption that if we've set the size it is properly formatted
+ if (size==TSize(0,0))
+ {
+ CWsScreenDevice *const screenDevice = iEikonEnv->ScreenDevice();
+ size = aBitmap->SizeInPixels();
+ size.iWidth = screenDevice->HorizontalTwipsToPixels(size.iWidth);
+ size.iHeight = screenDevice->VerticalTwipsToPixels(size.iHeight);
+ aBitmap->SetSizeInTwips(size);
+ }
+ }
+
+void CVideoAppView::Clear(TBool aClearFull, TDrawNow aDrawNow)
+ {
+ // if we have a bitmap buffer clear that. Otherwise clear the whole screen depending
+ // on aClearFull
+ if (iBmGc)
+ {
+ iBmGc->Reset();
+ iBmGc->SetPenStyle(CGraphicsContext::ENullPen);
+ iBmGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ iBmGc->SetBrushColor(iBackgroundColor);
+ iBmGc->Clear();
+ }
+ if (aDrawNow!=ENoDrawNow)
+ {
+ if (aClearFull)
+ DrawNow();
+ else
+ {
+ ActivateGc();
+ CWindowGc& gc = SystemGc();
+ RWindow& window = Window();
+ window.Invalidate(iBmRect);
+ window.BeginRedraw(iBmRect);
+ gc.SetPenStyle(CGraphicsContext::ENullPen);
+ gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+ gc.SetBrushColor(iBackgroundColor);
+ gc.Clear();
+ window.EndRedraw();
+ DeactivateGc();
+ }
+ }
+ }
+
+
+void CVideoAppView::MoveBy(const TPoint& aRelMove, TDrawNow aDrawNow)
+ {
+ iBmRect.Move(aRelMove);
+
+ if (aDrawNow!=ENoDrawNow)
+ DrawNow();
+ }
+
+void CVideoAppView::Center(TDrawNow aDrawNow)
+ {
+ ASSERT(iBitmapValid && iBmRect.Size() == iBmBuffer->SizeInPixels()); // should only be called when size setup properly
+
+#ifdef CENTRE_IMAGE
+ const TPoint center = Rect().Center();
+ const TSize bitmapSize = iBmRect.Size();
+ const TPoint requiredTl (center.iX-bitmapSize.iWidth/2, center.iY-bitmapSize.iHeight/2);
+ const TRect newRect(requiredTl, bitmapSize);
+ iBmRect = newRect;
+#endif
+
+ ASSERT(iBitmapValid && iBmRect.Size() == iBmBuffer->SizeInPixels()); // checked worked
+
+ if (aDrawNow!=ENoDrawNow)
+ DrawNow();
+ }
+
+TBool CVideoAppView::SetBackgroundColor(const TRgb& aColor, TDrawNow aDrawNow)
+ {
+ TBool changed = iBackgroundColor!=aColor;
+
+ iBackgroundColor = aColor;
+
+ if (aDrawNow!=ENoDrawNow)
+ DrawNow();
+
+ return changed;
+ }
+
+void CVideoAppView::SetDisplayModeL(TDisplayMode aDisplayMode, CWsBitmap* aFrame, TDrawNow aDrawNow)
+ {
+
+ TBool change=aDisplayMode!=iDisplayMode;
+
+ iDisplayMode = aDisplayMode;
+
+ if (iBitmapValid && change)
+ {
+ ASSERT(iBmBuffer->Handle());
+
+ // temp buffer becomes copy of original
+ CFbsBitmap* tempBuffer = new (ELeave) CWsBitmap(iCoeEnv->WsSession());
+ CleanupStack::PushL(tempBuffer);
+ User::LeaveIfError(tempBuffer->Duplicate(iBmBuffer->Handle()));
+
+ ASSERT(iBmRect.Size()==iBmBuffer->SizeInPixels()); // should be the same
+ ResizeBufferL(iBmBuffer->SizeInPixels(), iDisplayMode);
+ // change bitmap
+
+ // bitblt original back
+ iBmGc->BitBlt(TPoint(0,0), tempBuffer);
+ CleanupStack::PopAndDestroy(); // tempBuffer
+
+ aFrame->Reset(); // reset the frame
+ aFrame->Duplicate(iBmBuffer->Handle()); // duplicate the aFrame bitmap handle
+ }
+
+ Window().SetRequiredDisplayMode(iDisplayMode);
+
+ if (aDrawNow!=ENoDrawNow)
+ DrawNow();
+ }
+
+//
+// CVideoDisplayModeDialog
+//
+
+// list of supported display modes (it matches r_video_display_mode_array in TImageViewer.rss)
+
+const TDisplayMode KDispMode[] = { EGray2, EGray4, EGray16, EGray256, EColor16, EColor256, EColor4K, EColor64K, EColor16M, EColor16MU, EColor16MA, EColor16MAP };
+const TInt KNumDispMode = sizeof(KDispMode) / sizeof(KDispMode[0]);
+
+CVideoDisplayModeDialog::CVideoDisplayModeDialog(TDisplayMode& aDisplayMode,TBool& aUseNativeDisplayMode):
+ iDisplayMode(aDisplayMode), iUseNativeDisplayMode(aUseNativeDisplayMode)
+ {}
+
+void CVideoDisplayModeDialog::PreLayoutDynInitL()
+ {
+ TInt choice = -1;
+
+ for (TInt index=0; index<KNumDispMode; index++)
+ {
+ if (KDispMode[index]==iDisplayMode)
+ {
+ choice = index;
+ break;
+ }
+ }
+
+ SetCheckBoxState(EVideoIdUseImageNativeMode, iUseNativeDisplayMode ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+
+ ASSERT(choice>=0); // should always match something
+ SetChoiceListCurrentItem(EVideoIdDisplayMode,choice);
+ }
+
+TBool CVideoDisplayModeDialog::OkToExitL(TInt /*aButtonId*/)
+ {
+ const TInt chosenIndex = ChoiceListCurrentItem(EVideoIdDisplayMode);
+ ASSERT(chosenIndex<KNumDispMode);
+ iDisplayMode = KDispMode[chosenIndex];
+ iUseNativeDisplayMode = CheckBoxState(EVideoIdUseImageNativeMode) == CEikButtonBase::ESet ? ETrue : EFalse;
+ return ETrue;
+ }
+
+//
+// CVideoBackgroundColorDialog
+//
+
+CVideoBackgroundColorDialog::CVideoBackgroundColorDialog(TInt& aColor16, TBool& aOverride):
+ iColor16(aColor16), iOverride(aOverride)
+ {}
+
+void CVideoBackgroundColorDialog::PreLayoutDynInitL()
+ {
+ CEikButtonBase::TState state = iOverride ? CEikButtonBase::ESet : CEikButtonBase::EClear;
+ SetCheckBoxState(EVideoIdOverrideBackgroundColor, state);
+ SetChoiceListCurrentItem(EVideoIdBackgroundColor,iColor16);
+ if (!iOverride)
+ SetLineDimmedNow(EVideoIdBackgroundColor,ETrue);
+ }
+
+TBool CVideoBackgroundColorDialog::OkToExitL(TInt /*aButtonId*/)
+ {
+ iColor16 = ChoiceListCurrentItem(EVideoIdBackgroundColor);
+ CEikButtonBase::TState state = CheckBoxState(EVideoIdOverrideBackgroundColor);
+ iOverride = state != CEikButtonBase::EClear;
+ return ETrue;
+ }
+
+void CVideoBackgroundColorDialog::HandleControlStateChangeL(TInt aControlId)
+ {
+ if (aControlId == EVideoIdOverrideBackgroundColor)
+ {
+ CEikButtonBase::TState state = CheckBoxState(EVideoIdOverrideBackgroundColor);
+ TBool isSet = state != CEikButtonBase::EClear;
+ SetLineDimmedNow(EVideoIdBackgroundColor,!isSet);
+ }
+ }
+
+//
+// CVideoCurrentFrameDialog
+//
+
+CVideoCurrentFrameDialog::CVideoCurrentFrameDialog(TInt& aCurrentFrame,TInt aNumberOfFrames):
+ iCurrentFrame(aCurrentFrame),
+ iNumberOfFrames(aNumberOfFrames)
+ {}
+
+void CVideoCurrentFrameDialog::PreLayoutDynInitL()
+ {
+ SetNumberEditorValue(EVideoIdNumberOfFrames,iNumberOfFrames);
+ SetLineDimmedNow(EVideoIdNumberOfFrames,ETrue);
+ const TInt lastFrame = iNumberOfFrames - 1;
+ SetNumberEditorMinAndMax(EVideoIdCurrentFrameNumber,0,lastFrame);
+ SetNumberEditorValue(EVideoIdCurrentFrameNumber,Min(iCurrentFrame,lastFrame));
+ }
+
+TBool CVideoCurrentFrameDialog::OkToExitL(TInt /*aButtonId*/)
+ {
+ iCurrentFrame = NumberEditorValue(EVideoIdCurrentFrameNumber);
+ return ETrue;
+ }
+
+//
+// CVideoSaveAsDialog
+//
+
+CVideoSaveAsDialog::CVideoSaveAsDialog(TDes* aFileName,TFileSaveInfo& aSaveInfo,RArray<TInt>& aEncodeOperations,TBool& aCreateThumbnail,TBool& aSaveAsEXIF):
+ CEikFileSaveAsDialog(aFileName),
+ iSaveInfo(aSaveInfo),
+ iEncodeOperations(aEncodeOperations),
+ iCreateThumbnail(&aCreateThumbnail),
+ iSaveAsEXIF(&aSaveAsEXIF)
+ {}
+
+void CVideoSaveAsDialog::PreLayoutDynInitL()
+ {
+ SetTypeL();
+ SetCheckBoxState(EVideoIdCreateThumbnailChbx, *iCreateThumbnail ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+ SetCheckBoxState(EVideoIdSaveAsEXIFChbx, *iSaveAsEXIF ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+
+ CEikFileSaveAsDialog::PreLayoutDynInitL();
+ }
+
+void CVideoSaveAsDialog::SetTypeL()
+ {
+ const TUid imageType = iSaveInfo.iImageTypeUid;
+
+ if(imageType == KImageTypeBMPUid)
+ SetLabelL(EVideoIdSaveAsFormat,R_VIDEO_FILE_FORMAT_BMP);
+ else if(imageType == KImageTypeGIFUid)
+ SetLabelL(EVideoIdSaveAsFormat,R_VIDEO_FILE_FORMAT_GIF);
+ else if(imageType == KImageTypeJPGUid)
+ {
+ if ( *iSaveAsEXIF )
+ {
+ SetLabelL(EVideoIdSaveAsFormat,R_VIDEO_FILE_FORMAT_EXIF);
+ }
+ else
+ {
+ SetLabelL(EVideoIdSaveAsFormat,R_VIDEO_FILE_FORMAT_JPEG);
+ }
+ }
+ else if(imageType == KImageTypeMBMUid)
+ SetLabelL(EVideoIdSaveAsFormat,R_VIDEO_FILE_FORMAT_MBM);
+ else if(imageType == KImageTypePNGUid)
+ SetLabelL(EVideoIdSaveAsFormat,R_VIDEO_FILE_FORMAT_PNG);
+ else
+ SetLabelL(EVideoIdSaveAsFormat,R_VIDEO_FILE_FORMAT_CUSTOM);
+
+ }
+
+void CVideoSaveAsDialog::HandleControlStateChangeL(TInt aControlId)
+ {
+ if (aControlId == EVideoIdSaveAsEXIFChbx)
+ {
+ *iSaveAsEXIF = CheckBoxState(EVideoIdSaveAsEXIFChbx) == CEikButtonBase::ESet ? ETrue : EFalse;
+ SetTypeL();
+ }
+ }
+
+TBool CVideoSaveAsDialog::OkToExitL(TInt aButtonId)
+ {
+ if (aButtonId == EVideoIdSaveAsFormat)
+ {
+ CEikDialog* dialog = new(ELeave) CVideoFormatDialog(iSaveInfo);
+ if (dialog->ExecuteLD(R_VIDEO_FILE_FORMAT_DIALOG))
+ SetTypeL();
+
+ return EFalse;
+ }
+ else if (aButtonId == EVideoIdEncodeOperations)
+ {
+ CEikDialog* dialog = new(ELeave) CExtensionOptionsDialog(iEncodeOperations);
+ dialog->ExecuteLD(R_VIDEO_ENCODER_EXTENSION_DIALOG);
+ return EFalse;
+ }
+ else if (aButtonId == EEikBidOk)
+ {
+ *iCreateThumbnail = CheckBoxState(EVideoIdCreateThumbnailChbx) == CEikButtonBase::ESet ? ETrue : EFalse;
+ *iSaveAsEXIF = CheckBoxState(EVideoIdSaveAsEXIFChbx) == CEikButtonBase::ESet ? ETrue : EFalse;
+ }
+
+ return CEikFileSaveAsDialog::OkToExitL(aButtonId);
+ }
+
+SEikControlInfo CVideoSaveAsDialog::CreateCustomControlL(TInt /*aControlType*/)
+ {
+ /* never called */
+ SEikControlInfo info;
+ info.iTrailerTextId = 0;
+ info.iFlags = 0;
+ info.iControl = new (ELeave) CEikTextListBox;
+ return info;
+ }
+//
+// CVideoFormatDialog
+//
+
+CVideoFormatDialog::CVideoFormatDialog(TFileSaveInfo& aSaveInfo):
+ iSaveInfo(aSaveInfo)
+ {}
+
+void CVideoFormatDialog::PreLayoutDynInitL()
+ {
+ CEikChoiceList* formatList = STATIC_CAST(CEikChoiceList*,Control(EVideoIdFileFormatType));
+
+ //Add the available encoders to the dialog
+ iEncoderList = CPluginInfoArray::NewL();
+ formatList->SetArrayL(iEncoderList); //ownership of iEncoderList passed to dialog
+
+ const TInt noOfEncoders = iEncoderList->MdcaCount();
+ if(noOfEncoders == 0)
+ User::Leave(KErrNotFound);
+
+ //Find the index for the selected encoder (via ImageTypeUid)
+ //if it is not found use the first
+ TInt index;
+ for(index=noOfEncoders-1; index > 0; index--)
+ {
+ if(iEncoderList->ImageType(index) == iSaveInfo.iImageTypeUid)
+ break;
+ }
+ iSaveInfo.iImageTypeUid = iEncoderList->ImageType(index);
+
+ SetChoiceListCurrentItem(EVideoIdFileFormatType,index);
+ SetChoiceListCurrentItem(EVideoIdFileFormatBpp,iSaveInfo.iBpp);
+ SetChoiceListCurrentItem(EVideoIdFileFormatColor,iSaveInfo.iColor);
+ SetNumberEditorValue(EVideoIdFileFormatFactor,iSaveInfo.iQualityFactor);
+ SetChoiceListCurrentItem(EVideoIdFileFormatSampling,iSaveInfo.iSampling);
+ SetChoiceListCurrentItem(EVideoIdFileFormatCompression,iSaveInfo.iCompression);
+
+ ValidateControlState();
+ }
+
+void CVideoFormatDialog::HandleControlStateChangeL(TInt /*aControlId*/)
+ {
+ ValidateControlState();
+ }
+
+void CVideoFormatDialog::ValidateControlState()
+ {
+ TInt type = ChoiceListCurrentItem(EVideoIdFileFormatType);
+ TInt bpp = ChoiceListCurrentItem(EVideoIdFileFormatBpp);
+ TInt color = ChoiceListCurrentItem(EVideoIdFileFormatColor);
+ TInt compression = ChoiceListCurrentItem(EVideoIdFileFormatCompression);
+
+ TBool bppVisible = ETrue;
+ TBool colorVisible = ETrue;
+ TBool factorVisible = EFalse;
+ TBool samplingVisible = EFalse;
+ TBool compressionVisible = EFalse;
+
+
+ const TUid imageType = iEncoderList->ImageType(type);
+
+ if(imageType == KImageTypeBMPUid)
+ {
+ colorVisible = EFalse;
+ if (bpp == 1)
+ bpp = 2;
+ else if ((bpp > 3) && (bpp < 6))
+ bpp = 6;
+ else if (bpp > 6)
+ bpp = 0;
+ }
+ else if(imageType == KImageTypeGIFUid)
+ {
+ bppVisible = EFalse;
+ colorVisible = EFalse;
+ }
+ else if(imageType == KImageTypeJPGUid)
+ {
+ bppVisible = EFalse;
+ factorVisible = ETrue;
+ if (color)
+ samplingVisible = ETrue;
+ }
+ else if(imageType == KImageTypeMBMUid)
+ {
+ if (color == 0)
+ {
+ if (bpp > 3)
+ bpp = 0;
+ }
+ else
+ {
+ if (bpp < 2)
+ bpp = 2;
+ }
+ }
+ else if(imageType == KImageTypePNGUid)
+ {
+ if ((bpp > 3) && (bpp < 6))
+ bpp = 6;
+ else if (bpp > 6)
+ bpp = 0;
+ compressionVisible = ETrue;
+ }
+ else //Custom encoder
+ {
+ bppVisible = EFalse;
+ colorVisible = EFalse;
+ }
+
+ SetChoiceListCurrentItem(EVideoIdFileFormatBpp,bpp);
+ SetChoiceListCurrentItem(EVideoIdFileFormatColor,color);
+ SetChoiceListCurrentItem(EVideoIdFileFormatCompression,compression);
+
+ MakeLineVisible(EVideoIdFileFormatBpp,bppVisible);
+ MakeLineVisible(EVideoIdFileFormatColor,colorVisible);
+ MakeLineVisible(EVideoIdFileFormatFactor,factorVisible);
+ MakeLineVisible(EVideoIdFileFormatSampling,samplingVisible);
+ MakeLineVisible(EVideoIdFileFormatCompression,compressionVisible);
+ }
+
+TBool CVideoFormatDialog::OkToExitL(TInt /*aButtonId*/)
+ {
+ TInt type = ChoiceListCurrentItem(EVideoIdFileFormatType);
+ iSaveInfo.iImageTypeUid = iEncoderList->ImageType(type);
+ iSaveInfo.iBpp = ChoiceListCurrentItem(EVideoIdFileFormatBpp);
+ iSaveInfo.iColor = ChoiceListCurrentItem(EVideoIdFileFormatColor);
+ iSaveInfo.iQualityFactor = NumberEditorValue(EVideoIdFileFormatFactor);
+ iSaveInfo.iSampling = ChoiceListCurrentItem(EVideoIdFileFormatSampling);
+ iSaveInfo.iCompression = ChoiceListCurrentItem(EVideoIdFileFormatCompression);
+
+ return ETrue;
+ }
+
+CDecoderOptionsDialog::CDecoderOptionsDialog(TUint& aOptions):iOptions(aOptions)
+ {
+ }
+
+ // from CEikDialog
+void CDecoderOptionsDialog::PreLayoutDynInitL()
+ {
+ SetCheckBoxState(EVideoIdUseThreadForDecoder, iOptions&CImageDecoder::EOptionAlwaysThread ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+ SetCheckBoxState(EVideoIdDecoderDisableDithering, iOptions&CImageDecoder::EOptionNoDither ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+ SetCheckBoxState(EVideoIdDecoderAutogenMask, iOptions&CImageDecoder::EAllowGeneratedMask ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+ SetCheckBoxState(EVideoIdDecodeHighSpeedDecode, iOptions&CImageDecoder::EPreferFastDecode ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+ SetCheckBoxState(EVideoIdAutoRotateDecode, iOptions&CImageDecoder::EOptionAutoRotate ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+ }
+
+TBool CDecoderOptionsDialog::OkToExitL(TInt /*aButtonId*/)
+ {
+ iOptions = CheckBoxState(EVideoIdUseThreadForDecoder) == CEikButtonBase::ESet ? CImageDecoder::EOptionAlwaysThread : 0;
+ iOptions|= CheckBoxState(EVideoIdDecoderDisableDithering) == CEikButtonBase::ESet ? CImageDecoder::EOptionNoDither : 0;
+ iOptions|= CheckBoxState(EVideoIdDecoderAutogenMask) == CEikButtonBase::ESet ? CImageDecoder::EAllowGeneratedMask : 0;
+ iOptions|= CheckBoxState(EVideoIdDecodeHighSpeedDecode) == CEikButtonBase::ESet ? CImageDecoder::EPreferFastDecode : 0;
+ iOptions|= CheckBoxState(EVideoIdAutoRotateDecode) == CEikButtonBase::ESet ? CImageDecoder::EOptionAutoRotate : 0;
+
+ return ETrue;
+ }
+
+CExtensionOptionsDialog::CExtensionOptionsDialog(TRect& aClippingRect,
+ RArray<TInt>& aOperations,
+ TInt& aScalingCoefficient,
+ TImageConvScaler::TScalerQuality& aScalingQuality,
+ TBool& aLockAspectRatio)
+ : iClippingRect(&aClippingRect), iOperations(aOperations), iScalingCoefficient(&aScalingCoefficient),
+ iScalingQuality(&aScalingQuality), iLockAspectRatio(&aLockAspectRatio)
+ {
+ iSelectedOperations = new (ELeave) CDesCArrayFlat(20);
+ }
+
+CExtensionOptionsDialog::CExtensionOptionsDialog(RArray<TInt>& aOperations)
+ : iOperations(aOperations)
+ {
+ iSelectedOperations = new (ELeave) CDesCArrayFlat(20);
+ iOperationOnly = ETrue;
+ }
+
+void CExtensionOptionsDialog::PageChangedL(TInt /*aPageId*/)
+ {
+ // enable/disable add and clear buttons which are only enabled on Operation Page
+// The lines below panic on teh Control call. Looks like a dialog button is not a control
+// Control(EVideoIdAdd)->SetDimmed(aPageId != EDecoderExtensionOperationPage);
+// Control(EVideoIdClear)->SetDimmed(aPageId != EDecoderExtensionOperationPage);
+ }
+
+ // from CEikDialog
+void CExtensionOptionsDialog::PreLayoutDynInitL()
+ {
+ if ( !iOperationOnly )
+ {
+ // crop rect number edits
+ static_cast<CEikNumberEditor*>(Control(EVideoIdCropTopLeftX))->SetNumber(iClippingRect->iTl.iX);
+ static_cast<CEikNumberEditor*>(Control(EVideoIdCropTopLeftY))->SetNumber(iClippingRect->iTl.iY);
+ static_cast<CEikNumberEditor*>(Control(EVideoIdCropWidth))->SetNumber(iClippingRect->Width());
+ static_cast<CEikNumberEditor*>(Control(EVideoIdCropHeight))->SetNumber(iClippingRect->Height());
+
+ /* scaling
+ coefficient number edit
+ quality choicelist
+ aspectratio checkbox
+ */
+ static_cast<CEikNumberEditor*>(Control(EVideoIdScaleCoeff))->SetNumber(*iScalingCoefficient);
+ static_cast<CEikChoiceList*>(Control(EVideoIdScaleQuality))->SetCurrentItem(*iScalingQuality);
+ SetCheckBoxState(EVideoIdScalePreserveAspect, *iLockAspectRatio ? CEikButtonBase::ESet : CEikButtonBase::EClear);
+ }
+
+ /* operations
+ fill selected operations
+ */
+ CEikTextListBox* selectOpsListBox = static_cast<CEikTextListBox*>(Control(EVideoIdSelectedOperations));
+
+ selectOpsListBox->CreateScrollBarFrameL();
+ selectOpsListBox->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOn);
+
+ operationName[0] = _L("0x01 | ERotation90DegreesClockwise");
+ operationName[1] = _L("0x02 | ERotation180DegreesClockwise");
+ operationName[2] = _L("0x04 | ERotation270DegreesClockwise");
+ operationName[3] = _L("0x08 | EMirrorHorizontalAxis");
+ operationName[4] = _L("0x10 | EMirrorVerticalAxis");
+
+ for (TInt i = 0; i < iOperations.Count(); i++)
+ {
+ if ( iOperations[i] > 0 )
+ {
+ TInt temp = iOperations[i];
+ TInt shiftCount = 0;
+ while ( temp )
+ {
+ temp = temp >> 1;
+ ++shiftCount;
+ }
+ iSelectedOperations->AppendL(operationName[shiftCount-1]);
+ }
+ }
+
+ selectOpsListBox->Model()->SetItemTextArray(iSelectedOperations);
+ selectOpsListBox->Model()->SetOwnershipType(ELbmDoesNotOwnItemArray);
+
+ }
+
+// DEF115967: Panic while editing Setup extensions Value
+void CExtensionOptionsDialog::PrepareForFocusTransitionL()
+ {
+ // The dialog will check for blank input in the control that
+ // has been edited. If it is blank the value 9999...9 will be
+ // placed there to ensure control->Number() returns something.
+ // There appears to be no way of getting a different value put
+ // in a blank control (IsBlank function is protected).
+
+ CEikDialog::PrepareForFocusTransitionL();
+ }
+
+
+SEikControlInfo CExtensionOptionsDialog::CreateCustomControlL(TInt /*aControlType*/)
+ {
+ /* never called */
+ SEikControlInfo info;
+ info.iTrailerTextId = 0;
+ info.iFlags = 0;
+ info.iControl = new (ELeave) CEikTextListBox;
+ return info;
+ }
+
+TBool CExtensionOptionsDialog::OkToExitL(TInt aButtonId)
+ {
+ TBool exit = EFalse;
+
+ switch ( aButtonId )
+ {
+ case EEikBidOk:
+ {
+ if ( !iOperationOnly )
+ {
+ // get crop rect
+ iClippingRect->iTl.iX = static_cast<CEikNumberEditor*>(Control(EVideoIdCropTopLeftX))->Number();
+ iClippingRect->iTl.iY = static_cast<CEikNumberEditor*>(Control(EVideoIdCropTopLeftY))->Number();
+ iClippingRect->SetWidth(static_cast<CEikNumberEditor*>(Control(EVideoIdCropWidth))->Number());
+ iClippingRect->SetHeight(static_cast<CEikNumberEditor*>(Control(EVideoIdCropHeight))->Number());
+
+ // get scaling
+ *iScalingCoefficient = static_cast<CEikNumberEditor*>(Control(EVideoIdScaleCoeff))->Number();
+ *iScalingQuality = static_cast<TImageConvScaler::TScalerQuality>
+ (static_cast<CEikChoiceList*>(Control(EVideoIdScaleQuality))->CurrentItem());
+ *iLockAspectRatio = (CheckBoxState(EVideoIdScalePreserveAspect) == CEikButtonBase::ESet) ? ETrue : EFalse;
+ }
+
+ // get operations
+ CTextListBoxModel * selectOpsModel = static_cast<CEikTextListBox*>(Control(EVideoIdSelectedOperations))->Model();
+ iOperations.Reset();
+ for (TInt i = 0; i < selectOpsModel->NumberOfItems(); i++)
+ {
+ TLex enumLex(selectOpsModel->ItemText(i).Mid(2,2)); // Hex value of enum
+ TUint operation = 0;
+ enumLex.Val(operation,EHex);
+ iOperations.Append(operation);
+ }
+ }
+ // deliberate fall through
+ case EEikBidCancel:
+ {
+ // iOperations fill up from iSeletedOperations
+ delete iSelectedOperations;
+ exit = ETrue;
+ }
+ break;
+
+ case EVideoIdAdd:
+ {
+ TInt currentItem = static_cast<CEikChoiceList*>(Control(EVideoIdOperations))->CurrentItem();
+ iSelectedOperations->AppendL(operationName[currentItem]);
+ CEikTextListBox* selectOpsListBox = static_cast<CEikTextListBox*>(Control(EVideoIdSelectedOperations));
+ selectOpsListBox->Model()->SetItemTextArray(iSelectedOperations);
+ selectOpsListBox->HandleItemAdditionL();
+ }
+ break;
+
+ case EVideoIdClear:
+ {
+ iSelectedOperations->Reset();
+ CEikTextListBox* selectOpsListBox = static_cast<CEikTextListBox*>(Control(EVideoIdSelectedOperations));
+ selectOpsListBox->Model()->SetItemTextArray(iSelectedOperations);
+ selectOpsListBox->HandleItemAdditionL();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return exit;
+ }
+
+//
+// CVideoWalker implementation
+//
+
+CVideoWalker* CVideoWalker::NewL(CVideoAppUi* aAppUi)
+ {
+ CVideoWalker* result = new (ELeave) CVideoWalker(aAppUi);
+ return result;
+ }
+
+CVideoWalker::CVideoWalker(CVideoAppUi* aAppUi):
+ CActive(CActive::EPriorityStandard),
+ iAppUi(aAppUi)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CVideoWalker::~CVideoWalker()
+ {
+ Cancel();
+ }
+
+// used when we need to pass status variable - simultaneously calls SetActive
+TRequestStatus& CVideoWalker::ActiveStatus()
+ {
+ SetActive();
+ return iStatus;
+ }
+
+// for completion ASAP on this
+void CVideoWalker::SelfComplete(TInt aError)
+ {
+ TRequestStatus* status = &ActiveStatus();
+ User::RequestComplete(status, aError);
+ }
+
+// calls AppUi->RunL() which is expected to handle the call
+void CVideoWalker::RunL()
+ {
+ iAppUi->RunL(this, iStatus.Int());
+ }
+
+// calls AppUi->DoCancel() which is expected to handle the call
+void CVideoWalker::DoCancel()
+ {
+ iAppUi->DoCancel(this);
+ }
+
+//
+// CVideoDocument
+//
+
+CVideoDocument::CVideoDocument(CEikApplication& aApp)
+ : CEikDocument(aApp)
+ {
+ }
+
+CEikAppUi* CVideoDocument::CreateAppUiL()
+ {
+ return new(ELeave) CVideoAppUi;
+ }
+
+//
+// CVideoApp
+//
+
+TUid CVideoApp::AppDllUid() const
+ {
+ return KUidTVideo;
+ }
+
+CApaDocument* CVideoApp::CreateDocumentL()
+ {
+ return new(ELeave) CVideoDocument(*this);
+ }
+
+
+//
+// Base factory function
+//
+
+#include <eikstart.h>
+LOCAL_C CApaApplication* NewApplication()
+ {
+ return new CVideoApp;
+ }
+
+//
+// EXE Entry point
+//
+
+GLDEF_C TInt E32Main()
+ {
+ return EikStart::RunApplication(NewApplication);
+ }
+