svgtopt/gfx2d/src/GfxGeom/GfxAffineTransform.cpp
changeset 46 88edb906c587
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svgtopt/gfx2d/src/GfxGeom/GfxAffineTransform.cpp	Wed Nov 03 18:56:10 2010 +0200
@@ -0,0 +1,733 @@
+/*
+* Copyright (c) 2002 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:  Graphics Extension Library source file
+*
+*/
+
+
+#include "GfxAffineTransform.h"
+
+#include "GfxGeneralPath.h"
+#include "Gfxtrignometric.h"
+
+#include "e32debug.h"
+
+// ==========================================================================
+// Notes:
+//
+//    [ x']   [  m00  m01  m02  ] [ x ]   [ m00x + m01y + m02 ]
+//    [ y'] = [  m10  m11  m12  ] [ y ] = [ m10x + m11y + m12 ]
+//    [ 1 ]   [   0    0    1   ] [ 1 ]   [         1         ]
+//
+// ==========================================================================
+
+// ==========================================================================
+// Constructor
+// ==========================================================================
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform::TGfxAffineTransform()
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform::TGfxAffineTransform()
+   :iM00(KFloatFixOne),
+    iM10(KFloatFixZero),
+    iM01(KFloatFixZero),
+    iM11(KFloatFixOne),
+    iM02(KFloatFixZero),
+    iM12(KFloatFixZero)
+	{
+    iTransType = KTransformIdentity;
+    }
+
+
+// ==========================================================================
+// Constructor with elements
+// ==========================================================================
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform::TGfxAffineTransform( TReal32 aM00,
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform::TGfxAffineTransform( TReal32 aM00,
+                                                   TReal32 aM10,
+                                                   TReal32 aM01,
+                                                   TReal32 aM11,
+                                                   TReal32 aM02,
+                                                   TReal32 aM12 )
+    {
+    SetTransform( aM00, aM10, aM01, aM11, aM02, aM12 );
+    }
+
+// --------------------------------------------------------------------------
+// TGfxAffineTransform::TGfxAffineTransform( TReal32 aM00,
+// ---------------------------------------------------------------------------
+TGfxAffineTransform::TGfxAffineTransform( TReal32 aM00,
+                                          TReal32 aM10,
+                                          TReal32 aM01,
+                                          TReal32 aM11,
+                                          TReal32 aM02,
+                                          TReal32 aM12,
+                                          TGfxTransformType aType )
+										  :iM00(aM00),
+										  iM10(aM10),
+										  iM01(aM01),
+										  iM11(aM11),
+										  iM02(aM02),
+										  iM12(aM12)
+	{
+    iTransType = aType;
+    }
+
+// ==========================================================================
+// Generally used instance creation: Rotation matrix
+// ==========================================================================
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform TGfxAffineTransform::GetRotateInstance( TReal32 aTheta )
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform TGfxAffineTransform::GetRotateInstance( TReal32 aTheta )
+    {
+    TGfxAffineTransform tmp;
+    tmp.SetToRotate( aTheta );
+    return tmp;
+    }
+
+// ==========================================================================
+// Generally used instance creation: another Rotation matrix
+// ==========================================================================
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform TGfxAffineTransform::GetRotateInstance( TReal32 aTheta,
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform TGfxAffineTransform::GetRotateInstance( TReal32 aTheta,
+                                                                     const TFloatFixPt& aX,
+                                                                     const TFloatFixPt& aY )
+    {
+    TGfxAffineTransform tmp;
+    tmp.SetToRotate( aTheta );
+
+    TFloatFixPt x = aX;
+    TFloatFixPt y = aY;
+    TFloatFixPt KOne( KFloatFixOne );
+    tmp.iM02 = x * ( KOne - tmp.iM00 ) + y * tmp.iM10;
+    tmp.iM12 = y * ( KOne - tmp.iM00 ) - x * tmp.iM10;
+    tmp.iTransType |= KTransformTranslate;
+    return tmp;
+    }
+
+// ==========================================================================
+// Added Zoom Instance for better calculation
+// ==========================================================================
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform TGfxAffineTransform::GetZoomInstance( sf,ax,ay);
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform TGfxAffineTransform::GetZoomInstance( TReal32 aScaleFactor,
+                                                                     const TFloatFixPt& aX,
+                                                                     const TFloatFixPt& aY )
+    {
+    TFloatFixPt KOne( KFloatFixOne );
+    TGfxAffineTransform tmp;
+    tmp.iM00 = aScaleFactor;
+    tmp.iM11 = aScaleFactor;
+
+    TMatrixElType x = ( TMatrixElType ) aX;
+    TMatrixElType y = ( TMatrixElType ) aY;
+    tmp.iM02 = x * ( KOne - tmp.iM00 ); 
+    tmp.iM12 = y * ( KOne - tmp.iM11 ); 
+    tmp.iTransType |= KTransformTranslate | KTransformScale;
+    return tmp;
+    }
+
+// --------------------------------------------------------------------------
+// void TGfxAffineTransform::SetToRotate( TReal32 aTheta )
+// ---------------------------------------------------------------------------
+void TGfxAffineTransform::SetToRotate( TReal32 aTheta )
+    {
+    TFloatFixPt KZero;
+	#ifdef SVG_FLOAT_BUILD
+	TFloatFixPt cs = TFloatFixPt::CosFloatDouble( aTheta ); //(GfxMath::svgScalarCos((TInt32)(aTheta * TReal(0x10000))));
+	TFloatFixPt sn = TFloatFixPt::SinFloatDouble( aTheta ); //(GfxMath::svgScalarSin((TInt32)(aTheta * TReal(0x10000))));
+	#else
+	TFloatFixPt cs (GfxMath::svgScalarCos((TInt32)(aTheta * TReal(0x10000))), ETrue);
+	TFloatFixPt sn (GfxMath::svgScalarSin((TInt32)(aTheta * TReal(0x10000))), ETrue);
+	#endif
+    iM00 =  cs;
+    iM10 =  sn;
+    iM01 = KZero - sn;
+    iM11 =  cs;
+
+    iM02 = KZero;
+    iM12 = KZero;
+    iTransType = KTransformShear | KTransformScale;
+    }
+
+// ==========================================================================
+// Generally used instance creation: Scale matrix
+// ==========================================================================
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform TGfxAffineTransform::GetScaleInstance( TReal32 aSx,
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform TGfxAffineTransform::GetScaleInstance( TReal32 aSx,
+                                                                    TReal32 aSy )
+    {
+    return TGfxAffineTransform( ( TReal32 ) aSx,
+                                0.0f,
+                                0.0f,
+                                ( TReal32 ) aSy,
+                                0.0f,
+                                0.0f,
+                                KTransformScale );
+    }
+
+// ==========================================================================
+// Generally used instance creation: Shear matrix
+// ==========================================================================
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform TGfxAffineTransform::GetShearInstance( TReal32 aShx,
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform TGfxAffineTransform::GetShearInstance( TReal32 aShx,
+                                                                    TReal32 aShy )
+    {
+	#ifdef SVG_FLOAT_BUILD
+	TFloatFixPt tnshx = TFloatFixPt::TanFloatDouble( aShx ); //(GfxMath::svgScalarTan(TInt(aShx*0x10000)));
+	TFloatFixPt tnshy = TFloatFixPt::TanFloatDouble( aShy ); //(GfxMath::svgScalarTan(TInt(aShy*0x10000)));
+	#else
+	TFloatFixPt tnshx(GfxMath::svgScalarTan(TInt(aShx*0x10000)), ETrue);
+	TFloatFixPt tnshy(GfxMath::svgScalarTan(TInt(aShy*0x10000)), ETrue);
+	#endif
+
+    return TGfxAffineTransform( 1.0f,
+                                TReal32(tnshy),
+                                TReal32(tnshx),
+                                1.0f,
+                                0.0f,
+                                0.0f,
+                                KTransformShear );
+    }
+
+
+// ==========================================================================
+// Generally used instance creation: Translate matrix
+// ==========================================================================
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform TGfxAffineTransform::GetTranslateInstance( const TFixPt& aTx,
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform TGfxAffineTransform::GetTranslateInstance( const TFloatFixPt& aTx,
+                                                                        const TFloatFixPt& aTy )
+    {
+    return TGfxAffineTransform( 1.0f,
+                                0.0f,
+                                0.0f,
+                                1.0f,
+                                ( TReal32 ) aTx,
+                                ( TReal32 ) aTy,
+                                KTransformTranslate );
+    }
+
+// --------------------------------------------------------------------------
+//  TReal32 TGfxAffineTransform::Determinant() const
+// ---------------------------------------------------------------------------
+ TReal32 TGfxAffineTransform::Determinant() const
+    {
+    return iM00 * iM11 - iM10 * iM01;
+    }
+
+// --------------------------------------------------------------------------
+//  TBool TGfxAffineTransform::IsIdentity() const
+// ---------------------------------------------------------------------------
+ TBool TGfxAffineTransform::IsIdentity() const
+    {
+    return  ( (int)iTransType == KTransformIdentity );
+    }
+
+// --------------------------------------------------------------------------
+//  TReal32 TGfxAffineTransform::ScaleX() const
+// ---------------------------------------------------------------------------
+ TReal32 TGfxAffineTransform::ScaleX() const
+    {
+    return iM00;
+    }
+
+// --------------------------------------------------------------------------
+//  TReal32 TGfxAffineTransform::ScaleY() const
+// ---------------------------------------------------------------------------
+ TReal32 TGfxAffineTransform::ScaleY() const
+    {
+    return iM11;
+    }
+
+// --------------------------------------------------------------------------
+//  TReal32 TGfxAffineTransform::ShearX() const
+// ---------------------------------------------------------------------------
+ TReal32 TGfxAffineTransform::ShearX() const
+    {
+    return iM01;
+    }
+
+// --------------------------------------------------------------------------
+//  TReal32 TGfxAffineTransform::ShearY() const
+// ---------------------------------------------------------------------------
+ TReal32 TGfxAffineTransform::ShearY() const
+    {
+    return iM10;
+    }
+
+// --------------------------------------------------------------------------
+//  TReal32 TGfxAffineTransform::TranslateX() const
+// ---------------------------------------------------------------------------
+ TReal32 TGfxAffineTransform::TranslateX() const
+    {
+    return iM02;
+    }
+
+// --------------------------------------------------------------------------
+//  TReal32 TGfxAffineTransform::TranslateY() const
+// ---------------------------------------------------------------------------
+ TReal32 TGfxAffineTransform::TranslateY() const
+    {
+    return iM12;
+    }
+
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Concatenate( const TGfxAffineTransform& aTransform )
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Concatenate( const TGfxAffineTransform& aTransform )
+    {
+
+    if ( IsIdentity() )
+        {
+        iM00 = aTransform.iM00;
+        iM01 = aTransform.iM01;
+        iM02 = aTransform.iM02;
+        iM11 = aTransform.iM11;
+        iM10 = aTransform.iM10;
+        iM12 = aTransform.iM12;
+        iTransType = aTransform.iTransType;
+        }
+    else if ( aTransform.IsIdentity() )
+        {
+        // Do nothing
+        }
+    else
+        {
+        TFloatFixPt m0, m1;
+        m0 = iM00;
+        m1 = iM01;
+        iM00 = aTransform.iM00 * m0 + aTransform.iM10 * m1;
+        iM01 = aTransform.iM01 * m0 + aTransform.iM11 * m1;
+        iM02 += aTransform.iM02 * m0 + aTransform.iM12 * m1;
+        m0 = iM10;
+        m1 = iM11;
+        iM11 = aTransform.iM01 * m0 + aTransform.iM11 * m1;
+        iM10 = aTransform.iM00 * m0 + aTransform.iM10 * m1;
+        iM12 += aTransform.iM02 * m0 + aTransform.iM12 * m1;
+        iTransType |= aTransform.iTransType;
+        }
+    }
+
+// --------------------------------------------------------------------------
+//  TGfxAffineTransform TGfxAffineTransform::CreateInverse()
+// ---------------------------------------------------------------------------
+ TGfxAffineTransform TGfxAffineTransform::CreateInverse()
+    {
+    TFloatFixPt KZero;
+    TFloatFixPt det = iM00* iM11 - iM01* iM10;
+    if ( det == KZero )
+        return TGfxAffineTransform();
+    else
+		{
+	#ifdef SVG_FLOAT_BUILD	
+		TFloatFixPt idet = TFloatFixPt(1.0f) / det;
+	#else	
+		TFloatFixPt idet = TFloatFixPt(0x10000,ETrue)/ det;
+
+	#endif
+    return TGfxAffineTransform( iM11 * idet,
+                                    KZero - iM10 * idet,
+                                    KZero - iM01 * idet,
+                                    iM00 * idet,
+                                    ( iM01 * iM12 - iM11 * iM02 ) * idet,
+                                    ( iM10 * iM02 - iM00 * iM12 ) * idet );
+		}
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Rotate( TReal32 aTheta )
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Rotate( TReal32 aTheta )
+    {
+    Concatenate( GetRotateInstance( aTheta ) );
+    iTransType |= ( KTransformShear | KTransformScale );
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Rotate( TReal32 aTheta,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Rotate( TReal32 aTheta,
+                                           const TFloatFixPt& aX,
+                                           const TFloatFixPt& aY )
+    {
+    Concatenate( GetRotateInstance( aTheta, aX, aY ) );
+    iTransType |= ( KTransformShear | KTransformScale | KTransformTranslate );
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Scale( TReal32 aSx, TReal32 aSy )
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Scale( TReal32 aSx, TReal32 aSy )
+    {
+    Concatenate( GetScaleInstance( aSx, aSy ) );
+    iTransType |= KTransformScale;
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Translate( const TFixPt& aTx,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Translate( const TFloatFixPt& aTx,
+                                              const TFloatFixPt& aTy )
+    {
+    Concatenate( GetTranslateInstance( aTx, aTy ) );
+    iTransType |= KTransformTranslate;
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Shear( TReal32 aShX, TReal32 aShY )
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Shear( TReal32 aShX, TReal32 aShY )
+    {
+    Concatenate( GetShearInstance( aShX, aShY ) );
+    iTransType |= KTransformShear;
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::SetTransform( TReal32 aM00,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::SetTransform( TReal32 aM00,
+                                                 TReal32 aM10,
+                                                 TReal32 aM01,
+                                                 TReal32 aM11,
+                                                 TReal32 aM02,
+                                                 TReal32 aM12 )
+    {
+    iM00 = aM00;
+    iM01 = aM01;
+    iM02 = aM02;
+    iM10 = aM10;
+    iM11 = aM11;
+    iM12 = aM12;
+    UpdateState();
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Transform( TGfxPoint2D* aSrcPts,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Transform( TGfxPoint2D* aSrcPts,
+                                              TGfxPoint2D* aDstPts,
+                                              TInt32 aNumPts ) const
+    {
+
+    if ( (int)iTransType == KTransformIdentity )
+        {
+        if ( aSrcPts != aDstPts )
+            {
+            for ( TInt32 i = 0; i < aNumPts; i++ )
+                {
+                aDstPts[i] = aSrcPts[i];
+                }
+            }
+        return;
+        }
+
+    if ( (int)iTransType == KTransformScale )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i++ )
+            {
+            aDstPts[i].iX = aSrcPts[i].iX * iM00;
+            aDstPts[i].iY = aSrcPts[i].iY * iM11;
+            }
+        }
+    else if ( (int)iTransType == KTransformTranslate )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i++ )
+            {
+            aDstPts[i].iX = aSrcPts[i].iX + iM02;
+            aDstPts[i].iY = aSrcPts[i].iY + iM12;
+            }
+        }
+    else if ( (int)iTransType == ( KTransformScale | KTransformTranslate ) )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i++ )
+            {
+            aDstPts[i].iX = ( aSrcPts[i].iX * iM00 ) + iM02;
+            aDstPts[i].iY = ( aSrcPts[i].iY * iM11 ) + iM12;
+            }
+        }
+    else
+        {
+        TFloatFixPt x, y;
+
+        for ( TInt32 i = 0; i < aNumPts; i++ )
+            {
+            x = aSrcPts[i].iX;
+            y = aSrcPts[i].iY;
+            aDstPts[i].iX = ( iM00 * x ) + ( iM01 * y ) + iM02;
+            aDstPts[i].iY = ( iM10 * x ) + ( iM11 * y ) + iM12;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Transform( TFixPt* aSrcPts,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Transform( TFloatFixPt* aSrcPts,
+                                              TFloatFixPt* aDstPts,
+                                              TInt32 aNumPts ) const
+    {
+    aNumPts <<= 1;
+
+    if ( (int)iTransType == KTransformIdentity )
+        {
+        if ( aSrcPts != aDstPts )
+            {
+            for ( TInt32 i = 0; i < aNumPts; i++ )
+                {
+                *aDstPts++ = *aSrcPts++;
+                *aDstPts++ = *aSrcPts++;
+                }
+            }
+        return;
+        }
+
+    if ( (int)iTransType == KTransformScale )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i += 2 )
+            {
+            *aDstPts++ = *aSrcPts++ * iM00;
+            *aDstPts++ = *aSrcPts++ * iM11;
+            }
+        }
+    else if ( (int)iTransType == KTransformTranslate )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i += 2 )
+            {
+            *aDstPts++ = *aSrcPts++ + iM02;
+            *aDstPts++ = *aSrcPts++ + iM12;
+            }
+        }
+    else if ( (int)iTransType == ( KTransformScale | KTransformTranslate ) )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i += 2 )
+            {
+            *aDstPts++ = ( *aSrcPts++ * iM00 ) + iM02;
+            *aDstPts++ = ( *aSrcPts++ * iM11 ) + iM12;
+            }
+        }
+    else
+        {
+        TFloatFixPt x, y;
+
+        for ( TInt32 i = 0; i < aNumPts; i += 2 )
+            {
+            x = *aSrcPts++;
+            y = *aSrcPts++;
+            *aDstPts++ = ( iM00 * x ) + ( iM01 * y ) + iM02;
+            *aDstPts++ = ( iM10 * x ) + ( iM11 * y ) + iM12;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::Transform( TFixPt* aSrcDstPts,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Transform( TFloatFixPt* aSrcDstPts,
+                                              TInt32 aNumPts ) const
+    {
+    if ( (int)iTransType == KTransformIdentity )
+        return;
+
+    aNumPts <<= 1;
+
+    if ( (int)iTransType == KTransformScale )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i += 2 )
+            {
+            *aSrcDstPts++ *= iM00;
+            *aSrcDstPts++ *= iM11;
+            }
+        }
+    else if ( (int)iTransType == KTransformTranslate )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i += 2 )
+            {
+            *aSrcDstPts++ += iM02;
+            *aSrcDstPts++ += iM12;
+            }
+        }
+    else if ( (int)iTransType == ( KTransformScale | KTransformTranslate ) )
+        {
+        for ( TInt32 i = 0; i < aNumPts; i += 2 )
+            {
+            *aSrcDstPts *= iM00;
+            *aSrcDstPts++ += iM02;
+            *aSrcDstPts *= iM11;
+            *aSrcDstPts++ += iM12;
+            }
+        }
+    else
+        {
+        TFloatFixPt x, y;
+
+        for ( TInt32 i = 0; i < aNumPts; i += 2 )
+            {
+            x = *aSrcDstPts;
+            y = *( aSrcDstPts + 1 );
+            *aSrcDstPts++ = ( iM00 * x ) + ( iM01 * y ) + iM02;
+            *aSrcDstPts++ = ( iM10 * x ) + ( iM11 * y ) + iM12;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// void TGfxAffineTransform::UpdateState()
+// ---------------------------------------------------------------------------
+void TGfxAffineTransform::UpdateState()
+    {
+    TFloatFixPt KZero;
+    TFloatFixPt KOne( KFloatFixOne );
+    iTransType = KTransformIdentity;
+
+    if ( iM02 != KZero || iM12 != KZero )
+        iTransType |= KTransformTranslate;
+
+    if ( iM00 != KZero || iM11 != KZero )
+        iTransType |= KTransformScale;
+
+    if ( iM01 != KZero || iM10 != KZero )
+        iTransType |= KTransformShear;
+
+    if ( (int)iTransType == KTransformScale && iM00 == KOne && iM11 == KOne )
+         iTransType = KTransformIdentity;
+    }
+
+// --------------------------------------------------------------------------
+// TUint32 TGfxAffineTransform::TransformType()
+// ---------------------------------------------------------------------------
+TUint32 TGfxAffineTransform::TransformType()
+    {
+    return iTransType;
+    }
+
+// --------------------------------------------------------------------------
+// void TGfxAffineTransform::Print()
+// prints out the matrix
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::Print()
+{
+		RDebug::Printf("a=%f b=%f c=%f d=%f e=%f f=%f", (TReal32)iM00, (TReal32)iM10, (TReal32)iM01, (TReal32)iM11, (TReal32)iM02, (TReal32)iM12);
+}
+
+// --------------------------------------------------------------------------
+// Get the scaling factor set in this transform.  This function returns correctly
+// for a uniform scaling in both directions only.
+// ---------------------------------------------------------------------------
+ TFloatFixPt TGfxAffineTransform::ScalingFactor() const
+{
+    TGfxPoint2D ep( 1, 0 ), org( 2, 0 );
+    Transform( &ep, & ep, 1 );
+    Transform( &org, & org, 1 );
+    ep.iX -= org.iX;
+    ep.iY -= org.iY;
+    return TFloatFixPt::Sqrt( ep.iX * ep.iX + ep.iY * ep.iY );
+}
+
+
+
+// --------------------------------------------------------------------------
+//
+//  Appends this transform with the existing transform
+//  Multiply in reverse order
+//  For Ex:  In cases of zoom, rotate and pan of already transformed content.
+// If T is the existing transform and zoom operation has to be applied to it
+// the resultant transform would be Z*T.
+//
+//  void TGfxAffineTransform::AppendTransform( const TGfxAffineTransform& aTransform )
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::AppendTransform( const TGfxAffineTransform& aTransform )
+    {
+
+    if ( IsIdentity() )
+        {
+        iM00 = aTransform.iM00;
+        iM01 = aTransform.iM01;
+        iM02 = aTransform.iM02;
+        iM11 = aTransform.iM11;
+        iM10 = aTransform.iM10;
+        iM12 = aTransform.iM12;
+        iTransType = aTransform.iTransType;
+        }
+    else if ( aTransform.IsIdentity() )
+        {
+        // Do nothing
+        }
+    else
+        {
+        TMatrixElType m00, m01,m02,m10,m11,m12;
+        m00 = iM00;
+        m01 = iM01;
+        m02 = iM02;
+        m10 = iM10;
+        m11 = iM11;
+        m12 = iM12;
+        iM00 = aTransform.iM00 * m00 + aTransform.iM01 * m10;
+        iM01 = aTransform.iM00 * m01 + aTransform.iM01 * m11;
+        iM02 = aTransform.iM00 * m02 + aTransform.iM01 * m12 + aTransform.iM02;
+
+        iM10 = aTransform.iM10 * m00 + aTransform.iM11 * m10;
+        iM11 = aTransform.iM10 * m01 + aTransform.iM11 * m11;
+        iM12 = aTransform.iM10 * m02 + aTransform.iM11 * m12 + aTransform.iM12;
+        
+        iTransType |= aTransform.iTransType;
+        }
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::UserRoatate( TReal32 aTheta,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::UserRotate( TReal32 aTheta,
+                                           const TFloatFixPt& aX,
+                                           const TFloatFixPt& aY )
+    {
+    AppendTransform( GetRotateInstance( aTheta, aX, aY ) );
+    iTransType |= ( KTransformShear | KTransformScale | KTransformTranslate );
+    }
+    
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::UserZoom( TReal32 aScaleFactor,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::UserZoom( TReal32 aScaleFactor,
+                                           const TFloatFixPt& aX,
+                                           const TFloatFixPt& aY )
+    {
+    AppendTransform( GetZoomInstance( aScaleFactor, aX, aY ) );
+    iTransType |= ( KTransformScale | KTransformTranslate );
+    }
+
+// --------------------------------------------------------------------------
+//  void TGfxAffineTransform::UserPan( const TFloatFixPt& aTx,
+// ---------------------------------------------------------------------------
+ void TGfxAffineTransform::UserPan( const TFloatFixPt& aTx,
+                                              const TFloatFixPt& aTy )
+    {
+    AppendTransform( GetTranslateInstance( aTx, aTy ) );
+    iTransType |= KTransformTranslate;
+    }
+    
+
+//