scrsaver/scrsaverplugins/SlideshowPlugin/src/SlideshowSlideLoader.cpp
branchRCL_3
changeset 26 e8d784ac1a4b
parent 0 040fcad49f44
--- /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;
+	}