* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / System.Drawing / System.Drawing / Graphics.cs
index 9e91e968efb8d73bb2dbb15d25e45d8defd49769..a5a7c0984f1445f1c33bcd56794c56956dfd96bb 100644 (file)
@@ -40,25 +40,37 @@ using System.Text;
 
 namespace System.Drawing
 {
-       [ComVisible(false)]
+#if !NET_2_0
+       [ComVisible(false)]  
+#endif
        public sealed class Graphics : MarshalByRefObject, IDisposable
+#if NET_2_0
+       , IDeviceContext
+#endif
        {
                internal IntPtr nativeObject = IntPtr.Zero;
                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)]
+#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;
                }
@@ -74,6 +86,7 @@ namespace System.Drawing
                                        Bitmap bmp = new Bitmap (1, 1);
                                        Graphics g = Graphics.FromImage (bmp);
                                        defDpiX = g.DpiX;
+                                       defDpiY = g.DpiY;
                                }
                                return defDpiX;
                        }
@@ -84,6 +97,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;
@@ -99,40 +113,40 @@ namespace System.Drawing
                                nativeObject = value;
                        }
                }
-
+               
                [MonoTODO]
                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 ("rectangles and unit 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 ("rectangles and unit 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);
@@ -145,6 +159,104 @@ namespace System.Drawing
                        status = GDIPlus.GdipGraphicsClear (nativeObject, color.ToArgb ());
                        GDIPlus.CheckStatus (status);
                }
+#if NET_2_0            
+               public void CopyFromScreen (Point upperLeftSource, Point upperLeftDestination, Size blockRegionSize)
+               {
+                       CopyFromScreen (upperLeftSource.X, upperLeftSource.Y, upperLeftDestination.X, upperLeftDestination.Y,
+                               blockRegionSize, CopyPixelOperation.SourceCopy);                                
+               }
+
+               public void CopyFromScreen (Point upperLeftSource, Point upperLeftDestination, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
+               {
+                       CopyFromScreen (upperLeftSource.X, upperLeftSource.Y, upperLeftDestination.X, upperLeftDestination.Y,
+                               blockRegionSize, copyPixelOperation);
+               }\r
+               
+               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
+               {
+                       IntPtr window;                  
+
+                       if (!Enum.IsDefined (typeof (CopyPixelOperation), copyPixelOperation))
+                               throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for CopyPixelOperation", copyPixelOperation));
+
+                       if (GDIPlus.UseCocoaDrawable || GDIPlus.UseQuartzDrawable) {
+                               throw new NotImplementedException ();
+                       }
+                       
+                       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");
+               
+                               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 ();
+
+                               /* 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*/);
+                               
+                               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);
+                               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
+#endif
 
                public void Dispose ()
                {
@@ -237,10 +349,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];
@@ -264,10 +376,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];
@@ -378,7 +490,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
                
-               
                public void DrawCurve (Pen pen, PointF [] points, int offset, int numberOfSegments)
                {
                        if (pen == null)
@@ -407,7 +518,6 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void DrawCurve (Pen pen, PointF [] points, int offset, int numberOfSegments, float tension)
                {
                        if (pen == null)
@@ -456,20 +566,23 @@ namespace System.Drawing
 
                public void DrawIcon (Icon icon, Rectangle targetRect)
                {
-                       Image img = icon.ToBitmap ();
-                       DrawImage (img, targetRect);
+                       using (Image img = icon.ToBitmap ()) {
+                               DrawImage (img, targetRect);
+                       }
                }
 
                public void DrawIcon (Icon icon, int x, int y)
                {
-                       Image img = icon.ToBitmap ();
-                       DrawImage (img, x, y);
+                       using (Image img = icon.ToBitmap ()) {
+                               DrawImage (img, x, y);
+                       }
                }
 
                public void DrawIconUnstretched (Icon icon, Rectangle targetRect)
                {
-                       Image img = icon.ToBitmap ();
-                       DrawImageUnscaled (img, targetRect);
+                       using (Image img = icon.ToBitmap ()) {
+                               DrawImageUnscaled (img, targetRect);
+                       }
                }
                
                public void DrawImage (Image image, RectangleF rect)
@@ -846,6 +959,17 @@ namespace System.Drawing
                        g.Dispose ();
                }
 
+#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;
+
+                       DrawImageUnscaled (image, rect.X, rect.Y, width, height);                       
+               }\r
+#endif
+
                public void DrawLine (Pen pen, PointF pt1, PointF pt2)
                {
                        if (pen == null)
@@ -1053,8 +1177,10 @@ 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);
                }
@@ -1490,7 +1616,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);
                }
@@ -1499,7 +1627,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);
                }
@@ -1525,6 +1655,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)
@@ -1633,11 +1767,16 @@ namespace System.Drawing
                        throw new NotImplementedException ();
                }
 
+#if !NET_2_0
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+#endif
                public IntPtr GetHdc ()
                {
                        IntPtr hdc;
                        GDIPlus.CheckStatus (GDIPlus.GdipGetDC (this.nativeObject, out hdc));
+#if NET_2_0
+                       deviceContextHdc = hdc;
+#endif
                        return hdc;
                }
 
@@ -1901,10 +2040,28 @@ namespace System.Drawing
                {
                        Status status = GDIPlus.GdipReleaseDC (nativeObject, hdc);
                        GDIPlus.CheckStatus (status);
+#if NET_2_0
+                       if (hdc == deviceContextHdc)
+                               deviceContextHdc = IntPtr.Zero;
+#endif
                }
 
+#if NET_2_0
+               public void ReleaseHdc ()\r
+               {\r
+                       if (deviceContextHdc == IntPtr.Zero)
+                               throw new ArgumentException ("Invalid Handle");
+
+                       ReleaseHdc (deviceContextHdc);
+               }
+#endif
+
                [MonoTODO]
+#if NET_2_0
+               [EditorBrowsable (EditorBrowsableState.Never)]
+#else
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+#endif
                [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                public void ReleaseHdcInternal (IntPtr hdc)
                {
@@ -2215,6 +2372,7 @@ namespace System.Drawing
                        }
                }
 
+               [MonoTODO ("not supported by libgdiplus")]
                public PixelOffsetMode PixelOffsetMode {
                        get {
                                PixelOffsetMode pixelOffset = PixelOffsetMode.Invalid;
@@ -2258,6 +2416,7 @@ namespace System.Drawing
                        }
                }
 
+               [MonoTODO ("not supported by libgdiplus")]
                public int TextContrast {
                        get {   
                                 int contrast;
@@ -2313,6 +2472,14 @@ namespace System.Drawing
                                 return rect;
                        }
                }
+
+#if NET_2_0
+               [MonoTODO]
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               public object GetContextInfo ()
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
        }
 }
-