Matrix.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / CommonUI / System / Drawing / Advanced / Matrix.cs / 1305376 / Matrix.cs

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

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.
                        

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