imagehandlinglib/Src/CIHLImageViewer.cpp
changeset 0 2014ca87e772
equal deleted inserted replaced
-1:000000000000 0:2014ca87e772
       
     1 /*
       
     2 * Copyright (c) 2004 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:  Implementation of Image Viewer class.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "CIHLImageViewer.h"
       
    21 
       
    22 #include "CIHLBitmap.h"
       
    23 #include "CIHLBitmapProcessor.h"
       
    24 #include "IHLImplementationIds.h"
       
    25 #include "IHLDebugPrint.h" // Debug print
       
    26 #include <IHLInterfaceIds.h>
       
    27 #include <MIHLViewerObserver.h>
       
    28 #include <MIHLFileImage.h>
       
    29 #include <fbs.h>
       
    30 #include <e32math.h>
       
    31 
       
    32 // Private namespace for constants and functions
       
    33 namespace
       
    34 	{
       
    35 	// Panic function
       
    36     _LIT( KIHLPanicString, "IHLImageViewer" );
       
    37     void Panic( TInt aPanicCode ) { User::Panic( KIHLPanicString, aPanicCode ); }
       
    38 	}
       
    39 
       
    40 // ============================ MEMBER FUNCTIONS ===============================
       
    41 // -----------------------------------------------------------------------------
       
    42 //
       
    43 // C++ constructor can NOT contain any code, that might leave.
       
    44 // -----------------------------------------------------------------------------
       
    45 CIHLImageViewer::CIHLImageViewer( const TSize& aViewerSize,
       
    46 								  MIHLFileImage& aSource,
       
    47 								  MIHLBitmap& aDestination,
       
    48 								  MIHLViewerObserver& aObserver,
       
    49 								  const TUint32 aOptions )
       
    50 :CTimer( EPriorityNormal ), iObserver( aObserver ),
       
    51 iSource( aSource ), iDestination( aDestination ),
       
    52 iOptions( aOptions ), iViewerSize( aViewerSize ), iSrcBitmapScaleFactor(1)
       
    53     {
       
    54 	CActiveScheduler::Add( this );
       
    55 	iAnimDelay = 0;
       
    56 	iAnimLastFrameDrawTime = 0;
       
    57 	iAnimDrawStartFastTime = 0; 
       
    58     }
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 //
       
    62 // Two-phased constructor.
       
    63 // -----------------------------------------------------------------------------
       
    64 CIHLImageViewer* CIHLImageViewer::NewL( const TSize& aViewerSize,
       
    65 										MIHLFileImage& aSource,
       
    66 										MIHLBitmap& aDestination,
       
    67 										MIHLViewerObserver& aObserver,
       
    68 										const TUint32 aOptions )
       
    69     {
       
    70     CIHLImageViewer* self = new( ELeave ) CIHLImageViewer(
       
    71 		aViewerSize, aSource, aDestination, aObserver, aOptions );
       
    72     CleanupStack::PushL( self );
       
    73     self->ConstructL();
       
    74 	CleanupStack::Pop(); // self
       
    75     return self;
       
    76     }
       
    77 
       
    78 // -----------------------------------------------------------------------------
       
    79 //
       
    80 // Symbian constructor can leave.
       
    81 // -----------------------------------------------------------------------------
       
    82 void CIHLImageViewer::ConstructL()
       
    83 	{
       
    84 	CTimer::ConstructL();
       
    85 
       
    86 	HAL::Get(HALData::EFastCounterFrequency, iTickPeriod);
       
    87 	
       
    88 	iCacheSource = CIHLBitmap::NewL();
       
    89 	iCacheDestination = CIHLBitmap::NewL();
       
    90 	iProcessor = CIHLBitmapProcessor::NewL( iOptions );
       
    91 
       
    92 	// Initialize settings and start load (default is zoom to fit)
       
    93 	iSourceSize = iSource.Size();
       
    94 	CalculateZoomToFitRatio();
       
    95 	User::LeaveIfError( SetZoomRatio( iZoomToFitRatio ) );
       
    96 	}
       
    97 
       
    98 // -----------------------------------------------------------------------------
       
    99 // Destructor
       
   100 // -----------------------------------------------------------------------------
       
   101 CIHLImageViewer::~CIHLImageViewer()
       
   102     {
       
   103 	Cancel();
       
   104 	delete iProcessor;
       
   105 	delete iCacheDestination;
       
   106 	delete iCacheSource;
       
   107     }
       
   108 
       
   109 // -----------------------------------------------------------------------------
       
   110 // CIHLImageViewer::Id
       
   111 // -----------------------------------------------------------------------------
       
   112 TIHLInterfaceType CIHLImageViewer::Type() const
       
   113 	{
       
   114 	return TIHLInterfaceType( KIHLInterfaceIdImageViewer, KIHLImplementationIdImageViewer );
       
   115 	}
       
   116 
       
   117 // -----------------------------------------------------------------------------
       
   118 // CIHLImageViewer::IsAnimation
       
   119 // -----------------------------------------------------------------------------
       
   120 TBool CIHLImageViewer::IsAnimation() const
       
   121 	{
       
   122 	return iSource.IsAnimation();
       
   123 	}
       
   124 
       
   125 // -----------------------------------------------------------------------------
       
   126 // CIHLImageViewer::SheduleNextFrame
       
   127 // -----------------------------------------------------------------------------
       
   128 void CIHLImageViewer::SheduleNextFrame(TTimeIntervalMicroSeconds32 aDelay)
       
   129 	{
       
   130 	TInt delay=aDelay.Int();
       
   131 	
       
   132 	if (delay == 0) // 0 second deleay set in GIF file
       
   133 		{
       
   134 			iAnimDelay = TTimeIntervalMicroSeconds32(100000-iAnimLastFrameDrawTime);
       
   135 		}
       
   136 	else
       
   137 		{
       
   138 			iAnimDelay = delay - iAnimLastFrameDrawTime;
       
   139 		}
       
   140 	
       
   141 	if (iAnimDelay.Int() <=0) //last frame drawn longer than animation frame interval. 
       
   142 		{
       
   143 			iAnimDelay = KMinimumInterval;
       
   144 		}
       
   145 	iAnimInitFastTime=User::FastCounter(); //store the start time
       
   146 	HighRes(iAnimDelay);
       
   147 	}
       
   148 
       
   149 // -----------------------------------------------------------------------------
       
   150 // CIHLImageViewer::Play
       
   151 // -----------------------------------------------------------------------------
       
   152 void CIHLImageViewer::Play()
       
   153 	{
       
   154 	if( iSource.IsAnimation() )
       
   155 		{
       
   156 		iIsPlaying = ETrue;
       
   157 		if( iViewerState == EInactive)
       
   158 			{
       
   159 			iViewerState = EAnimation;
       
   160 			SheduleNextFrame(	iSource.AnimationFrameDelay( iAnimationIndex )	);
       
   161 			}
       
   162 		}
       
   163 	}
       
   164 
       
   165 // -----------------------------------------------------------------------------
       
   166 // CIHLImageViewer::Stop
       
   167 // -----------------------------------------------------------------------------
       
   168 void CIHLImageViewer::Stop()
       
   169 	{
       
   170 	iIsPlaying = EFalse;
       
   171 	if( iViewerState == EAnimation )
       
   172 		{
       
   173 		Cancel();
       
   174 		}
       
   175 	}
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // CIHLImageViewer::IsPlaying
       
   179 // -----------------------------------------------------------------------------
       
   180 TBool CIHLImageViewer::IsPlaying() const
       
   181 	{
       
   182 	return iIsPlaying;
       
   183 	}
       
   184 
       
   185 // -----------------------------------------------------------------------------
       
   186 // CIHLImageViewer::AnimationFrameCount
       
   187 // -----------------------------------------------------------------------------
       
   188 TInt CIHLImageViewer::AnimationFrameCount() const
       
   189 	{
       
   190 	return iSource.AnimationFrameCount();
       
   191 	}
       
   192 
       
   193 // -----------------------------------------------------------------------------
       
   194 // CIHLImageViewer::AnimationFrame
       
   195 // -----------------------------------------------------------------------------
       
   196 TInt CIHLImageViewer::AnimationFrame() const
       
   197 	{
       
   198 	return iAnimationIndex;
       
   199 	}
       
   200 
       
   201 // -----------------------------------------------------------------------------
       
   202 // CIHLImageViewer::SetAnimationFrame
       
   203 // -----------------------------------------------------------------------------
       
   204 TInt CIHLImageViewer::SetAnimationFrame( TInt aFrameIndex )
       
   205 	{
       
   206     // Public API, boundary check -> panic also on hardware
       
   207 	__ASSERT_ALWAYS( aFrameIndex >= 0 &&
       
   208 		aFrameIndex < iSource.AnimationFrameCount(), Panic( KErrArgument ) );
       
   209 
       
   210 	// Save new index and clear old source cache to force load new frame
       
   211 	iAnimationIndex = aFrameIndex;
       
   212 	iCacheSource->Reset();
       
   213 
       
   214 	// Start load
       
   215 	return ApplySettings();
       
   216 	}
       
   217 
       
   218 // -----------------------------------------------------------------------------
       
   219 // CIHLImageViewer::SetViewerSize
       
   220 // -----------------------------------------------------------------------------
       
   221 TInt CIHLImageViewer::SetViewerSize( const TSize& aViewerSize, int aSrcBitmapScaleFactor )
       
   222 	{
       
   223     // Public API, negative value check -> panic also on hardware
       
   224 	__ASSERT_ALWAYS( aViewerSize.iWidth >= 0 &&
       
   225 					 aViewerSize.iHeight >= 0, Panic( KErrArgument ) );
       
   226 
       
   227 	iSrcBitmapScaleFactor = aSrcBitmapScaleFactor;
       
   228 
       
   229 	// Save new viewer size
       
   230 	iViewerSize = aViewerSize;
       
   231 
       
   232 	// Recalculate source rect and destination size
       
   233 	CalculateSourceRectAndDestinationSize();
       
   234 
       
   235 	// Recalculate zoom to fit ratio
       
   236 	CalculateZoomToFitRatio();
       
   237 
       
   238 	// Start load
       
   239 	return ApplySettings();
       
   240 	}
       
   241 
       
   242 // -----------------------------------------------------------------------------
       
   243 // CIHLImageViewer::ViewerSize
       
   244 // -----------------------------------------------------------------------------
       
   245 TSize CIHLImageViewer::ViewerSize() const
       
   246 	{
       
   247 	return iViewerSize;
       
   248 	}
       
   249 
       
   250 // -----------------------------------------------------------------------------
       
   251 // CIHLImageViewer::MoveSourceRect
       
   252 // -----------------------------------------------------------------------------
       
   253 TInt CIHLImageViewer::MoveSourceRect( TInt aDx, TInt aDy )
       
   254 	{
       
   255 	TInt dx( aDx );
       
   256 	TInt dy( aDy );
       
   257 	switch( iRotationAngle )
       
   258 		{
       
   259 		case ERotationAngle0:
       
   260 			{
       
   261 			break;
       
   262 			}
       
   263 		case ERotationAngle90:
       
   264 			{
       
   265 			dx = aDy;
       
   266 			dy = -aDx;
       
   267 			break;
       
   268 			}
       
   269 		case ERotationAngle180:
       
   270 			{
       
   271 			dx = -aDx;
       
   272 			dy = -aDy;
       
   273 			break;
       
   274 			}
       
   275 		case ERotationAngle270:
       
   276 			{
       
   277 			dx = -aDy;
       
   278 			dy = aDx;
       
   279 			break;
       
   280 			}
       
   281 		default:
       
   282 			{
       
   283             // Internal state error, debug panic only
       
   284             #ifdef _DEBUG
       
   285 			    Panic( KErrGeneral );
       
   286             #endif
       
   287 			}
       
   288 		}
       
   289 	if( iHorizontalMirroring )
       
   290 		{
       
   291 		dx = -dx;
       
   292 		}
       
   293 	if( iVerticalMirroring )
       
   294 		{
       
   295 		dy = -dy;
       
   296 		}
       
   297 
       
   298 	if( iSourceRect.iTl.iX + dx < 0 ||
       
   299 		iSourceRect.iBr.iX + dx > iSourceSize.iWidth ||
       
   300 		iSourceRect.iTl.iY + dy < 0 ||
       
   301 		iSourceRect.iBr.iY + dy > iSourceSize.iHeight )
       
   302 		{
       
   303 		return KErrArgument;
       
   304 		}
       
   305 
       
   306 	iSourceRect.Move( dx, dy );
       
   307 
       
   308 	// Start load
       
   309 	return ApplySettings();
       
   310 	}
       
   311 
       
   312 // -----------------------------------------------------------------------------
       
   313 // CIHLImageViewer::SetSourceRectPosition
       
   314 // -----------------------------------------------------------------------------
       
   315 TInt CIHLImageViewer::SetSourceRectPosition( const TPoint& aPosition )
       
   316 	{
       
   317 	TPoint newPosition( aPosition );
       
   318 	TSize sourceRectSize( iSourceRect.Size() );
       
   319 	switch( iRotationAngle )
       
   320 		{
       
   321 		case ERotationAngle0:
       
   322 			{
       
   323 			break;
       
   324 			}
       
   325 		case ERotationAngle90:
       
   326 			{
       
   327 			newPosition.iX = aPosition.iY;
       
   328 			newPosition.iY = iSourceSize.iHeight - sourceRectSize.iHeight - aPosition.iX;
       
   329 			break;
       
   330 			}
       
   331 		case ERotationAngle180:
       
   332 			{
       
   333 			newPosition.iX = iSourceSize.iWidth - sourceRectSize.iWidth - aPosition.iX;
       
   334 			newPosition.iY = iSourceSize.iHeight - sourceRectSize.iHeight - aPosition.iY;
       
   335 			break;
       
   336 			}
       
   337 		case ERotationAngle270:
       
   338 			{
       
   339 			newPosition.iX = iSourceSize.iWidth - sourceRectSize.iWidth - aPosition.iY;
       
   340 			newPosition.iY = aPosition.iX;
       
   341 			break;
       
   342 			}
       
   343 		default:
       
   344 			{
       
   345             // Internal state error, debug panic only
       
   346             #ifdef _DEBUG
       
   347     			Panic( KErrGeneral );
       
   348             #endif
       
   349 			}
       
   350 		}
       
   351 	if( iHorizontalMirroring )
       
   352 		{
       
   353 		newPosition.iX = iSourceSize.iWidth - sourceRectSize.iWidth - newPosition.iX;
       
   354 		}
       
   355 	if( iVerticalMirroring )
       
   356 		{
       
   357 		newPosition.iY = iSourceSize.iHeight - sourceRectSize.iHeight - newPosition.iY;
       
   358 		}
       
   359 
       
   360 	if( newPosition.iX < 0 ||
       
   361 		newPosition.iX > ( iSourceSize.iWidth - sourceRectSize.iWidth ) ||
       
   362 		newPosition.iY < 0 ||
       
   363 		newPosition.iY > ( iSourceSize.iHeight - sourceRectSize.iHeight ) )
       
   364 		{
       
   365 		return KErrArgument;
       
   366 		}
       
   367 
       
   368 	iSourceRect = TRect( newPosition, sourceRectSize );
       
   369 
       
   370 	// Start load
       
   371 	return ApplySettings();
       
   372 	}
       
   373 
       
   374 // -----------------------------------------------------------------------------
       
   375 // CIHLImageViewer::SourceRect
       
   376 // -----------------------------------------------------------------------------
       
   377 TRect CIHLImageViewer::SourceRect() const
       
   378 	{
       
   379 	TRect mirroredSourceRect( iSourceRect );
       
   380 	if( iHorizontalMirroring )
       
   381 		{
       
   382 		mirroredSourceRect.iTl.iX  = iSourceSize.iWidth - iSourceRect.iBr.iX;
       
   383 		mirroredSourceRect.iBr.iX  = iSourceSize.iWidth - iSourceRect.iTl.iX;
       
   384 		}
       
   385 	if( iVerticalMirroring )
       
   386 		{
       
   387 		mirroredSourceRect.iTl.iY  = iSourceSize.iHeight - iSourceRect.iBr.iY;
       
   388 		mirroredSourceRect.iBr.iY  = iSourceSize.iHeight - iSourceRect.iTl.iY;
       
   389 		}
       
   390 
       
   391 	TRect rotatedSourceRect( mirroredSourceRect );
       
   392 	switch( iRotationAngle )
       
   393 		{
       
   394 		case ERotationAngle0:
       
   395 			{
       
   396 			break;
       
   397 			}
       
   398 		case ERotationAngle90:
       
   399 			{
       
   400 			rotatedSourceRect.iTl.iX = iSourceSize.iHeight - mirroredSourceRect.iBr.iY;
       
   401 			rotatedSourceRect.iTl.iY = mirroredSourceRect.iTl.iX;
       
   402 			rotatedSourceRect.iBr.iX = iSourceSize.iHeight - mirroredSourceRect.iTl.iY;
       
   403 			rotatedSourceRect.iBr.iY = mirroredSourceRect.iBr.iX;
       
   404 			break;
       
   405 			}
       
   406 		case ERotationAngle180:
       
   407 			{
       
   408 			rotatedSourceRect.iTl.iX = iSourceSize.iWidth - mirroredSourceRect.iBr.iX;
       
   409 			rotatedSourceRect.iTl.iY = iSourceSize.iHeight - mirroredSourceRect.iBr.iY;
       
   410 			rotatedSourceRect.iBr.iX = iSourceSize.iWidth - mirroredSourceRect.iTl.iX;
       
   411 			rotatedSourceRect.iBr.iY = iSourceSize.iHeight - mirroredSourceRect.iTl.iY;
       
   412 			break;
       
   413 			}
       
   414 		case ERotationAngle270:
       
   415 			{
       
   416 			rotatedSourceRect.iTl.iX = mirroredSourceRect.iTl.iY;
       
   417 			rotatedSourceRect.iTl.iY = iSourceSize.iWidth - mirroredSourceRect.iBr.iX;
       
   418 			rotatedSourceRect.iBr.iX = mirroredSourceRect.iBr.iY;
       
   419 			rotatedSourceRect.iBr.iY = iSourceSize.iWidth - mirroredSourceRect.iTl.iX;
       
   420 			break;
       
   421 			}
       
   422 		default:
       
   423 			{
       
   424             // Internal state error, debug panic only
       
   425             #ifdef _DEBUG
       
   426     			Panic( KErrGeneral );
       
   427             #endif
       
   428 			}
       
   429 		}
       
   430 
       
   431 	return rotatedSourceRect;
       
   432 	}
       
   433 
       
   434 // -----------------------------------------------------------------------------
       
   435 // CIHLImageViewer::SourceSize
       
   436 // -----------------------------------------------------------------------------
       
   437 TSize CIHLImageViewer::SourceSize() const
       
   438 	{
       
   439 	if( iRotationAngle == ERotationAngle90 ||
       
   440 		iRotationAngle == ERotationAngle270 )
       
   441 		{
       
   442 		return TSize( iSourceSize.iHeight, iSourceSize.iWidth );
       
   443 		}
       
   444 	else
       
   445 		{
       
   446 		return iSourceSize;
       
   447 		}
       
   448 	}
       
   449 
       
   450 // -----------------------------------------------------------------------------
       
   451 // CIHLImageViewer::SetZoomRatio
       
   452 // -----------------------------------------------------------------------------
       
   453 TInt CIHLImageViewer::SetZoomRatio( TReal aZoomRatio )
       
   454 	{
       
   455 	if( aZoomRatio <= 0 || Math::IsInfinite( aZoomRatio ) )
       
   456 		{
       
   457 		return KErrArgument;
       
   458 		}
       
   459 
       
   460 	iZoomRatio = aZoomRatio;
       
   461 
       
   462 	// Recalculate source rect and destination size
       
   463 	CalculateSourceRectAndDestinationSize();
       
   464 
       
   465 	// Start load
       
   466 	return ApplySettings();
       
   467 	}
       
   468 
       
   469 // -----------------------------------------------------------------------------
       
   470 // CIHLImageViewer::ZoomRatio
       
   471 // -----------------------------------------------------------------------------
       
   472 TReal CIHLImageViewer::ZoomRatio() const
       
   473 	{
       
   474 	return iZoomRatio;
       
   475 	}
       
   476 
       
   477 // -----------------------------------------------------------------------------
       
   478 // CIHLImageViewer::ZoomToFitRatio
       
   479 // -----------------------------------------------------------------------------
       
   480 TReal CIHLImageViewer::ZoomToFitRatio() const
       
   481 	{
       
   482 	return iZoomToFitRatio;
       
   483 	}
       
   484 
       
   485 // -----------------------------------------------------------------------------
       
   486 // CIHLImageViewer::RotateClockwise
       
   487 // -----------------------------------------------------------------------------
       
   488 TInt CIHLImageViewer::RotateClockwise()
       
   489 	{
       
   490 	TInt rotationAngle( iRotationAngle + ERotationAngle90 );
       
   491 	if( rotationAngle > ERotationAngle270 )
       
   492 		{
       
   493 		rotationAngle = ERotationAngle0;
       
   494 		}
       
   495 
       
   496 	return SetRotationAngle( rotationAngle );
       
   497 	}
       
   498 
       
   499 // -----------------------------------------------------------------------------
       
   500 // CIHLImageViewer::RotateCounterClockwise
       
   501 // -----------------------------------------------------------------------------
       
   502 TInt CIHLImageViewer::RotateCounterClockwise()
       
   503 	{
       
   504 	TInt rotationAngle( iRotationAngle - ERotationAngle90 );
       
   505 	if( rotationAngle < ERotationAngle0 )
       
   506 		{
       
   507 		rotationAngle = ERotationAngle270;
       
   508 		}
       
   509 
       
   510 	return SetRotationAngle( rotationAngle );
       
   511 	}
       
   512 
       
   513 // -----------------------------------------------------------------------------
       
   514 // CIHLImageViewer::SetRotationAngle
       
   515 // -----------------------------------------------------------------------------
       
   516 TInt CIHLImageViewer::SetRotationAngle( TInt aRotationAngle )
       
   517 	{
       
   518 	if( aRotationAngle != ERotationAngle0 &&
       
   519 		aRotationAngle != ERotationAngle90 &&
       
   520 		aRotationAngle != ERotationAngle180 &&
       
   521 		aRotationAngle != ERotationAngle270 )
       
   522 		{
       
   523 		return KErrArgument;
       
   524 		}
       
   525 
       
   526 	iRotationAngle = aRotationAngle;
       
   527 
       
   528 	// Recalculate source rect and destination size
       
   529 	CalculateSourceRectAndDestinationSize();
       
   530 
       
   531 	// Recalculate zoom to fit ratio
       
   532 	CalculateZoomToFitRatio();
       
   533 
       
   534 	// Start load
       
   535 	return ApplySettings();
       
   536 	}
       
   537 
       
   538 // -----------------------------------------------------------------------------
       
   539 // CIHLImageViewer::RotationAngle
       
   540 // -----------------------------------------------------------------------------
       
   541 TInt CIHLImageViewer::RotationAngle() const
       
   542 	{
       
   543 	return iRotationAngle;
       
   544 	}
       
   545 
       
   546 // -----------------------------------------------------------------------------
       
   547 // CIHLImageViewer::SetVerticalMirroring
       
   548 // -----------------------------------------------------------------------------
       
   549 TInt CIHLImageViewer::SetVerticalMirroring( TBool aValue )
       
   550 	{
       
   551 	if( iVerticalMirroring != aValue )
       
   552 		{
       
   553 		iVerticalMirroring = aValue;
       
   554 
       
   555 		// Start load
       
   556 		return ApplySettings();
       
   557 		}
       
   558 	return KErrNone;
       
   559 	}
       
   560 
       
   561 // -----------------------------------------------------------------------------
       
   562 // CIHLImageViewer::VerticalMirroring
       
   563 // -----------------------------------------------------------------------------
       
   564 TBool CIHLImageViewer::VerticalMirroring() const
       
   565 	{
       
   566 	return iVerticalMirroring;
       
   567 	}
       
   568 
       
   569 // -----------------------------------------------------------------------------
       
   570 // CIHLImageViewer::SetHorizontalMirroring
       
   571 // -----------------------------------------------------------------------------
       
   572 TInt CIHLImageViewer::SetHorizontalMirroring( TBool aValue )
       
   573 	{
       
   574 	if( iHorizontalMirroring != aValue )
       
   575 		{
       
   576 		iHorizontalMirroring = aValue;
       
   577 		return ApplySettings();
       
   578 		}
       
   579 	return KErrNone;
       
   580 	}
       
   581 
       
   582 // -----------------------------------------------------------------------------
       
   583 // CIHLImageViewer::HorizontalMirroring
       
   584 // -----------------------------------------------------------------------------
       
   585 TBool CIHLImageViewer::HorizontalMirroring() const
       
   586 	{
       
   587 	return iHorizontalMirroring;
       
   588 	}
       
   589 
       
   590 // -----------------------------------------------------------------------------
       
   591 // CIHLImageViewer::SetFilter
       
   592 // -----------------------------------------------------------------------------
       
   593 void CIHLImageViewer::SetFilter( MIHLFilter* /*aFilter*/ )
       
   594 	{
       
   595 	// Not in use
       
   596 	}
       
   597 
       
   598 
       
   599 
       
   600 // Private methods
       
   601 // -----------------------------------------------------------------------------
       
   602 // CIHLImageViewer::DoCancel
       
   603 // -----------------------------------------------------------------------------
       
   604 void CIHLImageViewer::DoCancel()
       
   605 	{
       
   606 	CTimer::DoCancel();
       
   607 	switch( iViewerState )
       
   608 		{
       
   609 		case ELoad:
       
   610 			{
       
   611 			// Cancel asynchronous source loading
       
   612 			iSource.CancelLoad();
       
   613 			iCacheSource->Reset();
       
   614 			break;
       
   615 			}
       
   616 		case EProcess:
       
   617 			{
       
   618 			// Cancel asynchronous processing
       
   619 			iProcessor->CancelProcess();
       
   620 			iCacheDestination->Reset();
       
   621 			break;
       
   622 			}
       
   623 		default:
       
   624 			{
       
   625 			break;
       
   626 			}
       
   627 		}
       
   628 
       
   629 	// Set state to inactive
       
   630 	iViewerState = EInactive;
       
   631 	}
       
   632 
       
   633 // -----------------------------------------------------------------------------
       
   634 // CIHLImageViewer::RunL
       
   635 // -----------------------------------------------------------------------------
       
   636 void CIHLImageViewer::RunL()
       
   637 	{
       
   638 	User::LeaveIfError( iStatus.Int() );
       
   639 
       
   640 	
       
   641 	TInt err( KErrNone );
       
   642 	switch( iViewerState )
       
   643 		{
       
   644 		case ELoad:
       
   645 			{
       
   646 			// Async load successful; start async processing if needed
       
   647             if( NeedAsyncProcess() )
       
   648                 {
       
   649                 err = AsyncProcess();
       
   650                 if( !err )
       
   651                     {
       
   652                     iViewerState = EProcess;
       
   653                     SetActive();
       
   654                     }
       
   655                 break;
       
   656                 }
       
   657             else
       
   658                 {
       
   659                 iViewerState=EInactive;
       
   660                 // Flowtrough to EProcess if no error
       
   661                 err = SyncProcess();
       
   662                 if( err )
       
   663                     {
       
   664                     break;
       
   665                     }
       
   666                 }
       
   667 			}
       
   668 		case EProcess:
       
   669 			{
       
   670 			// Process successful; finish and check if animation is needed
       
   671 			err = Finish();
       
   672 			if( !err )
       
   673 				{
       
   674 					TInt64 currentTime = User::FastCounter();
       
   675 					if(iAnimDrawStartFastTime > 0) 
       
   676 						{
       
   677 						iAnimLastFrameDrawTime=(currentTime-iAnimDrawStartFastTime)*1000000/iTickPeriod;
       
   678 						}
       
   679 
       
   680 					if( iIsPlaying )
       
   681 						{
       
   682 						iViewerState = EAnimation;
       
   683 						SheduleNextFrame(iSource.AnimationFrameDelay( iAnimationIndex ));
       
   684 						}
       
   685 					else 
       
   686 						{
       
   687 						iViewerState = EInactive;
       
   688 						}
       
   689 					// Notify client
       
   690 					// NOTE! client may call any API method in this point!
       
   691 					iObserver.ViewerBitmapChangedL();
       
   692 				}
       
   693 			break;
       
   694 			}
       
   695 		case EAnimation:
       
   696 			{
       
   697 			// Check if still playing..
       
   698 			iAnimDrawStartFastTime = User::FastCounter();
       
   699 			if( iIsPlaying )
       
   700 				{
       
   701 				// Change animation frame + 1
       
   702 				UpdateAnimationIndex();
       
   703 				err = AsyncLoad();
       
   704 				if( !err )
       
   705 					{
       
   706 					iViewerState = ELoad;
       
   707 					SetActive();
       
   708 					}
       
   709 				else 
       
   710 					{
       
   711 					iViewerState = EInactive;
       
   712 					}
       
   713 				}
       
   714 			else 
       
   715 				{
       
   716 				iViewerState = EInactive;
       
   717 				}
       
   718 			break;
       
   719 			}
       
   720 		default:
       
   721 			{
       
   722             // Internal state error, debug panic only
       
   723 			#ifdef _DEBUG
       
   724 				Panic( KErrGeneral );
       
   725 			#endif
       
   726 			}
       
   727 		}
       
   728 
       
   729 
       
   730 	User::LeaveIfError( err );
       
   731 	}
       
   732 
       
   733 // -----------------------------------------------------------------------------
       
   734 // CIHLImageViewer::RunError
       
   735 // -----------------------------------------------------------------------------
       
   736 TInt CIHLImageViewer::RunError( TInt aError )
       
   737 	{
       
   738 	switch( iViewerState )
       
   739 		{
       
   740 		case ELoad:
       
   741 			{
       
   742 			// Cleanup cached source if load has been failed
       
   743 			iCacheSource->Reset();
       
   744 			break;
       
   745 			}
       
   746 		case EProcess:
       
   747 			{
       
   748 			// Cleanup cached destination if process has been failed
       
   749 			iCacheDestination->Reset();
       
   750 			break;
       
   751 			}
       
   752 		default:
       
   753 			{
       
   754 			break;
       
   755 			}
       
   756 		}
       
   757 
       
   758 	iViewerState = EInactive;
       
   759 	iObserver.ViewerError( aError );
       
   760 	return KErrNone;
       
   761 	}
       
   762 
       
   763 // -----------------------------------------------------------------------------
       
   764 // CIHLImageViewer::Set
       
   765 // -----------------------------------------------------------------------------
       
   766 TInt CIHLImageViewer::ApplySettings()
       
   767 	{
       
   768 	// Assert source rect and destination, debug build only
       
   769 #ifdef _DEBUG
       
   770 	AssertSourceRectAndDestinationSize();
       
   771 #endif
       
   772 
       
   773 	// Cancel current process if any
       
   774 	Cancel();
       
   775 
       
   776 	// Check if cached source bitmap is already valid for processing..
       
   777 	TBool validSourceCache( EFalse );
       
   778 	const CFbsBitmap& cacheSource = iCacheSource->Bitmap();
       
   779 	if( cacheSource.Handle() )
       
   780 		{
       
   781 		const TSize cacheSize( cacheSource.SizeInPixels() );
       
   782 		const TSize minLoadSize( MinimumSourceLoadSize() );
       
   783 		if( cacheSize.iWidth >= minLoadSize.iWidth &&
       
   784 			cacheSize.iHeight >= minLoadSize.iHeight )
       
   785 			{
       
   786 			validSourceCache = ETrue;
       
   787 			}
       
   788 		}
       
   789 
       
   790 	// Start async load/process..
       
   791 	TInt err( KErrNone );
       
   792 	if( validSourceCache )
       
   793 		{
       
   794         if( NeedAsyncProcess() )
       
   795             {
       
   796             err = AsyncProcess();
       
   797             if( !err )
       
   798                 {
       
   799                 iViewerState = EProcess;
       
   800                 SetActive();
       
   801                 }
       
   802             }
       
   803         else
       
   804             {
       
   805             err = SyncProcess();
       
   806             if( !err )
       
   807                 {
       
   808                 iViewerState = EProcess;
       
   809                 SelfComplete();
       
   810                 }
       
   811             }
       
   812 		}
       
   813 	else
       
   814 		{
       
   815 		err = AsyncLoad();
       
   816 		if( !err )
       
   817 			{
       
   818 			iViewerState = ELoad;
       
   819 			SetActive();
       
   820 			}
       
   821 		}
       
   822 
       
   823 	return err;
       
   824 	}
       
   825 
       
   826 // -----------------------------------------------------------------------------
       
   827 // CIHLImageViewer::AsyncLoad
       
   828 // -----------------------------------------------------------------------------
       
   829 TInt CIHLImageViewer::AsyncLoad()
       
   830 	{
       
   831     // Internal state check, debug panic only
       
   832 	__ASSERT_DEBUG( !iCacheDestination->Bitmap().Handle(), Panic( KErrGeneral ) );
       
   833 
       
   834 	TInt err( KErrNone );
       
   835 	if( !iSource.IsAnimation() )
       
   836 		{
       
   837 		// Do not reset animation frame because loading
       
   838 		// might be faster if previous frame can be utilized
       
   839 		iCacheSource->Reset();
       
   840 		}
       
   841 	if( !iCacheSource->Bitmap().Handle() )
       
   842 		{
       
   843 		TDisplayMode transparency( iSource.MaskDisplayMode() );
       
   844 		if( transparency )
       
   845 			{
       
   846 			err = iCacheSource->Create( MinimumSourceLoadSize(),
       
   847 										iSource.DisplayMode(),
       
   848 										transparency );
       
   849 			}
       
   850 		else
       
   851 			{
       
   852 			err = iCacheSource->Create( MinimumSourceLoadSize(),
       
   853 										iSource.DisplayMode() );
       
   854 			}
       
   855 		}
       
   856 
       
   857 	// Load source bitmap
       
   858 	if( !err )
       
   859 		{
       
   860 		if( iSource.IsAnimation() )
       
   861 			{
       
   862 			err = iSource.LoadAnimation( iStatus, *iCacheSource, iAnimationIndex );
       
   863 			}
       
   864 		else
       
   865 			{
       
   866 			err = iSource.Load( iStatus, *iCacheSource, iSource.ImageIndex() );
       
   867 			}
       
   868 
       
   869 		}
       
   870 
       
   871 	// Error cleanup if needed
       
   872 	if( err )
       
   873 		{
       
   874 		iCacheSource->Reset();
       
   875 		}
       
   876 	return err;
       
   877 	}
       
   878 
       
   879 // -----------------------------------------------------------------------------
       
   880 // CIHLImageViewer::NeedAsyncProcess
       
   881 // -----------------------------------------------------------------------------
       
   882 TBool CIHLImageViewer::NeedAsyncProcess()
       
   883     {
       
   884     // Internal state check, debug panic only
       
   885     __ASSERT_DEBUG( iCacheSource->Bitmap().Handle(), Panic( KErrGeneral ) );
       
   886     __ASSERT_DEBUG( !iCacheDestination->Bitmap().Handle(), Panic( KErrGeneral ) );
       
   887 
       
   888     // First check if destination size differs from source size
       
   889     // (=scaling needed)
       
   890     TSize scaledSrcSize( iCacheSource->Bitmap().SizeInPixels() );
       
   891     if( scaledSrcSize.iWidth != iDestinationSize.iWidth ||
       
   892         scaledSrcSize.iHeight != iDestinationSize.iHeight )
       
   893         {
       
   894         return ETrue;
       
   895         }
       
   896 
       
   897     // Then check if source rect and source size differs
       
   898     // (=clipping needed)
       
   899     if( iSourceRect.iTl != TPoint( 0,0 ) ||
       
   900         iSourceRect.iBr != iSource.Size().AsPoint() )
       
   901         {
       
   902         return ETrue;
       
   903         }
       
   904 
       
   905     // Finally check rotation and mirroring
       
   906     if( iRotationAngle == ERotationAngle0 &&
       
   907         !iHorizontalMirroring &&
       
   908         !iVerticalMirroring )
       
   909         {
       
   910         return EFalse;
       
   911         }
       
   912     else if( iRotationAngle == ERotationAngle180 &&
       
   913         iHorizontalMirroring &&
       
   914         iVerticalMirroring )
       
   915         {
       
   916         return EFalse;
       
   917         }
       
   918     else
       
   919         {
       
   920         return ETrue;
       
   921         }
       
   922     }
       
   923 
       
   924 // -----------------------------------------------------------------------------
       
   925 // CIHLImageViewer::AsyncProcess
       
   926 // -----------------------------------------------------------------------------
       
   927 TInt CIHLImageViewer::AsyncProcess()
       
   928 	{
       
   929     IHL_DEBUG1( KIHLDebug, "IHL - CIHLImageViewer - AsyncProcess" );
       
   930 
       
   931     // Internal state check, debug panic only
       
   932 	__ASSERT_DEBUG( iCacheSource->Bitmap().Handle(), Panic( KErrGeneral ) );
       
   933 	__ASSERT_DEBUG( !iCacheDestination->Bitmap().Handle(), Panic( KErrGeneral ) );
       
   934 
       
   935 	const CFbsBitmap& srcBitmap = iCacheSource->Bitmap();
       
   936 	const CFbsBitmap& srcMask = iCacheSource->Mask();
       
   937 	TInt err( KErrNone );
       
   938 
       
   939 	// Create new cached destination
       
   940 	if( srcMask.Handle() )
       
   941 		{
       
   942 		err = iCacheDestination->Create( iDestinationSize,
       
   943 									srcBitmap.DisplayMode(), srcMask.DisplayMode() );
       
   944 		}
       
   945 	else
       
   946 		{
       
   947 		err = iCacheDestination->Create( iDestinationSize, srcBitmap.DisplayMode() );
       
   948 		}
       
   949 
       
   950 	// Scale and clip bitmap from cached source to new cached destination
       
   951 	if( !err )
       
   952 		{
       
   953 		TRect scaledSourceRect(
       
   954             CalculateProcessSourceRect( srcBitmap.SizeInPixels() ) );
       
   955 
       
   956 		TRect destinationRect( CalculateProcessDestinationRect() );
       
   957 
       
   958 		err = iProcessor->Process( iStatus, *iCacheSource, scaledSourceRect,
       
   959 									  *iCacheDestination, destinationRect );
       
   960 		}
       
   961 
       
   962 	// Error cleanup if needed
       
   963 	if( err )
       
   964 		{
       
   965 		iCacheDestination->Reset();
       
   966 		}
       
   967 
       
   968 	return err;
       
   969 	}
       
   970 
       
   971 // -----------------------------------------------------------------------------
       
   972 // CIHLImageViewer::SyncProcess
       
   973 // -----------------------------------------------------------------------------
       
   974 TInt CIHLImageViewer::SyncProcess()
       
   975     {
       
   976     IHL_DEBUG1( KIHLDebug, "IHL - CIHLImageViewer - SyncProcess" );
       
   977 
       
   978     // Internal state check, debug panic only
       
   979     __ASSERT_DEBUG( iCacheSource->Bitmap().Handle(), Panic( KErrGeneral ) );
       
   980     __ASSERT_DEBUG( !iCacheDestination->Bitmap().Handle(), Panic( KErrGeneral ) );
       
   981 
       
   982     // Duplicate destination cache to destination bitmap
       
   983     TInt err( iCacheDestination->Copy( *iCacheSource, EFalse ) );
       
   984     return err;
       
   985     }
       
   986 
       
   987 // -----------------------------------------------------------------------------
       
   988 // CIHLImageViewer::Finish
       
   989 // -----------------------------------------------------------------------------
       
   990 TInt CIHLImageViewer::Finish()
       
   991 	{
       
   992     // Internal state check, debug panic only
       
   993 	__ASSERT_DEBUG( iCacheDestination->Bitmap().Handle(), Panic( KErrGeneral ) );
       
   994 
       
   995 	// Duplicate destination cache to destination bitmap
       
   996 	TInt err( iDestination.Copy( *iCacheDestination, ETrue ) );
       
   997 	iCacheDestination->Reset();
       
   998 
       
   999 	// Error cleanup if needed
       
  1000 	if( err )
       
  1001 		{
       
  1002 		iDestination.Reset();
       
  1003 		}
       
  1004 	return err;
       
  1005 	}
       
  1006 
       
  1007 // -----------------------------------------------------------------------------
       
  1008 // CIHLImageViewer::UpdateAnimationIndex
       
  1009 // -----------------------------------------------------------------------------
       
  1010 void CIHLImageViewer::UpdateAnimationIndex()
       
  1011 	{
       
  1012     // Internal state check, debug panic only
       
  1013 	__ASSERT_DEBUG( iIsPlaying, Panic( KErrGeneral ) );
       
  1014 
       
  1015 	// Check if animation is in last frame
       
  1016 	if( iAnimationIndex == iSource.AnimationFrameCount() - 1 )
       
  1017 		{
       
  1018 		iAnimationIndex = 0;
       
  1019 		}
       
  1020 	else
       
  1021 		{
       
  1022 		// Not in last frame; move to next frame
       
  1023 		iAnimationIndex++;
       
  1024 		}
       
  1025 	}
       
  1026 
       
  1027 // -----------------------------------------------------------------------------
       
  1028 // CIHLImageViewer::SelfComplete
       
  1029 // -----------------------------------------------------------------------------
       
  1030 void CIHLImageViewer::SelfComplete()
       
  1031 	{
       
  1032 	SetActive();
       
  1033 	iStatus = KRequestPending;
       
  1034 	TRequestStatus* status = &iStatus;
       
  1035 	User::RequestComplete( status, KErrNone );
       
  1036 	}
       
  1037 
       
  1038 // -----------------------------------------------------------------------------
       
  1039 // CIHLImageViewer::MinimumSourceLoadSize
       
  1040 // -----------------------------------------------------------------------------
       
  1041 TSize CIHLImageViewer::MinimumSourceLoadSize()
       
  1042 	{
       
  1043 	TSize minumumLoadSize( iSource.Size() );
       
  1044 
       
  1045 	if( iSource.IsFullyScaleable() )
       
  1046 	    {
       
  1047     	const TSize originalSize( iSource.Size() );
       
  1048     	switch( iRotationAngle )
       
  1049     		{
       
  1050     		case ERotationAngle0:
       
  1051     		case ERotationAngle180:
       
  1052     			{
       
  1053             	minumumLoadSize.iWidth = originalSize.iWidth * iDestinationSize.iWidth / Abs( iSourceRect.Width() );
       
  1054             	minumumLoadSize.iHeight = originalSize.iHeight * iDestinationSize.iHeight / Abs( iSourceRect.Height() );
       
  1055     			break;
       
  1056     			}
       
  1057     		case ERotationAngle90:
       
  1058     		case ERotationAngle270:
       
  1059     			{
       
  1060             	minumumLoadSize.iWidth = originalSize.iWidth * iDestinationSize.iWidth / Abs( iSourceRect.Height() );
       
  1061             	minumumLoadSize.iHeight = originalSize.iHeight * iDestinationSize.iHeight / Abs( iSourceRect.Width() );
       
  1062     			break;
       
  1063     			}
       
  1064     		default:
       
  1065     			{
       
  1066                 // Internal state error, debug panic only
       
  1067                 #ifdef _DEBUG
       
  1068         			Panic( KErrGeneral );
       
  1069                 #endif
       
  1070     			}
       
  1071     		}
       
  1072     		
       
  1073         // Limit fully scaleable loadsize to original size
       
  1074     	if( minumumLoadSize.iWidth > originalSize.iWidth ||
       
  1075     	    minumumLoadSize.iHeight > originalSize.iHeight )
       
  1076     	    {
       
  1077     	    minumumLoadSize = originalSize;
       
  1078     	    }
       
  1079 	    }
       
  1080 	else
       
  1081 	    {
       
  1082     	const RArray<TSize>& loadSizeArray = iSource.CustomLoadSizeArray();
       
  1083     	const TInt count( loadSizeArray.Count() );
       
  1084 
       
  1085     	if( count )
       
  1086     		{
       
  1087     		TRect loadRect;
       
  1088     		TSize loadRectSize;
       
  1089     		TBool indexFound( EFalse );
       
  1090     		for( TInt i( 0 ); ( i < count ) && !indexFound; ++i )
       
  1091     			{
       
  1092     			loadRect = CalculateProcessSourceRect( loadSizeArray[ i ] );
       
  1093     			loadRectSize = loadRect.Size();
       
  1094     			loadRectSize.iWidth = Abs( loadRectSize.iWidth );
       
  1095     			loadRectSize.iHeight = Abs( loadRectSize.iHeight );
       
  1096 
       
  1097     			if( iDestinationSize.iWidth <= loadRectSize.iWidth &&
       
  1098     				iDestinationSize.iHeight <= loadRectSize.iHeight )
       
  1099     				{
       
  1100     				minumumLoadSize = loadSizeArray[ i ];
       
  1101     				indexFound = ETrue;
       
  1102     				}
       
  1103     			}
       
  1104     		}
       
  1105 	    }
       
  1106 
       
  1107 	return minumumLoadSize;
       
  1108 	}
       
  1109 
       
  1110 // -----------------------------------------------------------------------------
       
  1111 // CIHLImageViewer::CalculateProcessSourceRect
       
  1112 // -----------------------------------------------------------------------------
       
  1113 TRect CIHLImageViewer::CalculateProcessSourceRect( const TSize& aLoadSize )
       
  1114 	{
       
  1115 	const TSize originalSize( iSource.Size() );
       
  1116 	TRect loadRect;
       
  1117 	if ( aLoadSize.iWidth > KErrNone && aLoadSize.iHeight > KErrNone )
       
  1118 		{
       
  1119 		loadRect.iTl.iX = iSourceRect.iTl.iX * aLoadSize.iWidth / originalSize.iWidth;
       
  1120 		loadRect.iTl.iY = iSourceRect.iTl.iY * aLoadSize.iHeight / originalSize.iHeight;
       
  1121 		loadRect.iBr.iX = iSourceRect.iBr.iX * aLoadSize.iWidth / originalSize.iWidth;
       
  1122 		loadRect.iBr.iY = iSourceRect.iBr.iY * aLoadSize.iHeight / originalSize.iHeight;
       
  1123 		}
       
  1124 	else
       
  1125 		{
       
  1126 		loadRect.SetRect(0,0,0,0);
       
  1127 		return loadRect;
       
  1128 		}
       
  1129 
       
  1130 	switch( iRotationAngle )
       
  1131 		{
       
  1132 		case ERotationAngle0:
       
  1133 			{
       
  1134 			break;
       
  1135 			}
       
  1136 		case ERotationAngle90:
       
  1137 			{
       
  1138 			TInt tmp( loadRect.iTl.iY );
       
  1139 			loadRect.iTl.iY = loadRect.iBr.iY;
       
  1140 			loadRect.iBr.iY = tmp;
       
  1141 			break;
       
  1142 			}
       
  1143 		case ERotationAngle180:
       
  1144 			{
       
  1145 			TPoint tmp( loadRect.iTl );
       
  1146 			loadRect.iTl = loadRect.iBr;
       
  1147 			loadRect.iBr = tmp;
       
  1148 			break;
       
  1149 			}
       
  1150 		case ERotationAngle270:
       
  1151 			{
       
  1152 			TInt tmp( loadRect.iTl.iX );
       
  1153 			loadRect.iTl.iX = loadRect.iBr.iX;
       
  1154 			loadRect.iBr.iX = tmp;
       
  1155 			break;
       
  1156 			}
       
  1157 		default:
       
  1158 			{
       
  1159             // Internal state error, debug panic only
       
  1160             #ifdef _DEBUG
       
  1161     			Panic( KErrGeneral );
       
  1162             #endif
       
  1163 			}
       
  1164 		}
       
  1165 
       
  1166 	return loadRect;
       
  1167 	}
       
  1168 
       
  1169 // -----------------------------------------------------------------------------
       
  1170 // CIHLImageViewer::CalculateProcessDestinationRect
       
  1171 // -----------------------------------------------------------------------------
       
  1172 TRect CIHLImageViewer::CalculateProcessDestinationRect()
       
  1173 	{
       
  1174 	TRect dstRect( iDestinationSize );
       
  1175 	switch( iRotationAngle )
       
  1176 		{
       
  1177 		case ERotationAngle0:
       
  1178 		case ERotationAngle180:
       
  1179 			{
       
  1180 			if( iHorizontalMirroring )
       
  1181 				{
       
  1182 				TInt tmp( dstRect.iTl.iX );
       
  1183 				dstRect.iTl.iX = dstRect.iBr.iX;
       
  1184 				dstRect.iBr.iX = tmp;
       
  1185 				}
       
  1186 			if( iVerticalMirroring )
       
  1187 				{
       
  1188 				TInt tmp( dstRect.iTl.iY );
       
  1189 				dstRect.iTl.iY = dstRect.iBr.iY;
       
  1190 				dstRect.iBr.iY = tmp;
       
  1191 				}
       
  1192 			break;
       
  1193 			}
       
  1194 		case ERotationAngle90:
       
  1195 		case ERotationAngle270:
       
  1196 			{
       
  1197 			if( iHorizontalMirroring )
       
  1198 				{
       
  1199 				TInt tmp( dstRect.iTl.iY );
       
  1200 				dstRect.iTl.iY = dstRect.iBr.iY;
       
  1201 				dstRect.iBr.iY = tmp;
       
  1202 				}
       
  1203 			if( iVerticalMirroring )
       
  1204 				{
       
  1205 				TInt tmp( dstRect.iTl.iX );
       
  1206 				dstRect.iTl.iX = dstRect.iBr.iX;
       
  1207 				dstRect.iBr.iX = tmp;
       
  1208 				}
       
  1209 			break;
       
  1210 			}
       
  1211 		default:
       
  1212 			{
       
  1213             // Internal state error, debug panic only
       
  1214             #ifdef _DEBUG
       
  1215 			    Panic( KErrGeneral );
       
  1216             #endif
       
  1217 			}
       
  1218 		}
       
  1219 	return dstRect;
       
  1220 	}
       
  1221 
       
  1222 // -----------------------------------------------------------------------------
       
  1223 // CIHLImageViewer::CalculateZoomToFitRatio
       
  1224 // -----------------------------------------------------------------------------
       
  1225 void CIHLImageViewer::CalculateZoomToFitRatio()
       
  1226 	{
       
  1227 	TSize sourceSize( SourceSize() );
       
  1228 	TReal widthRatio( TReal( iViewerSize.iWidth ) / TReal( sourceSize.iWidth ) );
       
  1229 	TReal heightRatio( TReal( iViewerSize.iHeight ) / TReal( sourceSize.iHeight ) );
       
  1230 
       
  1231 	if( iOptions & MIHLImageViewer::EOptionIgnoreAspectRatio )
       
  1232 		{
       
  1233 		iZoomToFitRatio = ( widthRatio > heightRatio ) ? widthRatio : heightRatio;
       
  1234 		}
       
  1235 	else
       
  1236 		{
       
  1237 		iZoomToFitRatio = ( widthRatio < heightRatio ) ? widthRatio : heightRatio;
       
  1238 		}
       
  1239 	}
       
  1240 
       
  1241 // -----------------------------------------------------------------------------
       
  1242 // CIHLImageViewer::CalculateSourceRectAndDestinationSize
       
  1243 // -----------------------------------------------------------------------------
       
  1244 void CIHLImageViewer::CalculateSourceRectAndDestinationSize()
       
  1245 	{
       
  1246 	// Calculate new source rect
       
  1247 	TSize oldSourceRectSize( iSourceRect.Size() );
       
  1248 
       
  1249 	TReal newSourceRectWidth;
       
  1250 	TReal newSourceRectHeight;
       
  1251 	TReal widthZoomRatio( iZoomRatio );
       
  1252 	TReal heightZoomRatio( iZoomRatio );
       
  1253 
       
  1254 	if( iOptions & MIHLImageViewer::EOptionIgnoreAspectRatio )
       
  1255 		{
       
  1256 		TReal widthRatio( TReal( iViewerSize.iWidth ) / TReal( iSourceSize.iWidth ) );
       
  1257 		TReal heightRatio( TReal( iViewerSize.iHeight ) / TReal( iSourceSize.iHeight ) );
       
  1258 		if( widthRatio < heightRatio )
       
  1259 			{
       
  1260 			widthZoomRatio = widthZoomRatio * widthRatio / heightRatio;
       
  1261 			}
       
  1262 		else
       
  1263 			{
       
  1264 			heightZoomRatio = heightZoomRatio * heightRatio / widthRatio;
       
  1265 			}
       
  1266 		}
       
  1267 
       
  1268 	if( iRotationAngle == ERotationAngle90 ||
       
  1269 		iRotationAngle == ERotationAngle270 )
       
  1270 		{
       
  1271 		newSourceRectWidth = iSrcBitmapScaleFactor * iViewerSize.iHeight / heightZoomRatio; //widthZoomRatio
       
  1272 		newSourceRectHeight = iSrcBitmapScaleFactor * iViewerSize.iWidth / widthZoomRatio; //heightZoomRatio
       
  1273 		}
       
  1274 	else
       
  1275 		{
       
  1276 		newSourceRectWidth = iSrcBitmapScaleFactor * iViewerSize.iWidth / widthZoomRatio;
       
  1277 		newSourceRectHeight = iSrcBitmapScaleFactor * iViewerSize.iHeight / heightZoomRatio;
       
  1278 		}
       
  1279 
       
  1280 	// Check if source rect is not larger than source area
       
  1281 	if( newSourceRectWidth > iSourceSize.iWidth )
       
  1282 		{
       
  1283 		newSourceRectWidth = iSourceSize.iWidth;
       
  1284 		}
       
  1285 	if( newSourceRectHeight > iSourceSize.iHeight )
       
  1286 		{
       
  1287 		newSourceRectHeight = iSourceSize.iHeight;
       
  1288 		}
       
  1289 		
       
  1290 	// Rounding the results
       
  1291 	TReal roundedWidth;
       
  1292 	Math::Round( roundedWidth, newSourceRectWidth, 0 );
       
  1293 	TReal roundedHeight;
       
  1294 	Math::Round( roundedHeight, newSourceRectHeight, 0 );
       
  1295 	
       
  1296 	iSourceRect.SetWidth( (TInt)roundedWidth );
       
  1297 	iSourceRect.SetHeight( (TInt)roundedHeight );
       
  1298 
       
  1299 	// Calculate actual destination size (always same or smaller than iViewerSize !)
       
  1300 	if( iRotationAngle == ERotationAngle90 ||
       
  1301 		iRotationAngle == ERotationAngle270 )
       
  1302 		{
       
  1303 		iDestinationSize.iWidth = (TInt)( newSourceRectHeight * widthZoomRatio ); //heightZoomRatio
       
  1304 		iDestinationSize.iHeight = (TInt)( newSourceRectWidth * heightZoomRatio  ); //widthZoomRatio
       
  1305 		}
       
  1306 	else
       
  1307 		{
       
  1308 		iDestinationSize.iWidth = (TInt)( newSourceRectWidth * widthZoomRatio );
       
  1309 		iDestinationSize.iHeight = (TInt)( newSourceRectHeight * heightZoomRatio );
       
  1310 		}
       
  1311 	// Check that destination size is not rounded to zero
       
  1312 	if( iDestinationSize.iWidth == 0 )
       
  1313 		{
       
  1314 		iDestinationSize.iWidth = 1;
       
  1315 		}
       
  1316 	if( iDestinationSize.iHeight == 0 )
       
  1317 		{
       
  1318 		iDestinationSize.iHeight = 1;
       
  1319 		}
       
  1320 
       
  1321 	// Move source rect keeping center point in same location
       
  1322 	iSourceRect.Move( ( oldSourceRectSize.iWidth - (TInt)newSourceRectWidth ) / 2,
       
  1323 					  ( oldSourceRectSize.iHeight - (TInt)newSourceRectHeight ) / 2 );
       
  1324 
       
  1325 	// Move rect if partially out of source area
       
  1326 	TPoint moveOffset( 0, 0 );
       
  1327 	if( iSourceRect.iTl.iX < 0 )
       
  1328 		{
       
  1329 		moveOffset.iX = -iSourceRect.iTl.iX;
       
  1330 		}
       
  1331 	else if( iSourceRect.iBr.iX > iSourceSize.iWidth )
       
  1332 		{
       
  1333 		moveOffset.iX = iSourceSize.iWidth - iSourceRect.iBr.iX;
       
  1334 		}
       
  1335 	if( iSourceRect.iTl.iY < 0 ) //lint !e961
       
  1336 		{
       
  1337 		moveOffset.iY = -iSourceRect.iTl.iY;
       
  1338 		}
       
  1339 	else if( iSourceRect.iBr.iY > iSourceSize.iHeight )
       
  1340 		{
       
  1341 		moveOffset.iY = iSourceSize.iHeight - iSourceRect.iBr.iY;
       
  1342 		}
       
  1343 	iSourceRect.Move( moveOffset );  //lint !e961
       
  1344 
       
  1345 	// Assert that rectangle is valid, debug build only
       
  1346 #ifdef _DEBUG
       
  1347 	AssertSourceRectAndDestinationSize();
       
  1348 #endif
       
  1349 	}
       
  1350 
       
  1351 // -----------------------------------------------------------------------------
       
  1352 // CIHLImageViewer::AssertSourceRectAndDestinationSize
       
  1353 // Used in debug build only
       
  1354 // -----------------------------------------------------------------------------
       
  1355 #ifdef _DEBUG
       
  1356 void CIHLImageViewer::AssertSourceRectAndDestinationSize()
       
  1357 	{
       
  1358 	if( iSourceRect.iTl.iX < 0 ||
       
  1359 		iSourceRect.iBr.iX > iSourceSize.iWidth ||
       
  1360 		iSourceRect.iTl.iY < 0 ||
       
  1361 		iSourceRect.iBr.iY > iSourceSize.iHeight ||
       
  1362 		iDestinationSize.iWidth <= 0 || iDestinationSize.iHeight <= 0 )
       
  1363 		{
       
  1364 		Panic( KErrGeneral );
       
  1365 		}
       
  1366 	}
       
  1367 #endif
       
  1368 
       
  1369 //  End of File