--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/coreui_akn/src/startupscreen/startscreen.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,698 @@
+/*
+* Copyright (c) 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: A user start screen impl.
+*
+*/
+
+#include <iostream>
+#include <fstream>
+#include <AknsBasicBackgroundControlContext.h>
+#include <AknsDrawUtils.h>
+#include <AknUtils.h>
+#include <layoutmetadata.cdl.h>
+#include <imageconversion.h>
+
+#include "startscreen.h"
+#include "logger.h"
+#include "javasymbianoslayer.h"
+#include "coreuiavkonimpl.h"
+
+_LIT(KUserFolder, "startupimages\\");
+_LIT(KUserDefaultImage, "startupscreen.img");
+_LIT(KUserLandscapeImage, "startupscreen_landscape.img");
+_LIT(KUserPortraitImage, "startupscreen_portrait.img");
+
+_LIT(KAutoFolder, "autostartupimages\\");
+_LIT(KAutoLandscapeImage, "landscape.png"); // Gets prefixed by TUid
+_LIT(KAutoPortraitImage, "portrait.png"); // Gets prefixed by TUid
+
+
+CStartScreen* CStartScreen::NewL(CStartScreen::TStartScreenType aType,
+ const java::ui::CoreUiParams& aParams)
+{
+ JELOG2(EJavaUI);
+ CStartScreen* self = new(ELeave) CStartScreen(aType, aParams);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CStartScreen::~CStartScreen()
+{
+ JELOG2(EJavaUI);
+ Cancel();
+ delete mPortraitBmp;
+ delete mPortraitMask;
+ if (mPortraitBmp != mLandscapeBmp)
+ {
+ delete mLandscapeBmp;
+ delete mLandscapeMask;
+ }
+ delete mAsyncSaveBmp;
+ delete mDecoder;
+ delete mEncoder;
+ mPath.Close();
+ mAsyncSavePath.Close();
+}
+
+void CStartScreen::Draw(CWindowGc& aGc,
+ const TRect& aRect) const
+{
+ JELOG2(EJavaUI);
+
+ CFbsBitmap* bmp = 0;
+ CFbsBitmap* mask = 0;
+ if (Layout_Meta_Data::IsLandscapeOrientation())
+ {
+ bmp = mLandscapeBmp;
+ mask = mLandscapeMask;
+ }
+ else
+ {
+ bmp = mPortraitBmp;
+ mask = mPortraitMask;
+ }
+
+ if (!bmp)
+ {
+ return;
+ }
+
+ TPoint topLeft(aRect.iTl);
+ if (mType == EStartScreenAutomatic)
+ {
+ aGc.BitBlt(topLeft, bmp);
+ }
+ else
+ {
+ const TSize bmpSizeOrg(bmp->SizeInPixels());
+ const TSize rectSize(aRect.Size());
+ TSize bmpSize(bmpSizeOrg);
+
+ // Scale the image if needed
+ TBool scaled(EFalse);
+ if (bmpSize.iWidth > rectSize.iWidth || bmpSize.iHeight > rectSize.iHeight)
+ {
+ scaled = ETrue;
+ bmpSize = GetAspectRatioScaledBitmapSize(bmpSize, rectSize);
+ }
+
+ // Center the image
+ if (bmpSize.iWidth < rectSize.iWidth)
+ {
+ topLeft.iX = (rectSize.iWidth - bmpSize.iWidth) / 2;
+ }
+ if (bmpSize.iHeight < rectSize.iHeight)
+ {
+ topLeft.iY = (rectSize.iHeight - bmpSize.iHeight) / 2;
+ }
+
+ if (scaled)
+ {
+ TRect destRect(topLeft, bmpSize);
+ if (!mask)
+ {
+ aGc.DrawBitmap(destRect, bmp, TRect(bmpSizeOrg));
+ }
+ else
+ {
+ aGc.DrawBitmapMasked(destRect, bmp, TRect(bmpSizeOrg), mask, EFalse);
+ }
+ }
+ else
+ {
+ // Faster drawing
+ if (!mask)
+ {
+ aGc.BitBlt(topLeft, bmp);
+ }
+ else
+ {
+ aGc.BitBltMasked(topLeft, bmp, TRect(bmpSize), mask, EFalse);
+ }
+ }
+ }
+}
+
+void CStartScreen::HandleResolutionChange()
+{
+ if (mLandscapeBmp && mPortraitBmp)
+ {
+ return;
+ }
+
+ if (Layout_Meta_Data::IsLandscapeOrientation())
+ {
+ if (!mLandscapeBmp)
+ {
+ TRAP_IGNORE(SyncLoadImageL(EImageLandscape));
+ }
+ }
+ else
+ {
+ if (!mPortraitBmp)
+ {
+ TRAP_IGNORE(SyncLoadImageL(EImagePortrait));
+ }
+ }
+}
+
+TBool CStartScreen::IsEmpty() const
+{
+ if (Layout_Meta_Data::IsLandscapeOrientation())
+ {
+ return (mLandscapeBmp == 0);
+ }
+ else
+ {
+ return (mPortraitBmp == 0);
+ }
+}
+
+TSize CStartScreen::Size() const
+{
+ if (Layout_Meta_Data::IsLandscapeOrientation())
+ {
+ if (mLandscapeBmp)
+ return mLandscapeBmp->SizeInPixels();
+ }
+ else
+ {
+ if (mPortraitBmp)
+ return mPortraitBmp->SizeInPixels();
+ }
+
+ return TSize(0, 0);
+}
+
+void CStartScreen::AsyncSaveScreenL(TCallBack aCallBack)
+{
+ // Expecting this is done once and only once.
+ ASSERT(!mAsyncSaveBmp);
+ ASSERT(!mEncoder);
+
+ mCallBack = aCallBack;
+ mAsyncSaveBmp = TakeScreenShotL();
+ if (mAsyncSaveBmp)
+ {
+ if (Layout_Meta_Data::IsLandscapeOrientation())
+ {
+ AsyncSaveImageL(EImageLandscape, *mAsyncSaveBmp);
+ }
+ else
+ {
+ AsyncSaveImageL(EImagePortrait, *mAsyncSaveBmp);
+ }
+ }
+}
+
+CStartScreen::TStartScreenType CStartScreen::Type() const
+{
+ return mType;
+}
+
+TInt64 CStartScreen::LoadStartupTime()
+{
+ TInt64 res = 0;
+ std::ifstream file;
+ file.open(StartupTimeFileName().c_str(), std::ifstream::in);
+ file >> res;
+ file.close();
+ return res;
+}
+
+void CStartScreen::SaveStartupTime(TInt64 aPeriod)
+{
+ std::ofstream file;
+ file.open(StartupTimeFileName().c_str());
+ file << aPeriod;
+ file.close();
+}
+
+CStartScreen::CStartScreen(TStartScreenType aType,
+ const java::ui::CoreUiParams& aParams)
+ : CActive(EPriorityStandard), mType(aType), mParams(aParams)
+{
+ CActiveScheduler::Add(this);
+}
+
+void CStartScreen::ConstructL()
+{
+ JELOG2(EJavaUI);
+
+ InitPathL();
+ ScanFolderL();
+
+ if (mImageCount > 0)
+ {
+ if (mType == EStartScreenAutomatic || mImageCount >= 2)
+ {
+ if (Layout_Meta_Data::IsLandscapeOrientation())
+ {
+ TRAP_IGNORE(SyncLoadImageL(EImageLandscape));
+ }
+ else
+ {
+ TRAP_IGNORE(SyncLoadImageL(EImagePortrait));
+ }
+ }
+ else
+ {
+ TRAP_IGNORE(SyncLoadImageL(EImageDefault));
+ }
+ }
+}
+
+void CStartScreen::InitPathL()
+{
+ HBufC* root(wstringToBuf(mParams.getImagePath()));
+ if (!root || root->Length() == 0)
+ {
+ delete root;
+ User::Leave(KErrPathNotFound);
+ }
+ CleanupStack::PushL(root);
+ const TDesC& folder = FolderName();
+ mPath.CreateL(root->Length() + folder.Length());
+ mPath.Append(root->Des());
+ CleanupStack::PopAndDestroy(root);
+ mPath.Append(folder);
+}
+
+void CStartScreen::ScanFolderL()
+{
+ ASSERT(mPath.Length());
+
+ TUint fileAttrMask = KEntryAttNormal | KEntryAttSystem | KEntryAttDir;
+ CDir* dir = 0;
+ RFs& fs = CCoeEnv::Static()->FsSession();
+ TInt err = fs.GetDir(mPath, fileAttrMask, ESortByName, dir);
+
+ if (KErrNone == err)
+ {
+ if (!dir)
+ {
+ err = KErrNotFound;
+ ELOG1(EJavaUI, "CStartScreen::InitStateL, "
+ "RFs::GetDir failed: %d", err);
+ }
+ else
+ {
+ mImageCount = dir->Count();
+ }
+ }
+ else
+ {
+ ELOG1(EJavaUI, "CStartScreen::InitStateL, "
+ "RFs::GetDir failed: %d", err);
+ }
+
+ if (mType == EStartScreenAutomatic && KErrNone != err)
+ {
+ err = fs.MkDir(mPath);
+ }
+
+ User::LeaveIfError(err);
+}
+
+void CStartScreen::SyncLoadImageL(TImageId aId)
+{
+ RBuf fullPath;
+ const TDesC& img = ImageName(aId);
+ // Do prefixing here just to avoid dealing with another RBuf :)
+ TUidName uid;
+ if (mType == EStartScreenAutomatic)
+ uid = java::ui::CoreUiAvkonImpl::getInstanceImpl().getMidletTUid().Name();
+ fullPath.CreateL(mPath.Length() + img.Length() + uid.Length());
+ fullPath.CleanupClosePushL();
+ fullPath.Append(mPath);
+ if (mType == EStartScreenAutomatic)
+ fullPath.Append(uid);
+ fullPath.Append(img);
+
+ switch (aId)
+ {
+ case EImageDefault:
+ ASSERT(!mPortraitBmp);
+ ASSERT(!mLandscapeBmp);
+ DoSyncLoadImageL(fullPath, mPortraitBmp, mPortraitMask);
+ mLandscapeBmp = mPortraitBmp;
+ mLandscapeMask = mPortraitMask;
+ break;
+ case EImagePortrait:
+ ASSERT(!mPortraitBmp);
+ DoSyncLoadImageL(fullPath, mPortraitBmp, mPortraitMask);
+ break;
+ case EImageLandscape:
+ ASSERT(!mLandscapeBmp);
+ DoSyncLoadImageL(fullPath, mLandscapeBmp, mLandscapeMask);
+ break;
+ default:
+ break;
+ }
+
+ CleanupStack::PopAndDestroy(&fullPath);
+}
+
+
+void CStartScreen::DoSyncLoadImageL(const TDesC& aPath, CFbsBitmap*& aResBmp,
+ CFbsBitmap*& aResMask)
+{
+ ASSERT(!aResBmp);
+ ASSERT(!aResMask);
+
+ if (IsActive())
+ {
+ Cancel();
+ }
+
+ if (mDecoder != NULL)
+ {
+ delete mDecoder;
+ mDecoder = 0;
+ }
+
+ mDecoder = CImageDecoder::FileNewL(CCoeEnv::Static()->FsSession(), aPath);
+
+ CFbsBitmap* bmp = new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(bmp);
+
+ const TFrameInfo& frameInfo = mDecoder->FrameInfo();
+
+ TInt err = bmp->Create(frameInfo.iOverallSizeInPixels,
+ frameInfo.iFrameDisplayMode);
+ if (KErrNone != err)
+ {
+ CleanupStack::PopAndDestroy(bmp);
+ ELOG1(EJavaUI, "CStartScreen::DoSyncLoadImageL, "
+ "Bitmap creation failed: %d", err);
+ User::Leave(err);
+ }
+
+ CFbsBitmap* mask = 0;
+
+ if (!(frameInfo.iFlags & TFrameInfo::ETransparencyPossible))
+ {
+ mState = ESyncRead;
+ mDecoder->Convert(&iStatus, *bmp);
+ }
+ else
+ {
+ mask = new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(mask);
+
+ TDisplayMode mode(EGray2);
+ if (frameInfo.iFlags & TFrameInfo::EAlphaChannel)
+ {
+ mode = EGray256;
+ }
+
+ err = mask->Create(frameInfo.iOverallSizeInPixels, mode);
+ if (KErrNone != err)
+ {
+ CleanupStack::PopAndDestroy(mask);
+ CleanupStack::PopAndDestroy(bmp);
+ ELOG1(EJavaUI, "CImageReader::DoSyncLoadImageL, "
+ "Mask creation failed: %d", err);
+ User::Leave(err);
+ }
+
+ mState = ESyncRead;
+ mDecoder->Convert(&iStatus, *bmp, *mask);
+ }
+
+ SetActive();
+ mWait.Start();
+
+ err = iStatus.Int();
+ if (KErrNone != err)
+ {
+ if (mask)
+ {
+ CleanupStack::PopAndDestroy(mask);
+ }
+ CleanupStack::PopAndDestroy(bmp);
+ ELOG1(EJavaUI, "CImageReader::DoSyncLoadImageL, "
+ "CImageDecoder::Convert failed: %d", err);
+ User::Leave(err);
+ }
+
+ if (mask)
+ {
+ CleanupStack::Pop(mask);
+ }
+ CleanupStack::Pop(bmp);
+ aResBmp = bmp;
+ aResMask = mask;
+}
+
+void CStartScreen::AsyncSaveImageL(TImageId aId, const CFbsBitmap& aBmp)
+{
+ const TDesC& img = ImageName(aId);
+ // Do prefixing here just to avoid dealing with another RBuf :)
+ TUidName uid;
+ if (mType == EStartScreenAutomatic)
+ uid = java::ui::CoreUiAvkonImpl::getInstanceImpl().getMidletTUid().Name();
+ mAsyncSavePath.CreateL(mPath.Length() + img.Length() + uid.Length());
+ mAsyncSavePath.Append(mPath);
+ if (mType == EStartScreenAutomatic)
+ mAsyncSavePath.Append(uid);
+ mAsyncSavePath.Append(img);
+
+ DoAsyncSaveImageL(mAsyncSavePath, aBmp);
+}
+
+void CStartScreen::DoAsyncSaveImageL(const TDesC& aPath, const CFbsBitmap& aBmp)
+{
+ if (IsActive())
+ {
+ Cancel();
+ }
+
+ mEncoder = CImageEncoder::FileNewL(CCoeEnv::Static()->FsSession(), aPath,
+ CImageEncoder::EOptionNone, KImageTypePNGUid);
+
+ mState = EAsyncWrite;
+ mEncoder->Convert(&iStatus, aBmp);
+ SetActive();
+}
+
+TSize CStartScreen::GetAspectRatioScaledBitmapSize(
+ const TSize& aSourceSize, const TSize& aMaxDestSize) const
+{
+ JELOG2(EJavaUI);
+ TSize imageSize = aSourceSize;
+ TInt yDiff = 0;
+ TInt xDiff = 0;
+ TBool scalingNeeded = EFalse;
+
+ if (aSourceSize.iWidth == 0 || aSourceSize.iHeight == 0)
+ {
+ return imageSize;
+ }
+
+ // Figure out if any scaling is needed
+ if (aSourceSize.iHeight > aMaxDestSize.iHeight)
+ {
+ yDiff = aSourceSize.iHeight - aMaxDestSize.iHeight;
+ scalingNeeded = ETrue;
+ }
+ if (aSourceSize.iWidth > aMaxDestSize.iWidth)
+ {
+ xDiff = aSourceSize.iWidth - aMaxDestSize.iWidth;
+ scalingNeeded = ETrue;
+ }
+
+ if (scalingNeeded)
+ {
+ if (xDiff > yDiff)
+ {
+ imageSize.iWidth = aMaxDestSize.iWidth;
+ imageSize.iHeight = (aSourceSize.iHeight * aMaxDestSize.iWidth)
+ / aSourceSize.iWidth;
+ }
+ else if (yDiff > xDiff)
+ {
+ imageSize.iHeight = aMaxDestSize.iHeight;
+ imageSize.iWidth = (aSourceSize.iWidth * aMaxDestSize.iHeight)
+ / aSourceSize.iHeight;
+ }
+ else
+ {
+ // Aspect ratios are the same
+ imageSize = aMaxDestSize;
+ }
+ }
+
+ return imageSize;
+}
+
+CFbsBitmap* CStartScreen::TakeScreenShotL()
+{
+ CEikonEnv* env = CEikonEnv::Static();
+ CFbsBitmap* bmp = new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(bmp);
+ CWsScreenDevice* screenDevice = env->ScreenDevice();
+ TInt err = bmp->Create(screenDevice->SizeInPixels(), screenDevice->DisplayMode());
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaUI, "CStartScreen::TakeScreenShotL, "
+ "CFbsBitmap::Create failed: %d", err);
+ }
+ err = screenDevice->CopyScreenToBitmap(bmp);
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaUI, "CStartScreen::TakeScreenShotL, "
+ "CWsScreenDevice::CopyScreenToBitmap failed: %d", err);
+ }
+ User::LeaveIfError(err);
+ CleanupStack::Pop(bmp);
+ return bmp;
+}
+
+const TDesC& CStartScreen::FolderName() const
+{
+ if (mParams.getScreenMode() == java::ui::USER_DEFINED_SCREEN)
+ {
+ return KNullDesC;
+ }
+ if (mType == EStartScreenAutomatic)
+ {
+ return KAutoFolder;
+ }
+ else
+ {
+ return KUserFolder;
+ }
+}
+
+const TDesC& CStartScreen::ImageName(CStartScreen::TImageId aId) const
+{
+ if (mParams.getScreenMode() == java::ui::USER_DEFINED_SCREEN)
+ {
+ return KNullDesC;
+ }
+ if (mType == EStartScreenAutomatic)
+ {
+ switch (aId)
+ {
+ case EImagePortrait:
+ return KAutoPortraitImage;
+ case EImageLandscape:
+ return KAutoLandscapeImage;
+ default:
+ return KNullDesC;
+ }
+ }
+ else
+ {
+ switch (aId)
+ {
+ case EImagePortrait:
+ return KUserPortraitImage;
+ case EImageLandscape:
+ return KUserLandscapeImage;
+ case EImageDefault:
+ default:
+ return KUserDefaultImage;
+ }
+ }
+}
+
+std::string CStartScreen::StartupTimeFileName() const
+{
+ std::wstring temp(mParams.getImagePath());
+ temp.append(L"autostartupimages\\");
+ temp.append(java::ui::CoreUiAvkonImpl::getInstanceImpl().getMidletUid().toString());
+ temp.append(L"time.txt");
+ // This is ok as we know for sure we have only ascii in the path.
+ std::string path(temp.begin(), temp.end());
+ return path;
+}
+
+void CStartScreen::RunL()
+{
+ if (mState == ESyncRead)
+ {
+ if (iStatus == KErrUnderflow)
+ {
+ ELOG1(EJavaUI, "CStartScreen::RunL, "
+ "CImageDecoder::Convert failed: %d", KErrUnderflow);
+ mDecoder->ContinueConvert(&iStatus);
+ SetActive();
+ }
+ else
+ {
+ if (mWait.IsStarted())
+ {
+ mWait.AsyncStop();
+ }
+
+ // Release the lock on the file.
+ ASSERT(mDecoder);
+ delete mDecoder;
+ mDecoder = NULL;
+
+ // Reset state
+ mState = EIdle;
+ }
+ }
+ else if (mState == EAsyncWrite)
+ {
+ // Release the lock on the file.
+ ASSERT(mEncoder);
+ delete mEncoder;
+ mEncoder = 0;
+
+ // Reset state
+ mState = EIdle;
+
+ if (iStatus == KErrNone)
+ {
+ // The callback will delete the object in the current setup.
+ mCallBack.CallBack();
+ }
+ else
+ {
+ TInt err = iStatus.Int();
+ ELOG1(EJavaUI, "CStartScreen::RunL, "
+ "CImageEncoder::Convert failed: %d", err);
+ }
+ }
+}
+
+void CStartScreen::DoCancel()
+{
+ if (mState == ESyncRead)
+ {
+ if (mDecoder)
+ {
+ mDecoder->Cancel();
+ }
+ if (mWait.IsStarted())
+ {
+ mWait.AsyncStop();
+ }
+ }
+ else if (mState == EAsyncWrite)
+ {
+ if (mEncoder)
+ {
+ mEncoder->Cancel();
+ }
+ }
+
+ mState = EIdle;
+}