skins/AknSkins/srvsrc/aknssrvwallpaperscaling.cpp
changeset 0 05e9090e2422
equal deleted inserted replaced
-1:000000000000 0:05e9090e2422
       
     1 /*
       
     2 * Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Image decoding and scaling utility class.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <e32math.h>
       
    21 #include <centralrepository.h>
       
    22 #include <SVGEngineInterfaceImpl.h>
       
    23 
       
    24 #include "aknssrvwallpaperscaling.h"
       
    25 #include <aknswallpaperconfprivatecrkeys.h>
       
    26 #include <AknsSrvVariant.hrh>
       
    27 #include <IclExtJpegApi.h>
       
    28 // CONSTANTS
       
    29 // Default small image zooming to fullscreen threshold value.
       
    30 const TReal KAknsSrvDefaultSmallImageThreshold = 0.33f;
       
    31 
       
    32 // Extension for gif file.
       
    33 //_LIT( KAknsSkinSrvGifFileExt, ".gif" );
       
    34 
       
    35 // Extension for jpg file.
       
    36 _LIT( KAknsSkinSrvJpegFileExt1, ".jpg" );
       
    37 _LIT( KAknsSkinSrvJpegFileExt2, ".jpeg" );
       
    38 
       
    39 
       
    40 // -----------------------------------------------------------------------------
       
    41 // Map SVG specific errors to Symbian error codes.
       
    42 // -----------------------------------------------------------------------------
       
    43 //
       
    44 TInt SvgErrorToSymbianError( const TSvgErrorCode aError )
       
    45     {
       
    46     // most common mapping...
       
    47     TInt ret = KErrGeneral;
       
    48 
       
    49     switch ( aError )
       
    50         {
       
    51         case ESvgNoError:
       
    52             ret = KErrNone;
       
    53             break;
       
    54         case ESvgFileNotFound:
       
    55             ret = KErrNotFound;
       
    56             break;
       
    57         case ESvgDocumentNotValid: // fall through
       
    58         case ESvgDocumentNotAvailable:
       
    59             break;
       
    60         case ESvgNoMemory:
       
    61             ret = KErrNoMemory;
       
    62             break;
       
    63         case ESvgDiskFull:
       
    64             ret = KErrDiskFull;
       
    65             break;
       
    66         case ESvgUnknown: // fall through
       
    67         case ESvgMissingRequiredAttribute: // fall through
       
    68         case ESvgInvalidAttributeValue: // fall through
       
    69         default:
       
    70             break;
       
    71         }
       
    72     return ret;
       
    73     }
       
    74 
       
    75 // -----------------------------------------------------------------------------
       
    76 // CAknsSrvSVGImageDecoder::NewL
       
    77 // -----------------------------------------------------------------------------
       
    78 //
       
    79 CAknsSrvSVGImageDecoder* CAknsSrvSVGImageDecoder::NewL()
       
    80     {
       
    81     CAknsSrvSVGImageDecoder* self = new (ELeave) CAknsSrvSVGImageDecoder;
       
    82     CleanupStack::PushL( self );
       
    83     self->ConstructL();
       
    84     CleanupStack::Pop( self );
       
    85     return self;
       
    86     }
       
    87 
       
    88 // -----------------------------------------------------------------------------
       
    89 // CAknsSrvSVGImageDecoder::NewL
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 void CAknsSrvSVGImageDecoder::DecodeImageL(
       
    93     const TDesC& aFilename,
       
    94     const TSize& aTargetSize,
       
    95     CFbsBitmap*& aBitmap,
       
    96     CFbsBitmap*& aMask )
       
    97     {
       
    98     // create frame and frame mask buffers
       
    99     iBitmap = new( ELeave ) CFbsBitmap;
       
   100     User::LeaveIfError( iBitmap->Create( aTargetSize, EColor64K ) );
       
   101 
       
   102     iMask = new( ELeave ) CFbsBitmap;
       
   103     User::LeaveIfError( iMask->Create( aTargetSize, EGray256 ) );
       
   104 
       
   105     // Load and render SVG file
       
   106     TInt handle = 0;
       
   107     LeaveIfErrorL( iSvgEngine->PrepareDom( aFilename, handle ) );
       
   108     LeaveIfErrorL( iSvgEngine->UseDom( handle, iBitmap, iMask ) );
       
   109     iSvgEngine->SetPreserveAspectRatio(
       
   110         NULL,
       
   111         ESvgPreserveAspectRatio_XmidYmid,
       
   112         ESvgMeetOrSlice_Meet,
       
   113         ETrue);
       
   114     // render frame and frame mask
       
   115     iSvgEngine->Start();
       
   116     LeaveIfErrorL( iSvgEngine->UseDom( handle, NULL ) );
       
   117     LeaveIfErrorL( iSvgEngine->DeleteDom( handle ) );
       
   118     aBitmap = iBitmap;
       
   119     iBitmap = NULL;
       
   120     aMask = iMask;
       
   121     iMask = NULL;
       
   122     }
       
   123 
       
   124 // -----------------------------------------------------------------------------
       
   125 // CAknsSrvSVGImageDecoder::NewL
       
   126 // -----------------------------------------------------------------------------
       
   127 //
       
   128 CAknsSrvSVGImageDecoder::~CAknsSrvSVGImageDecoder()
       
   129     {
       
   130     delete iDummyBitmap;
       
   131     delete iSvgEngine;
       
   132     }
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // CAknsSrvSVGImageDecoder::CAknsSrvSVGImageDecoder
       
   136 // -----------------------------------------------------------------------------
       
   137 //
       
   138 CAknsSrvSVGImageDecoder::CAknsSrvSVGImageDecoder()
       
   139     {
       
   140     }
       
   141 
       
   142 // -----------------------------------------------------------------------------
       
   143 // CAknsSrvSVGImageDecoder::ConstructL
       
   144 // -----------------------------------------------------------------------------
       
   145 //
       
   146 void CAknsSrvSVGImageDecoder::ConstructL()
       
   147     {
       
   148     // Initialize SVG engine
       
   149     TFontSpec spec;
       
   150     if ( !iDummyBitmap )
       
   151         {
       
   152         // Have to give some bitmap to the engine in the constructor.
       
   153         iDummyBitmap = new( ELeave ) CFbsBitmap;
       
   154         User::LeaveIfError( iDummyBitmap->Create( TSize( 0, 0 ), EGray2 ) );
       
   155         }
       
   156     iSvgEngine = CSvgEngineInterfaceImpl::NewL( iDummyBitmap, this, spec );
       
   157     iSvgEngine->SetBackgroundColor( 0 );
       
   158     // No DRM check needed.
       
   159     iSvgEngine->SetDRMMode( EFalse );
       
   160     }
       
   161 
       
   162 // -----------------------------------------------------------------------------
       
   163 // CAknsSrvSVGImageDecoder::LeaveIfErrorL
       
   164 // -----------------------------------------------------------------------------
       
   165 //
       
   166 void CAknsSrvSVGImageDecoder::LeaveIfErrorL( MSvgError* aError )
       
   167     {
       
   168     if ( !aError )
       
   169         {
       
   170         User::Leave( KErrGeneral );
       
   171         }
       
   172     if ( aError->HasError() && !aError->IsWarning() )
       
   173         {
       
   174         User::Leave( SvgErrorToSymbianError( aError->ErrorCode() ) );
       
   175         }
       
   176     }
       
   177 
       
   178 // -----------------------------------------------------------------------------
       
   179 // CAknsSrvSVGImageDecoder::ScriptCall
       
   180 // -----------------------------------------------------------------------------
       
   181 //
       
   182 TBool CAknsSrvSVGImageDecoder::ScriptCall(
       
   183     const TDesC& /*aScript*/,
       
   184     CSvgElementImpl* /*aCallerElement*/ )
       
   185     {
       
   186     return EFalse;
       
   187     }
       
   188 
       
   189 // -----------------------------------------------------------------------------
       
   190 // CAknsSrvSVGImageDecoder::UpdatePresentation
       
   191 // -----------------------------------------------------------------------------
       
   192 //
       
   193 void CAknsSrvSVGImageDecoder::UpdatePresentation(
       
   194     const TInt32& /*aNoOfAnimation*/ )
       
   195     {
       
   196     }
       
   197 
       
   198 // -----------------------------------------------------------------------------
       
   199 // CAknsSrvSVGImageDecoder::FetchFont
       
   200 // -----------------------------------------------------------------------------
       
   201 //
       
   202 TInt CAknsSrvSVGImageDecoder::FetchFont( const TDesC& /*aUri*/, RFs& /*aSession*/, RFile& /*aFileHandle*/ )
       
   203     {
       
   204     return KErrNotSupported;
       
   205     }
       
   206 
       
   207 // -----------------------------------------------------------------------------
       
   208 // CAknsSrvSVGImageDecoder::FetchImage
       
   209 // -----------------------------------------------------------------------------
       
   210 //
       
   211 TInt CAknsSrvSVGImageDecoder::FetchImage(
       
   212     const TDesC& /*aUri*/, RFs& /*aSession*/, RFile& /*aFileHandle*/ )
       
   213     {
       
   214     return KErrNotSupported;
       
   215     }
       
   216 
       
   217 // -----------------------------------------------------------------------------
       
   218 // CAknsSrvSVGImageDecoder::UpdateScreen
       
   219 // -----------------------------------------------------------------------------
       
   220 //
       
   221 void CAknsSrvSVGImageDecoder::UpdateScreen()
       
   222     {
       
   223     }
       
   224 
       
   225 // -----------------------------------------------------------------------------
       
   226 // CAknsSrvImageConverter::CAknsSrvImageConverter
       
   227 // -----------------------------------------------------------------------------
       
   228 //
       
   229 CAknsSrvImageConverter::CAknsSrvImageConverter() :
       
   230     CActive(CActive::EPriorityStandard)
       
   231     {
       
   232     }
       
   233 
       
   234 // -----------------------------------------------------------------------------
       
   235 // CAknsSrvImageConverter::~CAknsSrvImageConverter
       
   236 // -----------------------------------------------------------------------------
       
   237 //
       
   238 CAknsSrvImageConverter::~CAknsSrvImageConverter()
       
   239     {
       
   240     Cancel();
       
   241     delete iBitmapScaler;
       
   242     iBitmapScaler = NULL;
       
   243     }
       
   244 
       
   245 // -----------------------------------------------------------------------------
       
   246 // CAknsSrvImageConverter::NewL
       
   247 // -----------------------------------------------------------------------------
       
   248 //
       
   249 CAknsSrvImageConverter* CAknsSrvImageConverter::NewL()
       
   250     {
       
   251     CAknsSrvImageConverter* self = new (ELeave) CAknsSrvImageConverter;
       
   252     CleanupStack::PushL(self);
       
   253     self->ConstructL();
       
   254     CleanupStack::Pop( self );
       
   255     return self;
       
   256     }
       
   257 
       
   258 // -----------------------------------------------------------------------------
       
   259 // CAknsSrvImageConverter::ConstructL
       
   260 // -----------------------------------------------------------------------------
       
   261 //
       
   262 void CAknsSrvImageConverter::ConstructL()
       
   263     {
       
   264     iBitmapScaler = CBitmapScaler::NewL();
       
   265     CActiveScheduler::Add(this);
       
   266     }
       
   267 
       
   268 // -----------------------------------------------------------------------------
       
   269 // CAknsSrvImageConverter::BeginWait
       
   270 // -----------------------------------------------------------------------------
       
   271 //
       
   272 void CAknsSrvImageConverter::BeginWait()
       
   273     {
       
   274     if ( iWaitActive || iWait.IsStarted() )
       
   275         {
       
   276         return;
       
   277         }
       
   278     else
       
   279         {
       
   280         iWaitActive = ETrue;
       
   281         iWait.Start();
       
   282         }
       
   283     }
       
   284 
       
   285 // -----------------------------------------------------------------------------
       
   286 // CAknsSrvImageConverter::EndWait
       
   287 // -----------------------------------------------------------------------------
       
   288 //
       
   289 void CAknsSrvImageConverter::EndWait()
       
   290     {
       
   291     if (!iWaitActive)
       
   292         {
       
   293         return;
       
   294         }
       
   295     else
       
   296         {
       
   297         iWaitActive = EFalse;
       
   298         iWait.AsyncStop();
       
   299         }
       
   300     }
       
   301 
       
   302 // -----------------------------------------------------------------------------
       
   303 // CAknsSrvImageConverter::RunL
       
   304 // -----------------------------------------------------------------------------
       
   305 //
       
   306 void CAknsSrvImageConverter::RunL()
       
   307     {
       
   308     iConversionError = iStatus.Int();
       
   309     EndWait();
       
   310     }
       
   311 
       
   312 // -----------------------------------------------------------------------------
       
   313 // CAknsSrvImageConverter::DoCancel
       
   314 // -----------------------------------------------------------------------------
       
   315 //
       
   316 void CAknsSrvImageConverter::DoCancel()
       
   317     {
       
   318     if (iBitmapScaler)
       
   319         {
       
   320         iBitmapScaler->Cancel();
       
   321         }
       
   322     }
       
   323 
       
   324 // Axis-selection enumeration.
       
   325 enum TPLSelection
       
   326     {
       
   327     EPlX,
       
   328     EPlY
       
   329     };
       
   330 
       
   331 // Result struct.
       
   332 struct TCalcStruct
       
   333     {
       
   334     TPLSelection iPlSelector; // 0 = x, 1 = y
       
   335     TReal32 iCropMul;
       
   336     TReal32 iStretchMul;
       
   337     TReal32 iZoomMul;
       
   338     };
       
   339 
       
   340 
       
   341 // -----------------------------------------------------------------------------
       
   342 // GetScreenSizeL - Calculates screensize.
       
   343 // -----------------------------------------------------------------------------
       
   344 //
       
   345 TSize GetScreenSizeL()
       
   346     {
       
   347     RWsSession wsSession;
       
   348     User::LeaveIfError(wsSession.Connect());
       
   349     CleanupClosePushL(wsSession);
       
   350     CWsScreenDevice* sc = new (ELeave) CWsScreenDevice(wsSession);
       
   351     CleanupStack::PushL(sc);
       
   352     sc->Construct();
       
   353 
       
   354     TSize screensize(0,0);
       
   355     TPixelsAndRotation currentSize;
       
   356     TPixelsAndRotation defaultSize;
       
   357 
       
   358     // Fetch all screen modes, and pick the system's active one.
       
   359     // We need to use system's screenmode, since default (i.e. foreground)
       
   360     // can be different (e.g. client in landscape mode, system in portrait).
       
   361     RArray<TInt> screenModes;
       
   362     sc->GetScreenSizeModeList(&screenModes);
       
   363     TInt currentScreenMode = sc->CurrentScreenMode();
       
   364     if ( currentScreenMode >= 0 && currentScreenMode <= screenModes.Count() -1 )
       
   365         {
       
   366         sc->GetScreenModeSizeAndRotation( screenModes[currentScreenMode], currentSize );
       
   367         // Let's assume that first mode is the default.
       
   368         sc->GetScreenModeSizeAndRotation( screenModes[0], defaultSize );
       
   369 
       
   370         // Check if the client is in different mode than default.
       
   371         TBool clientRotated = EFalse;
       
   372         if (( currentSize.iRotation == CFbsBitGc::EGraphicsOrientationRotated90 ||
       
   373               currentSize.iRotation == CFbsBitGc::EGraphicsOrientationRotated270 ) && 
       
   374             ( defaultSize.iRotation == CFbsBitGc::EGraphicsOrientationNormal ||
       
   375               defaultSize.iRotation == CFbsBitGc::EGraphicsOrientationRotated180 ))
       
   376             {
       
   377             clientRotated = ETrue;
       
   378             }
       
   379         if (( currentSize.iRotation == CFbsBitGc::EGraphicsOrientationNormal ||
       
   380               currentSize.iRotation == CFbsBitGc::EGraphicsOrientationRotated180 ) && 
       
   381             ( defaultSize.iRotation == CFbsBitGc::EGraphicsOrientationRotated90 ||
       
   382               defaultSize.iRotation == CFbsBitGc::EGraphicsOrientationRotated270 ))
       
   383             {
       
   384             clientRotated = ETrue;
       
   385             }
       
   386 
       
   387         // If client is in different screen mode than the system - flip values.
       
   388         if ( clientRotated )
       
   389             {            
       
   390             screensize.iWidth = currentSize.iPixelSize.iHeight;
       
   391             screensize.iHeight = currentSize.iPixelSize.iWidth;
       
   392             }
       
   393         else
       
   394             {
       
   395             screensize = currentSize.iPixelSize;
       
   396             }
       
   397         }
       
   398     else
       
   399         {
       
   400         // Some problem with layout - use foremost screen size.
       
   401         screensize = sc->SizeInPixels();
       
   402         }
       
   403     screenModes.Reset();
       
   404     screenModes.Close();
       
   405 
       
   406     CleanupStack::PopAndDestroy(2);// screendevice, wssession
       
   407     return screensize;
       
   408     }
       
   409 
       
   410 // -----------------------------------------------------------------------------
       
   411 // GetWallpaperParametersL - Gets wallpaper parameters.
       
   412 // -----------------------------------------------------------------------------
       
   413 //
       
   414 void GetWallpaperParametersL(
       
   415     TReal& aMaxCropFactor, TReal& aMaxStretchFactor,
       
   416     TInt& aScalePriority,
       
   417     TSize& aScreenSize,
       
   418     TReal& aMaxZoomThreshold )
       
   419     {
       
   420     aScreenSize = GetScreenSizeL();
       
   421     // Fetch the wallpaper configuration values from central repository.
       
   422     CRepository* wpRepository = CRepository::NewL( KCRUidWallpaperConfiguration );
       
   423     CleanupStack::PushL( wpRepository );
       
   424     TInt crError = KErrNone;
       
   425     if (aScreenSize.iWidth > aScreenSize.iHeight)
       
   426         {
       
   427         //Landscape
       
   428         crError = wpRepository->Get( KWpConfLandscapeMaxCropFactor, aMaxCropFactor );
       
   429         if ( crError == KErrNone )
       
   430             {
       
   431             crError = wpRepository->Get( KWpConfLandscapeMaxStretchFactor, aMaxStretchFactor );
       
   432             }
       
   433         if ( crError == KErrNone )
       
   434             {
       
   435             crError = wpRepository->Get( KWpConfLandscapeScalePriority, aScalePriority );
       
   436             }
       
   437         if ( crError == KErrNone )
       
   438             {
       
   439             crError = wpRepository->Get( KWpConfSmallImageZoomThreshold, aMaxZoomThreshold );
       
   440             }
       
   441         }
       
   442     else
       
   443         {
       
   444         //Portrait
       
   445         crError = wpRepository->Get( KWpConfPortraitMaxCropFactor, aMaxCropFactor );
       
   446         if ( crError == KErrNone )
       
   447             {
       
   448             crError = wpRepository->Get( KWpConfPortaitMaxStretchFactor, aMaxStretchFactor );
       
   449             }
       
   450         if ( crError == KErrNone )
       
   451             {
       
   452             crError = wpRepository->Get( KWpConfPortraitScalePriority, aScalePriority );
       
   453             }
       
   454         if ( crError == KErrNone )
       
   455             {
       
   456             crError = wpRepository->Get( KWpConfSmallImageZoomThreshold, aMaxZoomThreshold );
       
   457             }
       
   458         }
       
   459         
       
   460     CleanupStack::PopAndDestroy( wpRepository );
       
   461     }
       
   462 
       
   463 // -----------------------------------------------------------------------------
       
   464 // CalculateScaleFactor - calculates the scaling factors (for cropping, zooming
       
   465 //   and scaling).
       
   466 // -----------------------------------------------------------------------------
       
   467 //
       
   468 TCalcStruct CalculateScaleFactor(
       
   469     TSize aOriginalSize, TSize aTargetSize, TSize& aScreenSize )
       
   470     {
       
   471     TCalcStruct result;
       
   472     TReal maxCropfactor = 0.0f;
       
   473     TReal maxStretchFactor = 0.0f;
       
   474     TInt scalePriority = EPrioCrop;
       
   475     TReal maxZoomThreshold = 0.0f;
       
   476 
       
   477     // Fetch the wallpaper configuration values from central repository.
       
   478     TRAP_IGNORE(
       
   479         GetWallpaperParametersL(
       
   480             maxCropfactor,
       
   481             maxStretchFactor,
       
   482             scalePriority,
       
   483             aScreenSize,
       
   484             maxZoomThreshold ) );
       
   485 
       
   486     result.iPlSelector = EPlX;
       
   487     result.iCropMul = 1.0f;
       
   488     result.iStretchMul = 1.0f;
       
   489     result.iZoomMul = 1.0f;
       
   490 
       
   491     if ( (aOriginalSize.iWidth <= aTargetSize.iWidth) &&
       
   492          (aOriginalSize.iHeight <= aTargetSize.iHeight) && 
       
   493          (scalePriority != EPrioNHDWallpaper) )
       
   494         {
       
   495         // source fits completely to the target -> bail out no scaling needed
       
   496         return result;
       
   497         }
       
   498     result.iCropMul = 1.0f - maxCropfactor;
       
   499     result.iStretchMul = 1.0f - maxStretchFactor;
       
   500 
       
   501     TReal32 originalAspect;
       
   502     TReal32 targetAspect;
       
   503 
       
   504     TReal32 plTargetLen;
       
   505     TReal32 plZoomedTargetLen;
       
   506     TReal32 plOriginalLen;
       
   507 
       
   508     originalAspect = (TReal32)aOriginalSize.iWidth/(TReal32)aOriginalSize.iHeight;
       
   509     targetAspect = (TReal32)aTargetSize.iWidth/(TReal32)aTargetSize.iHeight;
       
   510 
       
   511     if (originalAspect>targetAspect)
       
   512         {
       
   513         result.iPlSelector = EPlX;
       
   514         plTargetLen = (TReal32)aOriginalSize.iHeight * targetAspect;
       
   515         plZoomedTargetLen = aTargetSize.iWidth;
       
   516         plOriginalLen = aOriginalSize.iWidth;
       
   517         }
       
   518     else
       
   519         {
       
   520         result.iPlSelector = EPlY;
       
   521         plOriginalLen = aOriginalSize.iHeight;
       
   522         plTargetLen = (TReal32)aOriginalSize.iWidth / targetAspect;
       
   523         plZoomedTargetLen = aTargetSize.iHeight;
       
   524         }
       
   525         
       
   526     if (scalePriority == EPrioNHDWallpaper)
       
   527         {
       
   528         if( ( aOriginalSize.iWidth < aTargetSize.iWidth * maxZoomThreshold ) &&
       
   529             ( aOriginalSize.iHeight < aTargetSize.iHeight * maxZoomThreshold ) ) 
       
   530             {
       
   531             result.iPlSelector = EPlX;
       
   532             result.iCropMul = 1.0f;
       
   533             result.iStretchMul = 1.0f;
       
   534             result.iZoomMul = 1.0f;
       
   535             }
       
   536         else if( ( aOriginalSize.iWidth >= aTargetSize.iWidth * maxZoomThreshold ) &&
       
   537             ( aOriginalSize.iHeight >= aTargetSize.iHeight * maxZoomThreshold ) )
       
   538             {
       
   539             result.iStretchMul = 1.0f;
       
   540             
       
   541             result.iCropMul = plTargetLen / plOriginalLen;
       
   542             result.iZoomMul = plZoomedTargetLen / plTargetLen;
       
   543             }
       
   544         else
       
   545             {
       
   546             result.iStretchMul = 1.0f;
       
   547             result.iZoomMul = 1.0f;
       
   548                 
       
   549             result.iCropMul = plZoomedTargetLen / plOriginalLen;
       
   550             }
       
   551             
       
   552         return result;
       
   553         }
       
   554         
       
   555         
       
   556     TReal32 reqMul = plTargetLen / plOriginalLen;
       
   557     if (reqMul < ( result.iCropMul * result.iStretchMul ) )
       
   558         {
       
   559         result.iZoomMul = plZoomedTargetLen /
       
   560             ( result.iCropMul * result.iStretchMul * plOriginalLen );
       
   561         return result;
       
   562         }
       
   563 
       
   564     result.iZoomMul = plZoomedTargetLen / (reqMul*plOriginalLen);
       
   565     if (scalePriority == EPrioStretch)
       
   566         {
       
   567         result.iCropMul = reqMul / result.iStretchMul;
       
   568         }
       
   569     else if (scalePriority == EPrioCrop)
       
   570         {
       
   571         result.iStretchMul = reqMul / result.iCropMul;
       
   572         if ( result.iStretchMul > 1.0f )
       
   573             {
       
   574             // Since stretch is not going to be performed, we can use the available
       
   575             // "space" for decreasing the cropped area.
       
   576             result.iCropMul = result.iCropMul * result.iStretchMul;
       
   577             }
       
   578         if ( result.iZoomMul > 1.0f )
       
   579             {
       
   580             // Since zooming is not going to be performed, we can use the available
       
   581             // "space" for decreasing the cropped area.
       
   582             result.iCropMul = result.iCropMul * result.iZoomMul;
       
   583             }
       
   584         }
       
   585     else
       
   586         {
       
   587         TReal reqMulSqr;
       
   588         Math::Sqrt( reqMulSqr,reqMul );
       
   589         if ( (reqMulSqr >= ( result.iStretchMul ) ) &&
       
   590              (reqMulSqr >= ( result.iCropMul ) ) )
       
   591             {
       
   592             result.iCropMul = reqMulSqr;
       
   593             result.iStretchMul = reqMul / result.iCropMul;
       
   594             }
       
   595         else
       
   596             {
       
   597             if ( maxCropfactor > maxStretchFactor )
       
   598                 {
       
   599                 result.iCropMul = reqMul / result.iStretchMul;
       
   600                 }
       
   601             else
       
   602                 {
       
   603                 result.iStretchMul = reqMul / result.iCropMul;
       
   604                 }
       
   605             }
       
   606         }
       
   607     return result;
       
   608     }
       
   609 
       
   610 // -----------------------------------------------------------------------------
       
   611 // CAknsSrvImageConverter::ScaleAndCropImageL
       
   612 // -----------------------------------------------------------------------------
       
   613 //
       
   614 void CAknsSrvImageConverter::ScaleAndCropImageL(
       
   615     CFbsBitmap*& aBitmap, const TSize& aTargetSize )
       
   616     {
       
   617     TSize bitmapsize = aBitmap->SizeInPixels();
       
   618     TSize screenSize;
       
   619 
       
   620     TCalcStruct calcres =
       
   621         CalculateScaleFactor( aBitmap->SizeInPixels(), aTargetSize, screenSize );
       
   622 
       
   623     if ( calcres.iCropMul == 1.0f &&
       
   624          calcres.iStretchMul == 1.0f &&
       
   625          calcres.iZoomMul == 1.0f )
       
   626         {
       
   627 #ifdef RD_FULLSCREEN_WALLPAPER
       
   628         if ( screenSize.iHeight == 0 ||
       
   629              screenSize.iWidth == 0 )
       
   630             {
       
   631             // error in getting screensize, bail out.
       
   632             return;
       
   633             }
       
   634         TReal32 imageScreenRatio =
       
   635             ((TReal32) bitmapsize.iHeight * (TReal32) bitmapsize.iWidth) /
       
   636             ((TReal32) screenSize.iHeight * (TReal32) screenSize.iWidth);
       
   637 
       
   638         TReal threshold = KAknsSrvDefaultSmallImageThreshold;
       
   639         TInt crError = KErrNone;
       
   640         CRepository* wpRepository = NULL;
       
   641         wpRepository = CRepository::NewL( KCRUidWallpaperConfiguration );
       
   642         CleanupStack::PushL( wpRepository );
       
   643         crError = wpRepository->Get( KWpConfSmallImageZoomThreshold, threshold );
       
   644         if ( crError != KErrNone )
       
   645             {
       
   646             // Error - use default value.
       
   647             threshold = KAknsSrvDefaultSmallImageThreshold;
       
   648             }
       
   649         CleanupStack::PopAndDestroy( wpRepository );
       
   650 
       
   651         if ( imageScreenRatio < threshold )
       
   652             {
       
   653             // image is so small that zooming will not look good enough
       
   654             return;
       
   655             }
       
   656         // If image does not fit, or screensize is corrupted, don't do anything.
       
   657         if ( bitmapsize.iHeight > screenSize.iHeight ||
       
   658              bitmapsize.iWidth > screenSize.iWidth )
       
   659             {
       
   660             // no scaling required, bail out
       
   661             return;
       
   662             }
       
   663         // Image is smaller than screen - zoom.
       
   664         TReal32 ratioX = ( (TReal32)bitmapsize.iWidth / (TReal32)screenSize.iWidth );
       
   665         TReal32 ratioY = ( (TReal32)bitmapsize.iHeight / (TReal32)screenSize.iHeight );
       
   666         if ( ratioX > ratioY )
       
   667             {
       
   668             calcres.iZoomMul = 1.0f / ( (TReal32)bitmapsize.iWidth / (TReal32)screenSize.iWidth );
       
   669             }
       
   670         else
       
   671             {
       
   672             calcres.iZoomMul = 1.0f / ( (TReal32)bitmapsize.iHeight / (TReal32)screenSize.iHeight );
       
   673             }
       
   674 #else
       
   675         // no scaling required, bail out
       
   676         return;
       
   677 #endif // RD_FULLSCREEN_WALLPAPER
       
   678         }
       
   679 
       
   680     TSize scaleSize = bitmapsize;
       
   681     if (calcres.iCropMul < 1.0f)
       
   682         {
       
   683         // Crop first.
       
   684         TSize cropSize = bitmapsize;
       
   685 
       
   686         if (calcres.iPlSelector == EPlX)
       
   687             {
       
   688             cropSize.iWidth = (TInt)(calcres.iCropMul*(TReal32)bitmapsize.iWidth+0.5f);
       
   689             }
       
   690         else
       
   691             {
       
   692             cropSize.iHeight = (TInt)(calcres.iCropMul*(TReal32)bitmapsize.iHeight+0.5f);
       
   693             }
       
   694 
       
   695         CFbsBitmap* newbmp = new (ELeave) CFbsBitmap;
       
   696         CleanupStack::PushL(newbmp);
       
   697         newbmp->Create(cropSize, aBitmap->DisplayMode());
       
   698         CFbsBitmapDevice* bmpdev = CFbsBitmapDevice::NewL(newbmp);
       
   699         CleanupStack::PushL(bmpdev);
       
   700         CFbsBitGc* bmpcxt;
       
   701         User::LeaveIfError(bmpdev->CreateContext(bmpcxt));
       
   702         CleanupStack::PushL(bmpcxt);
       
   703         bmpcxt->BitBlt(TPoint(0,0), aBitmap,
       
   704             TRect((bitmapsize.iWidth-cropSize.iWidth)/2,
       
   705             (bitmapsize.iHeight-cropSize.iHeight)/2,
       
   706             (bitmapsize.iWidth+cropSize.iWidth)/2,
       
   707             (bitmapsize.iHeight+cropSize.iHeight)/2));
       
   708         CleanupStack::PopAndDestroy(2); // bmpdev, bmpcxt
       
   709         aBitmap->Reset();
       
   710         User::LeaveIfError( aBitmap->Duplicate( newbmp->Handle() ) );
       
   711         bitmapsize = aBitmap->SizeInPixels();
       
   712         scaleSize = bitmapsize;
       
   713         CleanupStack::PopAndDestroy( newbmp );
       
   714         }
       
   715 
       
   716     if (calcres.iStretchMul < 1.0f)
       
   717         {
       
   718         if (calcres.iPlSelector == EPlX)
       
   719             {
       
   720             scaleSize.iWidth = (TInt)((TReal32)bitmapsize.iWidth*calcres.iStretchMul+0.5f);
       
   721             }
       
   722         else
       
   723             {
       
   724             scaleSize.iHeight = (TInt)((TReal32)bitmapsize.iHeight*calcres.iStretchMul+0.5f);
       
   725             }
       
   726         }
       
   727 #ifdef RD_FULLSCREEN_WALLPAPER
       
   728    // Finally zoom.
       
   729     scaleSize.iHeight =(TInt)(calcres.iZoomMul*(TReal32)scaleSize.iHeight+0.5f);
       
   730     scaleSize.iWidth =(TInt)(calcres.iZoomMul*(TReal32)scaleSize.iWidth+0.5f);
       
   731 #else
       
   732     if (calcres.iZoomMul < 1.0f)
       
   733         {
       
   734         scaleSize.iHeight =(TInt)(calcres.iZoomMul*(TReal32)scaleSize.iHeight+0.5f);
       
   735         scaleSize.iWidth =(TInt)(calcres.iZoomMul*(TReal32)scaleSize.iWidth+0.5f);
       
   736         }
       
   737 #endif // RD_FULLSCREEN_WALLPAPER
       
   738 
       
   739     if (scaleSize != bitmapsize)
       
   740         {
       
   741         iBitmapScaler->Scale(&iStatus, *aBitmap, scaleSize, EFalse);
       
   742         SetActive();
       
   743         BeginWait();
       
   744         User::LeaveIfError(iConversionError);
       
   745         }
       
   746     }
       
   747 
       
   748 // -----------------------------------------------------------------------------
       
   749 // DivAndRoundUp - divides and rounds up.
       
   750 // -----------------------------------------------------------------------------
       
   751 //
       
   752 TInt DivAndRoundUp( const TInt aNumber, const TInt aDivider )
       
   753     {
       
   754     TInt result = aNumber/aDivider;
       
   755     if( aNumber%aDivider )
       
   756         {
       
   757         result+=1;
       
   758         }
       
   759     return result;
       
   760     }
       
   761 
       
   762 // -----------------------------------------------------------------------------
       
   763 // CAknsSrvImageConverter::DecodeImageL
       
   764 // -----------------------------------------------------------------------------
       
   765 //
       
   766 void CAknsSrvImageConverter::DecodeImageL(
       
   767     RFs& aRFs, const TDesC& aFilename,
       
   768     const TSize& aTargetSize,
       
   769     CFbsBitmap*& aBitmap, CFbsBitmap*& aMask ,
       
   770     const TSize& aMaxSize)
       
   771     {
       
   772     TSize realsize = aTargetSize;
       
   773     TBool testDecode = (realsize == TSize(-1,-1));
       
   774     if ( testDecode )
       
   775         {
       
   776         realsize = TSize(10,10);
       
   777         }
       
   778     
       
   779     CImageDecoder* decoder = NULL;
       
   780     
       
   781     if ( ((aFilename).Right(4).CompareF( KAknsSkinSrvJpegFileExt1 ) == 0) 
       
   782         || ((aFilename).Right(5).CompareF( KAknsSkinSrvJpegFileExt2 ) == 0) )
       
   783     	{
       
   784         TRAPD( err, {decoder = CExtJpegDecoder::FileNewL( CExtJpegDecoder::EHwImplementation,
       
   785                            aRFs, aFilename,CImageDecoder::EOptionAlwaysThread );});
       
   786         if ( err != KErrNone )
       
   787             {
       
   788             decoder = CImageDecoder::FileNewL( aRFs,aFilename,
       
   789 							CImageDecoder::EOptionAlwaysThread,KImageTypeJPGUid);
       
   790             }
       
   791         }
       
   792      else
       
   793          {
       
   794          decoder = CImageDecoder::FileNewL( aRFs, aFilename,CImageDecoder::EOptionAlwaysThread);
       
   795          }
       
   796         
       
   797     CleanupStack::PushL(decoder);
       
   798     TFrameInfo frameinfo = decoder->FrameInfo();
       
   799     TDisplayMode mode;
       
   800     
       
   801     TSize imageSize = decoder->FrameInfo(0).iOverallSizeInPixels;
       
   802 	if( imageSize.iWidth*imageSize.iHeight > aMaxSize.iWidth*aMaxSize.iHeight  )
       
   803 		{
       
   804         // Image too large 
       
   805         User::Leave( KErrTooBig );
       
   806 		} 
       
   807 
       
   808     if (frameinfo.iFlags & TFrameInfo::ECanDither)
       
   809         {
       
   810         if ( testDecode )
       
   811             {
       
   812             mode = EColor256;
       
   813             }
       
   814         else
       
   815             {
       
   816             mode = EColor64K;
       
   817             }
       
   818         }
       
   819     else
       
   820         {
       
   821         mode = frameinfo.iFrameDisplayMode;
       
   822         }
       
   823 
       
   824     TSize bitmapsize = frameinfo.iOverallSizeInPixels;
       
   825     //Comment out for BUG ECLG-7NCFUG
       
   826 //    TBool skipReSizing = EFalse;
       
   827 //    TInt frameCount = decoder->FrameCount();
       
   828 //    if ( ((aFilename).Right(4).CompareF( KAknsSkinSrvGifFileExt ) == 0) && frameCount > 1 )
       
   829 //        {
       
   830 //       skipReSizing = ETrue;
       
   831 //        }
       
   832 
       
   833 //    // Skip resizing for animated gifs.
       
   834 //    if ( !skipReSizing )
       
   835 //        {
       
   836         if (bitmapsize.iWidth  >= realsize.iWidth*2&&
       
   837             bitmapsize.iHeight >= realsize.iHeight*2)
       
   838             {
       
   839             // 1/2 size
       
   840             bitmapsize.iWidth = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iWidth, 2);
       
   841             bitmapsize.iHeight = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iHeight, 2);
       
   842             if (bitmapsize.iWidth  >= realsize.iWidth*2&&
       
   843                 bitmapsize.iHeight >= realsize.iHeight*2)
       
   844                 {
       
   845                 // 1/4 size
       
   846                 bitmapsize.iWidth = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iWidth, 4);
       
   847                 bitmapsize.iHeight = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iHeight, 4);
       
   848                 if (bitmapsize.iWidth  >= realsize.iWidth*2&&
       
   849                     bitmapsize.iHeight >= realsize.iHeight*2)
       
   850                     {
       
   851                     // 1/8 size
       
   852                     bitmapsize.iWidth = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iWidth, 8);
       
   853                     bitmapsize.iHeight = DivAndRoundUp(frameinfo.iOverallSizeInPixels.iHeight, 8);
       
   854                     }
       
   855                 }
       
   856             }
       
   857 //        }
       
   858 
       
   859     aBitmap = new (ELeave) CFbsBitmap;
       
   860     User::LeaveIfError(aBitmap->Create(bitmapsize, mode));
       
   861     CleanupStack::PushL(aBitmap);
       
   862     // Does the image contain some kind of mask
       
   863     if (frameinfo.iFlags & TFrameInfo::ETransparencyPossible)
       
   864         {
       
   865         aMask = new (ELeave) CFbsBitmap;
       
   866         // alpha channel mask
       
   867         if (frameinfo.iFlags & TFrameInfo::EAlphaChannel)
       
   868             {
       
   869             User::LeaveIfError(aMask->Create(bitmapsize, EGray256));
       
   870             }
       
   871         // normal 1 bit mask
       
   872         else
       
   873             {
       
   874             User::LeaveIfError(aMask->Create(bitmapsize, EGray2));
       
   875             }
       
   876         CleanupStack::PushL(aMask);
       
   877         }
       
   878 
       
   879     TRequestStatus status;
       
   880     if (aMask)
       
   881         {
       
   882         decoder->Convert(&status, *aBitmap, *aMask,0);
       
   883         }
       
   884     else
       
   885         {
       
   886         decoder->Convert(&status, *aBitmap,0);
       
   887         }
       
   888 
       
   889     User::WaitForRequest(status);
       
   890     if ( status.Int() || testDecode )
       
   891         {
       
   892         if (aMask)
       
   893             {
       
   894             CleanupStack::Pop(2); // bitmap, mask
       
   895             }
       
   896         else
       
   897             {
       
   898             CleanupStack::Pop( aBitmap );
       
   899             }
       
   900         CleanupStack::PopAndDestroy( decoder );
       
   901 
       
   902         delete aBitmap;
       
   903         delete aMask;
       
   904         aBitmap = NULL;
       
   905         aMask = NULL;
       
   906         User::Heap().Compress();
       
   907 
       
   908         // Test decode successful.
       
   909         if ( testDecode && !status.Int() )
       
   910             {
       
   911             return;
       
   912             }
       
   913         // Decode (test or normal) failed.
       
   914         else
       
   915             {
       
   916             User::Leave(status.Int());
       
   917             }
       
   918         }
       
   919 
       
   920     // Skip image scale&crop with test decode.
       
   921     if ( !testDecode )
       
   922         {
       
   923         CAknsSrvImageConverter* converter = CAknsSrvImageConverter::NewL();
       
   924         CleanupStack::PushL(converter);
       
   925         converter->ScaleAndCropImageL(aBitmap, aTargetSize );
       
   926         if (aMask)
       
   927             {
       
   928             converter->ScaleAndCropImageL(aMask, aTargetSize );
       
   929             }
       
   930         CleanupStack::PopAndDestroy(converter);
       
   931 
       
   932         if (aMask)
       
   933             {
       
   934             CleanupStack::Pop(2); // bitmap, mask
       
   935             }
       
   936         else
       
   937             {
       
   938             CleanupStack::Pop( aBitmap );
       
   939             }
       
   940         CleanupStack::PopAndDestroy( decoder );
       
   941         }
       
   942     // Compress the heap after image conversion as
       
   943     // image decoder seems to leave heap uncompressed
       
   944     User::Heap().Compress();
       
   945     }
       
   946 
       
   947 // End of file