2007-05-30 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System.Drawing / System.Drawing / Graphics.cs
index c3cbd9bea2ba60195e872e9a793711961bfd2589..5b64367a4484a4b1858bea030a5a86d3d8e00c75 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
@@ -52,18 +52,23 @@ namespace System.Drawing
                private bool disposed = false;
                private static float defDpiX = 0;
                private static float defDpiY = 0;
+               private IntPtr deviceContextHdc;
 
+#if !NET_2_0
                [ComVisible(false)]
+#endif
                public delegate bool EnumerateMetafileProc (EmfPlusRecordType recordType,
                                                            int flags,
                                                            int dataSize,
                                                            IntPtr data,
                                                            PlayRecordCallback callbackData);
                
+#if !NET_2_0
                [ComVisible (false)]
+#endif
                public delegate bool DrawImageAbort (IntPtr callbackData);
 
-               private Graphics (IntPtr nativeGraphics)
+               internal Graphics (IntPtr nativeGraphics)
                {
                        nativeObject = nativeGraphics;
                }
@@ -79,6 +84,7 @@ namespace System.Drawing
                                        Bitmap bmp = new Bitmap (1, 1);
                                        Graphics g = Graphics.FromImage (bmp);
                                        defDpiX = g.DpiX;
+                                       defDpiY = g.DpiY;
                                }
                                return defDpiX;
                        }
@@ -89,6 +95,7 @@ namespace System.Drawing
                                if (defDpiY == 0) {
                                        Bitmap bmp = new Bitmap (1, 1);
                                        Graphics g = Graphics.FromImage (bmp);
+                                       defDpiX = g.DpiX;
                                        defDpiY = g.DpiY;
                                }
                                return defDpiY;
@@ -105,39 +112,39 @@ namespace System.Drawing
                        }
                }
                
-               [MonoTODO]
+               [MonoTODO ("Metafiles, both WMF and EMF formats, aren't supported.")]
                public void AddMetafileComment (byte [] data)
                {
                        throw new NotImplementedException ();
                }
 
-               
                public GraphicsContainer BeginContainer ()
                {
-                       int state;
+                       uint state;
                        Status status;
                        status = GDIPlus.GdipBeginContainer2 (nativeObject, out state);
                        GDIPlus.CheckStatus (status);
 
                         return new GraphicsContainer(state);
                }
-               
+
+               [MonoTODO ("The rectangles and unit parameters aren't supported in libgdiplus")]                
                public GraphicsContainer BeginContainer (Rectangle dstrect, Rectangle srcrect, GraphicsUnit unit)
                {
-                       int state;
+                       uint state;
                        Status status;
-                       status = GDIPlus.GdipBeginContainerI (nativeObject, dstrect, srcrect, unit, out state);
+                       status = GDIPlus.GdipBeginContainerI (nativeObject, ref dstrect, ref srcrect, unit, out state);
                        GDIPlus.CheckStatus (status);
 
                        return new GraphicsContainer (state);
                }
 
-               
+               [MonoTODO ("The rectangles and unit parameters aren't supported in libgdiplus")]                
                public GraphicsContainer BeginContainer (RectangleF dstrect, RectangleF srcrect, GraphicsUnit unit)
                {
-                       int state;
+                       uint state;
                        Status status;
-                       status = GDIPlus.GdipBeginContainer (nativeObject, dstrect, srcrect, unit, out state);
+                       status = GDIPlus.GdipBeginContainer (nativeObject, ref dstrect, ref srcrect, unit, out state);
                        GDIPlus.CheckStatus (status);
 
                        return new GraphicsContainer (state);
@@ -151,101 +158,115 @@ 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.UseCocoaDrawable || GDIPlus.UseQuartzDrawable) {
+                               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;
+               }
+
+               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);                     
+               }
+               
+               private void CopyFromScreenMac (int sourceX, int sourceY, int destinationX, int destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               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;
 
-                               if (copyPixelOperation != CopyPixelOperation.SourceCopy)
-                                       throw new NotImplementedException ("Operation not implemented under X11");
+                       if (copyPixelOperation != CopyPixelOperation.SourceCopy)
+                               throw new NotImplementedException ("Operation not implemented under X11");
                
-                               if (GDIPlus.Display == IntPtr.Zero) {
-                                       GDIPlus.Display = GDIPlus.XOpenDisplay (IntPtr.Zero);                                   
-                               }
+                       if (GDIPlus.Display == IntPtr.Zero) {
+                               GDIPlus.Display = GDIPlus.XOpenDisplay (IntPtr.Zero);                                   
+                       }
 
-                               window = GDIPlus.XRootWindow (GDIPlus.Display, 0);
-                               defvisual = GDIPlus.XDefaultVisual (GDIPlus.Display, 0);                                
-                               XVisualInfo visual = new XVisualInfo ();
+                       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));
+                       /* 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));
 
-                               /* 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*/);
+                       /* 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*/);
                                
-                               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;
+                       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));                                                     
                                }
+                       }
 
-                               DrawImage (bmp, 0, 0);
-                               bmp.Dispose ();
-                               GDIPlus.XDestroyImage (image);
-                               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, 0, 0);
+                       bmp.Dispose ();
+                       GDIPlus.XDestroyImage (image);
+                       GDIPlus.XFree (vPtr);
+               }
 #endif
 
                public void Dispose ()
@@ -339,10 +360,10 @@ namespace System.Drawing
                         int length = points.Length;
                        Status status;
 
-                        if (length < 3)
+                        if (length < 4)
                                 return;
 
-                       for (int i = 0; i < length; i += 3) {
+                       for (int i = 0; i < length - 1; i += 3) {
                                 Point p1 = points [i];
                                 Point p2 = points [i + 1];
                                 Point p3 = points [i + 2];
@@ -366,10 +387,10 @@ namespace System.Drawing
                        int length = points.Length;
                        Status status;
 
-                        if (length < 3)
+                        if (length < 4)
                                 return;
 
-                       for (int i = 0; i < length; i += 3) {
+                       for (int i = 0; i < length - 1; i += 3) {
                                 PointF p1 = points [i];
                                 PointF p2 = points [i + 1];
                                 PointF p3 = points [i + 2];
@@ -480,7 +501,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
                
-               
                public void DrawCurve (Pen pen, PointF [] points, int offset, int numberOfSegments)
                {
                        if (pen == null)
@@ -509,7 +529,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawCurve (Pen pen, PointF [] points, int offset, int numberOfSegments, float tension)
                {
                        if (pen == null)
@@ -558,20 +577,26 @@ namespace System.Drawing
 
                public void DrawIcon (Icon icon, Rectangle targetRect)
                {
-                       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)
                {
-                       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)
                {
-                       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)
@@ -583,7 +608,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, PointF point)
                {
                        if (image == null)
@@ -593,7 +617,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point [] destPoints)
                {
                        if (image == null)
@@ -605,7 +628,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point point)
                {
                        if (image == null)
@@ -613,7 +635,6 @@ namespace System.Drawing
                        DrawImage (image, point.X, point.Y);
                }
 
-               
                public void DrawImage (Image image, Rectangle rect)
                {
                        if (image == null)
@@ -621,7 +642,6 @@ namespace System.Drawing
                        DrawImage (image, rect.X, rect.Y, rect.Width, rect.Height);
                }
 
-               
                public void DrawImage (Image image, PointF [] destPoints)
                {
                        if (image == null)
@@ -632,7 +652,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, int x, int y)
                {
                        if (image == null)
@@ -641,7 +660,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, float x, float y)
                {
                        if (image == null)
@@ -650,7 +668,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit)
                {
                        if (image == null)
@@ -673,7 +690,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit)
                {
                        if (image == null)
@@ -688,7 +704,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit)
                {
                        if (image == null)
@@ -703,7 +718,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, 
                                 ImageAttributes imageAttr)
                {
@@ -727,7 +741,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, 
                                 ImageAttributes imageAttr)
                {
@@ -742,7 +755,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawImage (Image image, int x, int y, Rectangle srcRect, GraphicsUnit srcUnit)
                {                       
                        if (image == null)
@@ -767,7 +779,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)
@@ -781,7 +792,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)
@@ -796,7 +806,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)
@@ -811,7 +820,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)
@@ -832,7 +840,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)
@@ -844,7 +851,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)
@@ -891,7 +897,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 imageAttr, DrawImageAbort callback, IntPtr callbackData)
                {
                        if (image == null)
@@ -903,7 +908,6 @@ namespace System.Drawing
                        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)
                {
                        if (image == null)
@@ -917,15 +921,11 @@ namespace System.Drawing
                
                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);
                }
                
@@ -940,23 +940,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)
@@ -1166,223 +1173,227 @@ namespace System.Drawing
 
                public void EndContainer (GraphicsContainer container)
                {
+#if NET_2_0
                        if (container == null)
                                throw new ArgumentNullException ("container");
+#endif
                        Status status = GDIPlus.GdipEndContainer(nativeObject, container.NativeObject);
                        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 ();
@@ -1412,7 +1423,6 @@ namespace System.Drawing
                        Status status = GDIPlus.GdipFillClosedCurve (nativeObject, brush.NativeObject, points, points.Length);
                        GDIPlus.CheckStatus (status);
                }
-
                
                public void FillClosedCurve (Brush brush, Point [] points)
                {
@@ -1603,7 +1613,9 @@ namespace System.Drawing
                {
                        if (brush == null)
                                throw new ArgumentNullException ("brush");
-                       
+                       if (rects == null)
+                               throw new ArgumentNullException ("rects");
+
                        Status status = GDIPlus.GdipFillRectanglesI (nativeObject, brush.nativeObject, rects, rects.Length);
                        GDIPlus.CheckStatus (status);
                }
@@ -1612,7 +1624,9 @@ namespace System.Drawing
                {
                        if (brush == null)
                                throw new ArgumentNullException ("brush");
-                       
+                       if (rects == null)
+                               throw new ArgumentNullException ("rects");
+
                        Status status = GDIPlus.GdipFillRectangles (nativeObject, brush.nativeObject, rects, rects.Length);
                        GDIPlus.CheckStatus (status);
                }
@@ -1638,6 +1652,10 @@ namespace System.Drawing
                
                public void Flush (FlushIntention intention)
                {
+                       if (nativeObject == IntPtr.Zero) {
+                               return;
+                       }
+
                        Status status = GDIPlus.GdipFlush (nativeObject, intention);
                         GDIPlus.CheckStatus (status);                    
                        if (GDIPlus.UseQuartzDrawable || GDIPlus.UseCocoaDrawable)
@@ -1716,14 +1734,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);
                        }
@@ -1751,11 +1769,9 @@ namespace System.Drawing
 #endif
                public IntPtr GetHdc ()
                {
-                       IntPtr hdc;
-                       GDIPlus.CheckStatus (GDIPlus.GdipGetDC (this.nativeObject, out hdc));
-                       return hdc;
+                       GDIPlus.CheckStatus (GDIPlus.GdipGetDC (this.nativeObject, out deviceContextHdc));
+                       return deviceContextHdc;
                }
-
                
                public Color GetNearestColor (Color color)
                {
@@ -1851,10 +1867,21 @@ namespace System.Drawing
                }
 
                
-               public Region [] MeasureCharacterRanges (string text, Font font, RectangleF layoutRect, StringFormat stringFormat)
-               {       
-                       Status status;                  
+               public Region[] MeasureCharacterRanges (string text, Font font, RectangleF layoutRect, StringFormat stringFormat)
+               {
+                       if ((text == null) || (text.Length == 0))
+                               return new Region [0];
+
+                       if (font == null)
+                               throw new ArgumentNullException ("font");
+
+                       if (stringFormat == null)
+                               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];
                        
@@ -1863,35 +1890,32 @@ namespace System.Drawing
                                native_regions[i] = regions[i].NativeObject;
                        }
                        
-                       status =  GDIPlus.GdipMeasureCharacterRanges (nativeObject, text, text.Length,
-                               font.NativeObject, ref layoutRect, stringFormat.NativeObject, 
-                               regcount, out native_regions[0]); 
-                       
+                       Status status = GDIPlus.GdipMeasureCharacterRanges (nativeObject, text, text.Length,
+                               font.NativeObject, ref layoutRect, stringFormat.NativeObject, regcount, out native_regions[0]); 
                        GDIPlus.CheckStatus (status);                           
-                                                       
+
                        return regions;                                                 
                }
 
                
                public SizeF MeasureString (string text, Font font)
                {
-                       return MeasureString (text, font, new Size (0, 0));
+                       return MeasureString (text, font, SizeF.Empty);
                }
 
                
                public SizeF MeasureString (string text, Font font, SizeF layoutArea)
                {
-                       int charactersFitted, linesFilled;
-                       RectangleF boundingBox = new RectangleF ();
-                       RectangleF rect = new RectangleF (0, 0, layoutArea.Width,
-                                                         layoutArea.Height);
-
                        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,
@@ -1904,16 +1928,16 @@ namespace System.Drawing
                
                public SizeF MeasureString (string text, Font font, int width)
                {                               
-                       RectangleF boundingBox = new RectangleF ();
-                       RectangleF rect = new RectangleF (0, 0, width, 999999);
-                       int charactersFitted, linesFilled;
-
                        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, Int32.MaxValue);
+                       int charactersFitted, linesFilled;
+
                        Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
                                                                   font.NativeObject, ref rect,
                                                                   IntPtr.Zero, out boundingBox,
@@ -1936,7 +1960,7 @@ namespace System.Drawing
                public SizeF MeasureString (string text, Font font, int width, StringFormat format)
                {
                        int charactersFitted, linesFilled;                      
-                       return MeasureString (text, font, new SizeF (width, 999999), 
+                       return MeasureString (text, font, new SizeF (width, Int32.MaxValue), 
                                              format, out charactersFitted, out linesFilled);
                }
 
@@ -1944,22 +1968,20 @@ namespace System.Drawing
                public SizeF MeasureString (string text, Font font, PointF origin,
                                            StringFormat stringFormat)
                {
-                       RectangleF boundingBox = new RectangleF ();
-                       RectangleF rect = new RectangleF (origin.X, origin.Y, 0, 0);
-                       int charactersFitted, linesFilled;
-
                        if (text == null || text.Length == 0)
                                return SizeF.Empty;
 
                        if (font == null)
                                throw new ArgumentNullException ("font");
 
-                       if (stringFormat == null)
-                               stringFormat = new StringFormat ();
+                       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,
-                                                                  stringFormat.NativeObject, 
+                                                                  font.NativeObject, ref rect, format, 
                                                                   out boundingBox,
                                                                   out charactersFitted,
                                                                   out linesFilled);
@@ -1973,8 +1995,6 @@ namespace System.Drawing
                                            StringFormat stringFormat, out int charactersFitted,
                                            out int linesFilled)
                {       
-                       RectangleF boundingBox = new RectangleF ();
-                       RectangleF rect = new RectangleF (0, 0, layoutArea.Width, layoutArea.Height);
                        charactersFitted = 0;
                        linesFilled = 0;
 
@@ -1984,12 +2004,13 @@ namespace System.Drawing
                        if (font == null)
                                throw new ArgumentNullException ("font");
 
-                       if (stringFormat == null)
-                               stringFormat = new StringFormat ();
+                       RectangleF boundingBox = new RectangleF ();
+                       RectangleF rect = new RectangleF (0, 0, layoutArea.Width, layoutArea.Height);
+
+                       IntPtr format = (stringFormat == null) ? IntPtr.Zero : stringFormat.NativeObject;
 
                        Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
-                                                                  font.NativeObject, ref rect,
-                                                                  stringFormat.NativeObject,
+                                                                  font.NativeObject, ref rect, format,
                                                                   out boundingBox,
                                                                   out charactersFitted,
                                                                   out linesFilled);
@@ -2012,18 +2033,21 @@ namespace System.Drawing
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
                public void ReleaseHdc (IntPtr hdc)
                {
-                       Status status = GDIPlus.GdipReleaseDC (nativeObject, hdc);
-                       GDIPlus.CheckStatus (status);
+                       ReleaseHdcInternal (hdc);
                }
+
 #if NET_2_0
-               public void ReleaseHdc()\r
-               {\r
-                     \r
+               [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
@@ -2032,9 +2056,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 ()
                {
@@ -2339,6 +2367,7 @@ namespace System.Drawing
                        }
                }
 
+               [MonoTODO ("This property does not do anything when used with libgdiplus.")]
                public PixelOffsetMode PixelOffsetMode {
                        get {
                                PixelOffsetMode pixelOffset = PixelOffsetMode.Invalid;
@@ -2382,6 +2411,7 @@ namespace System.Drawing
                        }
                }
 
+               [MonoTODO ("This property does not do anything when used with libgdiplus.")]
                public int TextContrast {
                        get {   
                                 int contrast;
@@ -2437,6 +2467,15 @@ namespace System.Drawing
                                 return rect;
                        }
                }
+
+#if NET_2_0
+               [MonoTODO]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               public object GetContextInfo ()
+               {
+                       // only known source of information @ http://blogs.wdevs.com/jdunlap/Default.aspx
+                       throw new NotImplementedException ();
+               }
+#endif
        }
 }
-