scrsaver/scrsaverplugins/BmpAnimScrPlugin/src/CBmpAnimScrPlugin.cpp
changeset 14 8a173132b0aa
parent 2 058b1fc1663a
equal deleted inserted replaced
2:058b1fc1663a 14:8a173132b0aa
     1 /*
       
     2 * Copyright (c) 2003 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:   Main code file for plugin
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <eikenv.h>
       
    21 #include <e32math.h>
       
    22 #include <bitdev.h>
       
    23 #include <aknutils.h>
       
    24 #include <akniconutils.h>
       
    25 #include <mifconvdefs.h>
       
    26 
       
    27 #include "CBmpAnimScrPlugin.h"
       
    28 #include "BmpAnimUtils.h"
       
    29 
       
    30 #include <AknQueryDialog.h>
       
    31 #include <avkon.rsg>
       
    32 // "BmpAnimScrPlugin.rsg"
       
    33 
       
    34 const TInt KDefaultViewTime = 1000000;
       
    35 
       
    36 //
       
    37 // CBmpAnimSrcPlugin
       
    38 //
       
    39 
       
    40 // Creates and returns a new instance of CBmpAnimScrPlugin
       
    41 CBmpAnimScrPlugin* CBmpAnimScrPlugin::NewL()
       
    42     {
       
    43     CBmpAnimScrPlugin *plugin = new (ELeave) CBmpAnimScrPlugin();
       
    44 
       
    45     // Initialize settings object so that the plugin name can be retrieved
       
    46     iSettings = CBmpAnimSettings::NewL();
       
    47     
       
    48     return plugin;
       
    49     }
       
    50 
       
    51     
       
    52 // Default constructor
       
    53 CBmpAnimScrPlugin::CBmpAnimScrPlugin()
       
    54     : iState(EPluginStateLoading),
       
    55       iStopDisplaying(EFalse),
       
    56       iLoadedAnimation(ENone)
       
    57     {
       
    58     BMALOGGER_CREATE;
       
    59 
       
    60     }
       
    61     
       
    62 
       
    63 // Destructor
       
    64 CBmpAnimScrPlugin::~CBmpAnimScrPlugin()
       
    65     {
       
    66     delete iModel;
       
    67     delete iSettings;
       
    68 
       
    69     StopDisplayTimer();
       
    70     delete iDisplayTimer;
       
    71     
       
    72     BMALOGGER_DELETE;
       
    73     }
       
    74 
       
    75     
       
    76 // --- from Screensaverplugin ---
       
    77 
       
    78 
       
    79 // Initialization function. Must be called before anything but
       
    80 // name query can be done
       
    81 TInt CBmpAnimScrPlugin::InitializeL(MScreensaverPluginHost *aHost) 
       
    82     {
       
    83     ASSERT(aHost);
       
    84     
       
    85     // Sanity check
       
    86     if (!aHost)
       
    87         {
       
    88         return KErrArgument;
       
    89         }
       
    90     
       
    91     // Save the host interface
       
    92     iHost = aHost;
       
    93 
       
    94     // Start state
       
    95     iState = EPluginStateLoading;
       
    96 
       
    97     // Initial timing (may be overridden by settings)
       
    98     iHost->SetRefreshTimerValue(KDefaultViewTime);
       
    99 
       
   100     // Lie that we'll show indicators so that host does not prevent
       
   101     // plugin to be run if there are any to show. We'll stop after a
       
   102     // while anyway and the indicators are shown by normal Screensaver
       
   103     iHost->OverrideStandardIndicators();
       
   104     
       
   105     // Grab hold of the environment (this could be in the plugin host interface)
       
   106     iEikEnv = CEikonEnv::Static();
       
   107 
       
   108     // Create the model to store the animation in
       
   109     iModel = new(ELeave) CBmpAnimModel();
       
   110     iModel->ConstructL(iSettings);
       
   111 
       
   112     // Get screen info
       
   113     UpdateDisplayInfo();
       
   114     
       
   115     // Load the animation (Reload figures out which graphics should be used)
       
   116     ReloadAnimationL();
       
   117 
       
   118     // Create display timer
       
   119     iDisplayTimer = CPeriodic::NewL(CActive::EPriorityStandard);
       
   120 
       
   121     return KErrNone;
       
   122     }
       
   123 
       
   124     
       
   125 // Draw function being called repeatedly by the host
       
   126 TInt CBmpAnimScrPlugin::Draw(CWindowGc& aGc) 
       
   127     {
       
   128     // If initializing, start the timer and move on to animation state
       
   129     if (iState == EPluginStateInitializing)
       
   130         {
       
   131         BMALOGGER_WRITE("First draw, initializing");
       
   132         
       
   133         StartDisplayTimer();
       
   134         HandlePluginState();
       
   135         SetDisplayMode();
       
   136         TInt nLights = iModel->Settings()->Lights();
       
   137 
       
   138         if (nLights > 0)
       
   139             {
       
   140             Lights(nLights);
       
   141             }
       
   142 
       
   143         // Make sure the animation sequence starts from the beginning
       
   144         iModel->SetCurrentItemIndex(0);
       
   145         }
       
   146 
       
   147     // Retrieve the next image in sequence
       
   148     TBool endOfSequence = EFalse;
       
   149     CBmpAnimItem* pItem = iModel->NextItem(endOfSequence);
       
   150 
       
   151     if ((endOfSequence) || (!pItem))
       
   152         {
       
   153         // End of sequence reached, see if we've shown enough (1 minute)
       
   154         if (iStopDisplaying)
       
   155             {
       
   156             // Stop the timer
       
   157             StopDisplayTimer();
       
   158 
       
   159             // Back to square 1
       
   160             iState = EPluginStateInitializing;
       
   161 
       
   162 			// Set a lower refresh rate while plugin is suspended.
       
   163             // This allows the Screensaver to stop Window Server heartbeat
       
   164             // and the system is able to sleep normally
       
   165             // NOTE: Not needed anymore, Screensaver now shuts down
       
   166             // WSERV heartbeat for suspended plugins
       
   167             // iHost->SetRefreshTimerValue(KDefaultViewTime);
       
   168 
       
   169             TInt suspendTime = iModel->Settings()->SuspendTime();
       
   170             
       
   171             BMALOGGER_WRITEF(_L("BMA: Done drawing, suspending for %d"),
       
   172                              suspendTime);
       
   173             
       
   174             iHost->Suspend(suspendTime);
       
   175 
       
   176             return KErrNone;
       
   177             }
       
   178         }
       
   179 
       
   180     if (pItem)
       
   181         {
       
   182         // Make sure the window is empty in case the bitmap doesn't
       
   183         // fill the whole screen
       
   184         aGc.Clear();
       
   185 
       
   186         DrawCentered(aGc, pItem);
       
   187         }
       
   188 
       
   189 // Activate code if centering INI-controllable
       
   190 #if 0
       
   191         // Retrieve drawing information
       
   192         CGulIcon* pIcon = pItem->Icon();
       
   193         TPoint position = pItem->Position();
       
   194         CFbsBitmap* bitmap = pIcon->Bitmap();
       
   195         CFbsBitmap* mask = pIcon->Mask();
       
   196 
       
   197         // Draw the whole bitmap at position
       
   198         TRect rect(position, bitmap->SizeInPixels());
       
   199         
       
   200         if (mask)
       
   201             {
       
   202             // Looks like a real icon - draw masked
       
   203             aGc.BitBltMasked(position, bitmap, rect, mask, ETrue);
       
   204             }
       
   205         else
       
   206             {
       
   207             // Just the bitmap - no masked draw
       
   208             aGc.BitBlt(position, bitmap, rect);
       
   209             }
       
   210 
       
   211         // Wait for the specified time until next image
       
   212         //
       
   213         // TODO: The new wk28 Screensaver crashes if the next call
       
   214         // is uncommented. Maybe the timer is not stopped
       
   215         // before starting again? Hmm... doesn't seem to happen
       
   216         // anymore. I wonder what changed. Anyway, I'll have it
       
   217         // commented out for the time being, in order to control
       
   218         // all frames' rate with the single setting
       
   219         // 
       
   220         // NOTE: There was a flaw in Screensaver where it would try to
       
   221         // start refresh timer twice, if plugin changes the value during
       
   222         // the first draw. The fix is released for 2.6_wk40_FB4
       
   223         // iHost->SetRefreshTimerValue(pItem->Timing());
       
   224         }
       
   225 /*
       
   226     aGc.SetPenColor(TRgb(255,0,0));
       
   227     aGc.SetPenStyle(CGraphicsContext::ESolidPen);
       
   228     aGc.DrawRect(TRect(30, 30, 100, 100));
       
   229 
       
   230     aGc.SetPenColor(TRgb(255,0,0));
       
   231     aGc.SetPenSize(TSize(3,3));
       
   232     aGc.DrawRect(TRect(120, 100, 200, 150));
       
   233 */
       
   234 #endif
       
   235     return KErrNone;
       
   236     }
       
   237 
       
   238 
       
   239 // Return the name of the plugin
       
   240 const TDesC16& CBmpAnimScrPlugin::Name() const
       
   241     {
       
   242     if (iSettings)
       
   243         {
       
   244         return iSettings->PluginName();
       
   245         }
       
   246 
       
   247     return KPluginName;
       
   248     }
       
   249 
       
   250 
       
   251 // Handles events sent by the screensaver
       
   252 TInt CBmpAnimScrPlugin::HandleScreensaverEventL(
       
   253     TScreensaverEvent aEvent,
       
   254     TAny* /* aData */)
       
   255     {
       
   256     switch (aEvent)
       
   257         {
       
   258         case EScreensaverEventStarting:
       
   259             BMALOGGER_WRITE("Start event");
       
   260             break;
       
   261         case EScreensaverEventStopping:
       
   262             BMALOGGER_WRITE("Stop event");
       
   263             StopDisplayTimer();
       
   264             iState = EPluginStateInitializing;
       
   265             break;
       
   266         case EScreensaverEventDisplayChanged:
       
   267             BMALOGGER_WRITE("Display changed event");
       
   268             // Grab current screen info
       
   269             UpdateDisplayInfo();
       
   270             // Reload animation, if needed
       
   271             ReloadAnimationL();
       
   272             break;
       
   273         default:
       
   274             break;
       
   275         }
       
   276 
       
   277     return KErrNone;
       
   278     }
       
   279 
       
   280 
       
   281 // Return plugin capabilities (configurable)
       
   282 TInt CBmpAnimScrPlugin::Capabilities()
       
   283     {
       
   284     return EScpCapsConfigure;
       
   285     }
       
   286 
       
   287 
       
   288 // Perform a plugin function
       
   289 TInt CBmpAnimScrPlugin::PluginFunction(TScPluginCaps aFunction, TAny* aParam)
       
   290     {
       
   291     switch (aFunction)
       
   292         {
       
   293         case EScpCapsConfigure:
       
   294             {
       
   295             TRAPD(err, err = ConfigureL(aParam));
       
   296             return err;
       
   297             }
       
   298             break;
       
   299         default:
       
   300             return KErrNotSupported;
       
   301             break;
       
   302         }
       
   303     }
       
   304     
       
   305 
       
   306 // --- private functions ---
       
   307 
       
   308 // Draws centered items
       
   309 void CBmpAnimScrPlugin::DrawCentered(CWindowGc& aGc, CBmpAnimItem* aItem)
       
   310     {
       
   311     CGulIcon* pIcon = aItem->Icon();
       
   312     CFbsBitmap* bitmap = pIcon->Bitmap();
       
   313     CFbsBitmap* mask = pIcon->Mask();
       
   314 
       
   315     if (!bitmap)
       
   316         return;
       
   317 
       
   318     // Center the bitmap horizontally and vertically (crop off excess)    
       
   319     TPoint pos;
       
   320     TRect rectToDraw;
       
   321     TSize sizeBmp = bitmap->SizeInPixels();
       
   322     TInt screenWidth = iDi.iRect.Width();
       
   323     TInt screenHeight = iDi.iRect.Height();
       
   324 
       
   325     // Horizontally
       
   326     if (sizeBmp.iWidth <= screenWidth)
       
   327         {
       
   328         // Width fits on screen - center xpos
       
   329         pos.iX = (screenWidth - sizeBmp.iWidth) / 2;
       
   330         
       
   331         // Whole width of bmp can be drawn
       
   332         rectToDraw.SetWidth(sizeBmp.iWidth);
       
   333         }
       
   334     else
       
   335         {
       
   336         // Bmp wider than screen - xpos top left
       
   337         pos.iX = 0;
       
   338         
       
   339         // Adjust draw rect position and width
       
   340         rectToDraw.iTl.iX = (sizeBmp.iWidth - screenWidth) / 2;
       
   341         rectToDraw.SetWidth(screenWidth);
       
   342         }
       
   343 
       
   344     // Vertically
       
   345     if (sizeBmp.iHeight <= screenHeight)
       
   346         {
       
   347         // Height fits on screen - center ypos
       
   348         pos.iY = (screenHeight - sizeBmp.iHeight) / 2;
       
   349         
       
   350         // Whole height of bmp can be drawn
       
   351         rectToDraw.SetHeight(sizeBmp.iHeight);
       
   352         }
       
   353     else
       
   354         {
       
   355         // Bmp higher than screen - ypos top left
       
   356         pos.iY = 0;
       
   357         
       
   358         // Adjust draw rect position and height
       
   359         rectToDraw.iTl.iY = (sizeBmp.iHeight - screenHeight) / 2;
       
   360         rectToDraw.SetHeight(screenHeight);
       
   361         }
       
   362 
       
   363     // Do the drawing
       
   364     if (mask)
       
   365         {
       
   366         // Looks like a real icon - draw masked
       
   367         aGc.BitBltMasked(pos, bitmap, rectToDraw, mask, ETrue);
       
   368         }
       
   369     else
       
   370         {
       
   371         // Just the bitmap - no masked draw
       
   372         aGc.BitBlt(pos, bitmap, rectToDraw);
       
   373         }
       
   374     }
       
   375 
       
   376 
       
   377 // Loads the animation into the model
       
   378 void CBmpAnimScrPlugin::LoadAnimationL(TBool aLandscape, TBool aRotate)
       
   379     {
       
   380     // Rotated landscape not supported
       
   381     ASSERT(!(aLandscape && aRotate));
       
   382     
       
   383     // Start by getting rid of a possible loaded animation
       
   384     iModel->DeleteAll();
       
   385     
       
   386     // Bitmap index. If negative, loading is finished.
       
   387     TInt nIndex = KMifIdFirst;
       
   388     
       
   389     TFileName fileName;
       
   390 
       
   391     if (aLandscape)
       
   392         {
       
   393         fileName = iModel->Settings()->BitmapFilenameLandscape();
       
   394         }
       
   395     else
       
   396         {
       
   397         fileName = iModel->Settings()->BitmapFilename();
       
   398         }
       
   399 
       
   400     BMALOGGER_WRITEF(_L("BMA: Loading from: %S"), &(fileName));
       
   401             
       
   402     while (nIndex > 0)
       
   403         {
       
   404         CFbsBitmap* pBmp = NULL;
       
   405         
       
   406         TRAPD(err, pBmp = AknIconUtils::CreateIconL(fileName, nIndex));
       
   407 
       
   408         if ((pBmp) && (err == KErrNone))
       
   409             {
       
   410             // Got bitmap, push and set size
       
   411             CleanupStack::PushL(pBmp);
       
   412             TInt scaleErr = ScaleBitmap(pBmp, aRotate);
       
   413             if (scaleErr == KErrNone)
       
   414                 {
       
   415                 // Create an item with the bitmap and store it in the model
       
   416                 CBmpAnimItem* pItem = new(ELeave) CBmpAnimItem();
       
   417                 CleanupStack::PushL(pItem);
       
   418             
       
   419                 pItem->SetIconL(pBmp);
       
   420                 iModel->AppendItemL(pItem);
       
   421                 
       
   422                 CleanupStack::Pop(2); // pBmp, pItem
       
   423             
       
   424                 BMALOGGER_WRITEF(_L("BMA: Loaded bmp %d"), nIndex);
       
   425                 
       
   426                 // Try loading next bitmap (skip mask IDs)
       
   427                 nIndex += 2;
       
   428                 }
       
   429             else
       
   430                 {
       
   431                 BMALOGGER_WRITEF(_L("BMA: Bmp %d scale err %d"),
       
   432                                  nIndex, scaleErr);
       
   433 
       
   434                 // Apparently SVG icon was not found, this is not caught
       
   435                 // in CreateIconL(). Assume last image was loaded.
       
   436                 CleanupStack::PopAndDestroy();  // pBmp
       
   437                 nIndex = -1;
       
   438                 }
       
   439             }
       
   440         else
       
   441             {
       
   442             // Loading failed - maybe reached end of bitmaps 
       
   443             nIndex = -1;
       
   444             
       
   445             BMALOGGER_WRITEF(_L("BMA: Bmp load failed: %d"), err);
       
   446             }
       
   447         }
       
   448 
       
   449     // Save the type of loaded animation
       
   450     if (aLandscape)
       
   451         {
       
   452         iLoadedAnimation = ELandscape;
       
   453         }
       
   454     else if (aRotate)
       
   455         {
       
   456         iLoadedAnimation = EPortraitRotated;
       
   457         }
       
   458     else
       
   459         {
       
   460         iLoadedAnimation = EPortrait;
       
   461         }
       
   462 
       
   463     // On to next state
       
   464     HandlePluginState();
       
   465     
       
   466     // Start animating, when appropriate
       
   467     iHost->SetRefreshTimerValue(iModel->Settings()->Timing());
       
   468 
       
   469     BMALOGGER_WRITE("BMA: Animation loaded");
       
   470     }
       
   471 
       
   472 
       
   473 // Re-loads the animation into the model, if needed
       
   474 void CBmpAnimScrPlugin::ReloadAnimationL()
       
   475     {
       
   476     // Check if the correct graphics are already loaded
       
   477     if (!ReloadNeeded())
       
   478         {
       
   479         // Done! That was easy :)
       
   480         return;
       
   481         }
       
   482 
       
   483     // Load correct graphics
       
   484     LoadAnimationL(LoadLandscape(), RotateNeeded());
       
   485     }
       
   486 
       
   487     
       
   488 // Starts the display timer
       
   489 void CBmpAnimScrPlugin::StartDisplayTimer()
       
   490     {
       
   491     ASSERT(iDisplayTimer);
       
   492 
       
   493     TInt time = iModel->Settings()->RunningTime();
       
   494 
       
   495     BMALOGGER_WRITEF(_L("BMA: Start display timer for %d"), time);
       
   496 
       
   497     iStopDisplaying = EFalse;
       
   498     iDisplayTimer->Start(
       
   499         time,
       
   500         time,
       
   501         TCallBack(DisplayTimerCallback, this));
       
   502     }
       
   503 
       
   504     
       
   505 // Stops the display timer
       
   506 void CBmpAnimScrPlugin::StopDisplayTimer()
       
   507     {
       
   508     BMALOGGER_WRITE("BMA: Stop display timer");
       
   509 
       
   510     if (iDisplayTimer)
       
   511         {
       
   512         iDisplayTimer->Cancel();
       
   513         }
       
   514     
       
   515     iStopDisplaying = EFalse;
       
   516     }
       
   517 
       
   518 
       
   519 // Display timer callback - sets animation stop flag
       
   520 TInt CBmpAnimScrPlugin::DisplayTimerCallback(TAny* aPtr)
       
   521     {
       
   522     BMALOGGER_WRITE("BMA: Display timer timeout");
       
   523 
       
   524     CBmpAnimScrPlugin* _this = REINTERPRET_CAST(CBmpAnimScrPlugin*, aPtr);
       
   525     _this->iStopDisplaying = ETrue;
       
   526     return KErrNone;
       
   527     }
       
   528 
       
   529     
       
   530 // Changes the internal state flag    
       
   531 void CBmpAnimScrPlugin::HandlePluginState()
       
   532     {
       
   533     switch (iState)
       
   534         {
       
   535         case EPluginStateLoading:
       
   536             iState = EPluginStateInitializing;
       
   537             break;
       
   538         case EPluginStateInitializing:          
       
   539             iState = EPluginStateAnimation;
       
   540             break;
       
   541         case EPluginStateAnimation:
       
   542              break; 
       
   543         case EPluginStateStoppingAnimation:
       
   544              iHost->SetRefreshTimerValue(KDefaultViewTime);
       
   545              iState = EPluginStateInitializing;
       
   546              break;
       
   547         }
       
   548     }
       
   549 
       
   550 
       
   551 // Requests display mode from host
       
   552 void CBmpAnimScrPlugin::SetDisplayMode()
       
   553     {
       
   554     if (!iHost)
       
   555         {
       
   556         return;
       
   557         }
       
   558     
       
   559     // Exit partial mode
       
   560     iHost->ExitPartialMode();
       
   561     }
       
   562 
       
   563 
       
   564 void CBmpAnimScrPlugin::Lights(TInt aSecs)
       
   565     {
       
   566     BMALOGGER_WRITEF(_L("BMA: Request lights for %d secs"), aSecs);
       
   567     iHost->RequestLights(aSecs);
       
   568     }
       
   569 
       
   570     
       
   571 // Configure the plugin
       
   572 TInt CBmpAnimScrPlugin::ConfigureL(TAny* aParam)
       
   573     {
       
   574     if (!iSettings)
       
   575         {
       
   576         return KErrNotFound;
       
   577         }
       
   578     
       
   579     // Grab the parameter (CEikonEnv in this case)
       
   580     CEikonEnv* eikEnv = NULL;
       
   581 
       
   582     if (aParam)
       
   583         {
       
   584         // The host was kind enough to provide us with a param - use it
       
   585         eikEnv = REINTERPRET_CAST(CEikonEnv*, aParam);
       
   586         }
       
   587     else if (iEikEnv)
       
   588         {
       
   589         // Use own env, if initialized
       
   590         eikEnv = iEikEnv;
       
   591         }
       
   592 
       
   593     TInt setting = iSettings->Lights();
       
   594     
       
   595     CAknNumberQueryDialog* dlg = CAknNumberQueryDialog::NewL(setting);
       
   596     CleanupStack::PushL(dlg);
       
   597     _LIT(KPrompt, "Lights time (sec)");
       
   598     dlg->SetPromptL(KPrompt);
       
   599     dlg->SetMinimumAndMaximum(0, 30);
       
   600     CleanupStack::Pop();
       
   601     
       
   602     if (dlg->ExecuteLD(R_AVKON_DIALOG_QUERY_VALUE_NUMBER))
       
   603         {
       
   604         iSettings->SetLights(setting);
       
   605         iSettings->SaveSettingsL();
       
   606         }
       
   607     
       
   608     // All was swell!
       
   609     return KErrNone;
       
   610     }
       
   611 
       
   612 
       
   613 // Scale bitmap to screen size, set size of SVG bitmaps
       
   614 TInt CBmpAnimScrPlugin::ScaleBitmap(CFbsBitmap* aBmp, TBool aRotate)
       
   615     {
       
   616     TInt ret = KErrNone;
       
   617 
       
   618     // SVG size always screen size
       
   619     TSize size = iDi.iRect.Size();
       
   620 
       
   621     if (!AknIconUtils::IsMifIcon(aBmp))
       
   622         {
       
   623         // Bitmaps maintain their original size, unless scaling requested, in which
       
   624         // case screen size is OK 
       
   625         if (!iSettings->ScaleBmps())
       
   626             {
       
   627             // No scaling, use original size
       
   628             size = aBmp->SizeInPixels();
       
   629 
       
   630             if (aRotate)
       
   631                 {
       
   632                 // Lie the target size, otherwise IconUitls will think
       
   633                 // the image needs scaling (this won't work perfectly
       
   634                 // either, the image gets clipped a little :(
       
   635                 //size.SetSize(size.iHeight, size.iHeight);
       
   636 
       
   637                 // Flip size for rotation
       
   638                 size.SetSize(size.iHeight, size.iWidth);
       
   639                 }
       
   640             }
       
   641         }
       
   642     
       
   643     if (aRotate)
       
   644         {
       
   645         // Set image to screen size and rotate 90 deg left (270 right)
       
   646         // ret = SetSizeAndRotation(aBmp, size, 270);
       
   647         ret = AknIconUtils::SetSizeAndRotation(
       
   648             aBmp, size, EAspectRatioPreservedSlice, 270);
       
   649         }
       
   650     else
       
   651         {
       
   652         // Just set image to size
       
   653         ret = AknIconUtils::SetSize(aBmp, size, EAspectRatioPreserved);
       
   654         }
       
   655 
       
   656     return ret;
       
   657     }
       
   658 
       
   659 
       
   660 // Returns ETrue if reload of the animation is needed
       
   661 TBool CBmpAnimScrPlugin::ReloadNeeded()
       
   662     {
       
   663     // Assume reload needed
       
   664     TBool needed = ETrue;
       
   665 
       
   666     switch (iLoadedAnimation)
       
   667         {
       
   668         case EPortrait:
       
   669             // No reload if display portrait
       
   670             if (!DisplayIsLandscape())
       
   671                 {
       
   672                 needed = EFalse;
       
   673                 }
       
   674             break;
       
   675 
       
   676         case ELandscape:
       
   677         case EPortraitRotated:
       
   678             // No reload if display landscape
       
   679             if (DisplayIsLandscape())
       
   680                 {
       
   681                 needed = EFalse;
       
   682                 }
       
   683             break;
       
   684             
       
   685         case ENone:
       
   686         default:
       
   687             // Reload
       
   688             break;
       
   689         }
       
   690 
       
   691     return needed;
       
   692     }
       
   693 
       
   694     
       
   695 // Returns ETrue if display in landscape
       
   696 TBool CBmpAnimScrPlugin::DisplayIsLandscape()
       
   697     {
       
   698     // Should actually check the rotation and stuff, but what the hey...
       
   699     return (iDi.iRect.Width() > iDi.iRect.Height());
       
   700     }
       
   701 
       
   702 
       
   703 // Returns ETrue if graphics should be rotated
       
   704 TBool CBmpAnimScrPlugin::RotateNeeded()
       
   705     {
       
   706     // Rotate needed, if only portrait graphics are used, and
       
   707     // display is landscape
       
   708     return ((!iSettings->UseLandscape()) && (DisplayIsLandscape()));
       
   709     }
       
   710 
       
   711 
       
   712 // Returns ETrue if landscape graphics should be loaded
       
   713 TBool CBmpAnimScrPlugin::LoadLandscape()
       
   714     {
       
   715     // Landscape, if only available and display is landscape
       
   716     return ((iSettings->UseLandscape()) && (DisplayIsLandscape()));
       
   717     }
       
   718     
       
   719     
       
   720 // Updates the saved information about display
       
   721 void CBmpAnimScrPlugin::UpdateDisplayInfo()
       
   722     {
       
   723     iDi.iSize = sizeof(TScreensaverDisplayInfo);
       
   724     iHost->DisplayInfo(&iDi);
       
   725     }
       
   726 
       
   727 #if 0
       
   728 // Rotates and scales a source bitmap into target bitmap (non-leaving wrapper)
       
   729 TInt CBmpAnimScrPlugin::SetSizeAndRotation(
       
   730     CFbsBitmap* aBmp, TSize aSize, TInt aAngle)
       
   731     {
       
   732     // Anything to do?
       
   733     if ((aBmp) && (aBmp->SizeInPixels() == aSize) && ((aAngle % 360) == 0))
       
   734         {
       
   735         // Duh, the bitmap is already as requested
       
   736         return KErrNone;
       
   737         }
       
   738 
       
   739     // Call the actual workhorse
       
   740     TRAPD(err, SetSizeAndRotationL(aBmp, aSize, aAngle));
       
   741 
       
   742     return err;
       
   743     }
       
   744 
       
   745 
       
   746 // Rotates and scales a source bitmap into target bitmap (leaving version)
       
   747 void CBmpAnimScrPlugin::SetSizeAndRotationL(
       
   748     CFbsBitmap* aBmp, TSize aSize, TInt aAngle)
       
   749     {
       
   750     // Make a copy of the source bitmap, and use the original source as target
       
   751     CFbsBitmap* tmpBmp = new (ELeave) CFbsBitmap;
       
   752     CleanupStack::PushL(tmpBmp);
       
   753 
       
   754     User::LeaveIfError(tmpBmp->Duplicate(aBmp->Handle()));
       
   755     
       
   756     // Discard original bitmap
       
   757     aBmp->Reset();
       
   758 
       
   759     // Create new target bitmap in the original object
       
   760     User::LeaveIfError(aBmp->Create(aSize, tmpBmp->DisplayMode()));
       
   761 
       
   762     // Let the workhorse do its work
       
   763     RotateAndScaleBitmapL(TRect(aSize), aBmp, tmpBmp, aAngle);
       
   764 
       
   765     // Not interested in original anymore
       
   766     CleanupStack::PopAndDestroy(tmpBmp);
       
   767     }
       
   768     
       
   769 
       
   770 // Rotates and scales a source bitmap into target bitmap
       
   771 void CBmpAnimScrPlugin::RotateAndScaleBitmapL(
       
   772     const TRect& aTrgRect,
       
   773     CFbsBitmap* aTrgBitmap, 
       
   774     CFbsBitmap* aSrcBitmap,
       
   775     TInt aAngle)
       
   776     {
       
   777     aAngle = aAngle % 360;
       
   778     if (aAngle < 0)
       
   779         {
       
   780         aAngle+=360;
       
   781         }
       
   782 
       
   783     if (!aSrcBitmap) User::Leave(KErrArgument);
       
   784     if (!aTrgBitmap) User::Leave(KErrArgument);
       
   785     if (aSrcBitmap->DisplayMode() != aTrgBitmap->DisplayMode()) 
       
   786         User::Leave(KErrArgument);
       
   787     
       
   788     TSize trgBitmapSize = aTrgBitmap->SizeInPixels();
       
   789     if ((trgBitmapSize.iHeight < aTrgRect.iBr.iY) ||
       
   790         (trgBitmapSize.iWidth < aTrgRect.iBr.iX))
       
   791         {
       
   792         User::Leave(KErrArgument);
       
   793         }
       
   794 
       
   795     if (aTrgRect.IsEmpty())
       
   796         return;
       
   797 
       
   798     TSize srcSize = aSrcBitmap->SizeInPixels();
       
   799 
       
   800     TInt centerX = srcSize.iWidth / 2;
       
   801     TInt centerY = srcSize.iHeight / 2;
       
   802 
       
   803     TInt trgWidth = aTrgRect.Width();
       
   804     TInt trgHeight = aTrgRect.Height();
       
   805     
       
   806     TInt scalefactor = 65536;
       
   807     TInt xscalefactor = (srcSize.iWidth << 16) / trgWidth;
       
   808     TInt yscalefactor = (srcSize.iHeight << 16) / trgHeight;
       
   809 
       
   810     // Check if rotating 90 left or right, no need to scale
       
   811     if (((aAngle == 270) || (aAngle == 90)) &&
       
   812         (srcSize.iWidth == trgHeight) &&
       
   813         (srcSize.iHeight == trgWidth))
       
   814             {
       
   815             scalefactor = 65535;
       
   816             }
       
   817         else
       
   818             {
       
   819             if (xscalefactor < yscalefactor)
       
   820                 {
       
   821                 scalefactor = yscalefactor;
       
   822                 }
       
   823             else
       
   824                 {
       
   825                 scalefactor = xscalefactor;
       
   826                 }
       
   827             }
       
   828     
       
   829         TBool srcTemporary = EFalse;
       
   830         TBool hardMask = EFalse;
       
   831         if (aSrcBitmap->IsRomBitmap())
       
   832             {
       
   833             srcTemporary = ETrue;
       
   834             }
       
   835         if (aSrcBitmap->IsCompressedInRAM())
       
   836             {
       
   837             srcTemporary = ETrue;
       
   838             }
       
   839 
       
   840         TBool fallbackOnly = EFalse;
       
   841         TDisplayMode displayMode = aSrcBitmap->DisplayMode();
       
   842         TUint8 fillColor = 0;
       
   843         
       
   844         switch(displayMode)
       
   845             {
       
   846             case EGray2:
       
   847                 srcTemporary = ETrue;
       
   848                 hardMask = ETrue;
       
   849                 fillColor = 0xff; // white
       
   850                 break;
       
   851             case EGray4:
       
   852             case EGray16:
       
   853             case EColor16:
       
   854             case EColor16M:
       
   855             case ERgb:
       
   856                 fallbackOnly = ETrue;
       
   857                 break;
       
   858             case EColor256:
       
   859                 fillColor = 0xff; // should be black in our indexed palette....
       
   860             case EGray256:
       
   861             case EColor4K:
       
   862             case EColor64K:
       
   863 
       
   864             case EColor16MU:
       
   865             // These are the supported modes
       
   866                 break;
       
   867             default:
       
   868                 fallbackOnly = ETrue;
       
   869             }
       
   870 
       
   871         if (fallbackOnly)
       
   872             {
       
   873             // Color mode not supported
       
   874             User::Leave(KErrNotSupported);
       
   875             }
       
   876 
       
   877         CFbsBitmap* realSource = aSrcBitmap;
       
   878         CFbsBitmap* realTarget = aTrgBitmap;
       
   879         if (srcTemporary)
       
   880             {
       
   881             realSource = new (ELeave) CFbsBitmap();
       
   882             CleanupStack::PushL(realSource);
       
   883             if (hardMask)
       
   884                 {
       
   885                 realTarget = new (ELeave) CFbsBitmap();
       
   886                 CleanupStack::PushL(realTarget);
       
   887                 User::LeaveIfError(realSource->Create(srcSize, EGray256));
       
   888                 displayMode = EGray256;
       
   889                 User::LeaveIfError(realTarget->Create(
       
   890                     aTrgBitmap->SizeInPixels(), EGray256));
       
   891                 }
       
   892             else
       
   893                 {
       
   894                 User::LeaveIfError(realSource->Create(
       
   895                     srcSize, aSrcBitmap->DisplayMode()));
       
   896                 }
       
   897 
       
   898             CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(realSource);
       
   899             CleanupStack::PushL(dev);
       
   900             CFbsBitGc* gc = NULL;
       
   901             User::LeaveIfError(dev->CreateContext(gc));
       
   902             CleanupStack::PushL(gc);
       
   903             gc->BitBlt(TPoint(0,0), aSrcBitmap);
       
   904             CleanupStack::PopAndDestroy(2); // dev, gc
       
   905             }
       
   906 
       
   907         // Heap lock for FBServ large chunk is only needed with large bitmaps.
       
   908         if (realSource->IsLargeBitmap() || realTarget->IsLargeBitmap())
       
   909             {
       
   910             realTarget->LockHeapLC(ETrue); // fbsheaplock
       
   911             }
       
   912         else
       
   913             {
       
   914             // Bogus push so we can pop() anyway
       
   915             CleanupStack::PushL((TAny*)NULL);
       
   916             }
       
   917 
       
   918         TUint32* srcAddress = realSource->DataAddress();
       
   919         TUint32* trgAddress = realTarget->DataAddress();
       
   920 
       
   921         TReal realsin;
       
   922         TReal realcos;
       
   923         TInt sin;
       
   924         TInt cos;
       
   925 
       
   926         User::LeaveIfError(Math::Sin(realsin, ((2*KPi)/360) * aAngle));
       
   927         User::LeaveIfError(Math::Cos(realcos, ((2*KPi)/360) * aAngle));
       
   928 
       
   929         sin = ((TInt)(realsin * scalefactor));
       
   930         cos = ((TInt)(realcos * scalefactor));
       
   931 
       
   932         TInt xx = ((trgWidth)/2) - ((srcSize.iWidth/2) - centerX);
       
   933         TInt yy = ((trgHeight)/2) - ((srcSize.iHeight/2) - centerY);
       
   934 
       
   935         TInt x = 0;
       
   936         TInt y = 0;
       
   937         TInt u = 0;
       
   938         TInt v = 0;
       
   939 
       
   940         if( (displayMode==EGray256) || (displayMode==EColor256) )
       
   941             {
       
   942             TInt srcScanLen8 = CFbsBitmap::ScanLineLength(
       
   943                 srcSize.iWidth, displayMode);
       
   944             TInt trgScanLen8 = CFbsBitmap::ScanLineLength(
       
   945                 trgBitmapSize.iWidth, displayMode);
       
   946             TUint8* srcAddr8 = reinterpret_cast<TUint8*>(srcAddress);
       
   947             TUint8* trgAddr8 = reinterpret_cast<TUint8*>(trgAddress);
       
   948 
       
   949             // skip left and top margins in the beginning
       
   950             trgAddr8 += trgScanLen8 * aTrgRect.iTl.iY + aTrgRect.iTl.iX;
       
   951 
       
   952             for (y = 0; y < trgHeight; y++)
       
   953                 {
       
   954                 u = (-xx) * cos + (y-yy) * sin + (centerX<<16);
       
   955                 v = (y-yy) * cos - (-xx) * sin + (centerY<<16);
       
   956                 for (x = 0; x < trgWidth; x++)
       
   957                     {
       
   958                     if (((u>>16)>=srcSize.iWidth) ||
       
   959                          ((v>>16)>=srcSize.iHeight) ||
       
   960                          ((u>>16)<0) ||
       
   961                          ((v>>16)<0)) 
       
   962                         {
       
   963                         *trgAddr8++ = fillColor;
       
   964                         }
       
   965                     else
       
   966                         {            	
       
   967                         *trgAddr8++ = srcAddr8[(u>>16)+(((v>>16))*srcScanLen8)];
       
   968                         }
       
   969                     u += cos;
       
   970                     v -= sin;
       
   971                     }
       
   972                 trgAddr8 += trgScanLen8 - trgWidth;
       
   973                 }
       
   974             }
       
   975         else if( displayMode == EColor64K || displayMode == EColor4K)
       
   976             {
       
   977             TInt srcScanLen16 = CFbsBitmap::ScanLineLength(
       
   978                 srcSize.iWidth, displayMode) / 2;
       
   979             TInt trgScanLen16 = CFbsBitmap::ScanLineLength(
       
   980                 trgBitmapSize.iWidth, displayMode) / 2;
       
   981             TUint16* srcAddr16 = reinterpret_cast<TUint16*>(srcAddress);
       
   982             TUint16* trgAddr16 = reinterpret_cast<TUint16*>(trgAddress);
       
   983 
       
   984             // skip left and top margins in the beginning
       
   985             trgAddr16 += trgScanLen16 * aTrgRect.iTl.iY + aTrgRect.iTl.iX;
       
   986 
       
   987             for (y = 0; y < trgHeight; y++)
       
   988                 {
       
   989                 u = (-xx) * cos + (y-yy) * sin + (centerX<<16);
       
   990                 v = (y-yy) * cos - (-xx) * sin + (centerY<<16);
       
   991                 for (x = 0; x < trgWidth; x++)
       
   992                     {
       
   993                     if (((u>>16)>=srcSize.iWidth) ||
       
   994                         ((v>>16)>=srcSize.iHeight) ||
       
   995                         ((u>>16)<0) ||
       
   996                         ((v>>16)<0)) 
       
   997                         {
       
   998                         *trgAddr16++ = 0;
       
   999                         }
       
  1000                     else
       
  1001                         {
       
  1002                         *trgAddr16++ =
       
  1003                             srcAddr16[(u>>16)+(((v>>16))*srcScanLen16)];
       
  1004                         }
       
  1005                     u += cos;
       
  1006                     v -= sin;
       
  1007                     }
       
  1008                 trgAddr16 += trgScanLen16 - trgWidth;
       
  1009                 }        
       
  1010             }
       
  1011         else if(displayMode == EColor16MU)
       
  1012             {
       
  1013             TInt srcScanLen32 = CFbsBitmap::ScanLineLength(
       
  1014                 srcSize.iWidth, displayMode) / 4;
       
  1015             TInt trgScanLen32 = CFbsBitmap::ScanLineLength(
       
  1016                 trgBitmapSize.iWidth, displayMode) / 4;
       
  1017             TUint32* srcAddr32 = srcAddress;
       
  1018             TUint32* trgAddr32 = trgAddress;
       
  1019 
       
  1020             // skip left and top margins in the beginning
       
  1021             trgAddr32 += trgScanLen32 * aTrgRect.iTl.iY + aTrgRect.iTl.iX;
       
  1022 
       
  1023             for (y = 0; y < trgHeight; y++)
       
  1024                 {
       
  1025                 u = (-xx) * cos + (y-yy) * sin + (centerX<<16);
       
  1026                 v = (y-yy) * cos - (-xx) * sin + (centerY<<16);
       
  1027                 for (x = 0; x < trgWidth; x++)
       
  1028                     {
       
  1029                     if (((u>>16)>=srcSize.iWidth) ||
       
  1030                         ((v>>16)>=srcSize.iHeight) ||
       
  1031                         ((u>>16)<0) ||
       
  1032                         ((v>>16)<0)) 
       
  1033                         {
       
  1034                         *trgAddr32++ = 0;
       
  1035                         }
       
  1036                     else
       
  1037                         {
       
  1038                         *trgAddr32++ =
       
  1039                             srcAddr32[(u>>16)+(((v>>16))*srcScanLen32)];
       
  1040                         } 
       
  1041                     u += cos;
       
  1042                     v -= sin;
       
  1043                     }
       
  1044                 trgAddr32 += trgScanLen32 - trgWidth;
       
  1045                 }
       
  1046             }
       
  1047         else
       
  1048             {
       
  1049             // Display mode not supported - but this should've been caught
       
  1050             // already earlier
       
  1051             User::Leave(KErrUnknown);
       
  1052             }
       
  1053 
       
  1054         CleanupStack::PopAndDestroy(); // fbsheaplock
       
  1055 
       
  1056         if (srcTemporary)
       
  1057             {
       
  1058             if (hardMask)
       
  1059                 {
       
  1060                 CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(aTrgBitmap);
       
  1061                 CleanupStack::PushL(dev);
       
  1062                 CFbsBitGc* gc = NULL;
       
  1063                 User::LeaveIfError(dev->CreateContext(gc));
       
  1064                 CleanupStack::PushL(gc);  
       
  1065                 gc->BitBlt(TPoint(0,0), realTarget);
       
  1066                 CleanupStack::PopAndDestroy(3); // dev, gc, realtarget
       
  1067                 }
       
  1068             CleanupStack::PopAndDestroy(); // realSource
       
  1069             }
       
  1070         }
       
  1071 #endif
       
  1072     
       
  1073 // End of file