imagehandlinglib/Src/CIHLScaler.cpp
changeset 54 48dd0f169f0d
parent 42 2e2a89493e2b
equal deleted inserted replaced
42:2e2a89493e2b 54:48dd0f169f0d
     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 Scaling processor
       
    15 *              : using Font and Bitmap Server bitmaps.
       
    16 *
       
    17 */
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "CIHLScaler.h"
       
    21 #include "IHLDebugPrint.h" // Debug print
       
    22 #include <MIHLImageViewer.h>        // MIHLImageViewer
       
    23 #include <fbs.h>
       
    24 #include <hal.h>
       
    25 
       
    26 // Private namespace for constants and functions
       
    27 namespace
       
    28 	{
       
    29 	// Processed pixels per one activesheduler step
       
    30 	const TInt KProcessPixelsPerStep = 16384;
       
    31 	
       
    32 	// These make the fast path scalings step out about every 5-10ms
       
    33 	// no reason to cut more aggressively since it just slows down everything
       
    34 	const TInt KBytesPerStepFastPath = 640*480;
       
    35 	const TInt KBytesPerStepFastPathScaleOnly = 640*480*2;
       
    36 	
       
    37 	const TInt KStepPrecision = 16; // 16 bit = 65k subpixels
       
    38 	const TInt KMaxProcessSize = KMaxTInt / 2;
       
    39 	}
       
    40 
       
    41 //functions and typedefs used inside ProcessBilinear scaling
       
    42 namespace
       
    43 	{
       
    44 	// using our own RGB instead of TRGB as we need TInt32 for each value
       
    45 	typedef struct
       
    46 		{
       
    47 		TInt32 r, g, b, a;
       
    48 		} TColorRGB;
       
    49 	
       
    50 	// structure for handling data of 4 pixels
       
    51 	typedef struct
       
    52 		{
       
    53 		TColorRGB colXY00, colXY01, colXY10, colXY11;
       
    54 		TColorRGB col0, col1, col;
       
    55 		} TPixelData;
       
    56 
       
    57 	// functions to handle conversion between TColorRGB and colr value stored in TInt32
       
    58 	inline void IntToRgb(TInt32 aIntRGB_val, TColorRGB &col)
       
    59 		{
       
    60 		col.r = (aIntRGB_val >> 16) & 0x00ff;
       
    61 		col.g = (aIntRGB_val >> 8) & 0x00ff;
       
    62 		col.b =  aIntRGB_val & 0x00ff;
       
    63 		col.a = (aIntRGB_val >> 24) & 0x00ff;
       
    64 		}
       
    65 	inline TUint32 RgbToInt(TColorRGB &col)
       
    66 		{
       
    67 		return 0x00000000 | ( ( col.r & 0xff) << 16 ) | ( ( col.g & 0xff) << 8  ) 
       
    68 		                  | (   col.b & 0xff)         | ( ( col.a & 0xff) << 24 );
       
    69 		}
       
    70 
       
    71 	// function which interpolates color using gathered data
       
    72 	inline void ProcessColorData( TPixelData &dat, TPoint aSrcPos )
       
    73 		{
       
    74 		TInt32 pixel_width = 1 << KStepPrecision;
       
    75         
       
    76         //first pass (Y axis)
       
    77 		dat.col0.r = (dat.colXY01.r - dat.colXY00.r)*(aSrcPos.iY % pixel_width) / pixel_width + dat.colXY00.r;
       
    78 		dat.col0.g = (dat.colXY01.g - dat.colXY00.g)*(aSrcPos.iY % pixel_width) / pixel_width + dat.colXY00.g;
       
    79 		dat.col0.b = (dat.colXY01.b - dat.colXY00.b)*(aSrcPos.iY % pixel_width) / pixel_width + dat.colXY00.b;
       
    80 		dat.col0.a = (dat.colXY01.a - dat.colXY00.a)*(aSrcPos.iY % pixel_width) / pixel_width + dat.colXY00.a;
       
    81 
       
    82 		dat.col1.r = (dat.colXY11.r - dat.colXY10.r)*(aSrcPos.iY % pixel_width) / pixel_width + dat.colXY10.r;
       
    83 		dat.col1.g = (dat.colXY11.g - dat.colXY10.g)*(aSrcPos.iY % pixel_width) / pixel_width + dat.colXY10.g;
       
    84 		dat.col1.b = (dat.colXY11.b - dat.colXY10.b)*(aSrcPos.iY % pixel_width) / pixel_width + dat.colXY10.b;
       
    85 		dat.col1.a = (dat.colXY11.a - dat.colXY10.a)*(aSrcPos.iY % pixel_width) / pixel_width + dat.colXY10.a;
       
    86 
       
    87 		//second pass (X axis)
       
    88 		dat.col.r = (dat.col1.r - dat.col0.r)*(aSrcPos.iX % pixel_width) / pixel_width + dat.col0.r;
       
    89 		dat.col.g = (dat.col1.g - dat.col0.g)*(aSrcPos.iX % pixel_width) / pixel_width + dat.col0.g;
       
    90 		dat.col.b = (dat.col1.b - dat.col0.b)*(aSrcPos.iX % pixel_width) / pixel_width + dat.col0.b;
       
    91 		dat.col.a = (dat.col1.a - dat.col0.a)*(aSrcPos.iX % pixel_width) / pixel_width + dat.col0.a;
       
    92 		}
       
    93 	}
       
    94 	
       
    95 // ======================== STATIC FACTORY FUNCTION ============================
       
    96 // -----------------------------------------------------------------------------
       
    97 // IHLScaler::CreateL
       
    98 // -----------------------------------------------------------------------------
       
    99 //
       
   100 EXPORT_C MIHLScaler* IHLScaler::CreateL( const TUint32 aOptions )
       
   101 	{
       
   102 	return CIHLScaler::NewL( aOptions );
       
   103 	}
       
   104 
       
   105 // ============================ MEMBER FUNCTIONS ===============================
       
   106 // -----------------------------------------------------------------------------
       
   107 //
       
   108 // C++ default constructor can NOT contain any code, that
       
   109 // might leave.
       
   110 // -----------------------------------------------------------------------------
       
   111 CIHLScaler::CIHLScaler( const TUint32 aOptions )
       
   112 :CActive( CActive::EPriorityStandard ), iOptions( aOptions )
       
   113     {
       
   114 	CActiveScheduler::Add( this );
       
   115     }
       
   116 
       
   117 // -----------------------------------------------------------------------------
       
   118 //
       
   119 // Two-phased constructor.
       
   120 // -----------------------------------------------------------------------------
       
   121 CIHLScaler* CIHLScaler::NewL( const TUint32 aOptions )
       
   122     {
       
   123     CIHLScaler* self = new( ELeave ) CIHLScaler( aOptions );
       
   124     return self;
       
   125     }
       
   126 
       
   127 // -----------------------------------------------------------------------------
       
   128 // Destructor
       
   129 // -----------------------------------------------------------------------------
       
   130 CIHLScaler::~CIHLScaler()
       
   131     {
       
   132 	Cancel();
       
   133     }
       
   134 
       
   135 // -----------------------------------------------------------------------------
       
   136 // CIHLScaler::Scale
       
   137 // -----------------------------------------------------------------------------
       
   138 TInt CIHLScaler::Scale( TRequestStatus& aStatus,
       
   139 					const CFbsBitmap& aSrcBitmap, const TRect& aSrcRect,
       
   140 					CFbsBitmap& aDstBitmap, const TRect& aDstRect )
       
   141 	{
       
   142 	if( IsBusy() )
       
   143 		{
       
   144 		return KErrNotReady;
       
   145 		}
       
   146 
       
   147     TSize srcRectSize( aSrcRect.Size() );
       
   148     TSize dstRectSize( aDstRect.Size() );
       
   149 	if( Abs( srcRectSize.iWidth ) > KMaxProcessSize ||
       
   150 	    Abs( srcRectSize.iHeight ) > KMaxProcessSize ||
       
   151 	    Abs( dstRectSize.iWidth ) > KMaxProcessSize ||
       
   152 	    Abs( dstRectSize.iHeight ) > KMaxProcessSize )
       
   153 	    {
       
   154 	    return KErrTooBig;
       
   155 	    }
       
   156 
       
   157 	if( !aSrcBitmap.Handle() ||
       
   158 		!IsValidRect( aSrcBitmap.SizeInPixels(), aSrcRect ) )
       
   159 		{
       
   160 		return KErrArgument;
       
   161 		}
       
   162 
       
   163 	if( aDstBitmap.Handle() )
       
   164 		{
       
   165 		if( !IsValidRect( aDstBitmap.SizeInPixels(), aDstRect ) )
       
   166 			{
       
   167 			return KErrArgument;
       
   168 			}
       
   169 		}
       
   170 	else
       
   171 		{		
       
   172 		// Create destination bitmap
       
   173 		TSize dstSize( Abs( dstRectSize.iWidth ), Abs( dstRectSize.iHeight ) );
       
   174 		TInt err = aDstBitmap.Create( dstSize, aSrcBitmap.DisplayMode() );
       
   175 		if( err )
       
   176 			{
       
   177 			return err;
       
   178 			}
       
   179 		}
       
   180 
       
   181 #ifdef RD_MEASURE_THROUGHPUT
       
   182 	iStartTime = User::FastCounter(); // For measuring scaler throughput
       
   183 #endif
       
   184     
       
   185     TSize srcSize( aSrcBitmap.SizeInPixels() );
       
   186     TSize dstSize( aDstBitmap.SizeInPixels() );
       
   187     
       
   188     if( srcSize.iWidth == 0 || srcSize.iHeight == 0 ||
       
   189         dstSize.iWidth == 0 || dstSize.iHeight == 0 ||
       
   190         aSrcRect.iTl.iX == aSrcRect.iBr.iX ||
       
   191         aSrcRect.iTl.iY == aSrcRect.iBr.iY ||
       
   192         aDstRect.iTl.iX == aDstRect.iBr.iX ||
       
   193         aDstRect.iTl.iY == aDstRect.iBr.iY )
       
   194         {
       
   195         // Bitmap or rect width or height is zero so there is nothing to do.
       
   196         // Complete process without error.
       
   197         iNeedProcess = EFalse;
       
   198         }
       
   199     else
       
   200         {
       
   201         iNeedProcess = ETrue;
       
   202 
       
   203     	// Set parameters to member data references
       
   204     	iSrcBitmap = &aSrcBitmap;
       
   205     	iSrcRect = aSrcRect;
       
   206     	iDstBitmap = &aDstBitmap;
       
   207     	iDstRect = aDstRect;
       
   208     	
       
   209     	TDisplayMode srcMode(iSrcBitmap->DisplayMode());
       
   210     	TDisplayMode dstMode(iDstBitmap->DisplayMode());
       
   211 
       
   212 		IHL_DEBUG3( KIHLDebug1, "CIHLScaler: src bitmap size %dx%d", srcSize.iWidth, srcSize.iHeight);
       
   213 		IHL_DEBUG3( KIHLDebug2, "CIHLScaler: dst bitmap size %dx%d", dstSize.iWidth, dstSize.iHeight);
       
   214 		IHL_DEBUG5( KIHLDebug3, "CIHLScaler: src bitmap rect %d.%d -> %d.%d", iSrcRect.iTl.iX, iSrcRect.iTl.iY, iSrcRect.iBr.iX, iSrcRect.iBr.iY);
       
   215 		IHL_DEBUG5( KIHLDebug4, "CIHLScaler: dst bitmap rect %d.%d -> %d.%d", iDstRect.iTl.iX, iDstRect.iTl.iY, iDstRect.iBr.iX, iDstRect.iBr.iY);
       
   216 		IHL_DEBUG2( KIHLDebug5, "CIHLScaler: src bitmap mode %d", srcMode);
       
   217 		IHL_DEBUG2( KIHLDebug6, "CIHLScaler: dst bitmap mode %d", dstMode);
       
   218 		IHL_DEBUG2( KIHLDebug7, "CIHLScaler: src compressed %d", iSrcBitmap->IsCompressedInRAM());
       
   219 		IHL_DEBUG2( KIHLDebug8, "CIHLScaler: dst compressed %d", iSrcBitmap->IsCompressedInRAM());
       
   220 		
       
   221 		// Init stepper values
       
   222     	TBool onlyScaling = InitStepperValues();
       
   223     	
       
   224     	// Select correct code path
       
   225     	InitCodePath(srcSize, srcMode, dstSize, dstMode, onlyScaling);
       
   226         }
       
   227 
       
   228     IHL_DEBUG1( KIHLDebug, "IHL - CIHLScaler - Start  bitmap scaling" );
       
   229 	
       
   230 	// Start processing
       
   231 	iScalerStatus = &aStatus;
       
   232 	*iScalerStatus = KRequestPending;
       
   233 
       
   234 	SelfComplete();
       
   235 	return KErrNone;
       
   236 	}
       
   237 
       
   238 // -----------------------------------------------------------------------------
       
   239 // CIHLScaler::IsBusy
       
   240 // -----------------------------------------------------------------------------
       
   241 TBool CIHLScaler::IsBusy() const
       
   242 	{
       
   243 	return IsActive();
       
   244 	}
       
   245 
       
   246 // -----------------------------------------------------------------------------
       
   247 // CIHLScaler::CancelProcess
       
   248 // -----------------------------------------------------------------------------
       
   249 void CIHLScaler::CancelProcess()
       
   250 	{
       
   251 	Cancel();
       
   252 	}
       
   253 
       
   254 // -----------------------------------------------------------------------------
       
   255 // CIHLScaler::SetFilter
       
   256 // -----------------------------------------------------------------------------
       
   257 void CIHLScaler::SetFilter( MIHFilter* /*aFilter*/ )
       
   258 	{
       
   259 	// Not in use
       
   260 	}
       
   261 
       
   262 // -----------------------------------------------------------------------------
       
   263 // CIHLScaler::DoCancel
       
   264 // -----------------------------------------------------------------------------
       
   265 void CIHLScaler::DoCancel()
       
   266 	{
       
   267 	RequestComplete( KErrCancel );
       
   268 	}
       
   269 
       
   270 // -----------------------------------------------------------------------------
       
   271 // CIHLScaler::RunL
       
   272 // -----------------------------------------------------------------------------
       
   273 void CIHLScaler::RunL()
       
   274 	{
       
   275 	User::LeaveIfError( iStatus.Int() );
       
   276 
       
   277 	// Process bitmap (this if-else may look weird but it removes one extra triggering of the AS
       
   278 	if( iNeedProcess )
       
   279 		{
       
   280 		// Call the selected code path directly via a function pointer
       
   281 		iNeedProcess = (this->*ProcessingFunc)();
       
   282 		}
       
   283 	
       
   284 	if(!iNeedProcess)
       
   285 		{
       
   286 #ifdef RD_MEASURE_THROUGHPUT
       
   287 		// Calculate throughput
       
   288 		TUint32 end = User::FastCounter();
       
   289 		
       
   290 		TInt tickPeriod;
       
   291 		HAL::Get(HALData::EFastCounterFrequency, tickPeriod);
       
   292 		TReal time = TReal(end-iStartTime) / TReal(tickPeriod);
       
   293 		TReal bytes = iProcessSize.iWidth*iProcessSize.iHeight*2;
       
   294 		
       
   295 		IHL_DEBUG3("IHL - CIHLScaler - Scaling complete, %.3f ms, %.3f MB/s", time*1000.0, (bytes/time)/1024.0/1024.0);
       
   296 #else
       
   297         IHL_DEBUG1( KIHLDebug, "IHL - CIHLScaler - Scaling complete!" );
       
   298 #endif
       
   299 		// Process complete
       
   300 		RequestComplete( KErrNone );
       
   301 		}
       
   302 	else
       
   303 		{
       
   304 		// Another round
       
   305 		SelfComplete();
       
   306 		}
       
   307 	}
       
   308 
       
   309 // -----------------------------------------------------------------------------
       
   310 // CIHLScaler::RunError
       
   311 // -----------------------------------------------------------------------------
       
   312 TInt CIHLScaler::RunError( TInt aError )
       
   313 	{
       
   314     IHL_DEBUG2( KIHLDebug, "IHL - CIHLScaler - Scaling error: %d", aError );
       
   315 
       
   316 	RequestComplete( aError );
       
   317 	return KErrNone;
       
   318 	}
       
   319 
       
   320 // -----------------------------------------------------------------------------
       
   321 // CIHLScaler::IsValidRect
       
   322 // -----------------------------------------------------------------------------
       
   323 TBool CIHLScaler::IsValidRect( const TSize& aSize, const TRect& aRect )
       
   324 	{
       
   325 	if( aRect.iTl.iX >= 0 &&
       
   326 		aRect.iTl.iX <= aSize.iWidth &&
       
   327 		aRect.iTl.iY >= 0 &&
       
   328 		aRect.iTl.iY <= aSize.iHeight &&
       
   329 		aRect.iBr.iX >= 0 &&
       
   330 		aRect.iBr.iX <= aSize.iWidth &&
       
   331 		aRect.iBr.iY >= 0 &&
       
   332 		aRect.iBr.iY <= aSize.iHeight )
       
   333 		{
       
   334 		return ETrue;
       
   335 		}
       
   336 	return EFalse;
       
   337 	}
       
   338 
       
   339 // -----------------------------------------------------------------------------
       
   340 // CIHLScaler::InitStepperValues
       
   341 // -----------------------------------------------------------------------------
       
   342 TBool CIHLScaler::InitStepperValues()
       
   343 	{
       
   344 	TBool onlyScaling = EFalse;
       
   345 	
       
   346 	TSize srcRectSize( Abs( iSrcRect.Width() ), Abs( iSrcRect.Height() ) );
       
   347 	TSize dstRectSize( Abs( iDstRect.Width() ), Abs( iDstRect.Height() ) );
       
   348 
       
   349 	TReal srcW = srcRectSize.iWidth << KStepPrecision;
       
   350 	TReal srcH = srcRectSize.iHeight << KStepPrecision;
       
   351 	
       
   352     // -----------------------------------------
       
   353 	// Set source start point and increment
       
   354     // -----------------------------------------
       
   355 	if( iSrcRect.iTl.iX > iSrcRect.iBr.iX &&
       
   356 		iSrcRect.iTl.iY < iSrcRect.iBr.iY )
       
   357 		{
       
   358         TReal incrementInner( srcH / TReal(dstRectSize.iWidth) );
       
   359         TReal incrementOuter( srcW / TReal(dstRectSize.iHeight) );
       
   360 
       
   361 		iSrcIncrementInner.iX = 0;
       
   362 		iSrcIncrementInner.iY = incrementInner;
       
   363 		iSrcIncrementOuter.iX = -incrementOuter;
       
   364 		iSrcIncrementOuter.iY = 0;
       
   365 
       
   366 		iSrcPos.SetXY( (iSrcRect.iTl.iX << KStepPrecision) - (incrementOuter / 2.0),
       
   367 		               (iSrcRect.iTl.iY << KStepPrecision) + (incrementInner / 2.0) );
       
   368 		}
       
   369 	else if	( iSrcRect.iTl.iX > iSrcRect.iBr.iX &&
       
   370 			  iSrcRect.iTl.iY > iSrcRect.iBr.iY )
       
   371 		{
       
   372         TReal incrementInner( srcW / TReal(dstRectSize.iWidth) );
       
   373         TReal incrementOuter( srcH / TReal(dstRectSize.iHeight) );
       
   374 
       
   375 		iSrcIncrementInner.iX = -incrementInner;
       
   376 		iSrcIncrementInner.iY = 0;
       
   377 		iSrcIncrementOuter.iX = 0;
       
   378 		iSrcIncrementOuter.iY = -incrementOuter;
       
   379 
       
   380 		iSrcPos.SetXY( (iSrcRect.iTl.iX << KStepPrecision) - (incrementInner / 2.0),
       
   381 		               (iSrcRect.iTl.iY << KStepPrecision) - (incrementOuter / 2.0) );
       
   382 		}
       
   383 	else if	( iSrcRect.iTl.iX < iSrcRect.iBr.iX &&
       
   384 			  iSrcRect.iTl.iY > iSrcRect.iBr.iY )
       
   385 		{
       
   386         TReal incrementInner( srcH / TReal(dstRectSize.iWidth) );
       
   387         TReal incrementOuter( srcW / TReal(dstRectSize.iHeight) );
       
   388 
       
   389 		iSrcIncrementInner.iX = 0;
       
   390 		iSrcIncrementInner.iY = -incrementInner;
       
   391 		iSrcIncrementOuter.iX = incrementOuter;
       
   392 		iSrcIncrementOuter.iY = 0;
       
   393 
       
   394 		iSrcPos.SetXY( (iSrcRect.iTl.iX << KStepPrecision) + (incrementOuter / 2.0),
       
   395 		               (iSrcRect.iTl.iY << KStepPrecision) - (incrementInner / 2.0) );
       
   396 		}
       
   397 	else
       
   398 		{
       
   399         TReal incrementInner( srcW / TReal(dstRectSize.iWidth) );
       
   400         TReal incrementOuter( srcH / TReal(dstRectSize.iHeight) );
       
   401 
       
   402 		IHL_DEBUG3(KIHLDebug, "incrementInner: %f, incrementOuter: %f", incrementInner, incrementOuter);
       
   403 		
       
   404 		iSrcIncrementInner.iX = incrementInner;
       
   405 		iSrcIncrementInner.iY = 0;
       
   406 		iSrcIncrementOuter.iX = 0;
       
   407 		iSrcIncrementOuter.iY = incrementOuter;
       
   408 
       
   409 		iSrcPos.SetXY( (iSrcRect.iTl.iX << KStepPrecision) + (incrementInner / 2.0),
       
   410 		               (iSrcRect.iTl.iY << KStepPrecision) + (incrementOuter / 2.0) );
       
   411 		               
       
   412 		onlyScaling = ETrue;
       
   413 		}
       
   414 
       
   415 	// -----------------------------------------
       
   416 	// Set destination start point and increment
       
   417     // -----------------------------------------
       
   418 	
       
   419 	iDstPos.iX = iDstRect.iTl.iX;
       
   420 	iDstIncrementInner = 1;
       
   421 	iDstPos.iY = iDstRect.iTl.iY;
       
   422 	iDstIncrementOuter = 1;
       
   423 	
       
   424 	if( iDstRect.iTl.iX > iDstRect.iBr.iX )
       
   425 		{
       
   426 		// From right to left
       
   427 		iDstPos.iX--;
       
   428 		iDstIncrementInner = -1;
       
   429 		onlyScaling = EFalse;
       
   430 		}
       
   431 	
       
   432 	if( iDstRect.iTl.iY > iDstRect.iBr.iY )
       
   433 		{
       
   434 		// From bottom to up
       
   435 		iDstPos.iY--;
       
   436 		iDstIncrementOuter = -1;
       
   437 		onlyScaling = EFalse;
       
   438 		}
       
   439 
       
   440     // -----------------------------------------
       
   441 	// Reset process counters
       
   442     // -----------------------------------------
       
   443 	iProcessInner = 0;
       
   444 	iProcessOuter = 0;
       
   445 	iProcessSize = dstRectSize;
       
   446 	
       
   447 	// These are for fast code path
       
   448 	
       
   449 	// Init how many scanlines to process
       
   450 	iScanlinesLeft = iProcessSize.iHeight; 
       
   451 		
       
   452 	return onlyScaling;
       
   453 	}
       
   454 
       
   455 
       
   456 // Optimize the fast code paths properly for ARM
       
   457 #ifdef __ARMCC__
       
   458 #pragma push
       
   459 #pragma O3
       
   460 #pragma Otime
       
   461 #pragma arm
       
   462 #endif
       
   463 
       
   464 // -----------------------------------------------------------------------------
       
   465 // CIHLScaler::ProcessNearestNeighbour64K
       
   466 // Description: Scales & rotates 64K color bitmaps
       
   467 // -----------------------------------------------------------------------------
       
   468 TBool CIHLScaler::ProcessNearestNeighbour64K()
       
   469 	{
       
   470 	// Lock bitmap heaps
       
   471 	iSrcBitmap->LockHeap();
       
   472 	iDstBitmap->LockHeap();
       
   473 	
       
   474 	// Pointers to start of bitmap data
       
   475 	TUint16 *srcBitmapPtr = (TUint16*)iSrcBitmap->DataAddress();
       
   476 	TUint16 *dstBitmapPtr = (TUint16*)iDstBitmap->DataAddress();
       
   477 	
       
   478 	// Get pointer to correct destination pixel (offset is updated after every round)
       
   479 	register TUint16* dst = dstBitmapPtr + iDstStartOffset;
       
   480 	
       
   481 	TUint32 width = iProcessSize.iWidth;
       
   482 	
       
   483 	// Check how many scanlines we can process this round
       
   484 	register TUint32 scanlinesLeft = iScanlinesLeft;
       
   485 	if(scanlinesLeft>iScanlinesPerRound)
       
   486 		{
       
   487 		scanlinesLeft = iScanlinesPerRound;
       
   488 		}
       
   489 
       
   490 	// How many scanlines left for the next round
       
   491 	iScanlinesLeft-=scanlinesLeft;
       
   492 	
       
   493 	// Faster access to variables (it's slow to use member variables)
       
   494 	register TInt srcPosX(iSrcPos.iX);
       
   495 	register TInt srcPosY(iSrcPos.iY);
       
   496 	register TInt srcPitch = iSrcPitchInPixels;
       
   497 	
       
   498 	TInt incOuterSrcX = (-iSrcIncrementInner.iX * width) + iSrcIncrementOuter.iX;
       
   499 	TInt incOuterSrcY = (-iSrcIncrementInner.iY * width) + iSrcIncrementOuter.iY;
       
   500 	
       
   501 	while(scanlinesLeft!=0)
       
   502         {
       
   503 		for(register TUint32 x = width; x!=0; x--)
       
   504 			{
       
   505 			register TUint16* src = srcBitmapPtr + ((srcPosY >> KStepPrecision) * srcPitch) + (srcPosX>>KStepPrecision);
       
   506 			*dst = *src;
       
   507 
       
   508             // Add inner counters
       
   509 			srcPosX+=iSrcIncrementInner.iX;
       
   510 			srcPosY+=iSrcIncrementInner.iY;
       
   511 			
       
   512 			dst+=iDstIncrementInner;
       
   513 			}
       
   514 			
       
   515 		// Reset inner counters and add outer counters
       
   516 		srcPosX += incOuterSrcX;
       
   517 		srcPosY += incOuterSrcY;
       
   518 
       
   519 		// Move destination pointer to next pixel
       
   520 		dst += iDstResidualPixels;
       
   521 		
       
   522 		// One scanline done, n to go
       
   523 		scanlinesLeft--;
       
   524 		}
       
   525 	// Unlock bitmap heaps
       
   526 	iDstBitmap->UnlockHeap();
       
   527 	iSrcBitmap->UnlockHeap();
       
   528 	
       
   529 	if(iScanlinesLeft)
       
   530 		{
       
   531 		// Not all scanlines were processed yet
       
   532 		
       
   533 		// Save the necessary offsets for next round
       
   534 		iSrcPos.iX = srcPosX;
       
   535 		iSrcPos.iY = srcPosY;
       
   536 		iDstStartOffset = dst - dstBitmapPtr;
       
   537 		
       
   538 		return ETrue;
       
   539 		}
       
   540 	
       
   541 	// Processing done
       
   542 	return EFalse;
       
   543 	}
       
   544 
       
   545 // -----------------------------------------------------------------------------
       
   546 // CIHLScaler::ProcessNearestNeighbour64KScaleOnly
       
   547 // -----------------------------------------------------------------------------
       
   548 TBool CIHLScaler::ProcessNearestNeighbour64KScaleOnly()
       
   549 	{
       
   550 	// Lock bitmap heaps
       
   551 	iSrcBitmap->LockHeap();
       
   552 	iDstBitmap->LockHeap();
       
   553 	
       
   554 	// Get bitmap data start addresses
       
   555 	TUint16 *srcBitmapPtr = (TUint16*)iSrcBitmap->DataAddress();
       
   556 	TUint16 *dstBitmapPtr = (TUint16*)iDstBitmap->DataAddress();
       
   557 
       
   558 	// Target height and width
       
   559 	TInt width = iProcessSize.iWidth;
       
   560 	
       
   561 	// fixed point source coordinates
       
   562 	TInt startX = iSrcPos.iX;
       
   563 	TInt srcY = iSrcPos.iY;
       
   564 	
       
   565 	// How much to increase src position (in fixed point)
       
   566 	TInt srcYIncrement = iSrcIncrementOuter.iY;
       
   567 	register TInt srcXIncrement = iSrcIncrementInner.iX;
       
   568 	
       
   569 	// Set pointers to correct location (src = start of scanline, dst = start pixel)
       
   570 	register TUint16* dst = dstBitmapPtr + iDstStartOffset;
       
   571 	
       
   572 	// Calculate how many scanlines we can process this round
       
   573 	register TInt scanlinesLeft = iScanlinesLeft;
       
   574 	if(scanlinesLeft>iScanlinesPerRound)
       
   575 	{
       
   576 		scanlinesLeft = iScanlinesPerRound;
       
   577 	}
       
   578 	
       
   579 	iScanlinesLeft-=scanlinesLeft;
       
   580 		
       
   581 	while(scanlinesLeft--)
       
   582 		{
       
   583 		// Outer loop
       
   584 		
       
   585 		// Reset src X and scanline pointer
       
   586 		register TInt srcX = startX;
       
   587 		register TUint16* src = srcBitmapPtr + (srcY >> KStepPrecision) * iSrcPitchInPixels;
       
   588 		
       
   589 		// Init pixel counter
       
   590 		register TUint32 pixels = width;
       
   591 		
       
   592 		// Unaligned pixels to the left of 8B-aligned section
       
   593 		while((TUint32(dst)&0x7) && pixels)
       
   594 		{
       
   595 			*dst++ = (*(src + (srcX >> KStepPrecision)));
       
   596 
       
   597 			srcX += srcXIncrement;
       
   598 			
       
   599 			pixels--;
       
   600 		}
       
   601 		
       
   602 		// Aligned middle section		
       
   603 		register TUint32 middle = pixels&0xFFFFFFFC;
       
   604 		pixels &= 0x3;
       
   605 		
       
   606 		while(middle)
       
   607 			{
       
   608 			// Read four pixels
       
   609 			register TUint16 p1 = (*(src + (srcX >> KStepPrecision)));
       
   610 			srcX += srcXIncrement;
       
   611 			register TUint16 p2 = (*(src + (srcX >> KStepPrecision)));
       
   612 			srcX += srcXIncrement;
       
   613 			register TUint16 p3 = (*(src + (srcX >> KStepPrecision)));
       
   614 			srcX += srcXIncrement;
       
   615 			register TUint16 p4 = (*(src + (srcX >> KStepPrecision)));
       
   616 			srcX += srcXIncrement;
       
   617 			
       
   618 			// Write four pixels
       
   619 			*(dst++) = p1;
       
   620 			*(dst++) = p2;
       
   621 			*(dst++) = p3;
       
   622 			*(dst++) = p4;
       
   623 
       
   624 			middle-=4;
       
   625 			}
       
   626 			
       
   627 		// Unaligned residual pixels to the right of 8-aligned section
       
   628 		while(pixels)
       
   629 		{
       
   630 			*dst++ = (*(src + (srcX >> KStepPrecision)));
       
   631 
       
   632 			srcX += srcXIncrement;
       
   633 			
       
   634 			pixels--;
       
   635 		}
       
   636 		
       
   637 		// Move to next correct src scanline
       
   638 		srcY += srcYIncrement;
       
   639 		
       
   640 		// Advance dst to start of correct pixel in the next row
       
   641 		dst += iDstResidualPixels;
       
   642 		}
       
   643 	
       
   644 	iDstBitmap->UnlockHeap();
       
   645 	iSrcBitmap->UnlockHeap();
       
   646 	
       
   647 	if(iScanlinesLeft)
       
   648 		{
       
   649 		// Not all scanlines were processed yet
       
   650 		
       
   651 		// Save the necessary offsets for next round
       
   652 		iSrcPos.iY = srcY;
       
   653 		iDstStartOffset = dst - dstBitmapPtr;
       
   654 
       
   655 		return ETrue;
       
   656 		}
       
   657 	
       
   658 	return EFalse;
       
   659 	
       
   660 	}
       
   661 
       
   662 // -----------------------------------------------------------------------------
       
   663 // CIHLScaler::ProcessNearestNeighbour16MX
       
   664 // Description: Scales & rotates 16MU/MA color bitmaps
       
   665 // -----------------------------------------------------------------------------
       
   666 TBool CIHLScaler::ProcessNearestNeighbour16MX()
       
   667 	{
       
   668 	// Lock bitmap heaps
       
   669 	iSrcBitmap->LockHeap();
       
   670 	iDstBitmap->LockHeap();
       
   671 	
       
   672 	// Pointers to start of bitmap data
       
   673 	TUint32 *srcBitmapPtr = (TUint32*)iSrcBitmap->DataAddress();
       
   674 	TUint32 *dstBitmapPtr = (TUint32*)iDstBitmap->DataAddress();
       
   675 	
       
   676 	// Get pointer to correct destination pixel (offset is updated after every round)
       
   677 	register TUint32* dst = dstBitmapPtr + iDstStartOffset;
       
   678 	
       
   679 	TUint32 width = iProcessSize.iWidth;
       
   680 	
       
   681 	// Check how many scanlines we can process this round
       
   682 	register TUint32 scanlinesLeft = iScanlinesLeft;
       
   683 	if(scanlinesLeft>iScanlinesPerRound)
       
   684 		{
       
   685 		scanlinesLeft = iScanlinesPerRound;
       
   686 		}
       
   687 
       
   688 	// How many scanlines left for the next round
       
   689 	iScanlinesLeft-=scanlinesLeft;
       
   690 	
       
   691 	// Faster access to variables (it's slow to use member variables)
       
   692 	register TInt srcPosX(iSrcPos.iX);
       
   693 	register TInt srcPosY(iSrcPos.iY);
       
   694 	register TInt srcPitch = iSrcPitchInPixels;
       
   695 	
       
   696 	TInt incOuterSrcX = (-iSrcIncrementInner.iX * width) + iSrcIncrementOuter.iX;
       
   697 	TInt incOuterSrcY = (-iSrcIncrementInner.iY * width) + iSrcIncrementOuter.iY;
       
   698 	
       
   699 	while(scanlinesLeft!=0)
       
   700         {
       
   701 		for(register TUint32 x = width; x!=0; x--)
       
   702 			{
       
   703 			register TUint32* src = srcBitmapPtr + ((srcPosY >> KStepPrecision) * srcPitch) + (srcPosX>>KStepPrecision);
       
   704 			*dst = *src;
       
   705 
       
   706             // Add inner counters
       
   707 			srcPosX+=iSrcIncrementInner.iX;
       
   708 			srcPosY+=iSrcIncrementInner.iY;
       
   709 			
       
   710 			dst+=iDstIncrementInner;
       
   711 			}
       
   712 			
       
   713 		// Reset inner counters and add outer counters
       
   714 		srcPosX += incOuterSrcX;
       
   715 		srcPosY += incOuterSrcY;
       
   716 
       
   717 		// Move destination pointer to next pixel
       
   718 		dst += iDstResidualPixels;
       
   719 		
       
   720 		// One scanline done, n to go
       
   721 		scanlinesLeft--;
       
   722 		}
       
   723 	// Unlock bitmap heaps
       
   724 	iDstBitmap->UnlockHeap();
       
   725 	iSrcBitmap->UnlockHeap();
       
   726 	
       
   727 	if(iScanlinesLeft)
       
   728 		{
       
   729 		// Not all scanlines were processed yet
       
   730 		
       
   731 		// Save the necessary offsets for next round
       
   732 		iSrcPos.iX = srcPosX;
       
   733 		iSrcPos.iY = srcPosY;
       
   734 		iDstStartOffset = dst - dstBitmapPtr;
       
   735 		
       
   736 		return ETrue;
       
   737 		}
       
   738 	
       
   739 	// Processing done
       
   740 	return EFalse;
       
   741 	}
       
   742 	
       
   743 // -----------------------------------------------------------------------------
       
   744 // CIHLScaler::ProcessNearestNeighbour64KScaleOnly
       
   745 // -----------------------------------------------------------------------------
       
   746 TBool CIHLScaler::ProcessNearestNeighbour16MXScaleOnly()
       
   747 	{
       
   748 	// Lock bitmap heaps
       
   749 	iSrcBitmap->LockHeap();
       
   750 	iDstBitmap->LockHeap();
       
   751 	
       
   752 	// Get bitmap data start addresses
       
   753 	TUint32 *srcBitmapPtr = (TUint32*)iSrcBitmap->DataAddress();
       
   754 	TUint32 *dstBitmapPtr = (TUint32*)iDstBitmap->DataAddress();
       
   755 
       
   756 	// Target height and width
       
   757 	TInt width = iProcessSize.iWidth;
       
   758 	
       
   759 	// fixed point source coordinates
       
   760 	TInt startX = iSrcPos.iX;
       
   761 	TInt srcY = iSrcPos.iY;
       
   762 	
       
   763 	// How much to increase src position (in fixed point)
       
   764 	TInt srcYIncrement = iSrcIncrementOuter.iY;
       
   765 	register TInt srcXIncrement = iSrcIncrementInner.iX;
       
   766 	
       
   767 	// Set pointers to correct location (src = start of scanline, dst = start pixel)
       
   768 	register TUint32* dst = dstBitmapPtr + iDstStartOffset;
       
   769 	
       
   770 	// Calculate how many scanlines we can process this round
       
   771 	register TInt scanlinesLeft = iScanlinesLeft;
       
   772 	if(scanlinesLeft>iScanlinesPerRound)
       
   773 	{
       
   774 		scanlinesLeft = iScanlinesPerRound;
       
   775 	}
       
   776 	
       
   777 	iScanlinesLeft-=scanlinesLeft;
       
   778 		
       
   779 	while(scanlinesLeft--)
       
   780 		{
       
   781 		// Outer loop
       
   782 		
       
   783 		// Reset src X and scanline pointer
       
   784 		register TInt srcX = startX;
       
   785 		register TUint32* src = srcBitmapPtr + (srcY >> KStepPrecision) * iSrcPitchInPixels;
       
   786 		
       
   787 		// Init pixel counter
       
   788 		register TUint32 pixels = width;
       
   789 		
       
   790 		// Unaligned pixels to the left of 16B-aligned section
       
   791 		while((TUint32(dst)&0xF) && pixels)
       
   792 		{
       
   793 			*dst++ = (*(src + (srcX >> KStepPrecision)));
       
   794 
       
   795 			srcX += srcXIncrement;
       
   796 			
       
   797 			pixels--;
       
   798 		}
       
   799 		
       
   800 		// Aligned middle section		
       
   801 		register TUint32 middle = pixels&0xFFFFFFFC;
       
   802 		pixels &= 0x3;
       
   803 		
       
   804 		while(middle)
       
   805 			{
       
   806 			// Read four pixels
       
   807 			register TUint32 p1 = (*(src + (srcX >> KStepPrecision)));
       
   808 			srcX += srcXIncrement;
       
   809 			register TUint32 p2 = (*(src + (srcX >> KStepPrecision)));
       
   810 			srcX += srcXIncrement;
       
   811 			register TUint32 p3 = (*(src + (srcX >> KStepPrecision)));
       
   812 			srcX += srcXIncrement;
       
   813 			register TUint32 p4 = (*(src + (srcX >> KStepPrecision)));
       
   814 			srcX += srcXIncrement;
       
   815 			
       
   816 			// Write four pixels
       
   817 			*(dst+0) = p1;
       
   818 			*(dst+1) = p2;
       
   819 			*(dst+2) = p3;
       
   820 			*(dst+3) = p4;
       
   821 
       
   822 			middle-=4;
       
   823 			dst+=4;		
       
   824 			}
       
   825 			
       
   826 		// Unaligned residual pixels to the right of 8-aligned section
       
   827 		while(pixels)
       
   828 		{
       
   829 			*dst++ = (*(src + (srcX >> KStepPrecision)));
       
   830 
       
   831 			srcX += srcXIncrement;
       
   832 			
       
   833 			pixels--;
       
   834 		}
       
   835 		
       
   836 		// Move to next correct src scanline
       
   837 		srcY += srcYIncrement;
       
   838 		
       
   839 		// Advance dst to start of correct pixel in the next row
       
   840 		dst += iDstResidualPixels;
       
   841 		}
       
   842 	
       
   843 	iDstBitmap->UnlockHeap();
       
   844 	iSrcBitmap->UnlockHeap();
       
   845 	
       
   846 	if(iScanlinesLeft)
       
   847 		{
       
   848 		// Not all scanlines were processed yet
       
   849 		
       
   850 		// Save the necessary offsets for next round
       
   851 		iSrcPos.iY = srcY;
       
   852 		iDstStartOffset = dst - dstBitmapPtr;
       
   853 
       
   854 		return ETrue;
       
   855 		}
       
   856 	
       
   857 	return EFalse;
       
   858 	
       
   859 	}
       
   860 	
       
   861 // Restore previous pragma state
       
   862 #ifdef __ARMCC__
       
   863 #pragma pop
       
   864 #endif
       
   865 
       
   866 // -----------------------------------------------------------------------------
       
   867 // CIHLScaler::ProcessNearestNeighbour
       
   868 // -----------------------------------------------------------------------------
       
   869 TBool CIHLScaler::ProcessNearestNeighbour()
       
   870 	{
       
   871 	// Util needs non-const pointers even if it's only used for reading pixels
       
   872     TBitmapUtil srcBitmap( const_cast<CFbsBitmap*>( iSrcBitmap ) );
       
   873     TBitmapUtil dstBitmap( iDstBitmap );
       
   874     srcBitmap.Begin( TPoint( iSrcPos.iX >> KStepPrecision, iSrcPos.iY >> KStepPrecision ) );
       
   875     dstBitmap.Begin( iDstPos ); // heap already locked by srcBitmap
       
   876 	TInt pixelCounter( KProcessPixelsPerStep );
       
   877 
       
   878     // Start outer and inner process loops
       
   879     while( iProcessOuter < iProcessSize.iHeight && pixelCounter )
       
   880         {
       
   881 		while( iProcessInner < iProcessSize.iWidth && pixelCounter )
       
   882 			{
       
   883 			srcBitmap.SetPos( TPoint( iSrcPos.iX >> KStepPrecision, iSrcPos.iY >> KStepPrecision ) );
       
   884 			dstBitmap.SetPos( iDstPos );
       
   885 			dstBitmap.SetPixel( srcBitmap );
       
   886 
       
   887             // Add inner counters
       
   888 			iSrcPos += iSrcIncrementInner;
       
   889 			iDstPos.iX += iDstIncrementInner;
       
   890 			++iProcessInner;
       
   891 			--pixelCounter;
       
   892 			}
       
   893         // Check if inner loop is finished (not just pixel counter)
       
   894 		if( iProcessInner == iProcessSize.iWidth )
       
   895 			{
       
   896 			// Reset inner counters
       
   897 			iSrcPos.iX -= iSrcIncrementInner.iX * iProcessInner;
       
   898 			iSrcPos.iY -= iSrcIncrementInner.iY * iProcessInner;
       
   899 
       
   900 			iDstPos.iX -= iDstIncrementInner * iProcessInner;
       
   901 			iProcessInner = 0;
       
   902 
       
   903             // Add outer counters
       
   904 			iSrcPos += iSrcIncrementOuter;
       
   905 			iDstPos.iY += iDstIncrementOuter;
       
   906 			++iProcessOuter;
       
   907 			}
       
   908 		}
       
   909 
       
   910     // Release heap lock
       
   911     dstBitmap.End();
       
   912     srcBitmap.End();
       
   913 
       
   914     // ETrue if more processing is still needed
       
   915 	return ( iProcessOuter < iProcessSize.iHeight );
       
   916 	}
       
   917 
       
   918 // -----------------------------------------------------------------------------
       
   919 // CIHLScaler::ProcessBilinear
       
   920 // -----------------------------------------------------------------------------
       
   921 TBool CIHLScaler::ProcessBilinear()
       
   922 	{
       
   923 	// Util needs non-const pointers
       
   924 	//even if it's only used for reading pixels
       
   925 	TBitmapUtil srcBitmap( const_cast<CFbsBitmap*>( iSrcBitmap ) );
       
   926 	TBitmapUtil dstBitmap( iDstBitmap );
       
   927 
       
   928 	srcBitmap.Begin( TPoint( iSrcPos.iX >> KStepPrecision, iSrcPos.iY >> KStepPrecision ) );
       
   929 	dstBitmap.Begin( iDstPos ); // heap already locked by srcBitmap
       
   930 	TInt pixelCounter( KProcessPixelsPerStep );
       
   931 
       
   932 	TInt incSrcX = iSrcIncrementInner.iX + iSrcIncrementOuter.iX;
       
   933 	TInt incSrcY = iSrcIncrementInner.iY + iSrcIncrementOuter.iY;
       
   934 
       
   935 	TPixelData pixelData;
       
   936 	TUint32 color;
       
   937 
       
   938 	TInt32 pixel_width = 1 << KStepPrecision;
       
   939 
       
   940 	//if there is no scaling then process through loop using NearestNeighbour alghoritm
       
   941 	if ( incSrcX == pixel_width || -incSrcX == pixel_width ) 
       
   942 		{
       
   943 		while( iProcessOuter < iProcessSize.iHeight && pixelCounter )
       
   944 			{
       
   945 			while( iProcessInner < iProcessSize.iWidth && pixelCounter )
       
   946 				{
       
   947 				srcBitmap.SetPos( TPoint( iSrcPos.iX >> KStepPrecision, iSrcPos.iY >> KStepPrecision ) );
       
   948 				dstBitmap.SetPos( iDstPos );
       
   949 				dstBitmap.SetPixel( srcBitmap );
       
   950 
       
   951 				// Add inner counters
       
   952 				iSrcPos += iSrcIncrementInner;
       
   953 				iDstPos.iX += iDstIncrementInner;
       
   954 				++iProcessInner;
       
   955 				--pixelCounter;
       
   956 				}
       
   957 
       
   958 			// Check if inner loop is finished (not just pixel counter)
       
   959 			if( iProcessInner == iProcessSize.iWidth )
       
   960 				{
       
   961 				// Reset inner counters
       
   962 				iSrcPos.iX -= iSrcIncrementInner.iX * iProcessInner;
       
   963 				iSrcPos.iY -= iSrcIncrementInner.iY * iProcessInner;
       
   964 
       
   965 				iDstPos.iX -= iDstIncrementInner * iProcessInner;
       
   966 				iProcessInner = 0;
       
   967 
       
   968 				// Add outer counters
       
   969 				iSrcPos += iSrcIncrementOuter;
       
   970 				iDstPos.iY += iDstIncrementOuter;
       
   971 				++iProcessOuter;
       
   972 				}
       
   973 			}
       
   974 		}
       
   975 	// Process using bilinear method according to 
       
   976 	// orientation between source and destination bitmap
       
   977 	//
       
   978 	// There are 4 possibilities of orientation and can be
       
   979 	// determined by this if we're increasing or decreasing
       
   980 	// position on source bitmap.
       
   981 	else if ( ( incSrcY >= 0) && (incSrcX >= 0 ) )
       
   982 		{
       
   983 		while( iProcessOuter < iProcessSize.iHeight && pixelCounter )
       
   984 			{
       
   985 			while( iProcessInner < iProcessSize.iWidth && pixelCounter )
       
   986 				{
       
   987 				srcBitmap.SetPos( TPoint( iSrcPos.iX >> KStepPrecision, iSrcPos.iY >> KStepPrecision ) );
       
   988 				dstBitmap.SetPos( iDstPos );
       
   989 
       
   990 				// gather pixel data with step:
       
   991 				// 00 > 10 
       
   992 				//      V
       
   993 				// 01 < 11
       
   994 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY00);
       
   995 				srcBitmap.IncXPos();
       
   996 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY10);
       
   997 				srcBitmap.IncYPos();
       
   998 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY11);
       
   999 				srcBitmap.DecXPos();
       
  1000 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY01);
       
  1001 				//return to starting position
       
  1002 				srcBitmap.DecYPos();
       
  1003 
       
  1004 				// interpolate color using gathered pixel-data
       
  1005 				ProcessColorData(pixelData, iSrcPos);
       
  1006 
       
  1007 				// put color in destination package
       
  1008 				color = RgbToInt(pixelData.col);
       
  1009 				dstBitmap.SetPixel(color);
       
  1010 
       
  1011 				// Add inner counters
       
  1012 				iSrcPos += iSrcIncrementInner;
       
  1013 				iDstPos.iX += iDstIncrementInner;
       
  1014 				++iProcessInner;
       
  1015 				--pixelCounter;
       
  1016 				}
       
  1017 
       
  1018 			// Check if inner loop is finished (not just pixel counter)
       
  1019 			if( iProcessInner == iProcessSize.iWidth )
       
  1020 				{
       
  1021 				// Reset inner counters
       
  1022 				iSrcPos.iX -= iSrcIncrementInner.iX * iProcessInner;
       
  1023 				iSrcPos.iY -= iSrcIncrementInner.iY * iProcessInner;
       
  1024 
       
  1025 				iDstPos.iX -= iDstIncrementInner * iProcessInner;
       
  1026 				iProcessInner = 0;
       
  1027 
       
  1028 				// Add outer counters
       
  1029 				iSrcPos += iSrcIncrementOuter;
       
  1030 				iDstPos.iY += iDstIncrementOuter;
       
  1031 				++iProcessOuter;
       
  1032 				}
       
  1033 			}
       
  1034 		}
       
  1035 	else if ( ( incSrcY >= 0) && (incSrcX < 0 ) )
       
  1036 		{
       
  1037 		while( iProcessOuter < iProcessSize.iHeight && pixelCounter )
       
  1038 			{
       
  1039 			while( iProcessInner < iProcessSize.iWidth && pixelCounter )
       
  1040 				{
       
  1041 				srcBitmap.SetPos( TPoint( iSrcPos.iX >> KStepPrecision, iSrcPos.iY >> KStepPrecision ) );
       
  1042 				dstBitmap.SetPos( iDstPos );
       
  1043 
       
  1044 				// gather pixel data with step:
       
  1045 				// 00   10 
       
  1046 				// /\   V
       
  1047 				// 01 < 11
       
  1048 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY10);
       
  1049 				srcBitmap.IncYPos();
       
  1050 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY11);
       
  1051 				srcBitmap.DecXPos();
       
  1052 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY01);
       
  1053 				srcBitmap.DecYPos();
       
  1054 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY00);
       
  1055 				//return to starting position
       
  1056 				srcBitmap.IncXPos();
       
  1057 
       
  1058 				// interpolate color using gathered pixel-data
       
  1059 				ProcessColorData(pixelData, iSrcPos);
       
  1060 
       
  1061 				// put color in destination package
       
  1062 				color = RgbToInt(pixelData.col);
       
  1063 				dstBitmap.SetPixel(color);
       
  1064 
       
  1065 				// Add inner counters
       
  1066 				iSrcPos += iSrcIncrementInner;
       
  1067 				iDstPos.iX += iDstIncrementInner;
       
  1068 				++iProcessInner;
       
  1069 				--pixelCounter;
       
  1070 				}
       
  1071 
       
  1072 			// Check if inner loop is finished (not just pixel counter)
       
  1073 			if( iProcessInner == iProcessSize.iWidth )
       
  1074 				{
       
  1075 				// Reset inner counters
       
  1076 				iSrcPos.iX -= iSrcIncrementInner.iX * iProcessInner;
       
  1077 				iSrcPos.iY -= iSrcIncrementInner.iY * iProcessInner;
       
  1078 
       
  1079 				iDstPos.iX -= iDstIncrementInner * iProcessInner;
       
  1080 				iProcessInner = 0;
       
  1081 
       
  1082 				// Add outer counters
       
  1083 				iSrcPos += iSrcIncrementOuter;
       
  1084 				iDstPos.iY += iDstIncrementOuter;
       
  1085 				++iProcessOuter;
       
  1086 				}
       
  1087 
       
  1088 			}
       
  1089 		}
       
  1090 	else if ( ( incSrcY < 0) && (incSrcX >= 0 ) )
       
  1091 		{
       
  1092 		while( iProcessOuter < iProcessSize.iHeight && pixelCounter )
       
  1093 			{
       
  1094 			while( iProcessInner < iProcessSize.iWidth && pixelCounter )
       
  1095 				{
       
  1096 				srcBitmap.SetPos( TPoint( iSrcPos.iX >> KStepPrecision, iSrcPos.iY >> KStepPrecision ) );
       
  1097 				dstBitmap.SetPos( iDstPos );
       
  1098 
       
  1099 				// gather pixel data with step:
       
  1100 				// 00 > 10 
       
  1101 				// /\   V
       
  1102 				// 01   11
       
  1103 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY01);
       
  1104 				srcBitmap.DecYPos();
       
  1105 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY00);
       
  1106 				srcBitmap.IncXPos();
       
  1107 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY10);
       
  1108 				srcBitmap.IncYPos();
       
  1109 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY11);
       
  1110 				//return to starting position
       
  1111 				srcBitmap.DecXPos();
       
  1112 
       
  1113 				// interpolate color using gathered pixel-data
       
  1114 				ProcessColorData(pixelData, iSrcPos);
       
  1115 
       
  1116 				// put color in destination package
       
  1117 				color = RgbToInt(pixelData.col);
       
  1118 				dstBitmap.SetPixel(color);
       
  1119 
       
  1120 				// Add inner counters
       
  1121 				iSrcPos += iSrcIncrementInner;
       
  1122 				iDstPos.iX += iDstIncrementInner;
       
  1123 				++iProcessInner;
       
  1124 				--pixelCounter;
       
  1125 				}
       
  1126 
       
  1127 			// Check if inner loop is finished (not just pixel counter)
       
  1128 			if( iProcessInner == iProcessSize.iWidth )
       
  1129 				{
       
  1130 				// Reset inner counters
       
  1131 				iSrcPos.iX -= iSrcIncrementInner.iX * iProcessInner;
       
  1132 				iSrcPos.iY -= iSrcIncrementInner.iY * iProcessInner;
       
  1133 
       
  1134 				iDstPos.iX -= iDstIncrementInner * iProcessInner;
       
  1135 				iProcessInner = 0;
       
  1136 
       
  1137 				// Add outer counters
       
  1138 				iSrcPos += iSrcIncrementOuter;
       
  1139 				iDstPos.iY += iDstIncrementOuter;
       
  1140 				++iProcessOuter;
       
  1141 				}
       
  1142 			}
       
  1143 		}
       
  1144 	else
       
  1145 		{
       
  1146 		while( iProcessOuter < iProcessSize.iHeight && pixelCounter )
       
  1147 			{
       
  1148 			while( iProcessInner < iProcessSize.iWidth && pixelCounter )
       
  1149 				{
       
  1150 				srcBitmap.SetPos( TPoint( iSrcPos.iX >> KStepPrecision, iSrcPos.iY >> KStepPrecision ) );
       
  1151 				dstBitmap.SetPos( iDstPos );
       
  1152 
       
  1153 				// gather pixel data with step:
       
  1154 				// 00 > 10 
       
  1155 				// /\   
       
  1156 				// 01 < 11
       
  1157 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY11);
       
  1158 				srcBitmap.DecXPos();
       
  1159 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY01);
       
  1160 				srcBitmap.DecYPos();
       
  1161 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY00);
       
  1162 				srcBitmap.IncXPos();
       
  1163 				IntToRgb(srcBitmap.GetPixel(),pixelData.colXY10);
       
  1164 				//return to starting position
       
  1165 				srcBitmap.IncYPos();
       
  1166 
       
  1167 				// interpolate color using gathered pixel-data
       
  1168 				ProcessColorData(pixelData, iSrcPos);
       
  1169 
       
  1170 				// put color in destination package
       
  1171 				color = RgbToInt(pixelData.col);
       
  1172 				dstBitmap.SetPixel(color);
       
  1173 
       
  1174 				// Add inner counters
       
  1175 				iSrcPos += iSrcIncrementInner;
       
  1176 				iDstPos.iX += iDstIncrementInner;
       
  1177 				++iProcessInner;
       
  1178 				--pixelCounter;
       
  1179 				}
       
  1180 
       
  1181 			// Check if inner loop is finished (not just pixel counter)
       
  1182 			if( iProcessInner == iProcessSize.iWidth )
       
  1183 				{
       
  1184 				// Reset inner counters
       
  1185 				iSrcPos.iX -= iSrcIncrementInner.iX * iProcessInner;
       
  1186 				iSrcPos.iY -= iSrcIncrementInner.iY * iProcessInner;
       
  1187 
       
  1188 				iDstPos.iX -= iDstIncrementInner * iProcessInner;
       
  1189 				iProcessInner = 0;
       
  1190 
       
  1191 				// Add outer counters
       
  1192 				iSrcPos += iSrcIncrementOuter;
       
  1193 				iDstPos.iY += iDstIncrementOuter;
       
  1194 				++iProcessOuter;
       
  1195 				}
       
  1196 
       
  1197 			}
       
  1198 		}
       
  1199 
       
  1200 	// Release heap lock
       
  1201 	dstBitmap.End();
       
  1202 	srcBitmap.End();
       
  1203 
       
  1204 	// ETrue if more processing is still needed
       
  1205 	return ( iProcessOuter < iProcessSize.iHeight );
       
  1206 	}
       
  1207 
       
  1208 // -----------------------------------------------------------------------------
       
  1209 // CIHLScaler::SelfComplete
       
  1210 // -----------------------------------------------------------------------------
       
  1211 void CIHLScaler::SelfComplete()
       
  1212 	{
       
  1213 	SetActive();
       
  1214 	iStatus = KRequestPending;
       
  1215 	TRequestStatus* status = &iStatus;
       
  1216 	User::RequestComplete( status, KErrNone );
       
  1217 	}
       
  1218 
       
  1219 // -----------------------------------------------------------------------------
       
  1220 // CIHLScaler::RequestComplete
       
  1221 // -----------------------------------------------------------------------------
       
  1222 void CIHLScaler::RequestComplete( TInt aReason )
       
  1223 	{
       
  1224 	ASSERT( iScalerStatus );
       
  1225 	User::RequestComplete( iScalerStatus, aReason );
       
  1226 	}
       
  1227 
       
  1228 // -----------------------------------------------------------------------------
       
  1229 // CIHLScaler::InitCodePath
       
  1230 // -----------------------------------------------------------------------------
       
  1231 void CIHLScaler::InitCodePath(const TSize& aSrcSize, const TDisplayMode &aSrcMode, const TSize& aDstSize, const TDisplayMode &aDstMode, TBool aOnlyScaling)
       
  1232 	{
       
  1233 	// Choose the correct processing code path	
       
  1234 	ProcessingFunc = &CIHLScaler::ProcessNearestNeighbour;
       
  1235 	    	
       
  1236 	if( iOptions & MIHLImageViewer::EOptionUseBilinearInterpolation )
       
  1237 		{
       
  1238 		// TODO: optimize bilinear scaling
       
  1239 		IHL_DEBUG("CIHLScaler::InitCodePath: slow bilinear");
       
  1240 		ProcessingFunc = &CIHLScaler::ProcessBilinear;
       
  1241 		iScanlinesPerRound = KProcessPixelsPerStep / iProcessSize.iWidth;
       
  1242 		}
       
  1243 	else if(aSrcMode == EColor64K && aSrcMode==aDstMode && !iSrcBitmap->IsCompressedInRAM() && !iDstBitmap->IsCompressedInRAM())
       
  1244 		{
       
  1245 		// 16 bit non-compressed bitmaps
       
  1246 		
       
  1247 		// Calculate how many pixels the scanline is actually wide in the memory
       
  1248 		iSrcPitchInPixels = CFbsBitmap::ScanLineLength( aSrcSize.iWidth, aSrcMode ) >> 1;
       
  1249 		iDstPitchInPixels = CFbsBitmap::ScanLineLength( aDstSize.iWidth, aDstMode ) >> 1;
       
  1250 		
       
  1251 		// How many pixels to move destination pointer at the end of each scanline to get to next pixel
       
  1252 		iDstResidualPixels = iDstIncrementOuter*iDstPitchInPixels - iDstIncrementInner*iProcessSize.iWidth;
       
  1253 
       
  1254 		// Buffer offset to the first destination pixel
       
  1255 		iDstStartOffset = iDstPos.iY * iDstPitchInPixels + iDstPos.iX;
       
  1256 
       
  1257 		if(!aOnlyScaling)
       
  1258 			{
       
  1259 			IHL_DEBUG("CIHLScaler::InitCodePath: fast 64K scale&rotate");
       
  1260 			ProcessingFunc = &CIHLScaler::ProcessNearestNeighbour64K;
       
  1261 			
       
  1262 			// Calculate how often the process should allow AS to run
       
  1263 			iScanlinesPerRound = KBytesPerStepFastPath / (iProcessSize.iWidth<<1);
       
  1264 			}
       
  1265 		else
       
  1266 			{
       
  1267 			IHL_DEBUG("CIHLScaler::InitCodePath: fast 64K scale only");
       
  1268 			ProcessingFunc = &CIHLScaler::ProcessNearestNeighbour64KScaleOnly;
       
  1269 			
       
  1270 			// Calculate how often the process should allow AS to run
       
  1271 			iScanlinesPerRound = KBytesPerStepFastPathScaleOnly / (iProcessSize.iWidth<<1);
       
  1272 			}
       
  1273 		}
       
  1274 		
       
  1275 	else if((aSrcMode == EColor16MU || aSrcMode == EColor16MA) && aSrcMode==aDstMode && !iSrcBitmap->IsCompressedInRAM() && !iDstBitmap->IsCompressedInRAM())
       
  1276 		{
       
  1277 		// 32 bit non-compressed bitmaps
       
  1278 		
       
  1279 		// Calculate how many pixels the scanline is actually wide in the memory
       
  1280 		iSrcPitchInPixels = CFbsBitmap::ScanLineLength( aSrcSize.iWidth, aSrcMode ) >> 2;
       
  1281 		iDstPitchInPixels = CFbsBitmap::ScanLineLength( aDstSize.iWidth, aDstMode ) >> 2;
       
  1282 		
       
  1283 		// How many pixels to move destination pointer at the end of each scanline to get to next pixel
       
  1284 		iDstResidualPixels = iDstIncrementOuter*iDstPitchInPixels - iDstIncrementInner*iProcessSize.iWidth;
       
  1285 
       
  1286 		// Buffer offset to the first destination pixel
       
  1287 		iDstStartOffset = iDstPos.iY * iDstPitchInPixels + iDstPos.iX;
       
  1288 
       
  1289 		if(!aOnlyScaling)
       
  1290 			{
       
  1291 			IHL_DEBUG("CIHLScaler::InitCodePath: fast 16MX scale&rotate");
       
  1292 			ProcessingFunc = &CIHLScaler::ProcessNearestNeighbour16MX;
       
  1293 			
       
  1294 			// Calculate how often the process should allow AS to run
       
  1295 			iScanlinesPerRound = KBytesPerStepFastPath / (iProcessSize.iWidth<<2);
       
  1296 			}
       
  1297 		else
       
  1298 			{
       
  1299 			IHL_DEBUG("CIHLScaler::InitCodePath: fast 16MX scale only");
       
  1300 			ProcessingFunc = &CIHLScaler::ProcessNearestNeighbour16MXScaleOnly;
       
  1301 			
       
  1302 			// Calculate how often the process should allow AS to run
       
  1303 			iScanlinesPerRound = KBytesPerStepFastPathScaleOnly / (iProcessSize.iWidth<<2);
       
  1304 			}
       
  1305 		}
       
  1306 	else
       
  1307 		{
       
  1308 		IHL_DEBUG("CIHLScaler::InitCodePath: slow nearest neighbor");
       
  1309 		iScanlinesPerRound = KProcessPixelsPerStep / iProcessSize.iWidth;
       
  1310 		}
       
  1311 		
       
  1312 	IHL_DEBUG2(KIHLDebug, "CIHLScaler::InitCodePath: scanlines per round = %d", iScanlinesPerRound);
       
  1313 	}
       
  1314 
       
  1315 //  End of File