photosgallery/viewframework/views/zoomview/src/glxzoommathsengine.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 15 Jul 2010 18:39:01 +0300
branchRCL_3
changeset 23 b023a8d2866a
parent 21 f9e827349359
permissions -rw-r--r--
Revision: 201025 Kit: 2010127

/*
* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:    Implementation of Zoom Maths engine
*
*/


//includes 
#include "glxzoomeventhandler.h"
#include "glxzoommathsengine.h"
#include "glxzoomcontrol.h"

// Includes for Logs
#include <glxtracer.h>                      //  For Tracer
#include <glxlog.h>                         //  For Log

// LOCAL CONSTANTS AND MACROS
const TInt KGlxLargeImageMaximumZoomRatio   =   100     ;
const TInt KGlxSmallImageMaximumZoomRatio   =   150     ;

const TInt KGlxMinPanFactor                 =   1       ; // The min multiple of pixles to pan 
const TInt KGlxPanInertiaFactor             =   10      ; 
const TInt KGlxPanFactorUpdateMultiple      =   5       ; // The number of pan operations after which panning speed is increased by an order of magnitude 
const TInt KGlxMaxPanUpdateMultiple         =   6       ;
const TInt KGlxOrigin                       =   0       ;

const TInt KGlxMinRelativeZoomPercent       =   85       ;
const TInt KGlxMaxRelativeZoomPercent       =   115      ;

const TInt KGlxZoomPanInc                   =   10      ; // Min number of pixels panned in one keypress. This value is incremented exponentially by multiples of iPanFactor 

// ============================ MEMBER FUNCTIONS ===============================

void TGlxZoomAndPanMathsEngine::Initialize(TPoint& aCenter, 
        TSize& aScreenSize, 
        TSize& aImageSize,
        TUint8 aInitialZoomRatio,
        TUint8 aMinZoomRatio)
    {
    TRACER("void TGlxZoomAndPanMathsEngine::Initialize()");

    iCenter             = aCenter;
    iScreenSize         = aScreenSize;

    // This will only be set at initialization/constructiron. Never afterwards.
    // [TODO] Is there a way to make this constant.
    iActualImageSize    = aImageSize;
    
    iMinZoomRatio   = aMinZoomRatio;
    iZoomRatio      = aInitialZoomRatio;
    iMaxZoomRatio   = ((aInitialZoomRatio >= KGlxLargeImageMaximumZoomRatio) ? 
        KGlxSmallImageMaximumZoomRatio:KGlxLargeImageMaximumZoomRatio);
    GLX_LOG_INFO1("TGlxZoomAndPanMathsEngine::Initialize: Minimum ZoomRatio = [%d]   ", iMinZoomRatio     );
    GLX_LOG_INFO1("TGlxZoomAndPanMathsEngine::Initialize: Maximum ZoomRatio = [%d]   ", iMaxZoomRatio     );

    iPanFactor          = KGlxMinPanFactor;

    iImageVirtualSize.iHeight   = aImageSize.iHeight * aInitialZoomRatio /100;
    iImageVirtualSize.iWidth    = aImageSize.iWidth  * aInitialZoomRatio /100;
    
    iCenter.iX = iImageVirtualSize.iWidth/2 ;
    iCenter.iY = iImageVirtualSize.iHeight/2;
    
    iBorderWidth.iWidth     = (iScreenSize.iWidth  - iImageVirtualSize.iWidth )/2  ; 
    iBorderWidth.iHeight    = (iScreenSize.iHeight - iImageVirtualSize.iHeight)/2 ;
    
    GLX_LOG_INFO2("TGlxZoomAndPanMathsEngine::Initialize: Center at Initialization = [%f,%f]   ", iCenter.iX, iCenter.iY  );
    
    }

TInt TGlxZoomAndPanMathsEngine::NewCenterCoordinate(TInt aCenter, 
                                TInt aOffset, 
                                TUint16 aHalfScreenDimension, 
                                TInt aMinimumCoordinate, 
                                TInt aMaximumCoordinate, 
                                TBool *aThresholdReached)
    {
    TRACER("TGlxZoomAndPanMathsEngine::NewCenterCoordinate");
    if(aOffset)
        {
        //Add the No:of Pixels that has to be panned,the No:of pixels added will be more
        //if the pan key is held for long time,the PanFactor determines that
        aCenter = aCenter + (aOffset*iPanFactor);
        
        // For Checking the boundary condition
        if( (aCenter - aHalfScreenDimension)  < aMinimumCoordinate )
            {
            //This shows the black background on boundaries of the image and reset to the start of the image
            aCenter  = aHalfScreenDimension;
            // Set the variable as true, if the there EXISTS a Variable at that address 
            if (NULL != aThresholdReached)
                {
                *aThresholdReached = ETrue;
                }
            }
        if(aCenter + aHalfScreenDimension > aMaximumCoordinate )
            {
            //This shows the black background on boundaries of the image and reset to the end of the image
            aCenter  = aMaximumCoordinate - aHalfScreenDimension;
            if (NULL != aThresholdReached)
                {
                *aThresholdReached = ETrue;
                }
            }
        }
    return aCenter;
    }

    
void TGlxZoomAndPanMathsEngine::Pan(TPoint aOffset, 
        TPoint& aViewPortTopLeft, 
        TGlxPanIncrementType aPanIncrement,
        TBool * aThresholdReached)
    {
    TRACER("TGlxZoomAndPanMathsEngine::Pan");
    
    GLX_LOG_INFO2("Pan: Center before PAN= [%d,%d]   ", iCenter.iX, iCenter.iY  );
    GLX_LOG_INFO2("Pan: Pan Offset = [%d,%d]   ", aOffset.iX, aOffset.iY);
    
    TPoint panOffset = aOffset; 
    TUint16 halfScreenWidth     = iScreenSize.iWidth>>1;
    TUint16 halfScreenHeight    = iScreenSize.iHeight>>1;
    
    // if we are dragging or something like that the caller might want a uniform increase in panning factor.
    if (EGlxPanIncrementUniform == aPanIncrement)
        {
        iPanFactor = KGlxMinPanFactor ; 
        }
    else if ( EGlxPanIncrementInertic == aPanIncrement)
        {
        if (panOffset.iX > 0 )
            {
            panOffset.iX = panOffset.iX - KGlxPanInertiaFactor ;
            }
        else
            {
            panOffset.iX = panOffset.iX + KGlxPanInertiaFactor ;
            }

        if (panOffset.iY > 0 )
            {
            panOffset.iY = panOffset.iY - KGlxPanInertiaFactor ;
            }
        else
            {
            panOffset.iY = panOffset.iY + KGlxPanInertiaFactor ;
            }
        }

    GLX_LOG_INFO1("Pan: Pan Factor = %d   ", iPanFactor  );
    
    // dont pan on a dimension if image is smaller on that dimension than the screen. 
    if (iImageVirtualSize.iWidth > iScreenSize.iWidth)
        {
        iCenter.iX = NewCenterCoordinate(   iCenter.iX, panOffset.iX, halfScreenWidth,KGlxOrigin, 
                iImageVirtualSize.iWidth,   aThresholdReached)   ;
        }
    
    if (iImageVirtualSize.iHeight > iScreenSize.iHeight)
        {
        TBool thresholdReached = EFalse;
        iCenter.iY = NewCenterCoordinate(   iCenter.iY, panOffset.iY, halfScreenHeight,KGlxOrigin, 
                iImageVirtualSize.iHeight,  &thresholdReached)   ;

        if (NULL != aThresholdReached)
            {
            *aThresholdReached = *aThresholdReached || thresholdReached ; // if we reach the threshold along either axis this means we have reached the threshold
            }
        }
    
    aViewPortTopLeft.iX = iCenter.iX - halfScreenWidth;
    aViewPortTopLeft.iY = iCenter.iY - halfScreenHeight;
    
    iLastPanOffset = panOffset; 
    
    GLX_LOG_INFO2("Pan: Center after PAN= [%d,%d]   ", 
            TInt(iCenter.iX), TInt(iCenter.iY)  );
    GLX_LOG_INFO2("Pan: aViewPortTopLeft after PAN= [%d,%d]   ", 
            TInt(aViewPortTopLeft.iX), TInt(aViewPortTopLeft.iY)  );
    }


TInt TGlxZoomAndPanMathsEngine::Zoom(TZoomMode aZoomMode,
            TInt aExpectedZoomRatio,    // only for slider based zoom. = 0 for key based zoom
            TPoint& aViewPortTopLeft, 
            TSize& aViewPortDimension,
            TBool* aThresholdReached,
            TPoint* apZoomFocus, 
            TInt aRelativeZoomFactor)
    {
    TRACER("TGlxZoomAndPanMathsEngine::Zoom ");
    
    //[TODO] Unlike the above method this method is a very very very very very small method. 
    //[TODO] Consider making this larger. [:|]
    TUint16 halfScreenWidth     = iScreenSize.iWidth>>1;
    TUint16 halfScreenHeight    = iScreenSize.iHeight>>1;
    TPoint  centerTranslationfactor(0,0);
    
    //[TODO] try to make sure that this variable does not get used in calculations. it always should be the center and
    //existing and new screen and virtual image dimensions should be calculated using this one.
    TPoint viewPortTopLeft(TPoint(iCenter).iX - halfScreenWidth, 
            TPoint(iCenter).iY - halfScreenHeight) ;
    GLX_LOG_INFO2(" Zoom(): Center before Zoom= [%d,%d] ", iCenter.iX, iCenter.iY );
    GLX_LOG_INFO2(" Zoom(): viewPortTopLeft  Before Zoom  = [%d,%d] ", TInt(viewPortTopLeft.iX),
            TInt(viewPortTopLeft.iY)  );
    
    TReal oldZoomRatio = iZoomRatio ;  
    TReal newZoomRatio = NewZoomRatio(aExpectedZoomRatio, aRelativeZoomFactor, aZoomMode, aThresholdReached);

    // we have an offcenter focus for our zoom in certain cases ( e.g pinch operation) or a double tap at an offcenter point. 
    // In such a case the zoom happens around that point. So we need to translate (move) the 
    // center in such a way that the relative position of the zoom focus does not change. 
    // centerTranslationfactor is the vector representation of that amount. 
    if ( (NULL != apZoomFocus) )
        {
        centerTranslationfactor.iX = (((apZoomFocus->iX - halfScreenWidth   ) * newZoomRatio)/oldZoomRatio) + (halfScreenWidth  - apZoomFocus->iX);         
        centerTranslationfactor.iY = (((apZoomFocus->iY - halfScreenHeight  ) * newZoomRatio)/oldZoomRatio) + (halfScreenHeight - apZoomFocus->iY);
        }

    GLX_LOG_INFO1(" Zoom: newZoomRatio = %f.   ", newZoomRatio);
    
    TSize imageDimension = TSize(iActualImageSize);
    imageDimension.iWidth =  (imageDimension.iWidth  * newZoomRatio)/100;
    imageDimension.iHeight = (imageDimension.iHeight * newZoomRatio)/100;
    
    // Check if image size is bigger than screen size AND image is panned to such an extent that 
    // the an edge of the image comes within the screen rectange. If so go ahead,   
    // for everything else there is mastercard. I mean the else condition below. 
    // [TODO] The master card however needs more simplification. 
    if(
            ((iImageVirtualSize.iHeight > iScreenSize.iHeight) 
                    && (iImageVirtualSize.iWidth > iScreenSize.iWidth)) 
            &&  ((iCenter.iX != iImageVirtualSize.iWidth/2) 
                    || (iCenter.iY != iImageVirtualSize.iHeight/2))
            )
        {
        //Calculate the new Center posistion accordingly to the new zoom factor
        // [TODO] Suggest the use of overloaded operators so that points can be operated upon by vectors. 
        // specifically in this case to enable a point to be multiplied by a dimension resulting from the ratio of two dimension  
        iCenter.iX = (iCenter.iX * imageDimension.iWidth )/iImageVirtualSize.iWidth  ;
        iCenter.iY = (iCenter.iY * imageDimension.iHeight)/iImageVirtualSize.iHeight ;

        //HEIGHT Calculation
        // TODO: Hive center corrections into an different function.
        // If the image might have become smaller than the screen DUE to or AFTER the above calculations
        if((imageDimension.iHeight < iScreenSize.iHeight ))
            {
            iCenter.iY=(imageDimension.iHeight/2);
            }
        else
            {
            // Is Center positioned such that the top end of the image is inside the 
            // screen. 
            if( iCenter.iY < halfScreenHeight ) 
                {
                iCenter.iY = halfScreenHeight;
                }
            // Is Center positioned such that the Bottom end of the image is inside the 
            // screen. 
            else if((iCenter.iY + halfScreenHeight)> imageDimension.iHeight)
                {
                // if so pan the image so that the edge of the image and screen coincide.
                iCenter.iY = imageDimension.iHeight - halfScreenHeight ;
                }
            }

        //WIDTH Calculation
        if(imageDimension.iWidth < iScreenSize.iWidth )
            {
            iCenter.iX=(imageDimension.iWidth/2);
            }
        else
            {
            if( iCenter.iX < halfScreenWidth) 
                {
                iCenter.iX = halfScreenWidth;
                }
            else if((iCenter.iX + halfScreenWidth)> imageDimension.iWidth)
                {
                iCenter.iX = imageDimension.iWidth - halfScreenWidth;
                }
            }
        //Update the TopLeft corner and then re align to the center in the below code
        viewPortTopLeft.iY = iCenter.iY - halfScreenHeight ;
        viewPortTopLeft.iX = iCenter.iX - halfScreenWidth ;

        iImageVirtualSize = imageDimension;
        }
    else
        {
        //Conditions to Check.
        //1.Image Height is Smaller than screen Size and Width is Bigger than  screen Size.
        //2.Image Height is Bigger than screen Size and Width is Smaller than  screen Size.
        //3.Both Image Height and Width is  Smaller than screen Size 
        //4.Image Height is Bigger than screen Size and it is panned.
        //4.Image Height is Bigger than screen Size and it is not panned at all.
        //5.Image Width is Bigger than screen Size and it is panned.
        //6.Image Width is Bigger than screen Size and it is not panned at all.
        //7. First Time Zoom operation is performed.
        
        if( (imageDimension.iHeight <= iScreenSize.iHeight) ||
                ( (imageDimension.iHeight > iScreenSize.iHeight) && 
                        (iCenter.iY == (iImageVirtualSize.iHeight/2)) ) ||
                ( ((iCenter.iY + halfScreenHeight) > imageDimension.iHeight)&&
                        ((iCenter.iY - halfScreenHeight) < KGlxOrigin) ))
            {
            //The Image is not panned along Y axis, so the center of the image is the center co-ordinate on this axis.
            iCenter.iY=(imageDimension.iHeight/2);    
            }
        else
            {
            //The image is panned and shift the center posistion
            //Calculate the new Center posistion accordingly to the new zoom factor
            iCenter.iY = (iCenter.iY * imageDimension.iHeight)/iImageVirtualSize.iHeight;          
            if( (iCenter.iY + halfScreenHeight) > imageDimension.iHeight)   
                {
                //Stick the Image to bottom side and then re-posistion the center 
                iCenter.iY = imageDimension.iHeight - halfScreenHeight;
                }
            // New DIM is less than Old one. and all above conditions fail. 
            // This means that new DIM is smaller than VP DIM. So keep center 'centered'.
            // DIM = dimension
            else if(iCenter.iY < halfScreenHeight)      
                {
                iCenter.iY=halfScreenHeight;
                }
            }

        if((imageDimension.iWidth <= iScreenSize.iWidth) ||
                ( (imageDimension.iWidth > iScreenSize.iWidth) && (iCenter.iX == 
                (iImageVirtualSize.iWidth/2)) ) || ( (iCenter.iX + halfScreenWidth) > 
                imageDimension.iWidth )&&((iCenter.iX - halfScreenWidth) < KGlxOrigin) )
            {
            //The Image is not panned along X axis, ,so the center of the image is the center co-ordinate.
            iCenter.iX=(imageDimension.iWidth/2);
            }
        else
            {
            //The image is panned and shift the center posistion
            //Calculate the new Center posistion accordingly to the new zoom factor
            iCenter.iX = (iCenter.iX * imageDimension.iWidth )/iImageVirtualSize.iWidth ;
            if( (iCenter.iX + halfScreenWidth) > imageDimension.iWidth )
                {
                //Stick the Image to right side and then re-posistion the center 
                iCenter.iX = imageDimension.iWidth - halfScreenWidth ;
                }
            else if(iCenter.iX < halfScreenWidth)
                {
                //The Image is panned and while zooming out ,the center has to be possistioned to center of the screen.
                iCenter.iX = halfScreenWidth;
                }
            }
        viewPortTopLeft.iX = iCenter.iX - halfScreenWidth;
        viewPortTopLeft.iY = iCenter.iY - halfScreenHeight;
        iImageVirtualSize = imageDimension;
        }

    // if centerTranslationfactor exists that means we have an off center zoom, then 
    // pan that way to get the new center.
    Pan(centerTranslationfactor, viewPortTopLeft, EGlxPanIncrementUniform) ;
        
    aViewPortDimension  = imageDimension    ;
    aViewPortTopLeft    = viewPortTopLeft   ;
    
    GLX_LOG_INFO2("Zoom(): Center After Zoom = [%d,%d]   ", TInt(iCenter.iX), 
            TInt(iCenter.iY)  );
    GLX_LOG_INFO2("Zoom(): aViewPortDimension After Zoom  = [%d,%d]   ", 
            TInt(aViewPortDimension.iWidth), TInt(aViewPortDimension.iHeight)  );
    GLX_LOG_INFO2("Zoom(): viewPortTopLeft  After Zoom  = [%d,%d]   ", 
            TInt(viewPortTopLeft.iX), TInt(viewPortTopLeft.iY)  );

    return newZoomRatio;
    }

//-------------------------------------------------------------------------------------
// UpdatePanFactor: Calculates the Pan Factor based on time the key was pressed
//-------------------------------------------------------------------------------------
//
void TGlxZoomAndPanMathsEngine::UpdatePanFactor()
    {
    TRACER("void TGlxZoomAndPanMathsEngine::UpdatePanFactor()");
    
    iContinuousPanOperations++;
    
    TInt  elapsedPanOperationSetCount = iContinuousPanOperations/KGlxPanFactorUpdateMultiple;
    
    // Double the pan factor for every multiple of KGlxPanFactorUpdateMultiple that the key was pressed till
    // we have crossed 'KGlxMaxTimeMultiple' orders of magnitude  
    if (KGlxMaxPanUpdateMultiple > elapsedPanOperationSetCount )
        {
        iPanFactor = KGlxMinPanFactor << elapsedPanOperationSetCount ;
        }
    GLX_LOG_INFO1("iPanFactor %d", iPanFactor);
    }


//-------------------------------------------------------------------------------------
// NewZoomRatio: Calculates the Zoom Ratio 
//-------------------------------------------------------------------------------------
//
TReal TGlxZoomAndPanMathsEngine::NewZoomRatio( 
        TInt aExpectedZoomRatio,
        TInt aRelativeZoomFactor,
        TZoomMode aZoomMode,
        TBool *aThresholdReached)  
    {
    TRACER("TGlxZoomAndPanMathsEngine::NewZoomRatio ");
    GLX_LOG_INFO1("NewZoomRatio: Old Zoom Ratio = %f       .   ",iZoomRatio   );
    GLX_LOG_INFO1("NewZoomRatio: Expected Zoom Ratio  = %d .   ",aExpectedZoomRatio    );
    GLX_LOG_INFO1("NewZoomRatio: Relative Zoom Factor = %d .   ",aRelativeZoomFactor   );
    
    // We ignore zoommode and aRelativeZoomFactor if we have a aExpectedZoomRatio.
    // We ignore zoommode if we have a aRelativeZoomFactor.
    if (aExpectedZoomRatio > 0)
        {
        iZoomRatio = aExpectedZoomRatio    ;
        }
    else if (aRelativeZoomFactor > 0)
        {
        //Pruning extreme values. Not allowing more than 15% change in zoom ratio.
        TReal normalizedRelativeZoomFactor = aRelativeZoomFactor ;
        if (normalizedRelativeZoomFactor < KGlxMinRelativeZoomPercent)
            {
            normalizedRelativeZoomFactor = KGlxMinRelativeZoomPercent;
            }
        else if (normalizedRelativeZoomFactor > KGlxMaxRelativeZoomPercent)
            {
            normalizedRelativeZoomFactor = KGlxMaxRelativeZoomPercent;
            }
        iZoomRatio =  (iZoomRatio * ((normalizedRelativeZoomFactor - 100.0F)*0.75F + 100.0F))/100.0F ;
        GLX_LOG_INFO1("NewZoomRatio: New Zoom Ratio = %f       .   ",iZoomRatio   );
        }
    else
        {
        if(EZoomIn == aZoomMode)
            {
            iZoomRatio += KGlxZoomPanInc;
            }
        else  
            {
            iZoomRatio -= KGlxZoomPanInc;
            }
        }

    // if iZoomRatio crosses max or minimum limits, then peg them to those limits. 
    if (iZoomRatio >= iMaxZoomRatio) 
        {
        iZoomRatio = iMaxZoomRatio;
        if (NULL != aThresholdReached)
            {
            GLX_LOG_INFO1("NewZoomRatio: Max Threshold Reached iMaxZoomRatio = %d .",iMaxZoomRatio);
            *aThresholdReached = ETrue;
            }
        }
    else if( iZoomRatio <= iMinZoomRatio )
        {
        iZoomRatio = iMinZoomRatio;
        if (NULL != aThresholdReached)
            {
            GLX_LOG_INFO1("NewZoomRatio: Min Threshold Reached iMinZoomRatio = %d .", iMinZoomRatio );
            *aThresholdReached = ETrue;
            }
        }

    GLX_LOG_INFO1("NewZoomRatio: New Zoom Ratio = %f.   ",iZoomRatio  );
    return iZoomRatio;
    }


//-------------------------------------------------------------------------------------
// OrientationChanged:  
//-------------------------------------------------------------------------------------
//
void TGlxZoomAndPanMathsEngine::OrientationChanged(const TRect& aNewScreenRect)
    {
    TRACER("void TGlxZoomAndPanMathsEngine::OrientationChanged()");
    iScreenSize.iWidth          = aNewScreenRect.Width();    
    iScreenSize.iHeight         = aNewScreenRect.Height();
	
    //Choose the minimum of the below.
    TReal32 imageWidthRatio  = ((TReal32)iScreenSize.iWidth  / iActualImageSize.iWidth  )*100.0F;
    TReal32 imageHeightRatio = ((TReal32)iScreenSize.iHeight / iActualImageSize.iHeight )*100.0F;
	iMinZoomRatio = Min(imageWidthRatio, imageHeightRatio);
    GLX_LOG_INFO1("NewZoomRatio: New minimum Zoom Ratio = %d", TInt(iMinZoomRatio));		
    }

//-------------------------------------------------------------------------------------
// ImageVirtualSize: retieves the virtual size of the image.    
//-------------------------------------------------------------------------------------
//
TSize TGlxZoomAndPanMathsEngine::ImageVirtualSize()
    {
    TRACER("TGlxZoomAndPanMathsEngine::ImageVirtualSize()");
    return iImageVirtualSize;
    }


//-------------------------------------------------------------------------------------
// ScreenSize: retrieves the screen size .    
//-------------------------------------------------------------------------------------
//
TSize TGlxZoomAndPanMathsEngine::ScreenSize()
    {
    TRACER("TGlxZoomAndPanMathsEngine::ScreenSize()");
    return iScreenSize;
    }

//-------------------------------------------------------------------------------------
// SetupPanOperation: Starts the Pan operations from the maths Engine's pont of view.    
//-------------------------------------------------------------------------------------
//
void TGlxZoomAndPanMathsEngine::SetupPanOperation()
    {
    TRACER("TGlxZoomAndPanMathsEngine::SetupPanOperation()");
    iContinuousPanOperations = 0 ; 
    }

//-------------------------------------------------------------------------------------
// LastPanOffset: retrieves the last pan Offset.    
//-------------------------------------------------------------------------------------
//
TPoint TGlxZoomAndPanMathsEngine::LastPanOffset()
    {
    TRACER("TGlxZoomAndPanMathsEngine::LastPanOffset()");
    return iLastPanOffset;
    }

//-------------------------------------------------------------------------------------
// MinimumZoomRatio: Retrieves the minimum Zoom threshold.    
//-------------------------------------------------------------------------------------
//
TInt TGlxZoomAndPanMathsEngine::MinimumZoomRatio()
    {
    TRACER("TGlxZoomAndPanMathsEngine::MinimumZoomRatio");
	return iMinZoomRatio;
    }