Browse Source

* Matrix.cs: Rewrote to use GDI+ implementation, doing all the
math in unmanaged code instead of doing it in C#.

* gdipFunctions.cs
(GdipResetWorldTransform, GdipSetWorldTransform):
(GdipGetWorldTransform, GdipScaleWorldTransform): Imported.

* Graphics.cs: Remove unnecessary TODO, and reformatted the code.
(transform): Removed this field. Always use the
matrix associated in the GpGraphics ptr.
(DrawBeziers): Implemented.
(DrawLine): Don't need to manually invoke the transform now.
(MultiplyTransform, ResetTransform):
(ScaleTransform, TranslateTransform): Use GDI+ implementation.
(Transform): Instead of storing a Matrix in managed code, use
equivalent GDI+ functions.

* matrix.c (GdipCreateMatrix3, GdipCreateMatrix3I): Implemented.
(GdipCloneMatrix): Fixed.
(GdipShearMatrix, set_shear): Implemented.

* graphics.c:
(GdipGetWorldTransform, GdipMultiplyWorldTransform): Implemented.
(GdipRotatePenTransform, GdipTranslatePenTransform): Use GDI+
functions instead.

* gdip.h
(GdipRotatePenTransform, GdipTranslatePenTransform): Fix
signature.
(GdipCreateMatrix3, GdipCreateMatrix3I): Use const appropriately.

svn path=/trunk/mcs/; revision=20344

Duncan Mak 22 years ago
parent
commit
9cf400d341

+ 9 - 4
mcs/class/System.Drawing/System.Drawing.Drawing2D/ChangeLog

@@ -1,7 +1,12 @@
-2003-11-04  Miguel de Icaza  <[email protected]>
-
-	* GraphicsPathIterator.cs: Do not make this protected.
-
+2003-11-22  Duncan Mak  <[email protected]>
+
+	* Matrix.cs: Rewrote to use GDI+ implementation, doing all the
+	math in unmanaged code instead of doing it in C#.
+
+2003-11-04  Miguel de Icaza  <[email protected]>
+
+	* GraphicsPathIterator.cs: Do not make this protected.
+
 2003-11-13  Andreas Nahr <[email protected]>
 
 	* QualityMode.cs: Fixed typo

+ 222 - 411
mcs/class/System.Drawing/System.Drawing.Drawing2D/Matrix.cs

@@ -4,6 +4,7 @@
 // Author:
 //   Stefan Maierhofer <[email protected]>
 //   Dennis Hayes ([email protected])
+//   Duncan Mak ([email protected])
 //
 // (C) Ximian, Inc.  http://www.ximian.com
 //
@@ -14,441 +15,251 @@ using System.Runtime.InteropServices;
 
 namespace System.Drawing.Drawing2D
 {
-    public sealed class Matrix : MarshalByRefObject, IDisposable
-    {
-        // initialize to identity
-        private float[] m = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
-        
-        // constructors
-        public Matrix() { }
-        
-        /* TODO: depends on System.Drawing.Drawing2D.Rectangle
-        public Matrix(Rectangle rect , Point[] plgpts)
-        {
-            // TODO
-        }
-        */
-        
-        /* TODO: depends on System.Drawing.Drawing2D.RectangleF
-        public Matrix(RectangleF rect , PointF[] pa)
-        {
-            // TODO
-        }
-        */
-        public Matrix(float m11, float m12, 
-                      float m21, float m22, 
-                      float dx, float dy)
-        {
-            m[0] = m11; m[1] = m12;
-            m[2] = m21; m[3] = m22;
-            m[4] = dx; m[5] = dy;
-        }
-        
-        // properties
-        public float[] Elements
-        {
-            get { return m; }
-        }
-        
-        public bool IsIdentity
-        {
-            get 
-            {
-                if ( (m[0] == 1.0f) && (m[1] == 0.0f) &&
-                     (m[2] == 0.0f) && (m[3] == 1.0f) &&
-                     (m[4] == 0.0f) && (m[5] == 0.0f) )
-                    return true;
-                else 
-                    return false;
-            }
-        }
-        
-        public bool IsInvertible
-        {
-            get 
-            { 
-                // matrix M is invertible if det(M) != 0
-                float det = m[0] * m[3] - m[2] * m[1];
-                if (det != 0.0f) return true;
-                else return false;
-            }
-        }
-        
-        public float OffsetX
+        public  sealed class Matrix : MarshalByRefObject, IDisposable
         {
-            get { return m[4]; }
-        }
-        
-        public float OffsetY
-        {
-            get { return m[5]; }
-        }
-        
-        // methods
-        public Matrix Clone()
-        {
-            return new Matrix(m[0], m[1], m[2], m[3], m[4], m[5]);
-        }
-        
-        public void Dispose() { }
-        
-        public override bool Equals(object obj)
-        {
-            if (obj is Matrix)
-            {
-                float[] a = ((Matrix)obj).Elements;
-                if ( m[0] == a[0] && m[1] == a[1] &&
-                     m[2] == a[2] && m[3] == a[3] &&
-                     m[4] == a[4] && m[5] == a[5] ) 
-                    return true;
-                else 
-                    return false;
-            }
-            else
-            {
-                return false;
-            }
-        }
+                internal IntPtr nativeMatrix;
+                
+                // constructors
+                Matrix (IntPtr ptr)
+                {
+                        nativeMatrix = ptr;
+                }
+                
+                public Matrix ()
+                {
+                        Status s = GDIPlus.GdipCreateMatrix (out nativeMatrix);
+                }
         
-        ~Matrix() {}
+                public Matrix (Rectangle rect , Point[] plgpts)
+                {
+                        GpRect rectangle = new GpRect (rect);
+
+                        GDIPlus.GdipCreateMatrix3I (rectangle, plgpts, out nativeMatrix);
+                }
         
-        [StructLayout(LayoutKind.Explicit)]
-        internal struct BitConverter 
-        {
-            [FieldOffset(0)] public float f;
-            [FieldOffset(0)] public int i;
-        }
+                public Matrix (RectangleF rect , PointF[] pa)
+                {
+                        GpRectF rectangle = new GpRectF (rect);
+
+                        GDIPlus.GdipCreateMatrix3 (rectangle, pa, out nativeMatrix);
+                }
+
+                public Matrix (float m11, float m12, float m21, float m22, float dx, float dy)
+                {
+                        GDIPlus.GdipCreateMatrix2 (m11, m12, m21, m22, dx, dy, out nativeMatrix);
+                }
         
-        public override int GetHashCode()
-        {
-            BitConverter b;
-            // compiler is not smart
-            b.i = 0;
-            int h = 0;
-            for (int i = 0; i < 6; i++) 
-            {
-                b.f = m[i];
-                h ^= b.i >> i;
-            }
-            return h;
-        }
+                // properties
+                public float[] Elements {
+                        get {
+                                IntPtr tmp = Marshal.AllocHGlobal (8 * 6);
+
+                                Status s = GDIPlus.GdipGetMatrixElements (nativeMatrix, tmp);
+
+                                float [] retval = new float [6];
+
+                                Marshal.Copy (tmp, retval, 0, 6);
+
+                                Marshal.FreeHGlobal (tmp);
+                                return retval;
+                        }
+                }
+        
+                public bool IsIdentity {
+                        get {
+                                bool retval;
+                                GDIPlus.GdipIsMatrixIdentity (nativeMatrix, out retval);
+
+                                return retval;
+                        }
+                }
+        
+                public bool IsInvertible {
+                        get {
+                                bool retval;
+                                GDIPlus.GdipIsMatrixInvertible (nativeMatrix, out retval);
+
+                                return retval;
+                        }
+                }
+        
+                public float OffsetX {
+                        get {
+                                return this.Elements [4];
+                        }
+                }
+        
+                public float OffsetY {
+                        get {
+                                return this.Elements [5];
+                        }
+                }
+
+                public Matrix Clone()
+                {
+                        IntPtr retval;
+                        Status s = GDIPlus.GdipCloneMatrix (nativeMatrix, out retval);
+                        return new Matrix (retval);
+                }
+                
         
-        public void Invert()
-        {
-            float det = m[0] * m[3] - m[2] * m[1];
-            if (det != 0.0f)    // if invertible
-            {
-                float[] r = 
+                public void Dispose ()
                 {
-                    m[3] / det, 
-                    -m[1] / det,
-                    -m[2] / det,
-                     m[0] / det,
-                    (-m[3] * m[4] + m[1] * m[5]) / det,
-                    (m[2] * m[4] - m[0] * m[5]) / det
-                };
-                m = r;
-            }
-        }
+                        GDIPlus.GdipDeleteMatrix (nativeMatrix); 
+                }                       
         
-        public void Multiply(Matrix matrix)
-        {
-            Multiply(matrix, MatrixOrder.Prepend);
-        }
+                public override bool Equals (object obj)
+                {
+                        Matrix m = obj as Matrix;
+
+                        if (m != null) {
+                                bool retval;
+                                GDIPlus.GdipIsMatrixEqual (nativeMatrix, m.nativeMatrix, out retval);
+
+                                return retval;
+
+                        } else
+                                return false;
+                }
         
-        public void Multiply(Matrix matrix, MatrixOrder order)
-        {
-            switch (order)
-            {
-                case MatrixOrder.Prepend:
-                    // this = matrix * this
-                    float[] p = matrix.Elements;
-                    float[] r0 = 
-                    {
-                        p[0] * m[0] + p[1] * m[2],
-                        p[0] * m[1] + p[1] * m[3],
-                        p[2] * m[0] + p[3] * m[2],
-                        p[2] * m[1] + p[3] * m[3],
-                        p[4] * m[0] + p[5] * m[2] + m[4],
-                        p[4] * m[1] + p[5] * m[3] + m[5]
-                    };
-                    m = r0;
-                    break;
-                case MatrixOrder.Append:
-                    // this = this * matrix
-                    float[] a = matrix.Elements;
-                    float[] r1 = 
-                    {
-                        m[0] * a[0] + m[1] * a[2],
-                        m[0] * a[1] + m[1] * a[3],
-                        m[2] * a[0] + m[3] * a[2],
-                        m[2] * a[1] + m[3] * a[3],
-                        m[4] * a[0] + m[5] * a[2] + a[4],
-                        m[4] * a[1] + m[5] * a[3] + a[5]
-                    };
-                    m = r1;
-                    break;
-            }
-        }
+                ~Matrix()
+                {
+                        Dispose ();
+                }
+                
+                public override int GetHashCode ()
+                {
+                        return base.GetHashCode ();
+                }
         
-        public void Reset()
-        {
-            m[0] = 1.0f; m[1] = 0.0f;
-            m[2] = 0.0f; m[3] = 1.0f;
-            m[4] = 0.0f; m[5] = 0.0f;
-        }
+                public void Invert ()
+                {
+                        GDIPlus.GdipInvertMatrix (nativeMatrix);
+                }
         
-        public void Rotate(float angle)
-        {
-            Rotate(angle, MatrixOrder.Prepend);
-        }
+                public void Multiply (Matrix matrix)
+                {
+                        Multiply (matrix, MatrixOrder.Prepend);
+                }
         
-        public void Rotate(float angle, MatrixOrder order)
-        {
-            angle *= (float)(Math.PI / 180.0);  // degrees to randians
-            float cos = (float)Math.Cos(angle);
-            float sin = (float)Math.Sin(angle);
-            switch (order)
-            {
-                case MatrixOrder.Prepend:
-                    // this = rotation * this
-                    float[] r0 = 
-                    {
-                         cos * m[0] + sin * m[2],
-                         cos * m[1] + sin * m[3],
-                        -sin * m[0] + cos * m[2],
-                        -sin * m[1] + cos * m[3],
-                        m[4],
-                        m[5]
-                    };
-                    m = r0;
-                    break;
-                case MatrixOrder.Append:
-                    // this = this * rotation
-                    float[] r1 = 
-                    {
-                        m[0] * cos + m[1] * -sin,
-                        m[0] * sin + m[1] *  cos,
-                        m[2] * cos + m[3] * -sin,
-                        m[2] * sin + m[3] *  cos,
-                        m[4] * cos + m[5] * -sin,
-                        m[4] * sin + m[5] *  cos
-                    };
-                    m = r1;
-                    break;
-            }
-        }
+                public void Multiply (Matrix matrix, MatrixOrder order)
+                {
+                        GDIPlus.GdipMultiplyMatrix (nativeMatrix, matrix.nativeMatrix, order);
+                }
         
-        public void RotateAt(float angle, PointF point)
-        {
-            RotateAt(angle, point, MatrixOrder.Prepend);
-        }
+                public void Reset()
+                {
+                        GDIPlus.GdipSetMatrixElements (nativeMatrix, 1, 0, 0, 1, 0, 0);
+                }
+
+                public override string ToString ()
+                {
+                        System.Text.StringBuilder sb = new System.Text.StringBuilder ();
+                        sb.Append ("(");
+                        sb.Append (Elements [0] + " ");
+                        sb.Append (Elements [1] + " ");
+                        sb.Append (Elements [2] + " ");
+                        sb.Append (Elements [3] + " ");
+                        sb.Append (Elements [4] + " ");
+                        sb.Append (Elements [5] + ")");                        
+                        return sb.ToString ();
+                }
+        
+                public void Rotate (float angle)
+                {
+                        Rotate (angle, MatrixOrder.Prepend);
+                }
         
-        public void RotateAt(float angle, PointF point, MatrixOrder order)
-        {
-            angle *= (float)(Math.PI / 180.0);  // degrees to randians
-            float cos = (float)Math.Cos(angle);
-            float sin = (float)Math.Sin(angle);
-            float e4 = -point.X * cos + point.Y * sin + point.X;
-            float e5 = -point.X * sin - point.Y * cos + point.Y;
-            switch (order)
-            {
-                case MatrixOrder.Prepend:
-                    // this = rotation * this
-                    float[] r0 = 
-                    {
-                        cos * m[0] + sin * m[2],
-                        cos * m[1] + sin * m[3],
-                        -sin * m[0] + cos * m[2],
-                        -sin * m[1] + cos * m[3],
-                        e4 * m[0] + e5 * m[2] + m[4],
-                        e4 * m[1] + e5 * m[3] + m[5]
-                    };
-                    m = r0;
-                    break;
-                case MatrixOrder.Append:
-                    // this = this * rotation
-                    float[] r1 = 
-                    {
-                        m[0] * cos + m[1] * -sin,
-                        m[0] * sin + m[1] * cos,
-                        m[2] * cos + m[3] * -sin,
-                        m[2] * sin + m[3] * cos,
-                        m[4] * cos + m[5] * -sin + e4,
-                        m[4] * sin + m[5] * cos + e5
-                    };
-                    m = r1;
-                    break;
-            }
-        }
+                public void Rotate (float angle, MatrixOrder order)
+                {
+                        GDIPlus.GdipRotateMatrix (nativeMatrix, angle, order);
+                }
         
-        public void Scale(float scaleX, float scaleY)
-        {
-            Scale(scaleX, scaleY, MatrixOrder.Prepend);
-        }
+                public void RotateAt (float angle, PointF point)
+                {
+                        RotateAt (angle, point, MatrixOrder.Prepend);
+                }
         
-        public void Scale(float scaleX, float scaleY, MatrixOrder order)
-        {
-            switch (order)
-            {
-                case MatrixOrder.Prepend:
-                    // this = scale * this
-                    m[0] *= scaleX; m[1] *= scaleX;
-                    m[2] *= scaleY; m[3] *= scaleY;
-                    break;
-                case MatrixOrder.Append:
-                    // this = this * scale
-                    m[0] *= scaleX; m[1] *= scaleY;
-                    m[2] *= scaleX; m[3] *= scaleY;
-                    m[4] *= scaleX; m[5] *= scaleY;
-                    break;
-            }
-        }
+                public void RotateAt (float angle, PointF point, MatrixOrder order)
+                {
+                        angle *= (float) (Math.PI / 180.0);  // degrees to radians
+                        float cos = (float) Math.Cos (angle);
+                        float sin = (float) Math.Sin (angle);
+                        float e4 = -point.X * cos + point.Y * sin + point.X;
+                        float e5 = -point.X * sin - point.Y * cos + point.Y;
+                        float[] m = this.Elements;
+
+                        if (order == MatrixOrder.Prepend)
+                                GDIPlus.GdipSetMatrixElements (nativeMatrix,
+                                                cos * m[0] + sin * m[2],
+                                                cos * m[1] + sin * m[3],
+                                                -sin * m[0] + cos * m[2],
+                                                -sin * m[1] + cos * m[3],
+                                                e4 * m[0] + e5 * m[2] + m[4],
+                                                e4 * m[1] + e5 * m[3] + m[5]);
+                        else
+                                GDIPlus.GdipSetMatrixElements (nativeMatrix,
+                                                m[0] * cos + m[1] * -sin,
+                                                m[0] * sin + m[1] * cos,
+                                                m[2] * cos + m[3] * -sin,
+                                                m[2] * sin + m[3] * cos,
+                                                m[4] * cos + m[5] * -sin + e4,
+                                                m[4] * sin + m[5] * cos + e5);
+                }
+        
+                public void Scale (float scaleX, float scaleY)
+                {
+                        Scale (scaleX, scaleY, MatrixOrder.Prepend);
+                }
         
-        public void Shear(float shearX, float shearY)
-        {
-            Shear(shearX, shearY, MatrixOrder.Prepend);
-        }
+                public void Scale (float scaleX, float scaleY, MatrixOrder order)
+                {
+                        GDIPlus.GdipScaleMatrix (nativeMatrix, scaleX, scaleY, order);
+                }
         
-        // LAMESPEC: quote from beta 2 sdk docs: "[To be supplied!]"
-        //
-        // assuming transformation matrix:
-        //
-        //      (1       shearY  0)
-        //      (shearX  1       0)
-        //      (0       0       1)
-        //
-        public void Shear(float shearX, float shearY, MatrixOrder order)
-        {
-            switch (order)
-            {
-                case MatrixOrder.Prepend:
-                    // this = shear * this
-                    float[] r0 = 
-                    {
-                        m[0] + shearY * m[2],
-                        m[1] + shearY * m[3],
-                        shearX * m[0] + m[2],
-                        shearX * m[1] + m[3],
-                        m[4],
-                        m[5]
-                    };
-                    m = r0;
-                    break;
-                case MatrixOrder.Append:
-                    // this = this * shear
-                    float[] r1 = 
-                    {
-                        m[0] + m[1] * shearX,
-                        m[0] * shearY + m[1],
-                        m[2] + m[3] * shearX,
-                        m[2] * shearY + m[3],
-                        m[4] + m[5] * shearX ,
-                        m[4] * shearY + m[5]
-                    };
-                    m = r1;
-                    break;
-            }
-        }
+                public void Shear (float shearX, float shearY)
+                {
+                        Shear (shearX, shearY, MatrixOrder.Prepend);
+                }
         
-        public void TransformPoints(Point[] pts)
-        {
-            for (int i = 0; i < pts.Length; i++)
-            {
-                float x = (float)pts[i].X;
-                float y = (float)pts[i].Y;
-                pts[i].X = (int)(x * m[0] + y * m[2] + m[4]);
-                pts[i].Y = (int)(x * m[1] + y * m[3] + m[5]);
-            }
-        }
+                public void Shear (float shearX, float shearY, MatrixOrder order)
+                {
+                        GDIPlus.GdipShearMatrix (nativeMatrix, shearX, shearY, order);
+                }
         
-        public void TransformPoints(PointF[] pts)
-        {
-            for (int i = 0; i < pts.Length; i++)
-            {
-                float x = pts[i].X;
-                float y = pts[i].Y;
-                pts[i].X = x * m[0] + y * m[2] + m[4];
-                pts[i].Y = x * m[1] + y * m[3] + m[5];
-            }
-        }
+                public void TransformPoints (Point[] pts)
+                {
+                        GDIPlus.GdipTransformMatrixPointsI (nativeMatrix, pts, pts.Length);
+                }
         
-        public void TransformVectors(Point[] pts)
-        {
-            for (int i = 0; i < pts.Length; i++)
-            {
-                float x = (float)pts[i].X;
-                float y = (float)pts[i].Y;
-                pts[i].X = (int)(x * m[0] + y * m[2]);
-                pts[i].Y = (int)(x * m[1] + y * m[3]);
-            }
-        }
+                public void TransformPoints (PointF[] pts)
+                {
+                        GDIPlus.GdipTransformMatrixPoints (nativeMatrix, pts, pts.Length);
+                }
         
-        public void TransformVectors(PointF[] pts)
-        {
-            for (int i = 0; i < pts.Length; i++)
-            {
-                float x = pts[i].X;
-                float y = pts[i].Y;
-                pts[i].X = x * m[0] + y * m[2];
-                pts[i].Y = x * m[1] + y * m[3];
-            }
-        }
+                public void TransformVectors (Point[] pts)
+                {
+                        GDIPlus.GdipVectorTransformMatrixPointsI (nativeMatrix, pts, pts.Length);
+                }
         
-        public void Translate(float offsetX, float offsetY)
-        {
-            Translate(offsetX, offsetY, MatrixOrder.Prepend);
-        }
+                public void TransformVectors (PointF[] pts)
+                {
+                        GDIPlus.GdipVectorTransformMatrixPoints (nativeMatrix, pts, pts.Length);                        
+                }
         
-        public void Translate(float offsetX, float offsetY, MatrixOrder order)
-        {
-            switch (order)
-            {
-                case MatrixOrder.Prepend:
-                    // this = translation * this
-                    m[4] = offsetX * m[0] + offsetY * m[2] + m[4];
-                    m[5] = offsetX * m[1] + offsetY * m[3] + m[5];
-                    break;
-                case MatrixOrder.Append:
-                    // this = this * translation
-                    m[4] += offsetX;
-                    m[5] += offsetY;
-                    break;
-            }
-        }
+                public void Translate (float offsetX, float offsetY)
+                {
+                        Translate (offsetX, offsetY, MatrixOrder.Prepend);
+                }
         
-        // LAMESPEC: quote from beta 2 sdk docs: "[To be supplied!]"
-//	[MonoTODO]    
-	public void VectorTransformPoints(Point[] pts)
-        {
-            // TODO
-        }
+                public void Translate (float offsetX, float offsetY, MatrixOrder order)
+                {
+                        GDIPlus.GdipTranslateMatrix (nativeMatrix, offsetX, offsetY, order);
+                }
         
-        // some simple test (TODO: remove)
-        /*
-        public static void Main()
-        {
-            PointF[] p = {new PointF(1.0f, 2.0f)};
-            Console.WriteLine("(" + p[0].X + " " + p[0].Y + ")");
-            Matrix m = new Matrix();
-            
-            m.Translate(1.0f, 1.0f); 
-            m.Scale(2.0f, 2.0f); 
-            m.Rotate(180.0f);
-            
-            m.TransformPoints(p);
-            Console.WriteLine("(" + p[0].X + " " + p[0].Y + ")");
-            m.Invert();
-            m.TransformPoints(p);
-            Console.WriteLine("(" + p[0].X + " " + p[0].Y + ")");
-            
-            Matrix a = new Matrix(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
-            Matrix b = new Matrix(2.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f);
-            
-            Console.WriteLine("h(a) = " + a.GetHashCode());
-            Console.WriteLine("h(b) = " + b.GetHashCode());
+                public void VectorTransformPoints (Point[] pts)
+                {
+                        TransformVectors (pts);
+                }
         }
-        */
-        
-    }
 }

+ 16 - 0
mcs/class/System.Drawing/System.Drawing/ChangeLog

@@ -1,3 +1,19 @@
+2003-11-22  Duncan Mak  <[email protected]>
+
+	* gdipFunctions.cs
+	(GdipResetWorldTransform, GdipSetWorldTransform):
+	(GdipGetWorldTransform, GdipScaleWorldTransform): Imported.
+
+	* Graphics.cs: Remove unnecessary TODO, and reformatted the code.
+	(transform): Removed this field. Always use the
+	matrix associated in the GpGraphics ptr.
+	(DrawBeziers): Implemented.
+	(DrawLine): Don't need to manually invoke the transform now.
+	(MultiplyTransform, ResetTransform): 
+	(ScaleTransform, TranslateTransform): Use GDI+ implementation.
+	(Transform): Instead of storing a Matrix in managed code, use
+	equivalent GDI+ functions.
+
 2003-11-21  Gonzalo Paniagua Javier <[email protected]>
 
 	* SizeConverter.cs: fixed class signature and implemented some methods.

+ 72 - 89
mcs/class/System.Drawing/System.Drawing/Graphics.cs

@@ -18,9 +18,7 @@ namespace System.Drawing
 	[ComVisible(false)]
 	public sealed class Graphics : MarshalByRefObject, IDisposable
 	{
-		internal IntPtr	nativeObject;
-		
-		internal Matrix transform = new Matrix();
+		internal IntPtr nativeObject;
 		
 		public delegate bool EnumerateMetafileProc (EmfPlusRecordType recordType,
 							    int flags,
@@ -110,16 +108,44 @@ namespace System.Drawing
                         GDIPlus.GdipDrawBezier (nativeObject, pen.nativeObject, x1, y1, x2, y2, x3, y3, x4, y4);
 		}
 
-		[MonoTODO]
+                [MonoTODO]
 		public void DrawBeziers (Pen pen, Point [] points)
 		{
-			throw new NotImplementedException ();
+                        int length = points.Length;
+
+                        if (length < 3)
+                                return;
+
+			for (int i = 0; i < length; i += 3) {
+                                Point p1 = points [i];
+                                Point p2 = points [i + 1];
+                                Point p3 = points [i + 2];
+                                Point p4 = points [i + 3];
+
+                                GDIPlus.GdipDrawBezier (nativeObject, pen.nativeObject,
+                                                        p1.X, p1.Y, p2.X, p2.Y, 
+                                                        p3.X, p3.Y, p4.X, p4.Y);
+                        }
 		}
 
-		[MonoTODO]
+                [MonoTODO]
 		public void DrawBeziers (Pen pen, PointF [] points)
 		{
-			throw new NotImplementedException ();
+			int length = points.Length;
+
+                        if (length < 3)
+                                return;
+
+			for (int i = 0; i < length; i += 3) {
+                                PointF p1 = points [i];
+                                PointF p2 = points [i + 1];
+                                PointF p3 = points [i + 2];
+                                PointF p4 = points [i + 3];
+
+                                GDIPlus.GdipDrawBezier (nativeObject, pen.nativeObject,
+                                                        p1.X, p1.Y, p2.X, p2.Y, 
+                                                        p3.X, p3.Y, p4.X, p4.Y);
+                        }
 		}
 
 		[MonoTODO]
@@ -188,13 +214,11 @@ namespace System.Drawing
 			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
 		public void DrawEllipse (Pen pen, Rectangle rect)
 		{
 			DrawEllipse (pen, rect.X, rect.Y, rect.Width, rect.Height);
 		}
 
-		[MonoTODO]
 		public void DrawEllipse (Pen pen, RectangleF rect)
 		{
 			DrawEllipse (pen, rect.X, rect.Y, rect.Width, rect.Height);
@@ -432,32 +456,20 @@ namespace System.Drawing
 			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
 		public void DrawLine (Pen pen, PointF pt1, PointF pt2)
 		{
-			PointF[] pts = new PointF[2];
-			pts[0] = pt1;
-			pts[1] = pt2;
-			transform.TransformPoints(pts);
-
                         GDIPlus.GdipDrawLine (
                                 nativeObject, pen.nativeObject,
-                                pts [0].X, pts [0].Y,
-                                pts [1].X, pts [1].Y);
+                                pt1.X, pt1.Y,
+                                pt2.X, pt2.Y);
 		}
 
-		[MonoTODO]
 		public void DrawLine (Pen pen, Point pt1, Point pt2)
 		{
-			Point[] pts = new Point[2];
-			pts[0] = pt1;
-			pts[1] = pt2;
-			transform.TransformPoints(pts);
-
                         GDIPlus.GdipDrawLine (
                                 nativeObject, pen.nativeObject,
-                                pts [0].X, pts [0].Y,
-                                pts [1].X, pts [1].Y);
+                                pt1.X, pt1.Y,
+                                pt2.X, pt2.Y);
                 }
 
 		public void DrawLine (Pen pen, int x1, int y1, int x2, int y2)
@@ -515,7 +527,6 @@ namespace System.Drawing
 			GDIPlus.GdipDrawPolygonI (nativeObject, pen.nativeObject, points, points.Length);
 		}
 
-		[MonoTODO]
 		public void DrawPolygon (Pen pen, PointF [] points)
 		{
 			GDIPlus.GdipDrawPolygon (nativeObject, pen.nativeObject, points, points.Length);
@@ -541,20 +552,16 @@ namespace System.Drawing
 			GDIPlus.GdipDrawRectangleI (nativeObject, pen.nativeObject, x, y, width, height);
 		}
 
-		[MonoTODO]
 		public void DrawRectangles (Pen pen, RectangleF [] rects)
 		{
-			foreach( RectangleF rc in rects) {
-				DrawRectangle(pen, rc.Left, rc.Top, rc.Width, rc.Height);
-			}
+			foreach (RectangleF rc in rects)
+				DrawRectangle (pen, rc.Left, rc.Top, rc.Width, rc.Height);
 		}
 
-		[MonoTODO]
 		public void DrawRectangles (Pen pen, Rectangle [] rects)
 		{
-			foreach( RectangleF rc in rects) {
+			foreach (RectangleF rc in rects)
 				DrawRectangle(pen, rc.Left, rc.Top, rc.Width, rc.Height);
-			}
 		}
 
 		[MonoTODO("Ignores the font")]
@@ -947,48 +954,36 @@ namespace System.Drawing
 			GDIPlus.GdipFillPolygon (nativeObject, brush.nativeObject, points, points.Length, fillMode);
 		}
 
-		[MonoTODO]
 		public void FillRectangle (Brush brush, RectangleF rect)
 		{
-		    FillRectangle( brush, rect.Left, rect.Top, rect.Width, rect.Height);
+                        FillRectangle (brush, rect.Left, rect.Top, rect.Width, rect.Height);
 		}
 
-		[MonoTODO]
 		public void FillRectangle (Brush brush, Rectangle rect)
 		{
-		    FillRectangle( brush, rect.Left, rect.Top, rect.Width, rect.Height);
+                        FillRectangle (brush, rect.Left, rect.Top, rect.Width, rect.Height);
 		}
 
-		[MonoTODO]
 		public void FillRectangle (Brush brush, int x, int y, int width, int height)
 		{
 			GDIPlus.GdipFillRectangle (nativeObject, brush.nativeObject, (float)x, (float)y, (float)width, (float)height);
 		}
 
-		[MonoTODO]
 		public void FillRectangle (Brush brush, float x, float y, float width, float height)
 		{
 			GDIPlus.GdipFillRectangle (nativeObject, brush.nativeObject, x, y, width, height);
 		}
 
-		[MonoTODO]
 		public void FillRectangles (Brush brush, Rectangle [] rects)
 		{
-		    if(rects != null) {
-				foreach( Rectangle rc in rects) {
-				    FillRectangle(brush, rc);
-				}
-		    }
+                        foreach (Rectangle rc in rects)
+                                FillRectangle(brush, rc);
 		}
 
-		[MonoTODO]
 		public void FillRectangles (Brush brush, RectangleF [] rects)
 		{
-		    if(rects != null) {
-			foreach( RectangleF rc in rects) {
-			    FillRectangle(brush, rc);
-			}
-		    }
+			foreach (RectangleF rc in rects)
+                                FillRectangle(brush, rc);
 		}
 
 		[MonoTODO]
@@ -1194,7 +1189,7 @@ namespace System.Drawing
 
 		public void MultiplyTransform (Matrix matrix, MatrixOrder order)
 		{
-			// GDIPlus.GdipMultiplyWorldTransform (nativeObject, matrix.nativeMatrix, order);
+			GDIPlus.GdipMultiplyWorldTransform (nativeObject, matrix.nativeMatrix, order);
 		}
 
 		[MonoTODO]
@@ -1215,16 +1210,15 @@ namespace System.Drawing
 			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
 		public void ResetTransform ()
 		{
-			throw new NotImplementedException ();
+			GDIPlus.GdipResetWorldTransform (nativeObject);
 		}
 
 		[MonoTODO]
 		public void Restore (GraphicsState gstate)
 		{
-			transform = gstate.matrix.Clone();
+			Transform = gstate.matrix.Clone();
 			GDIPlus.GdipRestoreGraphics (nativeObject, gstate.nativeState);
 		}
 
@@ -1238,7 +1232,7 @@ namespace System.Drawing
 		public void RotateTransform (float angle, MatrixOrder order)
 		{
 			//transform.Rotate(angle, order);
-			GDIPlus.GdipRotateWorldTransform (nativeObject, angle, order);
+			// GDIPlus.GdipRotateWorldTransform (nativeObject, angle, order);
 		}
 
 		[MonoTODO]
@@ -1246,21 +1240,19 @@ namespace System.Drawing
 		{
 			//return implementation.Save();
 			GraphicsState state = new GraphicsState();
-			state.matrix = transform.Clone();
+			state.matrix = Transform.Clone();
 			GDIPlus.GdipSaveGraphics (nativeObject, out state.nativeState);
 			return state;
 		}
 
-		[MonoTODO]
 		public void ScaleTransform (float sx, float sy)
 		{
-			throw new NotImplementedException ();
+			ScaleTransform (sx, sy, MatrixOrder.Prepend);
 		}
 
-		[MonoTODO]
 		public void ScaleTransform (float sx, float sy, MatrixOrder order)
 		{
-			throw new NotImplementedException ();
+                        GDIPlus.GdipScaleWorldTransform (nativeObject, sx, sy, order);
 		}
 
 		[MonoTODO]
@@ -1341,10 +1333,9 @@ namespace System.Drawing
 			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
 		public void TranslateTransform (float dx, float dy)
 		{
-			TranslateTransform(dx, dy, MatrixOrder.Prepend);
+			TranslateTransform (dx, dy, MatrixOrder.Prepend);
 		}
 
 		[MonoTODO]
@@ -1354,8 +1345,7 @@ namespace System.Drawing
 			GDIPlus.GdipTranslateWorldTransform (nativeObject, dx, dy, order);
 		}
 
-		public Region Clip
-		{
+		public Region Clip {
 			get {
 				throw new NotImplementedException ();
 			}
@@ -1364,15 +1354,13 @@ namespace System.Drawing
 			}
 		}
 
-		public RectangleF ClipBounds
-		{
+		public RectangleF ClipBounds {
 			get {
 				throw new NotImplementedException ();
 			}
 		}
 
-		public CompositingMode CompositingMode
-		{
+		public CompositingMode CompositingMode {
 			get {
 				throw new NotImplementedException ();
 			}
@@ -1381,8 +1369,8 @@ namespace System.Drawing
 			}
 
 		}
-		public CompositingQuality CompositingQuality
-		{
+
+		public CompositingQuality CompositingQuality {
 			get {
 				throw new NotImplementedException ();
 			}
@@ -1391,22 +1379,19 @@ namespace System.Drawing
 			}
 		}
 
-		public float DpiX
-		{
+		public float DpiX {
 			get {
 				throw new NotImplementedException ();
 			}
 		}
 
-		public float DpiY
-		{
+		public float DpiY {
 			get {
 				throw new NotImplementedException ();
 			}
 		}
 
-		public InterpolationMode InterpolationMode
-		{
+		public InterpolationMode InterpolationMode {
 			get {
 				throw new NotImplementedException ();
 			}
@@ -1415,22 +1400,19 @@ namespace System.Drawing
 			}
 		}
 
-		public bool IsClipEmpty
-		{
+		public bool IsClipEmpty {
 			get {
 				throw new NotImplementedException ();
 			}
 		}
 
-		public bool IsVisibleClipEmpty
-		{
+		public bool IsVisibleClipEmpty {
 			get {
 				throw new NotImplementedException ();
 			}
 		}
 
-		public float PageScale
-		{
+		public float PageScale {
 			get {
 				throw new NotImplementedException ();
 			}
@@ -1439,8 +1421,7 @@ namespace System.Drawing
 			}
 		}
 
-		public GraphicsUnit PageUnit
-		{
+		public GraphicsUnit PageUnit {
 			get {
 				throw new NotImplementedException ();
 			}
@@ -1449,8 +1430,7 @@ namespace System.Drawing
 			}
 		}
 
-		public PixelOffsetMode PixelOffsetMode
-		{
+		public PixelOffsetMode PixelOffsetMode {
 			get {
 				throw new NotImplementedException ();
 			}
@@ -1502,10 +1482,13 @@ namespace System.Drawing
 
 		public Matrix Transform {
 			get {
-                                return transform;
+                                Matrix matrix = new Matrix ();
+                                GDIPlus.GdipGetWorldTransform (nativeObject, matrix.nativeMatrix);
+
+                                return matrix;
 			}
 			set {
-				transform = value.Clone();
+                                GDIPlus.GdipSetWorldTransform (nativeObject, value.nativeMatrix);
 			}
 		}
 

+ 8 - 2
mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs

@@ -122,8 +122,14 @@ namespace System.Drawing {
 		static internal extern Status GdipSetRenderingOrigin (IntPtr graphics, int x, int y);
  		[DllImport("gdiplus.dll")]
  		internal static extern Status GdipCloneBitmapAreaI (int x, int y, int width, int height, PixelFormat format, IntPtr original, out int bitmap);
-
-                
+ 		[DllImport("gdiplus.dll")]
+ 		internal static extern Status GdipResetWorldTransform (IntPtr graphics);
+ 		[DllImport("gdiplus.dll")]
+ 		internal static extern Status GdipSetWorldTransform (IntPtr graphics, IntPtr matrix);
+ 		[DllImport("gdiplus.dll")]
+ 		internal static extern Status GdipGetWorldTransform (IntPtr graphics, IntPtr matrix);
+ 		[DllImport("gdiplus.dll")]
+ 		internal static extern Status GdipScaleWorldTransform (IntPtr graphics, float sx, float sy, MatrixOrder order);
 		
 		// Pen functions
 		[DllImport("gdiplus.dll")]

+ 29 - 3
mcs/class/System.Drawing/gdiplus/ChangeLog

@@ -1,8 +1,35 @@
+2003-11-22  Duncan Mak  <[email protected]>
+
+	* matrix.c (GdipCreateMatrix3, GdipCreateMatrix3I): Implemented.
+	(GdipCloneMatrix): Fixed.
+	(GdipShearMatrix, set_shear): Implemented.
+	
+	* graphics.c:
+	(GdipGetWorldTransform, GdipMultiplyWorldTransform): Implemented.
+	(GdipRotatePenTransform, GdipTranslatePenTransform): Use GDI+
+	functions instead.
+
+	* gdip.h
+	(GdipRotatePenTransform, GdipTranslatePenTransform): Fix
+	signature.
+	(GdipCreateMatrix3, GdipCreateMatrix3I): Use const appropriately.
+	
+2003-11-17  Duncan Mak  <[email protected]>
+
+	* matrix.c (matrix_equals): New helper function help test matrix
+	equality.
+	(GdipIsMatrixIdentity, GdipIsMatrixEqual): Use matrix_equals.
+	(GdipGetMatrixElements): Don't malloc here, because the caller
+	should hand us an allocated array.
+
 2003-11-16  Duncan Mak  <[email protected]>
 
+	* matrix.c (GdipCreateMatrix2, GdipCreateMatrix3) 
+	(GdipCreateMatrix3I): Implemented.
+
 	* pen.c (GdipResetPenTransform):
 	(GdipMultiplyPenTransform, GdipTranslatePenTransform):
-	(GdipScalePenTransform, GdipRotatePenTransform): Implemented..
+	(GdipScalePenTransform, GdipRotatePenTransform): Implemented.
 
 	* matrix.c (set_translate, set_scale, set_rotate): Helper
 	functions copied from Cairo. We are doing this because you can
@@ -21,8 +48,7 @@
 	(GdipSetMatrixElements, GdipGetMatrixElements):
 	(GdipIsMatrixInvertible): Implemented.
 
-	* matrix.c (GdipIsMatrixIdentity, GdipIsMatrixEqual): Implemented,
-	but pending commit for cairo_matrix_equals to Cairo.
+	* matrix.c (GdipIsMatrixIdentity, GdipIsMatrixEqual): Implemented.
 
 2003-11-14  Duncan Mak  <[email protected]>	
 

+ 4 - 4
mcs/class/System.Drawing/gdiplus/gdip.h

@@ -279,8 +279,8 @@ GpStatus GdipGetDC (GpGraphics *graphics, int *hDC);
 GpStatus GdipReleaseDC (GpGraphics *graphics, int hDC);
 GpStatus GdipRestoreGraphics (GpGraphics *graphics, unsigned int graphicsState);
 GpStatus GdipSaveGraphics(GpGraphics *graphics, unsigned int * state);
-GpStatus GdipRotateWorldTransform (GpGraphics *graphics, float angle, int order);
-GpStatus GdipTranslateWorldTransform (GpGraphics *graphics, float dx, float dy, int order);
+GpStatus GdipRotateWorldTransform (GpGraphics *graphics, float angle, GpMatrixOrder order);
+GpStatus GdipTranslateWorldTransform (GpGraphics *graphics, float dx, float dy, GpMatrixOrder order);
 GpStatus GdipDrawBezier (GpGraphics *graphics, GpPen *pen, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
 GpStatus GdipDrawBezierI (GpGraphics *graphics, GpPen *pen, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
 GpStatus GdipDrawBeziers (GpGraphics *graphics, GpPen *pen, GpPointF *points, int count);
@@ -329,8 +329,8 @@ GpStatus GdipDrawString (GpGraphics *graphics, const char *string, int len, void
 /* Matrix */
 GpStatus GdipCreateMatrix (GpMatrix **matrix);
 GpStatus GdipCreateMatrix2 (float m11, float m12, float m21, float m22, float dx, float dy, GpMatrix **matrix);
-GpStatus GdipCreateMatrix3 (GpRectF *rect, GpPointF *dstplg, GpMatrix **matrix);
-GpStatus GdipCreateMatrix3I (GpRect *rect, GpPoint *dstplg, GpMatrix **matrix);
+GpStatus GdipCreateMatrix3 (const GpRectF *rect, const GpPointF *dstplg, GpMatrix **matrix);
+GpStatus GdipCreateMatrix3I (const GpRect *rect, const GpPoint *dstplg, GpMatrix **matrix);
 GpStatus GdipCloneMatrix (GpMatrix *matrix, GpMatrix **cloneMatrix);
 GpStatus GdipDeleteMatrix (GpMatrix *matrix);
 GpStatus GdipSetMatrixElements (GpMatrix *matrix, float m11, float m12, float m21, float m22, float dx, float dy);

+ 60 - 16
mcs/class/System.Drawing/gdiplus/graphics.c

@@ -281,25 +281,73 @@ GdipSaveGraphics(GpGraphics *graphics, unsigned int *state)
 	}
 	return Ok;
 }
+GpStatus
+GdipResetWorldTransform (GpGraphics *graphics)
+{
+        GpStatus s = cairo_matrix_set_identity (graphics->copy_of_ctm);
+
+        if (s != Ok)
+                return s;
+        else {
+                cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+                return Ok;
+        }
+}
+
+GpStatus
+GdipSetWorldTransform (GpGraphics *graphics, GpMatrix *matrix)
+{
+        graphics->copy_of_ctm = matrix;
+        cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+        return Ok;
+}
 
 GpStatus 
-GdipRotateWorldTransform (GpGraphics *graphics, float angle, int order)
+GdipGetWorldTransform (GpGraphics *graphics, GpMatrix *matrix)
 {
-	cairo_matrix_t *mtx = cairo_matrix_create ();
-	cairo_matrix_rotate (mtx, angle * DEGTORAD);
-	cairo_matrix_multiply (graphics->copy_of_ctm, mtx, graphics->copy_of_ctm );
-	cairo_matrix_destroy ( mtx);
-	cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
-	return Ok;
+        cairo_current_matrix (graphics->ct, matrix);
+        return Ok;
+}
+
+GpStatus
+GdipMultiplyWorldTransform (GpGraphics *graphics, const GpMatrix *matrix, GpMatrixOrder order)
+{
+        GpMatrix *tmp = matrix;
+        Status s = GdipMultiplyMatrix (graphics->copy_of_ctm, tmp, order);
+        
+        if (s != Ok)
+                return s;
+
+        else {
+                cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+                return Ok;
+        }
 }
 
 GpStatus 
-GdipTranslateWorldTransform (GpGraphics *graphics, float dx, float dy, int order)
+GdipRotateWorldTransform (GpGraphics *graphics, float angle, GpMatrixOrder order)
 {
-	/* FIXME: consider order here */
-	cairo_matrix_translate (graphics->copy_of_ctm, dx, dy);
-	cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
-	return Ok;
+	GpStatus s = GdipRotateMatrix (graphics->copy_of_ctm, angle, order);
+
+        if (s != Ok)
+                return s;
+        else {
+                cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+                return Ok;
+        }
+}
+
+GpStatus 
+GdipTranslateWorldTransform (GpGraphics *graphics, float dx, float dy, GpMatrixOrder order)
+{
+        GpStatus s = GdipTranslateMatrix (graphics->copy_of_ctm, dx, dy, order);
+
+        if (s != Ok) 
+                return s;
+        else {
+                cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+                return Ok;
+        }
 }
 
 /* XXX: TODO */
@@ -633,10 +681,6 @@ GdipSetRenderingOrigin (GpGraphics *graphics, int x, int y)
         return gdip_get_status (cairo_status (graphics->ct));
 }
 
-/*
- * FIXME: cairo_current_point does not reflect changes made from
- * cairo_move_to.
- */
 GpStatus 
 GdipGetRenderingOrigin (GpGraphics *graphics, int *x, int *y)
 {

+ 82 - 33
mcs/class/System.Drawing/gdiplus/matrix.c

@@ -10,11 +10,11 @@
 #include <math.h>
 #include "gdip.h"
 
-GpStatus
+GpStatus 
 GdipCreateMatrix (GpMatrix **matrix)
 {
         *matrix = cairo_matrix_create ();
-
+        cairo_matrix_set_affine (*matrix, 1, 0, 0, 1, 0, 0);
         return Ok;
 }
 
@@ -29,20 +29,44 @@ GdipCreateMatrix2 (float m11, float m12, float m21, float m22, float dx, float d
 }
 
 GpStatus
-GdipCreateMatrix3 (GpRectF *rect, GpPointF *dstplg, GpMatrix **matrix)
+GdipCreateMatrix3 (const GpRectF *rect, const GpPointF *dstplg, GpMatrix **matrix)
 {
-        return NotImplemented;
+        *matrix = cairo_matrix_create ();
+        double m11 = rect->left;
+        double m12 = rect->top;
+        double m21 = (rect->right) - (rect->left); /* width */
+        double m22 = (rect->bottom) - (rect->top); /* height */
+        double dx = dstplg->X;
+        double dy = dstplg->Y;
+
+        Status s = cairo_matrix_set_affine (
+                        *matrix, m11, m12, m21, m22, dx, dy);
+
+        return gdip_get_status (s);
 }
 
 GpStatus
-GdipCreateMatrix3I (GpRect *rect, GpPoint *dstplg, GpMatrix **matrix)
+GdipCreateMatrix3I (const GpRect *rect, const GpPoint *dstplg, GpMatrix **matrix)
 {
-        return NotImplemented;
+        *matrix = cairo_matrix_create ();
+        double m11 = rect->left;
+        double m12 = rect->top;
+        double m21 = (rect->right) - (rect->left); /* width */
+        double m22 = (rect->bottom) - (rect->top); /* height */
+        double dx = dstplg->X;
+        double dy = dstplg->Y;
+        
+        Status s = cairo_matrix_set_affine (
+                        *matrix, m11, m12, m21, m22, dx, dy);
+
+        return gdip_get_status (s);
 }
 
 GpStatus
 GdipCloneMatrix (GpMatrix *matrix, GpMatrix **cloneMatrix)
 {
+        *cloneMatrix = cairo_matrix_create ();
+        
         return gdip_get_status (
                 cairo_matrix_copy (*cloneMatrix, matrix));
 }
@@ -50,7 +74,8 @@ GdipCloneMatrix (GpMatrix *matrix, GpMatrix **cloneMatrix)
 GpStatus
 GdipDeleteMatrix (GpMatrix *matrix)
 {
-        cairo_matrix_destroy (matrix);
+        if (matrix)
+                cairo_matrix_destroy (matrix);
         return Ok;
 }
 
@@ -65,16 +90,15 @@ GpStatus
 GdipGetMatrixElements (GpMatrix *matrix, float *matrixOut)
 {
         double a, b, c, d, tx, ty;
-        matrixOut = malloc (6 * sizeof (float));
-
+        
         cairo_matrix_get_affine (matrix, &a, &b, &c, &d, &tx, &ty);
         
-        matrixOut [0] = (float) a;
-        matrixOut [1] = (float) b;
-        matrixOut [2] = (float) c;
-        matrixOut [3] = (float) d;
-        matrixOut [4] = (float) tx;
-        matrixOut [5] = (float) ty;
+        matrixOut[0] = (float) a;
+        matrixOut[1] = (float) b;
+        matrixOut[2] = (float) c;
+        matrixOut[3] = (float) d;
+        matrixOut[4] = (float) tx;
+        matrixOut[5] = (float) ty;
 
         return Ok;
 }
@@ -82,19 +106,17 @@ GdipGetMatrixElements (GpMatrix *matrix, float *matrixOut)
 GpStatus
 GdipMultiplyMatrix (GpMatrix *matrix, GpMatrix *matrix2, GpMatrixOrder order)
 {
-        GpMatrix *result = NULL;
         cairo_status_t status;
 
         if (order == MatrixOrderPrepend)
-                status = cairo_matrix_multiply (result, matrix, matrix2);
-
-        if (order == MatrixOrderAppend)
-                status = cairo_matrix_multiply (result, matrix2, matrix);
+                status = cairo_matrix_multiply (matrix, matrix, matrix2);
 
+        else if (order == MatrixOrderAppend)
+                status = cairo_matrix_multiply (matrix, matrix2, matrix);
+        
         else
                 return GenericError;
 
-        matrix = result;
         return gdip_get_status (status);
 }
 
@@ -154,10 +176,22 @@ GdipRotateMatrix (GpMatrix *matrix, float angle, GpMatrixOrder order)
         return s;
 }
 
+static GpMatrix *
+set_shear (float shearX, float shearY)
+{
+        GpMatrix *matrix = cairo_matrix_create ();
+        cairo_matrix_set_affine (matrix, 1, shearX, shearY, 1, 0, 0);
+        return matrix;
+}
+
 GpStatus
 GdipShearMatrix (GpMatrix *matrix, float shearX, float shearY, GpMatrixOrder order)
 {
-        return NotImplemented;
+        GpMatrix *tmp = set_shear (shearX, shearY);
+        GpStatus s = GdipMultiplyMatrix (matrix, tmp, order);
+        GdipDeleteMatrix (tmp);
+
+        return s;
 }
 
 GpStatus
@@ -179,6 +213,7 @@ GdipTransformMatrixPoints (GpMatrix *matrix, GpPointF *pts, int count)
                 status = cairo_matrix_transform_point (matrix, &x, &y);
                 if (status != CAIRO_STATUS_SUCCESS)
                         return gdip_get_status (status);
+
                 pts->X = (float) x;
                 pts->Y = (float) y;
         }
@@ -250,30 +285,44 @@ GdipIsMatrixInvertible (GpMatrix *matrix, int *result)
         cairo_status_t status = cairo_matrix_invert (matrix);
 
         if (status == CAIRO_STATUS_INVALID_MATRIX)
-                *result = 1;
+                *result = 0;
 
-        *result = 0;
+        *result = 1;
         return Ok;
 }
 
+static int
+matrix_equals (GpMatrix *x, GpMatrix *y)
+{
+        double ax, bx, cx, dx, ex, fx;
+        double ay, by, cy, dy, ey, fy;
+
+        cairo_matrix_get_affine (x, &ax, &bx, &cx, &dx, &ex, &fx);
+        cairo_matrix_get_affine (y, &ay, &by, &cy, &dy, &ey, &fy);
+
+        if ((ax != ay) || (bx != by) || (cx != cy) ||
+            (dx != dy) || (ex != ey) || (fx != fy))
+                return 0;
+
+        return 1;
+}
+
 GpStatus
 GdipIsMatrixIdentity (GpMatrix *matrix, int *result)
 {
-        cairo_matrix_t *identity = cairo_matrix_create ();
-
-/*         if (cairo_matrix_equals (matrix, identity)) */
-/*                 *result = 1; */
+        GpMatrix *identity = cairo_matrix_create ();
+        cairo_matrix_set_identity (identity);
 
-        *result = 0;
+        Status s = GdipIsMatrixEqual (matrix, identity, result);
+        GdipDeleteMatrix (identity);
 
-        cairo_matrix_destroy (identity);
-        return Ok;
+        return s;
 }
 
 GpStatus
 GdipIsMatrixEqual (GpMatrix *matrix, GpMatrix *matrix2, int *result)
 {
-/*         *result = cairo_matrix_equals (matrix, matrix2); */
-
+        *result = matrix_equals (matrix, matrix2);
         return Ok;
 }
+

+ 1 - 1
mcs/class/System.Drawing/gdiplus/pen.c

@@ -188,7 +188,7 @@ GdipResetPenTransform (GpPen *pen)
 }
 
 GpStatus
-GdipMultiplyPenTransform (GpPen *pen, const GpMatrix *matrix, GpMatrixOrder order)
+GdipMultiplyPenTransform (GpPen *pen, GpMatrix *matrix, GpMatrixOrder order)
 {
         return GdipMultiplyMatrix (pen->matrix, matrix, order);
 }