Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / System.Drawing / System.Drawing / Graphics.cs
index 3034fc6abb1ef3a73eb79d0b8fc23ca94cdf1e60..827bdee0881b82eb3f42d9b18bc5f9052eda5709 100644 (file)
@@ -5,10 +5,10 @@
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com) (stubbed out)
 //      Alexandre Pigolkine(pigolkine@gmx.de)
 //     Jordi Mas i Hernandez (jordi@ximian.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // Copyright (C) 2003 Ximian, Inc. (http://www.ximian.com)
-//
-// Copyright (C) 2004-2005 Novell, Inc. (http://www.novell.com)
+// Copyright (C) 2004-2006 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -49,12 +49,11 @@ namespace System.Drawing
 #endif
        {
                internal IntPtr nativeObject = IntPtr.Zero;
+               internal IMacContext maccontext;
                private bool disposed = false;
                private static float defDpiX = 0;
                private static float defDpiY = 0;
-#if NET_2_0
                private IntPtr deviceContextHdc;
-#endif
 
 #if !NET_2_0
                [ComVisible(false)]
@@ -114,7 +113,7 @@ namespace System.Drawing
                        }
                }
                
-               [MonoTODO]
+               [MonoTODO ("Metafiles, both WMF and EMF formats, aren't supported.")]
                public void AddMetafileComment (byte [] data)
                {
                        throw new NotImplementedException ();
@@ -130,7 +129,7 @@ namespace System.Drawing
                         return new GraphicsContainer(state);
                }
 
-               [MonoTODO ("rectangles and unit aren't supported in libgdiplus")]               
+               [MonoTODO ("The rectangles and unit parameters aren't supported in libgdiplus")]                
                public GraphicsContainer BeginContainer (Rectangle dstrect, Rectangle srcrect, GraphicsUnit unit)
                {
                        uint state;
@@ -141,7 +140,7 @@ namespace System.Drawing
                        return new GraphicsContainer (state);
                }
 
-               [MonoTODO ("rectangles and unit aren't supported in libgdiplus")]               
+               [MonoTODO ("The rectangles and unit parameters aren't supported in libgdiplus")]                
                public GraphicsContainer BeginContainer (RectangleF dstrect, RectangleF srcrect, GraphicsUnit unit)
                {
                        uint state;
@@ -160,113 +159,154 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 #if NET_2_0            
+               [MonoLimitation ("Works on Win32 and on X11 (but not on Cocoa and Quartz)")]
                public void CopyFromScreen (Point upperLeftSource, Point upperLeftDestination, Size blockRegionSize)
                {
                        CopyFromScreen (upperLeftSource.X, upperLeftSource.Y, upperLeftDestination.X, upperLeftDestination.Y,
                                blockRegionSize, CopyPixelOperation.SourceCopy);                                
                }
 
+               [MonoLimitation ("Works on Win32 and (for CopyPixelOperation.SourceCopy only) on X11 but not on Cocoa and Quartz")]
                public void CopyFromScreen (Point upperLeftSource, Point upperLeftDestination, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
                {
                        CopyFromScreen (upperLeftSource.X, upperLeftSource.Y, upperLeftDestination.X, upperLeftDestination.Y,
                                blockRegionSize, copyPixelOperation);
-               }\r
+               }
                
+               [MonoLimitation ("Works on Win32 and on X11 (but not on Cocoa and Quartz)")]
                public void CopyFromScreen (int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize)
                {
                        CopyFromScreen (sourceX, sourceY, destinationX, destinationY, blockRegionSize,
                                CopyPixelOperation.SourceCopy);
                }
 
-               public void CopyFromScreen (int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation)\r
+               [MonoLimitation ("Works on Win32 and (for CopyPixelOperation.SourceCopy only) on X11 but not on Cocoa and Quartz")]
+               public void CopyFromScreen (int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
                {
-                       IntPtr window;                  
-
                        if (!Enum.IsDefined (typeof (CopyPixelOperation), copyPixelOperation))
-                               throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for CopyPixelOperation", copyPixelOperation));
+                               throw new InvalidEnumArgumentException (Locale.GetText ("Enum argument value '{0}' is not valid for CopyPixelOperation", copyPixelOperation));
 
-                       if (GDIPlus.UseCocoaDrawable || GDIPlus.UseQuartzDrawable) {
-                               throw new NotImplementedException ();
+                       if (GDIPlus.UseX11Drawable) {
+                               CopyFromScreenX11 (sourceX, sourceY, destinationX, destinationY, blockRegionSize, copyPixelOperation);
+                       } else if (GDIPlus.UseCarbonDrawable) {
+                               CopyFromScreenMac (sourceX, sourceY, destinationX, destinationY, blockRegionSize, copyPixelOperation);
+                       } else if (GDIPlus.UseCocoaDrawable) {
+                               CopyFromScreenMac (sourceX, sourceY, destinationX, destinationY, blockRegionSize, copyPixelOperation);
+                       } else {
+                               CopyFromScreenWin32 (sourceX, sourceY, destinationX, destinationY, blockRegionSize, copyPixelOperation);
                        }
-                       
-                       if (GDIPlus.UseX11Drawable) { // X11 implementation
-                               IntPtr image, defvisual, vPtr;
-                               int AllPlanes = ~0, nitems = 0, pixel;
+               }
 
-                               if (copyPixelOperation != CopyPixelOperation.SourceCopy)
-                                       throw new NotImplementedException ("Operation not implemented under X11");
+               private void CopyFromScreenWin32 (int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
+               {
+                       IntPtr window = GDIPlus.GetDesktopWindow ();
+                       IntPtr srcDC = GDIPlus.GetDC (window);
+                       IntPtr dstDC = GetHdc ();
+                       GDIPlus.BitBlt (dstDC, destinationX, destinationY, blockRegionSize.Width,
+                               blockRegionSize.Height, srcDC, sourceX, sourceY, (int) copyPixelOperation);
+
+                       GDIPlus.ReleaseDC (IntPtr.Zero, srcDC);
+                       ReleaseHdc (dstDC);                     
+               }
                
-                               if (GDIPlus.Display == IntPtr.Zero) {
-                                       GDIPlus.Display = GDIPlus.XOpenDisplay (IntPtr.Zero);                                   
-                               }
+               private void CopyFromScreenMac (int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
+               {
+                       throw new NotImplementedException ();
+               }
 
-                               window = GDIPlus.XRootWindow (GDIPlus.Display, 0);
-                               defvisual = GDIPlus.XDefaultVisual (GDIPlus.Display, 0);                                
-                               XVisualInfo visual = new XVisualInfo ();
+               private void CopyFromScreenX11 (int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
+               {
+                       IntPtr window, image, defvisual, vPtr;
+                       int AllPlanes = ~0, nitems = 0, pixel;
 
-                               /* Get XVisualInfo for this visual */
-                               visual.visualid = GDIPlus.XVisualIDFromVisual(defvisual);
-                               vPtr = GDIPlus.XGetVisualInfo (GDIPlus.Display, 0x1 /* VisualIDMask */, ref visual, ref nitems);
-                               visual = (XVisualInfo) Marshal.PtrToStructure(vPtr, typeof (XVisualInfo));
+                       if (copyPixelOperation != CopyPixelOperation.SourceCopy)
+                               throw new NotImplementedException ("Operation not implemented under X11");
+               
+                       if (GDIPlus.Display == IntPtr.Zero) {
+                               GDIPlus.Display = GDIPlus.XOpenDisplay (IntPtr.Zero);
+                       }
 
-                               /* Sorry I do not have access to a computer with > deepth. Fell free to add more pixel formats */       
-                               image = GDIPlus.XGetImage (GDIPlus.Display, window, sourceX, sourceY, blockRegionSize.Width,
-                                       blockRegionSize.Height, AllPlanes, 2 /* ZPixmap*/);
+                       window = GDIPlus.XRootWindow (GDIPlus.Display, 0);
+                       defvisual = GDIPlus.XDefaultVisual (GDIPlus.Display, 0);
+                       XVisualInfo visual = new XVisualInfo ();
+
+                       /* Get XVisualInfo for this visual */
+                       visual.visualid = GDIPlus.XVisualIDFromVisual(defvisual);
+                       vPtr = GDIPlus.XGetVisualInfo (GDIPlus.Display, 0x1 /* VisualIDMask */, ref visual, ref nitems);
+                       visual = (XVisualInfo) Marshal.PtrToStructure(vPtr, typeof (XVisualInfo));
+#if false
+                       Console.WriteLine ("visual\t{0}", visual.visual);
+                       Console.WriteLine ("visualid\t{0}", visual.visualid);
+                       Console.WriteLine ("screen\t{0}", visual.screen);
+                       Console.WriteLine ("depth\t{0}", visual.depth);
+                       Console.WriteLine ("klass\t{0}", visual.klass);
+                       Console.WriteLine ("red_mask\t{0:X}", visual.red_mask);
+                       Console.WriteLine ("green_mask\t{0:X}", visual.green_mask);
+                       Console.WriteLine ("blue_mask\t{0:X}", visual.blue_mask);
+                       Console.WriteLine ("colormap_size\t{0}", visual.colormap_size);
+                       Console.WriteLine ("bits_per_rgb\t{0}", visual.bits_per_rgb);
+#endif
+                       image = GDIPlus.XGetImage (GDIPlus.Display, window, sourceX, sourceY, blockRegionSize.Width,
+                               blockRegionSize.Height, AllPlanes, 2 /* ZPixmap*/);
+                       if (image == IntPtr.Zero) {
+                               string s = String.Format ("XGetImage returned NULL when asked to for a {0}x{1} region block", 
+                                       blockRegionSize.Width, blockRegionSize.Height);
+                               throw new InvalidOperationException (s);
+                       }
                                
-                               Bitmap bmp = new Bitmap (blockRegionSize.Width, blockRegionSize.Height);
-                               int red, blue, green;
-                               for (int y = sourceY; y <  sourceY + blockRegionSize.Height; y++) {
-                                       for (int x = sourceX; x <  sourceX + blockRegionSize.Width; x++) {
-                                               pixel = GDIPlus.XGetPixel (image, x, y);                        
-
-                                               switch (visual.depth) {
-                                                       case 16: /* 16bbp pixel transformation */
-                                                               red = (int) ((pixel & visual.red_mask ) >> 8) & 0xff;
-                                                               green = (int) (((pixel & visual.green_mask ) >> 3 )) & 0xff;
-                                                               blue = (int) ((pixel & visual.blue_mask ) << 3 ) & 0xff;
-                                                               break;
-                                                       case 24:
-                                                       case 32:
-                                                               red = (int) ((pixel & visual.red_mask ) >> 16) & 0xff;
-                                                               green = (int) (((pixel & visual.green_mask ) >> 8 )) & 0xff;
-                                                               blue = (int) ((pixel & visual.blue_mask )) & 0xff;
-                                                               break;
-                                                       default:
-                                                               throw new NotImplementedException ("Deepth not supported right now");
-                                               }
-                                               
-                                               bmp.SetPixel (x, y, Color.FromArgb (255, red, green, blue));                                                     
+                       Bitmap bmp = new Bitmap (blockRegionSize.Width, blockRegionSize.Height);
+                       int red, blue, green;
+                       int red_mask = (int) visual.red_mask;
+                       int blue_mask = (int) visual.blue_mask;
+                       int green_mask = (int) visual.green_mask;
+                       for (int y = 0; y < blockRegionSize.Height; y++) {
+                               for (int x = 0; x < blockRegionSize.Width; x++) {
+                                       pixel = GDIPlus.XGetPixel (image, x, y);
+
+                                       switch (visual.depth) {
+                                               case 16: /* 16bbp pixel transformation */
+                                                       red = (int) ((pixel & red_mask ) >> 8) & 0xff;
+                                                       green = (int) (((pixel & green_mask ) >> 3 )) & 0xff;
+                                                       blue = (int) ((pixel & blue_mask ) << 3 ) & 0xff;
+                                                       break;
+                                               case 24:
+                                               case 32:
+                                                       red = (int) ((pixel & red_mask ) >> 16) & 0xff;
+                                                       green = (int) (((pixel & green_mask ) >> 8 )) & 0xff;
+                                                       blue = (int) ((pixel & blue_mask )) & 0xff;
+                                                       break;
+                                               default:
+                                                       string text = Locale.GetText ("{0}bbp depth not supported.", visual.depth);
+                                                       throw new NotImplementedException (text);
                                        }
+                                               
+                                       bmp.SetPixel (x, y, Color.FromArgb (255, red, green, blue));                                                     
                                }
+                       }
 
-                               DrawImage (bmp, 0, 0);
-                               bmp.Dispose ();
-                               GDIPlus.XDestroyImage (image);
-                               GDIPlus.XFree (vPtr);
-                               return;
-                       }                       
-
-                       // Win32 implementation
-                       window = GDIPlus.GetDesktopWindow ();
-                       IntPtr srcDC = GDIPlus.GetDC (window);
-                       IntPtr dstDC = GetHdc ();
-                       GDIPlus.BitBlt (dstDC, destinationX, destinationY, blockRegionSize.Width,
-                               blockRegionSize.Height, srcDC, sourceX, sourceY, (int) copyPixelOperation);
-
-                       GDIPlus.ReleaseDC (srcDC);
-                       ReleaseHdc (dstDC);                     
-               }\r
+                       DrawImage (bmp, destinationX, destinationY);
+                       bmp.Dispose ();
+                       GDIPlus.XDestroyImage (image);
+                       GDIPlus.XFree (vPtr);
+               }
 #endif
 
                public void Dispose ()
                {
                        Status status;
                        if (! disposed) {
+                               if (GDIPlus.UseCarbonDrawable || GDIPlus.UseCocoaDrawable) {
+                                       Flush ();
+                                       if (maccontext != null)
+                                               maccontext.Release ();
+                               }
+
                                status = GDIPlus.GdipDeleteGraphics (nativeObject);
                                nativeObject = IntPtr.Zero;
                                GDIPlus.CheckStatus (status);
                                disposed = true;                                
                        }
+
                        GC.SuppressFinalize(this);
                }
 
@@ -418,6 +458,8 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
                        
+               // according to MSDN fillmode "is required but ignored" which makes _some_ sense since the unmanaged 
+               // GDI+ call doesn't support it (issue spotted using Gendarme's AvoidUnusedParametersRule)
                public void DrawClosedCurve (Pen pen, Point [] points, float tension, FillMode fillmode)
                {
                        if (pen == null)
@@ -429,7 +471,9 @@ namespace System.Drawing
                        status = GDIPlus.GdipDrawClosedCurve2I (nativeObject, pen.nativeObject, points, points.Length, tension);
                        GDIPlus.CheckStatus (status);
                }
-               
+
+               // according to MSDN fillmode "is required but ignored" which makes _some_ sense since the unmanaged 
+               // GDI+ call doesn't support it (issue spotted using Gendarme's AvoidUnusedParametersRule)
                public void DrawClosedCurve (Pen pen, PointF [] points, float tension, FillMode fillmode)
                {
                        if (pen == null)
@@ -566,23 +610,26 @@ namespace System.Drawing
 
                public void DrawIcon (Icon icon, Rectangle targetRect)
                {
-                       using (Image img = icon.ToBitmap ()) {
-                               DrawImage (img, targetRect);
-                       }
+                       if (icon == null)
+                               throw new ArgumentNullException ("icon");
+
+                       DrawImage (icon.GetInternalBitmap (), targetRect);
                }
 
                public void DrawIcon (Icon icon, int x, int y)
                {
-                       using (Image img = icon.ToBitmap ()) {
-                               DrawImage (img, x, y);
-                       }
+                       if (icon == null)
+                               throw new ArgumentNullException ("icon");
+
+                       DrawImage (icon.GetInternalBitmap (), x, y);
                }
 
                public void DrawIconUnstretched (Icon icon, Rectangle targetRect)
                {
-                       using (Image img = icon.ToBitmap ()) {
-                               DrawImageUnscaled (img, targetRect);
-                       }
+                       if (icon == null)
+                               throw new ArgumentNullException ("icon");
+
+                       DrawImageUnscaled (icon.GetInternalBitmap (), targetRect);
                }
                
                public void DrawImage (Image image, RectangleF rect)
@@ -594,7 +641,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, PointF point)
                {
                        if (image == null)
@@ -604,7 +650,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point [] destPoints)
                {
                        if (image == null)
@@ -616,7 +661,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point point)
                {
                        if (image == null)
@@ -624,7 +668,6 @@ namespace System.Drawing
                        DrawImage (image, point.X, point.Y);
                }
 
-               
                public void DrawImage (Image image, Rectangle rect)
                {
                        if (image == null)
@@ -632,7 +675,6 @@ namespace System.Drawing
                        DrawImage (image, rect.X, rect.Y, rect.Width, rect.Height);
                }
 
-               
                public void DrawImage (Image image, PointF [] destPoints)
                {
                        if (image == null)
@@ -643,7 +685,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, int x, int y)
                {
                        if (image == null)
@@ -652,7 +693,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, float x, float y)
                {
                        if (image == null)
@@ -661,7 +701,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit)
                {
                        if (image == null)
@@ -684,7 +723,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit)
                {
                        if (image == null)
@@ -699,7 +737,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit)
                {
                        if (image == null)
@@ -714,7 +751,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, 
                                 ImageAttributes imageAttr)
                {
@@ -738,7 +774,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, 
                                 ImageAttributes imageAttr)
                {
@@ -753,7 +788,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, int x, int y, Rectangle srcRect, GraphicsUnit srcUnit)
                {                       
                        if (image == null)
@@ -778,7 +812,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
                {
                        if (image == null)
@@ -792,7 +825,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
                {
                        if (image == null)
@@ -807,7 +839,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, int callbackData)
                {
                        if (image == null)
@@ -822,7 +853,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit)
                {
                        if (image == null)
@@ -843,7 +873,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit)
                {
                        if (image == null)
@@ -855,7 +884,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs)
                {
                        if (image == null)
@@ -890,53 +918,47 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
                
-               public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
+               public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs, DrawImageAbort callback)
                {
                        if (image == null)
                                throw new ArgumentNullException ("image");
                        Status status = GDIPlus.GdipDrawImageRectRect (nativeObject, image.NativeObject, 
                                         destRect.X, destRect.Y, destRect.Width, 
                                        destRect.Height, srcX, srcY, srcWidth, srcHeight,
-                                       srcUnit, imageAttr != null ? imageAttr.NativeObject : IntPtr.Zero, 
+                                       srcUnit, imageAttrs != null ? imageAttrs.NativeObject : IntPtr.Zero, 
                                        callback, IntPtr.Zero);
                        GDIPlus.CheckStatus (status);
                }
 
-               
-               public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, IntPtr callbackData)
+               public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs, DrawImageAbort callback, IntPtr callbackData)
                {
                        if (image == null)
                                throw new ArgumentNullException ("image");
                        Status status = GDIPlus.GdipDrawImageRectRect (nativeObject, image.NativeObject, 
                                destRect.X, destRect.Y, destRect.Width, destRect.Height,
                                srcX, srcY, srcWidth, srcHeight, srcUnit, 
-                               imageAttr != null ? imageAttr.NativeObject : IntPtr.Zero, callback, callbackData);
+                               imageAttrs != null ? imageAttrs.NativeObject : IntPtr.Zero, callback, callbackData);
                        GDIPlus.CheckStatus (status);
                }
 
-               
-               public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, IntPtr callbackData)
+               public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs, DrawImageAbort callback, IntPtr callbackData)
                {
                        if (image == null)
                                throw new ArgumentNullException ("image");
                        Status status = GDIPlus.GdipDrawImageRectRect (nativeObject, image.NativeObject, 
                                        destRect.X, destRect.Y, destRect.Width, destRect.Height,
                                srcX, srcY, srcWidth, srcHeight, srcUnit,
-                               imageAttr != null ? imageAttr.NativeObject : IntPtr.Zero, callback, callbackData);
+                               imageAttrs != null ? imageAttrs.NativeObject : IntPtr.Zero, callback, callbackData);
                        GDIPlus.CheckStatus (status);
                }               
                
                public void DrawImageUnscaled (Image image, Point point)
                {
-                       if (image == null)
-                               throw new ArgumentNullException ("image");
                        DrawImageUnscaled (image, point.X, point.Y);
                }
                
                public void DrawImageUnscaled (Image image, Rectangle rect)
                {
-                       if (image == null)
-                               throw new ArgumentNullException ("image");
                        DrawImageUnscaled (image, rect.X, rect.Y, rect.Width, rect.Height);
                }
                
@@ -951,23 +973,30 @@ namespace System.Drawing
                {
                        if (image == null)
                                throw new ArgumentNullException ("image");
-                       Image tmpImg = new Bitmap (width, height);
-                       Graphics g = FromImage (tmpImg);
-                       g.DrawImage (image, 0, 0, image.Width, image.Height);
-                       this.DrawImage (tmpImg, x, y, width, height);
-                       tmpImg.Dispose ();
-                       g.Dispose ();
+
+                       // avoid creating an empty, or negative w/h, bitmap...
+                       if ((width <= 0) || (height <= 0))
+                               return;
+
+                       using (Image tmpImg = new Bitmap (width, height)) {
+                               using (Graphics g = FromImage (tmpImg)) {
+                                       g.DrawImage (image, 0, 0, image.Width, image.Height);
+                                       DrawImage (tmpImg, x, y, width, height);
+                               }
+                       }
                }
 
 #if NET_2_0
                public void DrawImageUnscaledAndClipped (Image image, Rectangle rect)
                {
-                       int height, width;                      
-                       width = (image.Width > rect.Width) ? rect.Width : image.Width;
-                       height = (image.Height > rect.Height) ? rect.Height : image.Height;
+                       if (image == null)
+                               throw new ArgumentNullException ("image");
+
+                       int width = (image.Width > rect.Width) ? rect.Width : image.Width;
+                       int height = (image.Height > rect.Height) ? rect.Height : image.Height;
 
                        DrawImageUnscaled (image, rect.X, rect.Y, width, height);                       
-               }\r
+               }
 #endif
 
                public void DrawLine (Pen pen, PointF pt1, PointF pt2)
@@ -1000,8 +1029,11 @@ namespace System.Drawing
                {
                        if (pen == null)
                                throw new ArgumentNullException ("pen");
-                       Status status = GDIPlus.GdipDrawLine (nativeObject, pen.nativeObject, x1, y1, x2, y2);
-                       GDIPlus.CheckStatus (status);
+                       if (!float.IsNaN(x1) && !float.IsNaN(y1) &&
+                           !float.IsNaN(x2) && !float.IsNaN(y2)) {
+                               Status status = GDIPlus.GdipDrawLine (nativeObject, pen.nativeObject, x1, y1, x2, y2);
+                               GDIPlus.CheckStatus (status);
+                       }
                }
 
                public void DrawLines (Pen pen, PointF [] points)
@@ -1087,13 +1119,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               internal void DrawRectangle (Pen pen, RectangleF rect)
-               {
-                       if (pen == null)
-                               throw new ArgumentNullException ("pen");
-                       DrawRectangle (pen, rect.Left, rect.Top, rect.Width, rect.Height);
-               }
-
                public void DrawRectangle (Pen pen, Rectangle rect)
                {
                        if (pen == null)
@@ -1185,217 +1210,219 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               [MonoTODO]
+               private const string MetafileEnumeration = "Metafiles enumeration, for both WMF and EMF formats, isn't supported.";
+
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoTODO (MetafileEnumeration)]
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
                {
                        throw new NotImplementedException ();
@@ -1425,7 +1452,6 @@ namespace System.Drawing
                        Status status = GDIPlus.GdipFillClosedCurve (nativeObject, brush.NativeObject, points, points.Length);
                        GDIPlus.CheckStatus (status);
                }
-
                
                public void FillClosedCurve (Brush brush, Point [] points)
                {
@@ -1661,8 +1687,9 @@ namespace System.Drawing
 
                        Status status = GDIPlus.GdipFlush (nativeObject, intention);
                         GDIPlus.CheckStatus (status);                    
-                       if (GDIPlus.UseQuartzDrawable || GDIPlus.UseCocoaDrawable)
-                               Carbon.CGContextSynchronize (GDIPlus.Display);
+
+                       if (maccontext != null)
+                               maccontext.Synchronize ();
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]               
@@ -1695,22 +1722,32 @@ namespace System.Drawing
                        IntPtr graphics;
 
                        if (GDIPlus.UseCocoaDrawable) {
-                               CarbonContext cgContext = Carbon.GetCGContextForNSView (hwnd);
-                               GDIPlus.GdipCreateFromQuartz_macosx (cgContext.ctx, cgContext.width, cgContext.height, out graphics);
-                               
-                               GDIPlus.Display = cgContext.ctx;
-                               return new Graphics (graphics);
+                               CocoaContext context = MacSupport.GetCGContextForNSView (hwnd);
+                               GDIPlus.GdipCreateFromContext_macosx (context.ctx, context.width, context.height, out graphics);
+
+                               Graphics g = new Graphics (graphics);
+                               g.maccontext = context;
+
+                               return g;
                        }
-                       if (GDIPlus.UseQuartzDrawable) {
-                               CarbonContext cgContext = Carbon.GetCGContextForView (hwnd);
-                               GDIPlus.GdipCreateFromQuartz_macosx (cgContext.ctx, cgContext.width, cgContext.height, out graphics);
+
+                       if (GDIPlus.UseCarbonDrawable) {
+                               CarbonContext context = MacSupport.GetCGContextForView (hwnd);
+                               GDIPlus.GdipCreateFromContext_macosx (context.ctx, context.width, context.height, out graphics);
+                               
+                               Graphics g = new Graphics (graphics);
+                               g.maccontext = context;
                                
-                               GDIPlus.Display = cgContext.ctx;
-                               return new Graphics (graphics);
+                               return g;
                        }
                        if (GDIPlus.UseX11Drawable) {
                                if (GDIPlus.Display == IntPtr.Zero) {
                                        GDIPlus.Display = GDIPlus.XOpenDisplay (IntPtr.Zero);
+                                       if (GDIPlus.Display == IntPtr.Zero)
+                                               throw new NotSupportedException ("Could not open display (X-Server required. Check you DISPLAY environment variable)");
+                               }
+                               if (hwnd == IntPtr.Zero) {
+                                       hwnd = GDIPlus.XRootWindow (GDIPlus.Display, GDIPlus.XDefaultScreen (GDIPlus.Display));
                                }
 
                                return FromXDrawable (hwnd, GDIPlus.Display);
@@ -1737,14 +1774,14 @@ namespace System.Drawing
                        if (image == null) 
                                throw new ArgumentNullException ("image");
 
+                       if ((image.PixelFormat & PixelFormat.Indexed) != 0)
+                               throw new Exception (Locale.GetText ("Cannot create Graphics from an indexed bitmap."));
+
                        Status status = GDIPlus.GdipGetImageGraphicsContext (image.nativeObject, out graphics);
                        GDIPlus.CheckStatus (status);
                        Graphics result = new Graphics (graphics);
                                
-                       // check for Unix platforms - see FAQ for more details
-                       // http://www.mono-project.com/FAQ:_Technical#How_to_detect_the_execution_platform_.3F
-                       int platform = (int) Environment.OSVersion.Platform;
-                       if ((platform == 4) || (platform == 128)) {
+                       if (GDIPlus.RunningOnUnix ()) {
                                Rectangle rect  = new Rectangle (0,0, image.Width, image.Height);
                                GDIPlus.GdipSetVisibleClip_linux (result.NativeObject, ref rect);
                        }
@@ -1772,14 +1809,9 @@ namespace System.Drawing
 #endif
                public IntPtr GetHdc ()
                {
-                       IntPtr hdc;
-                       GDIPlus.CheckStatus (GDIPlus.GdipGetDC (this.nativeObject, out hdc));
-#if NET_2_0
-                       deviceContextHdc = hdc;
-#endif
-                       return hdc;
+                       GDIPlus.CheckStatus (GDIPlus.GdipGetDC (this.nativeObject, out deviceContextHdc));
+                       return deviceContextHdc;
                }
-
                
                public Color GetNearestColor (Color color)
                {
@@ -1884,9 +1916,12 @@ namespace System.Drawing
                                throw new ArgumentNullException ("font");
 
                        if (stringFormat == null)
-                               stringFormat = StringFormat.GenericDefault;
+                               throw new ArgumentException ("stringFormat");
 
                        int regcount = stringFormat.GetMeasurableCharacterRangeCount ();
+                       if (regcount == 0)
+                               return new Region[0];
+
                        IntPtr[] native_regions = new IntPtr [regcount];
                        Region[] regions = new Region [regcount];
                        
@@ -1902,108 +1937,69 @@ namespace System.Drawing
                        return regions;                                                 
                }
 
-               
-               public SizeF MeasureString (string text, Font font)
-               {
-                       return MeasureString (text, font, SizeF.Empty);
-               }
-
-               
-               public SizeF MeasureString (string text, Font font, SizeF layoutArea)
+               private unsafe SizeF GdipMeasureString (IntPtr graphics, string text, Font font, ref RectangleF layoutRect,
+                       IntPtr stringFormat)
                {
-                       if (text == null || text.Length == 0)
+                       if ((text == null) || (text.Length == 0))
                                return SizeF.Empty;
 
                        if (font == null)
                                throw new ArgumentNullException ("font");
 
-                       int charactersFitted, linesFilled;
                        RectangleF boundingBox = new RectangleF ();
-                       RectangleF rect = new RectangleF (0, 0, layoutArea.Width, layoutArea.Height);
 
-                       Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length,
-                                                                  font.NativeObject, ref rect,
-                                                                  IntPtr.Zero, out boundingBox,
-                                                                  out charactersFitted, out linesFilled);
+                       Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, font.NativeObject, 
+                               ref layoutRect, stringFormat, out boundingBox, null, null);
                        GDIPlus.CheckStatus (status);
 
                        return new SizeF (boundingBox.Width, boundingBox.Height);
                }
 
-               
-               public SizeF MeasureString (string text, Font font, int width)
-               {                               
-                       if (text == null || text.Length == 0)
-                               return SizeF.Empty;
-
-                       if (font == null)
-                               throw new ArgumentNullException ("font");
-
-                       RectangleF boundingBox = new RectangleF ();
-                       RectangleF rect = new RectangleF (0, 0, width, 999999);
-                       int charactersFitted, linesFilled;
+               public SizeF MeasureString (string text, Font font)
+               {
+                       return MeasureString (text, font, SizeF.Empty);
+               }
 
-                       Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
-                                                                  font.NativeObject, ref rect,
-                                                                  IntPtr.Zero, out boundingBox,
-                                                                  out charactersFitted, out linesFilled);
-                       GDIPlus.CheckStatus (status);
+               public SizeF MeasureString (string text, Font font, SizeF layoutArea)
+               {
+                       RectangleF rect = new RectangleF (0, 0, layoutArea.Width, layoutArea.Height);
+                       return GdipMeasureString (nativeObject, text, font, ref rect, IntPtr.Zero);
+               }
 
-                       return new SizeF (boundingBox.Width, boundingBox.Height);
+               public SizeF MeasureString (string text, Font font, int width)
+               {                               
+                       RectangleF rect = new RectangleF (0, 0, width, Int32.MaxValue);
+                       return GdipMeasureString (nativeObject, text, font, ref rect, IntPtr.Zero);
                }
 
-               
-               public SizeF MeasureString (string text, Font font, SizeF layoutArea,
-                                           StringFormat stringFormat)
+               public SizeF MeasureString (string text, Font font, SizeF layoutArea, StringFormat stringFormat)
                {
-                       int charactersFitted, linesFilled;                      
-                       return MeasureString (text, font, layoutArea, stringFormat,
-                                             out charactersFitted, out linesFilled);
+                       RectangleF rect = new RectangleF (0, 0, layoutArea.Width, layoutArea.Height);
+                       IntPtr format = (stringFormat == null) ? IntPtr.Zero : stringFormat.NativeObject;
+                       return GdipMeasureString (nativeObject, text, font, ref rect, format);
                }
 
-               
                public SizeF MeasureString (string text, Font font, int width, StringFormat format)
                {
-                       int charactersFitted, linesFilled;                      
-                       return MeasureString (text, font, new SizeF (width, 999999), 
-                                             format, out charactersFitted, out linesFilled);
+                       RectangleF rect = new RectangleF (0, 0, width, Int32.MaxValue);
+                       IntPtr stringFormat = (format == null) ? IntPtr.Zero : format.NativeObject;
+                       return GdipMeasureString (nativeObject, text, font, ref rect, stringFormat);
                }
 
-               
-               public SizeF MeasureString (string text, Font font, PointF origin,
-                                           StringFormat stringFormat)
+               public SizeF MeasureString (string text, Font font, PointF origin, StringFormat stringFormat)
                {
-                       if (text == null || text.Length == 0)
-                               return SizeF.Empty;
-
-                       if (font == null)
-                               throw new ArgumentNullException ("font");
-
-                       RectangleF boundingBox = new RectangleF ();
                        RectangleF rect = new RectangleF (origin.X, origin.Y, 0, 0);
-                       int charactersFitted, linesFilled;
-
                        IntPtr format = (stringFormat == null) ? IntPtr.Zero : stringFormat.NativeObject;
-
-                       Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
-                                                                  font.NativeObject, ref rect, format, 
-                                                                  out boundingBox,
-                                                                  out charactersFitted,
-                                                                  out linesFilled);
-                       GDIPlus.CheckStatus (status);
-
-                       return new SizeF (boundingBox.Width, boundingBox.Height);
+                       return GdipMeasureString (nativeObject, text, font, ref rect, format);
                }
 
-               
-               public SizeF MeasureString (string text, Font font, SizeF layoutArea,
-                                           StringFormat stringFormat, out int charactersFitted,
-                                           out int linesFilled)
+               public SizeF MeasureString (string text, Font font, SizeF layoutArea, StringFormat stringFormat, 
+                       out int charactersFitted, out int linesFilled)
                {       
                        charactersFitted = 0;
                        linesFilled = 0;
 
-                       if (text == null || text.Length == 0)
+                       if ((text == null) || (text.Length == 0))
                                return SizeF.Empty;
 
                        if (font == null)
@@ -2014,13 +2010,13 @@ namespace System.Drawing
 
                        IntPtr format = (stringFormat == null) ? IntPtr.Zero : stringFormat.NativeObject;
 
-                       Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
-                                                                  font.NativeObject, ref rect, format,
-                                                                  out boundingBox,
-                                                                  out charactersFitted,
-                                                                  out linesFilled);
-                       GDIPlus.CheckStatus (status);
-
+                       unsafe {
+                               fixed (int* pc = &charactersFitted, pl = &linesFilled) {
+                                       Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
+                                       font.NativeObject, ref rect, format, out boundingBox, pc, pl);
+                                       GDIPlus.CheckStatus (status);
+                               }
+                       }
                        return new SizeF (boundingBox.Width, boundingBox.Height);
                }
 
@@ -2031,34 +2027,29 @@ namespace System.Drawing
 
                public void MultiplyTransform (Matrix matrix, MatrixOrder order)
                {
-                       Status status = GDIPlus.GdipMultiplyWorldTransform (nativeObject,
-                                                                           matrix.nativeMatrix,
-                                                                           order);
+                       if (matrix == null)
+                               throw new ArgumentNullException ("matrix");
+
+                       Status status = GDIPlus.GdipMultiplyWorldTransform (nativeObject, matrix.nativeMatrix, order);
                        GDIPlus.CheckStatus (status);
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
                public void ReleaseHdc (IntPtr hdc)
                {
-                       Status status = GDIPlus.GdipReleaseDC (nativeObject, hdc);
-                       GDIPlus.CheckStatus (status);
-#if NET_2_0
-                       if (hdc == deviceContextHdc)
-                               deviceContextHdc = IntPtr.Zero;
-#endif
+                       ReleaseHdcInternal (hdc);
                }
 
 #if NET_2_0
-               public void ReleaseHdc ()\r
-               {\r
-                       if (deviceContextHdc == IntPtr.Zero)
-                               throw new ArgumentException ("Invalid Handle");
-
-                       ReleaseHdc (deviceContextHdc);
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
+               public void ReleaseHdc ()
+               {
+                       ReleaseHdcInternal (deviceContextHdc);
                }
 #endif
 
-               [MonoTODO]
+               [MonoLimitation ("Can only be used when hdc was provided by Graphics.GetHdc() method")]
 #if NET_2_0
                [EditorBrowsable (EditorBrowsableState.Never)]
 #else
@@ -2067,9 +2058,13 @@ namespace System.Drawing
                [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                public void ReleaseHdcInternal (IntPtr hdc)
                {
-                       throw new NotImplementedException ();
+                       Status status = Status.InvalidParameter;
+                       if (hdc == deviceContextHdc) {
+                               status = GDIPlus.GdipReleaseDC (nativeObject, deviceContextHdc);
+                               deviceContextHdc = IntPtr.Zero;
+                       }
+                       GDIPlus.CheckStatus (status);
                }
-
                
                public void ResetClip ()
                {
@@ -2085,11 +2080,11 @@ namespace System.Drawing
 
                public void Restore (GraphicsState gstate)
                {                       
+                       // the possible NRE thrown by gstate.nativeState match MS behaviour
                        Status status = GDIPlus.GdipRestoreGraphics (nativeObject, gstate.nativeState);
                        GDIPlus.CheckStatus (status);
                }
 
-
                public void RotateTransform (float angle)
                {
                        RotateTransform (angle, MatrixOrder.Prepend);
@@ -2097,7 +2092,6 @@ namespace System.Drawing
 
                public void RotateTransform (float angle, MatrixOrder order)
                {
-
                        Status status = GDIPlus.GdipRotateWorldTransform (nativeObject, angle, order);
                        GDIPlus.CheckStatus (status);
                }
@@ -2374,7 +2368,7 @@ namespace System.Drawing
                        }
                }
 
-               [MonoTODO ("not supported by libgdiplus")]
+               [MonoTODO ("This property does not do anything when used with libgdiplus.")]
                public PixelOffsetMode PixelOffsetMode {
                        get {
                                PixelOffsetMode pixelOffset = PixelOffsetMode.Invalid;
@@ -2418,7 +2412,7 @@ namespace System.Drawing
                        }
                }
 
-               [MonoTODO ("not supported by libgdiplus")]
+               [MonoTODO ("This property does not do anything when used with libgdiplus.")]
                public int TextContrast {
                        get {   
                                 int contrast;
@@ -2480,6 +2474,7 @@ namespace System.Drawing
                [EditorBrowsable (EditorBrowsableState.Never)]
                public object GetContextInfo ()
                {
+                       // only known source of information @ http://blogs.wdevs.com/jdunlap/Default.aspx
                        throw new NotImplementedException ();
                }
 #endif