diff -r aaeeca1f15af -r e8d784ac1a4b scrsaver/scrsaverplugins/SlideshowPlugin/src/SlideshowSlideLoader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scrsaver/scrsaverplugins/SlideshowPlugin/src/SlideshowSlideLoader.cpp Wed Sep 01 12:30:40 2010 +0100 @@ -0,0 +1,286 @@ +/* +* Copyright (c) 2006 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: Loads a slide from file +* +*/ + + + +// INCLUDES +#include "SlideshowPluginUtils.h" +#include "SlideshowSlideLoader.h" + +// --------------------------------------------------------------------------- +// DivAndRoundUp +// --------------------------------------------------------------------------- +// +TInt DivAndRoundUp(const TInt aNumber, const TInt aDivider) + { + TInt result = aNumber / aDivider; + + if (aNumber % aDivider) + { + result += 1; + } + + return result; + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::NewL +// --------------------------------------------------------------------------- +// +CSlideshowSlideLoader* CSlideshowSlideLoader::NewL(CSlideshowSlide *aSlide) + { + CSlideshowSlideLoader * self = new (ELeave)CSlideshowSlideLoader(aSlide); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::ConstructL +// --------------------------------------------------------------------------- +// +void CSlideshowSlideLoader::ConstructL() + { + // Add this object to active scheduler + CActiveScheduler::Add(this); + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::CSlideshowSlideLoader +// --------------------------------------------------------------------------- +// +CSlideshowSlideLoader::CSlideshowSlideLoader(CSlideshowSlide *aSlide) + : CActive(CActive::EPriorityStandard),iSlide(aSlide) + { + // Empty + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::~CSlideshowSlideLoader +// --------------------------------------------------------------------------- +// +CSlideshowSlideLoader::~CSlideshowSlideLoader() + { + if(IsActive()) + { + Cancel(); + } + + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::DeleteDecoder +// --------------------------------------------------------------------------- +// +void CSlideshowSlideLoader::DeleteDecoder() + { + if(iDecoder) + { + delete iDecoder; + iDecoder = NULL; + } + + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::DoCancel +// --------------------------------------------------------------------------- +// +void CSlideshowSlideLoader::DoCancel() + { + iDecoder->Cancel(); + DeleteDecoder(); + // delete the image + if(iSlide->iImage) + { + delete iSlide->iImage; + iSlide->iImage = NULL; + } + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::RunL +// --------------------------------------------------------------------------- +// +void CSlideshowSlideLoader::RunL() + { + // delete the decoder to save some memory. + DeleteDecoder(); + if(iStatus != KErrNone) + { + iSlide->ReleaseImage(); + // SSS_DECODEFAILED says that Image could not be decoded. Corrupted image. + (iSlide->iFlags) |= SSS_DECODEFAILED; + return; + } + + // Image loaded, size scaled down while loading. Find out, if the + // image still needs to be scaled smaller to fit the screen + + TReal aspectRatio = (TReal) iBitmapsize.iWidth / (TReal) iBitmapsize.iHeight; + + if ((iBitmapsize.iWidth <= iTargetSize.iWidth) && + (iBitmapsize.iHeight <= iTargetSize.iHeight)) + { + // Fits completely - finish + SSPLOGGER_WRITE("No resize needed"); + + // Compress the heap after imageconversion as + // imagedecoder seems to leave heap uncompressed + User::Heap().Compress(); + (iSlide->iFlags) |= SSS_IMAGELOADED; + return; + } + + // Figure out which dimension needs most scaling + TReal xFactor = (TReal) iTargetSize.iWidth / (TReal) iBitmapsize.iWidth; + TReal yFactor = (TReal) iTargetSize.iHeight / (TReal) iBitmapsize.iHeight; + + // Start with target (screen) size + TSize finalSize = iTargetSize; + + if (xFactor <= yFactor) + { + // X-dimension needs most scaling - fit to x, re-calc y + finalSize.iHeight = (TInt) ((TReal) finalSize.iWidth / aspectRatio); + } + else + { + // Y-dimension needs most scaling - fit to y, re-calc x + finalSize.iWidth = (TInt) ((TReal) finalSize.iHeight * aspectRatio); + } + + SSPLOGGER_WRITEF(_L("SSP: Final size (%d, %d)"), + finalSize.iWidth, finalSize.iHeight); + + // Create a final bitmap with the final size, and draw to it + CFbsBitmap* finalBmp = new (ELeave) CFbsBitmap; + CleanupStack::PushL(finalBmp); + User::LeaveIfError(finalBmp->Create(finalSize, (iSlide->iImage)->DisplayMode())); + + CFbsBitmapDevice* bmpDev = CFbsBitmapDevice::NewL(finalBmp); + CleanupStack::PushL(bmpDev); + + CFbsBitGc* bmpCxt; + User::LeaveIfError(bmpDev->CreateContext(bmpCxt)); + CleanupStack::PushL(bmpCxt); + bmpCxt->DrawBitmap(TRect(0, 0, finalSize.iWidth, finalSize.iHeight), + (iSlide->iImage), + TRect(0, 0, iBitmapsize.iWidth, iBitmapsize.iHeight)); + + CleanupStack::PopAndDestroy(2); // bmpDev, bmpCxt + // Return the result in the original bitmap parameter + (iSlide->iImage)->Reset(); + + User::LeaveIfError((iSlide->iImage)->Duplicate(finalBmp->Handle())); + CleanupStack::PopAndDestroy(finalBmp); + // Compress the heap after imageconversion as + // imagedecoder seems to leave heap uncompressed + User::Heap().Compress(); + (iSlide->iFlags) |= SSS_IMAGELOADED; + return; + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::LoadSlideL +// --------------------------------------------------------------------------- +// +void CSlideshowSlideLoader::LoadSlideL( + const TDesC& aFilename, const TSize& aTargetSize) + { + + iTargetSize = aTargetSize; + RFs filesys; + User::LeaveIfError(filesys.Connect()); + CleanupClosePushL(filesys); + // this line can leave if decoder is not found..need to cacth this. + iDecoder = CImageDecoder::FileNewL(filesys, aFilename, ContentAccess::EView,CImageDecoder::EOptionAlwaysThread); + if (aTargetSize == TSize(-1,-1)) + { + CleanupStack::PopAndDestroy(&filesys); + iDecoder = NULL; + return; + } + + // Get image information + TFrameInfo frameinfo = iDecoder->FrameInfo(); + TDisplayMode mode; + + // Tone down colors if possible (saves memory) + if (frameinfo.iFlags & TFrameInfo::ECanDither) + { + mode = EColor64K; + } + else + { + mode = frameinfo.iFrameDisplayMode; + } + + // Find out if the image can be downscaled during loading + iBitmapsize = frameinfo.iOverallSizeInPixels; + + + if ((iBitmapsize.iWidth >= aTargetSize.iWidth * 2) && + (iBitmapsize.iHeight >= aTargetSize.iHeight * 2)) + { + // 1/2 size + iBitmapsize.iWidth = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iWidth, 2); + iBitmapsize.iHeight = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iHeight, 2); + + if ((iBitmapsize.iWidth >= aTargetSize.iWidth * 2) && + (iBitmapsize.iHeight >= aTargetSize.iHeight * 2)) + { + // 1/4 size + iBitmapsize.iWidth = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iWidth, 4); + iBitmapsize.iHeight = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iHeight, 4); + + if ((iBitmapsize.iWidth >= aTargetSize.iWidth * 2) && + (iBitmapsize.iHeight >= aTargetSize.iHeight * 2)) + { + // 1/8 size + iBitmapsize.iWidth = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iWidth, 8); + iBitmapsize.iHeight = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iHeight, 8); + } + } + } + + // Create a target bitmap + iSlide->iImage = new (ELeave) CFbsBitmap; + User::LeaveIfError((iSlide->iImage)->Create(iBitmapsize, mode)); + // for filesys + CleanupStack::PopAndDestroy(&filesys); + + //Start decoding the image ... + // RunL method is called when decoding is done. + iDecoder->Convert(&iStatus, *(iSlide->iImage),0); + SetActive(); + } + +// --------------------------------------------------------------------------- +// CSlideshowSlideLoader::RunError +// --------------------------------------------------------------------------- +// +TInt CSlideshowSlideLoader::RunError(TInt aError) + { + if (NULL != iSlide->iImage) + { + delete iSlide->iImage; + iSlide->iImage = NULL; + } + return aError; + }