--- /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;
+ }
+
+
+//