photosgallery/slideshow/engine/effectsrc/shwzoomandpaneffect.cpp
changeset 0 4e91876724a2
child 14 ce1c7ad1f18b
child 16 0bc0ea26031e
equal deleted inserted replaced
-1:000000000000 0:4e91876724a2
       
     1 /*
       
     2 * Copyright (c) 2007-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:    The zoom and pan effect
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 //  Include Files
       
    22 #include "shwzoomandpaneffect.h"
       
    23 
       
    24 #include <glxsetvaluelayout.h>
       
    25 #include <alf/alfvisual.h>
       
    26 
       
    27 #include <alf/alfcurvepath.h>
       
    28 #include <alf/alftimedvalue.h>
       
    29 
       
    30 #include "shwresourceutility.h"
       
    31 #include "shwzoomandpanlayout.h"
       
    32 #include "shwcurvefactory.h"
       
    33 #include "shwconstants.h"
       
    34 #include "shwslideshowenginepanic.h"
       
    35 #include "shwcrossfadelayout.h"
       
    36 #include "shwtimer.h"
       
    37 #include "shwcallback.h"
       
    38 #include "shwgeometryutilities.h"
       
    39 
       
    40 #include <glxlog.h>
       
    41 
       
    42 using namespace NShwSlideshow;
       
    43 
       
    44 /**
       
    45  * CShwZoomAndPanEffectImpl
       
    46  * Zoom and pan dependencies
       
    47  * This class makes our clients indepandant of the effect implementation
       
    48  * This gives greater flexibitily in testing as the test suites can just
       
    49  * re-implement all the methods in the real class interface without the 
       
    50  * need to stub all our real dependencies. 
       
    51  * If for example TShwCrossFadeLayout was a direct member of
       
    52  * CShwZoomAndPanEffect class, all the clients would need to have access 
       
    53  * to TShwCrossFadeLayout constructor and destructor and the test suite
       
    54  * would need to either create a stub implementation for it or include
       
    55  * the real class in the test (and all its dependencies)
       
    56  *
       
    57  * There is however no point of duplicating the whole CShwZoomAndPanEffect
       
    58  * interface as it would mean double maintenance
       
    59  * so we use the iImpl pointer when referencing the class members
       
    60  */
       
    61 NONSHARABLE_CLASS( CShwZoomAndPanEffect::CShwZoomAndPanEffectImpl )
       
    62 	: public CBase
       
    63 	{
       
    64 	public:
       
    65 		
       
    66 		/**
       
    67 		 * Constructor
       
    68 		 */
       
    69 		inline CShwZoomAndPanEffectImpl();
       
    70 
       
    71 		/**
       
    72 		 * Destructor
       
    73 		 */
       
    74 		inline ~CShwZoomAndPanEffectImpl();
       
    75 
       
    76 		/**
       
    77 		 * 2nd phase constructor
       
    78 		 */
       
    79 		inline void ConstructL();
       
    80 
       
    81 	public:	// Data
       
    82 
       
    83 		/// Own: the size of the screen
       
    84 		TSize iScreenSize;
       
    85 		/// Own: the maximum thumbnail size
       
    86 		TSize iMaxThumbnailSize;
       
    87 		/// Own: the opacity layout
       
    88 		TShwCrossFadeLayout iOpacityLayout;
       
    89 		/// Own: the zoom and pan layout
       
    90 		TShwZoomAndPanLayout iZoomAndPanLayout;
       
    91 		/// Own: the pan curve
       
    92 		CAlfCurvePath* iCurve;
       
    93 		/// Own: Zoom and pan loop timer
       
    94 		CShwTimer* iLoopTimer;
       
    95 		/// Own: flag that defines if the image is large enough for zoom&pan
       
    96 		TBool iShouldZoom;
       
    97         /// Own: Count to change the zoom direction
       
    98         TInt iCount;
       
    99 		/// Own: the effect's info.
       
   100 		TShwEffectInfo iEffectInfo;
       
   101 
       
   102 	};
       
   103 
       
   104 // -----------------------------------------------------------------------------
       
   105 // C++ Constructor. Save a few bits of rom with inlining
       
   106 // -----------------------------------------------------------------------------
       
   107 inline CShwZoomAndPanEffect::CShwZoomAndPanEffectImpl::CShwZoomAndPanEffectImpl()
       
   108 	{
       
   109 	// CBase clears the values
       
   110 	// set layout chain
       
   111 	iOpacityLayout.SetNext( &iZoomAndPanLayout );
       
   112 	}
       
   113 
       
   114 // -----------------------------------------------------------------------------
       
   115 // Destructor. Save a few bits of rom with inlining
       
   116 // -----------------------------------------------------------------------------
       
   117 inline CShwZoomAndPanEffect::CShwZoomAndPanEffectImpl::~CShwZoomAndPanEffectImpl()
       
   118 	{
       
   119 	delete iCurve;
       
   120 	delete iLoopTimer;
       
   121 	}
       
   122 
       
   123 // -----------------------------------------------------------------------------
       
   124 // 2nd phase constructor for the implementation
       
   125 // -----------------------------------------------------------------------------
       
   126 inline void CShwZoomAndPanEffect::CShwZoomAndPanEffectImpl::ConstructL()
       
   127     {
       
   128     // timer for zoom and pan looping
       
   129     iLoopTimer = CShwTimer::NewL( CActive::EPriorityStandard );
       
   130 
       
   131     // load string for effect name, no need to cleanup stack 
       
   132     // as no leaves between here and delete
       
   133     HBufC* effectName = 
       
   134         ShwResourceUtility::LocalisedNameL( R_SHW_EFFECT_ZOOM_AND_PAN );
       
   135     if( !effectName )
       
   136         {
       
   137         // have to use a non-localised version
       
   138         iEffectInfo.iName = KEffectNameZoomAndPan;
       
   139         }
       
   140     else
       
   141         {
       
   142         // set the localised version
       
   143         iEffectInfo.iName = *effectName;
       
   144         }
       
   145 
       
   146     // info - uid
       
   147     iEffectInfo.iId.iPluginUid = KDefaultEffectPluginUid;
       
   148     iEffectInfo.iId.iIndex     = KEffectUidZoomAndPan;
       
   149     // delete the local string
       
   150     delete effectName;
       
   151     }
       
   152 
       
   153 // -----------------------------------------------------------------------------
       
   154 // C++ Constructor. Save a few bits of rom with inlining
       
   155 // -----------------------------------------------------------------------------
       
   156 inline CShwZoomAndPanEffect::CShwZoomAndPanEffect()
       
   157 	{
       
   158 	}
       
   159 
       
   160 // -----------------------------------------------------------------------------
       
   161 // NewLC. Static construction
       
   162 // -----------------------------------------------------------------------------
       
   163 CShwZoomAndPanEffect* CShwZoomAndPanEffect::NewLC()
       
   164 	{
       
   165 	CShwZoomAndPanEffect* self = new (ELeave) CShwZoomAndPanEffect;
       
   166 	CleanupStack::PushL( self );
       
   167     
       
   168 	// create the implementation class
       
   169     self->iImpl = new( ELeave ) CShwZoomAndPanEffectImpl;
       
   170     // do the second phase, if it leaves impl will be deleted
       
   171 	self->iImpl->ConstructL();
       
   172 
       
   173 	return self;
       
   174 	}
       
   175 
       
   176 // -----------------------------------------------------------------------------
       
   177 // Destructor
       
   178 // -----------------------------------------------------------------------------
       
   179 CShwZoomAndPanEffect::~CShwZoomAndPanEffect()
       
   180 	{
       
   181 	delete iImpl;
       
   182 	}
       
   183 
       
   184 // -----------------------------------------------------------------------------
       
   185 // CloneLC
       
   186 // -----------------------------------------------------------------------------
       
   187 MShwEffect* CShwZoomAndPanEffect::CloneLC()
       
   188 	{
       
   189 	GLX_LOG_INFO( "CShwZoomAndPanEffect::CloneLC" );
       
   190 	// create a copy
       
   191 	CShwZoomAndPanEffect* copy = CShwZoomAndPanEffect::NewLC();
       
   192 	// transfer the member variables, only screen 
       
   193 	// size has relevant value this point
       
   194 	copy->iImpl->iScreenSize = iImpl->iScreenSize;
       
   195 	// set count to be one greater so it has a different zoom direction
       
   196 	copy->iImpl->iCount = iImpl->iCount + 1;
       
   197     // copy the max thumbnail size
       
   198     copy->iImpl->iMaxThumbnailSize = iImpl->iMaxThumbnailSize;
       
   199 	// return the clone
       
   200 	return copy;
       
   201 	}
       
   202 
       
   203 // -----------------------------------------------------------------------------
       
   204 // InitializeL
       
   205 // -----------------------------------------------------------------------------
       
   206 void CShwZoomAndPanEffect::InitializeL( 
       
   207 	CAlfEnv* /*aHuiEnv*/, MGlxVisualList* /*aVisualList*/,
       
   208     MGlxMediaList* /*aMediaList*/, TSize aScreenSize )
       
   209 	{
       
   210 	GLX_LOG_INFO( "CShwZoomAndPanEffect::SetHuiEnv" );
       
   211 	// set the screen size
       
   212 	iImpl->iScreenSize = aScreenSize;
       
   213 
       
   214     // zoom and pan wants at least triple the screen size thumbnails
       
   215     TInt width = iImpl->iScreenSize.iWidth;
       
   216     TInt height = iImpl->iScreenSize.iHeight;
       
   217 
       
   218     // set the maximum thumbnail size, we need to optimize memory usage
       
   219     // so dont load more pixels than KMaxThumbnailSize x Screen size thumbnail
       
   220     iImpl->iMaxThumbnailSize.iWidth = width * KMaxThumbnailSize;
       
   221 	iImpl->iMaxThumbnailSize.iHeight = height * KMaxThumbnailSize;
       
   222 	}
       
   223 
       
   224 // -----------------------------------------------------------------------------
       
   225 // PrepareViewL
       
   226 // -----------------------------------------------------------------------------
       
   227 TSize CShwZoomAndPanEffect::PrepareViewL( 
       
   228 	CAlfVisual* /*aVisual*/, TSize aImageSize )
       
   229 	{
       
   230 	GLX_LOG_INFO( "CShwZoomAndPanEffect::PrepareViewL()" );
       
   231 
       
   232     // use the namespace for coord utilities
       
   233     using namespace NShwGeometryUtilities;
       
   234 
       
   235     TSize originalImageSize = aImageSize;
       
   236     // take a local copy of the size
       
   237     TSize thumbnailSize = aImageSize;
       
   238     // check that size was really found
       
   239     if( ( aImageSize.iWidth == KErrNotFound )|| 
       
   240         ( aImageSize.iHeight == KErrNotFound ) )
       
   241         {
       
   242         // size attribute not available so use screen size
       
   243         thumbnailSize = iImpl->iScreenSize;
       
   244         // need to also adjust aImageSize as its used further to make sure
       
   245         // we dont load too big thumbnail; in this case we load screen size
       
   246         originalImageSize = iImpl->iScreenSize;
       
   247         }
       
   248 
       
   249     // calculate zoom first as after that we know the real panning
       
   250 	// optimist assumes we can zoom every image
       
   251 	iImpl->iShouldZoom = ETrue;
       
   252 	// set the sizes for layout chain, return value is the zoom factor
       
   253 	TReal32 zoomFactor = 
       
   254 		iImpl->iZoomAndPanLayout.SetSizes( 
       
   255 			iImpl->iScreenSize, thumbnailSize, iImpl->iMaxThumbnailSize );
       
   256 	// if the zoomfactor is smaller than minimal desired, dont zoom&pan
       
   257 	if( zoomFactor < KMinZoomAndPanFactor )
       
   258 		{
       
   259 		iImpl->iShouldZoom = EFalse;
       
   260 		}
       
   261     // ask for the maximum size from the layout
       
   262     TSize maxSize = iImpl->iZoomAndPanLayout.MaximumSize();
       
   263     // make sure we don't load the image larger than maximum size
       
   264     thumbnailSize = maxSize;
       
   265     // thumbnail is never loaded larger than image size, 
       
   266     // either in image size or smaller... zooming may go past image size though
       
   267     FitInsideBox( 
       
   268         thumbnailSize.iWidth, thumbnailSize.iHeight,
       
   269         originalImageSize.iWidth, originalImageSize.iHeight );
       
   270 
       
   271 	// calculate the area for the curve using the maximum size
       
   272 	// it must not cause the panning to get outside screen so need to calculate
       
   273 	// the delta box. We dont allow negative pan, 
       
   274 	// however we need to support panning only in either direction.
       
   275     // Note that curve will have negative values, its just curve -defining 
       
   276     // box that we make positive as negative value means too small image to pan
       
   277     TInt curveWidth = Max( 
       
   278         ( maxSize.iWidth - iImpl->iScreenSize.iWidth ) / 2,
       
   279         0 );
       
   280     TInt curveHeight = Max( 
       
   281         ( maxSize.iHeight - iImpl->iScreenSize.iHeight ) / 2,
       
   282         0 );
       
   283 	// delete old curve and set to NULL to prevent double delete
       
   284 	delete iImpl->iCurve;
       
   285 	iImpl->iCurve = NULL;
       
   286 	// if both are zero, dont bother creating curve
       
   287 	if( ( curveWidth > 0 ) || ( curveHeight > 0 ) )
       
   288 		{
       
   289     	// create size
       
   290     	TSize curvearea( curveWidth, curveHeight );
       
   291 
       
   292 		// construct new curve inside TRAP, if it fails we just dont pan
       
   293 	    TRAP_IGNORE(
       
   294 	        {
       
   295 	        CAlfCurvePath* curve = 
       
   296 	            NShwCurveFactory::CreateEllipsisL( 
       
   297 	                curvearea, KZoomAndPanCurveLength );
       
   298 	        // set new curve
       
   299 	        iImpl->iCurve = curve;
       
   300 	        } );
       
   301 		}
       
   302 	// set the curve for the layout, its ok to set NULL
       
   303 //	iImpl->iZoomAndPanLayout.SetPanningCurve( iImpl->iCurve );
       
   304 
       
   305     // return the calculated thumbnail size
       
   306     return thumbnailSize;
       
   307 	}
       
   308 
       
   309 // -----------------------------------------------------------------------------
       
   310 // EnterViewL
       
   311 // -----------------------------------------------------------------------------
       
   312 MGlxLayout* CShwZoomAndPanEffect::EnterViewL(
       
   313 	CAlfVisual* /*aVisual*/, TInt aDuration, TInt aFadeInDuration )
       
   314     {
       
   315 	GLX_LOG_INFO1( 
       
   316 		"CShwZoomAndPanEffect::EnterViewL( %d )", aDuration );
       
   317 
       
   318 	// calculate zoom&pan length
       
   319 	// minimum length is the view duration and transition duration * 2
       
   320 	// this is because there is transition, view and transition while
       
   321 	// this visual is visible (at least partially)
       
   322 	TInt zoom_and_pan_dur = aDuration + aFadeInDuration * 2;
       
   323     
       
   324 	// set value, 0% -> 100%
       
   325 	iImpl->iOpacityLayout.Set( KMinOpacity );
       
   326 	iImpl->iOpacityLayout.Set( KMaxOpacity, aFadeInDuration );
       
   327 
       
   328 	// check if the image was large enough for zooming
       
   329 	if( iImpl->iShouldZoom )
       
   330 		{
       
   331 		// start with zoom in
       
   332 		TShwZoomAndPanLayout::TZoomDirection zoomdir = 
       
   333 			TShwZoomAndPanLayout::EZoomIn;
       
   334 		if( iImpl->iCount % 2 )
       
   335 			{
       
   336 			zoomdir = TShwZoomAndPanLayout::EZoomOut;
       
   337 			}
       
   338 
       
   339 		// start zoom
       
   340 		// minimum length is the view duration and transition duration * 2
       
   341 		// this is because there is transition, view and transition while
       
   342 		// this visual is visible (at least partially)
       
   343 		iImpl->iZoomAndPanLayout.StartZoom( 
       
   344 			zoomdir, zoom_and_pan_dur );
       
   345 
       
   346 		// need to start a timer to invert the zoom in case image load 
       
   347 		// takes longer than view mode lasts
       
   348 		iImpl->iLoopTimer->Start( 
       
   349 			zoom_and_pan_dur, 
       
   350 			zoom_and_pan_dur,
       
   351 			TShwCallBack< 
       
   352 				TShwZoomAndPanLayout, 
       
   353 				TShwZoomAndPanLayout::InvertZoom >( 
       
   354 				&iImpl->iZoomAndPanLayout ) );
       
   355 		}
       
   356 	else
       
   357 		{
       
   358 		// reset the size to minimum
       
   359 		iImpl->iZoomAndPanLayout.ResetSizeToMinimum();
       
   360 		// cancel loop timer in case it is running, if not then 
       
   361 		// this is a no-op
       
   362 		iImpl->iLoopTimer->Cancel();
       
   363 		}
       
   364 	// return layout chain
       
   365 	return &iImpl->iOpacityLayout;
       
   366     }
       
   367 
       
   368 // -----------------------------------------------------------------------------
       
   369 // ExitView
       
   370 // -----------------------------------------------------------------------------
       
   371 void CShwZoomAndPanEffect::ExitView( CAlfVisual* /*aVisual*/ )
       
   372     {
       
   373 	GLX_LOG_INFO( "CShwZoomAndPanEffect::ExitView" );
       
   374 	// Cancel the loop timer as we are already going to the 
       
   375 	// next effect and visual
       
   376 	iImpl->iLoopTimer->Cancel();
       
   377     }
       
   378 
       
   379 // -----------------------------------------------------------------------------
       
   380 // EnterTransitionL
       
   381 // -----------------------------------------------------------------------------
       
   382 MGlxLayout* CShwZoomAndPanEffect::EnterTransitionL(
       
   383 	CAlfVisual* /*aVisual*/, TInt aDuration )
       
   384     {
       
   385     GLX_LOG_INFO1( "CShwZoomAndPanEffect::EnterTransitionL( %d )", aDuration );
       
   386 
       
   387 	// increase count, so every other time we can zoom in and out but only if we 
       
   388 	// really got to transition
       
   389 	iImpl->iCount++;
       
   390 
       
   391 	// set value, drop from 100% to 0%
       
   392     iImpl->iOpacityLayout.Set( KMaxOpacity );
       
   393     iImpl->iOpacityLayout.Set( KMinOpacity, aDuration );
       
   394 
       
   395 	return &iImpl->iOpacityLayout;
       
   396     }
       
   397 
       
   398 // -----------------------------------------------------------------------------
       
   399 // ExitTransition
       
   400 // -----------------------------------------------------------------------------
       
   401 void CShwZoomAndPanEffect::ExitTransition( CAlfVisual* /*aVisual*/ )
       
   402     {
       
   403 	GLX_LOG_INFO( "CShwZoomAndPanEffect::ExitTransition" );
       
   404     }
       
   405 
       
   406 // -----------------------------------------------------------------------------
       
   407 // PauseL
       
   408 // -----------------------------------------------------------------------------
       
   409 void CShwZoomAndPanEffect::PauseL()
       
   410     {
       
   411 	GLX_LOG_INFO( "CShwZoomAndPanEffect::PauseL" );
       
   412 	// need to pause the layouts, start with opacity
       
   413 	iImpl->iOpacityLayout.Pause();
       
   414 	// freeze zoom and pan layout
       
   415 	iImpl->iZoomAndPanLayout.Pause();
       
   416 	// pause loop timer, it is safe to pause the timer even if its not active
       
   417     iImpl->iLoopTimer->Pause();
       
   418 	}
       
   419 
       
   420 // -----------------------------------------------------------------------------
       
   421 // Resume
       
   422 // -----------------------------------------------------------------------------
       
   423 void CShwZoomAndPanEffect::Resume()
       
   424     {
       
   425 	GLX_LOG_INFO( "CShwZoomAndPanEffect::Resume" );
       
   426 	// resume layouts
       
   427 	// start with opacity
       
   428 	iImpl->iOpacityLayout.Resume();
       
   429 	// resume zoom and pan layout
       
   430 	iImpl->iZoomAndPanLayout.Resume();
       
   431 	// resume loop timer
       
   432 	iImpl->iLoopTimer->Resume();
       
   433     }
       
   434 
       
   435 // -----------------------------------------------------------------------------
       
   436 // EffectInfo.
       
   437 // -----------------------------------------------------------------------------
       
   438 TShwEffectInfo CShwZoomAndPanEffect::EffectInfo()
       
   439 	{
       
   440 	return iImpl->iEffectInfo;
       
   441 	}