Matrix.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / CommonUI / System / Drawing / Advanced / Matrix.cs / 1 / Matrix.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/*************************************************************************\ 
* 
* Copyright (c) 1998  Microsoft Corporation
* 
* Module Name:
*
*   Matrix.cs
* 
* Abstract:
* 
*   GDI+ affine transformation matrix 
*
* Revision History: 
*
*   01/11/1999 [....]
*       Code review changes.
* 
*   12/15/1998 [....]
*       Created it. 
* 
\**************************************************************************/
 
namespace System.Drawing.Drawing2D {
    using System.Runtime.InteropServices;

    using System.Diagnostics; 

    using System; 
    using System.Drawing; 
    using Microsoft.Win32;
    using System.ComponentModel; 
    using System.Drawing.Internal;

    /**
     * Represent a Matrix object 
     */
    ///  
    ///  
    ///    Encapsulates a 3 X 3 affine matrix that
    ///    represents a geometric transform. 
    /// 
    public sealed class Matrix : MarshalByRefObject, IDisposable {
        internal IntPtr nativeMatrix;
 
        /*
         * Create a new identity matrix 
         */ 

        ///  
        /// 
        ///    Initializes a new instance of the  class.
        /// 
        public Matrix() { 
            IntPtr matrix = IntPtr.Zero;
 
            int status = SafeNativeMethods.Gdip.GdipCreateMatrix(out matrix); 

            if (status != SafeNativeMethods.Gdip.Ok) 
                throw SafeNativeMethods.Gdip.StatusException(status);

            this.nativeMatrix = matrix;
        } 

        ///  
        ///  
        ///    
        ///       Initialized a new instance of the  class with the specified 
        ///       elements.
        ///    
        /// 
        public Matrix(float m11, 
                      float m12,
                      float m21, 
                      float m22, 
                      float dx,
                      float dy) { 
            IntPtr matrix = IntPtr.Zero;

            int status = SafeNativeMethods.Gdip.GdipCreateMatrix2(m11, m12, m21, m22, dx, dy,
                                                   out matrix); 

            if (status != SafeNativeMethods.Gdip.Ok) 
                throw SafeNativeMethods.Gdip.StatusException(status); 

            this.nativeMatrix = matrix; 
        }

        // float version
        ///  
        /// 
        ///     
        ///       Initializes a new instance of the  class to the geometrical transform 
        ///       defined by the specified rectangle and array of points.
        ///     
        /// 
        public Matrix(RectangleF rect, PointF[] plgpts) {
            if (plgpts == null) {
                throw new ArgumentNullException("plgpts"); 
            }
            if (plgpts.Length != 3) { 
                throw SafeNativeMethods.Gdip.StatusException(SafeNativeMethods.Gdip.InvalidParameter); 
            }
 
            IntPtr buf = SafeNativeMethods.Gdip.ConvertPointToMemory(plgpts);

            try {
                IntPtr matrix = IntPtr.Zero; 

                GPRECTF gprectf = new GPRECTF(rect); 
                int status = SafeNativeMethods.Gdip.GdipCreateMatrix3(ref gprectf, new HandleRef(null, buf), out matrix); 

                if (status != SafeNativeMethods.Gdip.Ok) { 
                    throw SafeNativeMethods.Gdip.StatusException(status);
                }

                this.nativeMatrix = matrix; 
            }
            finally { 
                Marshal.FreeHGlobal(buf); 
            }
        } 

        // int version
        /// 
        ///  
        ///    
        ///       Initializes a new instance of the  class to the geometrical transform 
        ///       defined by the specified rectangle and array of points. 
        ///    
        ///  
        public Matrix(Rectangle rect, Point[] plgpts) {
            if (plgpts == null) {
                throw new ArgumentNullException("plgpts");
            } 
            if (plgpts.Length != 3) {
                throw SafeNativeMethods.Gdip.StatusException(SafeNativeMethods.Gdip.InvalidParameter); 
            } 

            IntPtr buf = SafeNativeMethods.Gdip.ConvertPointToMemory(plgpts); 

            try {
                IntPtr matrix = IntPtr.Zero;
 
                GPRECT gprect = new GPRECT(rect);
                int status = SafeNativeMethods.Gdip.GdipCreateMatrix3I(ref gprect, new HandleRef(null, buf), out matrix); 
 
                if (status != SafeNativeMethods.Gdip.Ok) {
                    throw SafeNativeMethods.Gdip.StatusException(status); 
                }

                this.nativeMatrix = matrix;
            } 
            finally {
                Marshal.FreeHGlobal(buf); 
            } 
        }
 
        /// 
        /// 
        ///    Cleans up resources allocated for this
        /// . 
        /// 
        public void Dispose() { 
            Dispose(true); 
            GC.SuppressFinalize(this);
        } 

        void Dispose(bool disposing) {
            if (nativeMatrix != IntPtr.Zero) {
                SafeNativeMethods.Gdip.GdipDeleteMatrix(new HandleRef(this, nativeMatrix)); 
                nativeMatrix = IntPtr.Zero;
            } 
        } 

        ///  
        /// 
        ///    Cleans up resources allocated for this
        /// .
        ///  
        ~Matrix() {
            Dispose(false); 
        } 

        ///  
        /// 
        ///    Creates an exact copy of this .
        /// 
        public Matrix Clone() { 
            IntPtr cloneMatrix = IntPtr.Zero;
 
            int status = SafeNativeMethods.Gdip.GdipCloneMatrix(new HandleRef(this, nativeMatrix), out cloneMatrix); 

            if (status != SafeNativeMethods.Gdip.Ok) 
                throw SafeNativeMethods.Gdip.StatusException(status);

            return new Matrix(cloneMatrix);
        } 

        ///  
        ///  
        ///    Gets an array of floating-point values that
        ///    represent the elements of this . 
        /// 
        public float[] Elements
        {
            get { 
                float[] m;
 
                IntPtr buf = Marshal.AllocHGlobal(6 * 8); // 6 elements x 8 bytes (float) 

                try { 
                    int status = SafeNativeMethods.Gdip.GdipGetMatrixElements(new HandleRef(this, nativeMatrix), buf);

                    if (status != SafeNativeMethods.Gdip.Ok) {
                        throw SafeNativeMethods.Gdip.StatusException(status); 
                    }
 
                    m = new float[6]; 

                    Marshal.Copy(buf, m, 0, 6); 

                }
                finally {
                    Marshal.FreeHGlobal(buf); 
                }
 
                return m; 
            }
        } 

        /// 
        /// 
        ///    Gets the x translation value (the dx value, 
        ///    or the element in the third row and first column) of this .
        ///  
        public float OffsetX  { 
            get { return Elements[4];}
        } 

        /// 
        /// 
        ///    Gets the y translation value (the dy 
        ///    value, or the element in the third row and second column) of this .
        ///  
        public float OffsetY  { 
            get { return Elements[5];}
        } 

        /// 
        /// 
        ///    Resets this  to identity. 
        /// 
        public void Reset() { 
            int status = SafeNativeMethods.Gdip.GdipSetMatrixElements(new HandleRef(this, nativeMatrix), 
                                                       1.0f, 0.0f, 0.0f,
                                                       1.0f, 0.0f, 0.0f); 

            if (status != SafeNativeMethods.Gdip.Ok)
                throw SafeNativeMethods.Gdip.StatusException(status);
        } 

        ///  
        ///  
        ///    
        ///       Multiplies this  by the specified  by prepending the specified . 
        ///    
        /// 
        public void Multiply(Matrix matrix) {
            Multiply(matrix, MatrixOrder.Prepend); 
        }
 
        ///  
        /// 
        ///     
        ///       Multiplies this  by the specified  in the specified order.
        ///    
        /// 
        public void Multiply(Matrix matrix, MatrixOrder order) { 

            if (matrix == null) { 
                throw new ArgumentNullException("matrix"); 
            }
 
            int status = SafeNativeMethods.Gdip.GdipMultiplyMatrix(new HandleRef(this, nativeMatrix), new HandleRef(matrix, matrix.nativeMatrix),
                                                    order);

            if (status != SafeNativeMethods.Gdip.Ok) 
                throw SafeNativeMethods.Gdip.StatusException(status);
        } 
 
        /// 
        ///  
        ///    
        ///       Applies the specified translation vector to
        ///       the this  by
        ///       prepending the translation vector. 
        ///    
        ///  
        public void Translate(float offsetX, float offsetY) { 
            Translate(offsetX, offsetY, MatrixOrder.Prepend);
        } 

        /// 
        /// 
        ///     
        ///       Applies the specified translation vector to
        ///       the this  in the specified order. 
        ///     
        /// 
        public void Translate(float offsetX, float offsetY, MatrixOrder order) { 
            int status = SafeNativeMethods.Gdip.GdipTranslateMatrix(new HandleRef(this, nativeMatrix),
                                                     offsetX, offsetY, order);

            if (status != SafeNativeMethods.Gdip.Ok) 
                throw SafeNativeMethods.Gdip.StatusException(status);
        } 
 
        /// 
        ///  
        ///    Applies the specified scale vector to this
        ///  by prepending the scale vector.
        /// 
        public void Scale(float scaleX, float scaleY) { 
            Scale(scaleX, scaleY, MatrixOrder.Prepend);
        } 
 
        /// 
        ///  
        ///    
        ///       Applies the specified scale vector to this
        ///     using the specified order.
        ///     
        /// 
        public void Scale(float scaleX, float scaleY, MatrixOrder order) { 
            int status = SafeNativeMethods.Gdip.GdipScaleMatrix(new HandleRef(this, nativeMatrix), scaleX, scaleY, order); 

            if (status != SafeNativeMethods.Gdip.Ok) 
                throw SafeNativeMethods.Gdip.StatusException(status);
        }

        ///  
        /// 
        ///     
        ///       Rotates this  clockwise about the 
        ///       origin by the specified angle.
        ///     
        /// 
        public void Rotate(float angle) {
            Rotate(angle, MatrixOrder.Prepend);
        } 

        ///  
        ///  
        ///    
        ///       Rotates this  clockwise about the 
        ///       origin by the specified
        ///       angle in the specified order.
        ///    
        ///  
        public void Rotate(float angle, MatrixOrder order) {
            int status = SafeNativeMethods.Gdip.GdipRotateMatrix(new HandleRef(this, nativeMatrix), angle, order); 
 
            if (status != SafeNativeMethods.Gdip.Ok)
                throw SafeNativeMethods.Gdip.StatusException(status); 
        }

        /// 
        ///  
        ///    
        ///       Applies a clockwise rotation about the 
        ///       specified point to this  by prepending the rotation. 
        ///    
        ///  
        public void RotateAt(float angle, PointF point) {
            RotateAt(angle, point, MatrixOrder.Prepend);
        }
 
        /// 
        ///  
        ///     
        ///       Applies a clockwise rotation about the specified point
        ///       to this  in the 
        ///       specified order.
        ///    
        /// 
        public void RotateAt(float angle, PointF point, MatrixOrder order) { 
            int status;
 
            // !! TO DO: We cheat with error codes here... 
            if (order == MatrixOrder.Prepend) {
                status = SafeNativeMethods.Gdip.GdipTranslateMatrix(new HandleRef(this, nativeMatrix), point.X, point.Y, order); 
                status |= SafeNativeMethods.Gdip.GdipRotateMatrix(new HandleRef(this, nativeMatrix), angle, order);
                status |= SafeNativeMethods.Gdip.GdipTranslateMatrix(new HandleRef(this, nativeMatrix), -point.X, -point.Y, order);
            }
            else { 
                status = SafeNativeMethods.Gdip.GdipTranslateMatrix(new HandleRef(this, nativeMatrix), -point.X, -point.Y, order);
                status |= SafeNativeMethods.Gdip.GdipRotateMatrix(new HandleRef(this, nativeMatrix), angle, order); 
                status |= SafeNativeMethods.Gdip.GdipTranslateMatrix(new HandleRef(this, nativeMatrix), point.X, point.Y, order); 
            }
 
            if (status != SafeNativeMethods.Gdip.Ok)
                throw SafeNativeMethods.Gdip.StatusException(status);
        }
 
        /// 
        ///  
        ///    Applies the specified shear 
        ///    vector to this  by prepending the shear vector.
        ///  
        public void Shear(float shearX, float shearY) {
            int status = SafeNativeMethods.Gdip.GdipShearMatrix(new HandleRef(this, nativeMatrix), shearX, shearY, MatrixOrder.Prepend);

            if (status != SafeNativeMethods.Gdip.Ok) 
                throw SafeNativeMethods.Gdip.StatusException(status);
        } 
 
        /// 
        ///  
        ///    
        ///       Applies the specified shear
        ///       vector to this  in the specified order.
        ///     
        /// 
        public void Shear(float shearX, float shearY, MatrixOrder order) { 
            int status = SafeNativeMethods.Gdip.GdipShearMatrix(new HandleRef(this, nativeMatrix), shearX, shearY, order); 

            if (status != SafeNativeMethods.Gdip.Ok) 
                throw SafeNativeMethods.Gdip.StatusException(status);
        }

        ///  
        /// 
        ///    Inverts this , if it is 
        ///    invertible. 
        /// 
        public void Invert() { 
            int status = SafeNativeMethods.Gdip.GdipInvertMatrix(new HandleRef(this, nativeMatrix));

            if (status != SafeNativeMethods.Gdip.Ok)
                throw SafeNativeMethods.Gdip.StatusException(status); 
        }
 
        // float version 
        /// 
        ///  
        ///    
        ///       Applies the geometrical transform this represents to an
        ///       array of points.
        ///     
        /// 
        public void TransformPoints(PointF[] pts) { 
            if (pts == null) 
                throw new ArgumentNullException("pts");
            IntPtr buf = SafeNativeMethods.Gdip.ConvertPointToMemory(pts); 

            try {
                int status = SafeNativeMethods.Gdip.GdipTransformMatrixPoints(new HandleRef(this, nativeMatrix),
                    new HandleRef(null, buf), 
                    pts.Length);
 
                if (status != SafeNativeMethods.Gdip.Ok) { 
                    throw SafeNativeMethods.Gdip.StatusException(status);
                } 

                PointF[] newPts = SafeNativeMethods.Gdip.ConvertGPPOINTFArrayF(buf, pts.Length);

                for (int i=0; i
        ///  
        ///     
        ///       Applies the geometrical transform this  represents to an array of points.
        ///     
        /// 
        public void TransformPoints(Point[] pts) {
            if (pts == null)
                throw new ArgumentNullException("pts"); 
            IntPtr buf = SafeNativeMethods.Gdip.ConvertPointToMemory(pts);
 
            try { 
                int status = SafeNativeMethods.Gdip.GdipTransformMatrixPointsI(new HandleRef(this, nativeMatrix),
                    new HandleRef(null, buf), 
                    pts.Length);

                if (status != SafeNativeMethods.Gdip.Ok) {
                    throw SafeNativeMethods.Gdip.StatusException(status); 
                }
 
                // must do an in-place copy because we only have a reference 
                Point[] newPts = SafeNativeMethods.Gdip.ConvertGPPOINTArray(buf, pts.Length);
 
                for (int i=0; i
        /// 
        ///    [To be supplied.]
        ///  
        public void TransformVectors(PointF[] pts) {
            if (pts == null) { 
                throw new ArgumentNullException("pts"); 
            }
 
            IntPtr buf = SafeNativeMethods.Gdip.ConvertPointToMemory(pts);

            try {
                int status = SafeNativeMethods.Gdip.GdipVectorTransformMatrixPoints(new HandleRef(this, nativeMatrix), 
                    new HandleRef(null, buf),
                    pts.Length); 
 
                if (status != SafeNativeMethods.Gdip.Ok) {
                    throw SafeNativeMethods.Gdip.StatusException(status); 
                }

                // must do an in-place copy because we only have a reference
                PointF[] newPts = SafeNativeMethods.Gdip.ConvertGPPOINTFArrayF(buf, pts.Length); 

                for (int i=0; i 
        /// 
        ///    [To be supplied.] 
        /// 
        public void VectorTransformPoints(Point[] pts) {
            TransformVectors(pts);
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        public void TransformVectors(Point[] pts) {
            if (pts == null) {
                throw new ArgumentNullException("pts");
            } 

            IntPtr buf = SafeNativeMethods.Gdip.ConvertPointToMemory(pts); 
 
            try {
                int status = SafeNativeMethods.Gdip.GdipVectorTransformMatrixPointsI(new HandleRef(this, nativeMatrix), 
                    new HandleRef(null, buf),
                    pts.Length);

                if (status != SafeNativeMethods.Gdip.Ok) { 
                    throw SafeNativeMethods.Gdip.StatusException(status);
                } 
 
                // must do an in-place copy because we only have a reference
                Point[] newPts = SafeNativeMethods.Gdip.ConvertGPPOINTArray(buf, pts.Length); 

                for (int i=0; i
        /// 
        ///    Gets a value indicating whether this 
        ///  is invertible.
        ///  
        public bool IsInvertible { 
            get {
                int isInvertible; 

                int status = SafeNativeMethods.Gdip.GdipIsMatrixInvertible(new HandleRef(this, nativeMatrix), out isInvertible);

                if (status != SafeNativeMethods.Gdip.Ok) 
                    throw SafeNativeMethods.Gdip.StatusException(status);
 
                return isInvertible != 0; 
            }
        } 

        /// 
        /// 
        ///    Gets a value indicating whether this  is the identity matrix. 
        /// 
        public bool IsIdentity { 
            get { 
                int isIdentity;
 
                int status = SafeNativeMethods.Gdip.GdipIsMatrixIdentity(new HandleRef(this, nativeMatrix), out isIdentity);

                if (status != SafeNativeMethods.Gdip.Ok)
                    throw SafeNativeMethods.Gdip.StatusException(status); 

                return isIdentity != 0; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Tests whether the specified object is a 
        ///     and is identical to this .
        ///     
        ///  
        public override bool Equals(object obj) {
 
            Matrix matrix2 = obj as Matrix;
            if (matrix2 == null) return false;

            int isEqual; 

            int status = SafeNativeMethods.Gdip.GdipIsMatrixEqual(new HandleRef(this, nativeMatrix), 
                                                   new HandleRef(matrix2, matrix2.nativeMatrix), 
                                                   out isEqual);
 
            if (status != SafeNativeMethods.Gdip.Ok)
                throw SafeNativeMethods.Gdip.StatusException(status);

            return isEqual != 0; 
        }
 
        ///  
        /// 
        ///     
        ///       Returns a hash code.
        ///    
        /// 
        public override int GetHashCode() { 
            return base.GetHashCode();
        } 
 
        internal Matrix(IntPtr nativeMatrix) {
            SetNativeMatrix(nativeMatrix); 
        }

        internal void SetNativeMatrix(IntPtr nativeMatrix) {
            this.nativeMatrix = nativeMatrix; 
        }
 
    } 
}
 
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK