2005-09-26 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System.Drawing / System.Drawing / Graphics.cs
old mode 100755 (executable)
new mode 100644 (file)
index 56563ce..42b107c
@@ -8,7 +8,7 @@
 //
 // Copyright (C) 2003 Ximian, Inc. (http://www.ximian.com)
 //
-// Copyright (C) 2004 Novell, Inc. (http://www.novell.com)
+// Copyright (C) 2004-2005 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
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-using System;
+
 using System.Drawing.Drawing2D;
 using System.Drawing.Imaging;
 using System.Drawing.Text;
 using System.ComponentModel;
 using System.Runtime.InteropServices;
+using System.Security.Permissions;
 using System.Text;
 
 namespace System.Drawing
@@ -46,10 +47,6 @@ namespace System.Drawing
                private bool disposed = false;
                private static float defDpiX = 0;
                private static float defDpiY = 0;
-               private static IntPtr display = IntPtr.Zero;
-
-               // We use X Drawable on Linux.
-               private static bool use_x_drawable = (Environment.OSVersion.Platform == (PlatformID) 128);
 
                [ComVisible(false)]
                public delegate bool EnumerateMetafileProc (EmfPlusRecordType recordType,
@@ -154,6 +151,7 @@ namespace System.Drawing
                        Status status;
                        if (! disposed) {
                                status = GDIPlus.GdipDeleteGraphics (nativeObject);
+                               nativeObject = IntPtr.Zero;
                                GDIPlus.CheckStatus (status);
                                disposed = true;                                
                        }
@@ -790,50 +788,43 @@ namespace System.Drawing
                }
 
                public void DrawString (string s, Font font, Brush brush, RectangleF layoutRectangle)
-               {                       
-                       Status status = GDIPlus.GdipDrawString (nativeObject, s, s.Length, font.NativeObject, ref layoutRectangle, IntPtr.Zero, brush.nativeObject);
-                       GDIPlus.CheckStatus (status);
+               {
+                       DrawString (s, font, brush, layoutRectangle, null);
                }
-               
+
                public void DrawString (string s, Font font, Brush brush, PointF point)
                {
-                       RectangleF rc = new RectangleF (point.X, point.Y, 0, 0);
-                       Status status = GDIPlus.GdipDrawString (nativeObject, s, s.Length, font.NativeObject, ref rc, IntPtr.Zero, brush.nativeObject);
-                       GDIPlus.CheckStatus (status);
+                       DrawString (s, font, brush, new RectangleF (point.X, point.Y, 0, 0), null);
                }
-               
+
                public void DrawString (string s, Font font, Brush brush, PointF point, StringFormat format)
                {
-                       RectangleF rc = new RectangleF (point.X, point.Y, 0, 0);
-                       Status status = GDIPlus.GdipDrawString (nativeObject, s, s.Length, font.NativeObject, ref rc, format.NativeObject, brush.nativeObject);
-                       GDIPlus.CheckStatus (status);
-               }
-               
-               public void DrawString (string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)
-               {
-                       Status status = GDIPlus.GdipDrawString (nativeObject, s, s.Length, font.NativeObject, ref layoutRectangle, format.NativeObject, brush.nativeObject);
-                       GDIPlus.CheckStatus (status);
+                       DrawString(s, font, brush, new RectangleF(point.X, point.Y, 0, 0), format);
                }
 
                public void DrawString (string s, Font font, Brush brush, float x, float y)
                {
-                       RectangleF rc = new RectangleF (x, y, 0, 0);
-                       
-                       Status status = GDIPlus.GdipDrawString (nativeObject, s, s.Length, font.NativeObject, 
-                               ref rc, IntPtr.Zero, brush.nativeObject);
-                       GDIPlus.CheckStatus (status);
+                       DrawString (s, font, brush, new RectangleF (x, y, 0, 0), null);
                }
 
                public void DrawString (string s, Font font, Brush brush, float x, float y, StringFormat format)
                {
-                       RectangleF rc = new RectangleF (x, y, 0, 0);
+                       DrawString (s, font, brush, new RectangleF(x, y, 0, 0), format);
+               }
+
+               public void DrawString (string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)
+               {
+                       if (font == null)
+                               throw new ArgumentNullException ("font");
+                       if (brush == null)
+                               throw new ArgumentNullException ("brush");
+                       if (s == null || s.Length == 0)
+                               return;
 
-                       Status status = GDIPlus.GdipDrawString (nativeObject, s, s.Length, font.NativeObject,
-                               ref rc, format.NativeObject, brush.nativeObject);
+                       Status status = GDIPlus.GdipDrawString (nativeObject, s, s.Length, font.NativeObject, ref layoutRectangle, format != null ? format.NativeObject : IntPtr.Zero, brush.nativeObject);
                        GDIPlus.CheckStatus (status);
                }
 
-               
                public void EndContainer (GraphicsContainer container)
                {
                        Status status = GDIPlus.GdipEndContainer(nativeObject, container.NativeObject);
@@ -1226,7 +1217,9 @@ namespace System.Drawing
                public void Flush (FlushIntention intention)
                {
                        Status status = GDIPlus.GdipFlush (nativeObject, intention);
-                        GDIPlus.CheckStatus (status);                     
+                        GDIPlus.CheckStatus (status);                    
+                       if (GDIPlus.UseQuartzDrawable || GDIPlus.UseCocoaDrawable)
+                               Carbon.CGContextSynchronize (GDIPlus.Display);
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]               
@@ -1246,9 +1239,10 @@ namespace System.Drawing
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                public static Graphics FromHdcInternal (IntPtr hdc)
                {
-                       display = hdc;
+                       GDIPlus.Display = hdc;
                        return null;
                }
 
@@ -1257,12 +1251,27 @@ namespace System.Drawing
                {
                        IntPtr graphics;
 
-                       if (use_x_drawable) {
-                               if (display == IntPtr.Zero) {
-                                       display = GDIPlus.XOpenDisplay (IntPtr.Zero);
+                       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);
+                       }
+                       if (GDIPlus.UseQuartzDrawable) {
+                               CarbonContext cgContext = Carbon.GetCGContextForView (hwnd);
+                               GDIPlus.GdipCreateFromQuartz_macosx (cgContext.ctx, cgContext.width, cgContext.height, out graphics);
+                               
+                               GDIPlus.Display = cgContext.ctx;
+                               return new Graphics (graphics);
+                       }
+                       if (GDIPlus.UseX11Drawable) {
+                               if (GDIPlus.Display == IntPtr.Zero) {
+                                       GDIPlus.Display = GDIPlus.XOpenDisplay (IntPtr.Zero);
                                }
 
-                               return FromXDrawable (hwnd, display);
+                               return FromXDrawable (hwnd, GDIPlus.Display);
+
                        }
 
                        Status status = GDIPlus.GdipCreateFromHWND (hwnd, out graphics);
@@ -1270,24 +1279,29 @@ namespace System.Drawing
 
                        return new Graphics (graphics);
                }
-
-               [MonoTODO]
+               
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                public static Graphics FromHwndInternal (IntPtr hwnd)
                {
-                       throw new NotImplementedException ();
+                       return FromHwnd (hwnd);
                }
 
                public static Graphics FromImage (Image image)
                {
-                       if (image == null) throw new ArgumentException ();
+                       IntPtr graphics;
+
+                       if (image == null) 
+                               throw new ArgumentNullException ();
 
-                       int graphics;
                        Status status = GDIPlus.GdipGetImageGraphicsContext (image.nativeObject, out graphics);
                        GDIPlus.CheckStatus (status);
-                       Graphics result = new Graphics ((IntPtr) graphics);
+                       Graphics result = new Graphics (graphics);
                                
-                       if (Environment.OSVersion.Platform == (PlatformID) 128)  {
+                       // 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)) {
                                Rectangle rect  = new Rectangle (0,0, image.Width, image.Height);
                                GDIPlus.GdipSetVisibleClip_linux (result.NativeObject, ref rect);
                        }
@@ -1298,6 +1312,7 @@ namespace System.Drawing
                internal static Graphics FromXDrawable (IntPtr drawable, IntPtr display)
                {
                        IntPtr graphics;
+
                        Status s = GDIPlus.GdipCreateFromXDrawable_linux (drawable, display, out graphics);
                        GDIPlus.CheckStatus (s);
                        return new Graphics (graphics);
@@ -1309,15 +1324,12 @@ namespace System.Drawing
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                [EditorBrowsable (EditorBrowsableState.Advanced)]
                public IntPtr GetHdc ()
                {
-                       int hdc;
-                       Status status = GDIPlus.GdipGetDC (nativeObject, out hdc);
-                       GDIPlus.CheckStatus (status);
-
-                       return (IntPtr) hdc;
+                       IntPtr hdc;
+                       GDIPlus.CheckStatus (GDIPlus.GdipGetDC (this.nativeObject, out hdc));
+                       return hdc;
                }
 
                
@@ -1422,8 +1434,8 @@ namespace System.Drawing
                        
                        for (int i = 0; i < regcount; i++) {
                                regions[i] = new Region ();
-                               native_regions[i] = regions[i].NativeObject;                            
-                       }                                                                                               
+                               native_regions[i] = regions[i].NativeObject;
+                       }
                        
                        status =  GDIPlus.GdipMeasureCharacterRanges (nativeObject, text, text.Length,
                                font.NativeObject, ref layoutRect, stringFormat.NativeObject, 
@@ -1437,22 +1449,30 @@ namespace System.Drawing
                
                public SizeF MeasureString (string text, Font font)
                {
-                       return MeasureString (text, font, new Size(0,0));
+                       return MeasureString (text, font, new Size (0, 0));
                }
 
                
                public SizeF MeasureString (string text, Font font, SizeF layoutArea)
                {
-                       int charactersFitted, linesFilled;                      
+                       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);
+                       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");
+
+                       Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length,
+                                                                  font.NativeObject, ref rect,
+                                                                  IntPtr.Zero, out boundingBox,
+                                                                  out charactersFitted, out linesFilled);
                        GDIPlus.CheckStatus (status);
 
-                       return new SizeF(boundingBox.Width, boundingBox.Height);
+                       return new SizeF (boundingBox.Width, boundingBox.Height);
                }
 
                
@@ -1462,19 +1482,28 @@ namespace System.Drawing
                        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");
+
                        Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
-                               font.NativeObject, ref rect, IntPtr.Zero, 
-                               out boundingBox, out charactersFitted, out linesFilled);
+                                                                  font.NativeObject, ref rect,
+                                                                  IntPtr.Zero, out boundingBox,
+                                                                  out charactersFitted, out linesFilled);
                        GDIPlus.CheckStatus (status);
 
                        return new SizeF (boundingBox.Width, boundingBox.Height);
                }
 
                
-               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);
+                       return MeasureString (text, font, layoutArea, stringFormat,
+                                             out charactersFitted, out linesFilled);
                }
 
                
@@ -1482,32 +1511,62 @@ namespace System.Drawing
                {
                        int charactersFitted, linesFilled;                      
                        return MeasureString (text, font, new SizeF (width, 999999), 
-                               format, out charactersFitted, out linesFilled);
+                                             format, out charactersFitted, out linesFilled);
                }
 
                
-               public SizeF MeasureString (string text, Font font, PointF origin, StringFormat stringFormat)
+               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);
+                       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 ();
+
                        Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
-                               font.NativeObject, ref rect, stringFormat.NativeObject, 
-                               out boundingBox, out charactersFitted, out linesFilled);
+                                                                  font.NativeObject, ref rect,
+                                                                  stringFormat.NativeObject, 
+                                                                  out boundingBox,
+                                                                  out charactersFitted,
+                                                                  out linesFilled);
                        GDIPlus.CheckStatus (status);
 
                        return new SizeF (boundingBox.Width, boundingBox.Height);
                }
 
                
-               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)
                {       
                        RectangleF boundingBox = new RectangleF ();
-                       RectangleF rect = new RectangleF (0,0,layoutArea.Width, layoutArea.Height);
+                       RectangleF rect = new RectangleF (0, 0, layoutArea.Width, layoutArea.Height);
+                       charactersFitted = 0;
+                       linesFilled = 0;
+
+                       if (text == null || text.Length == 0)
+                               return SizeF.Empty;
+
+                       if (font == null)
+                               throw new ArgumentNullException ("font");
+
+                       if (stringFormat == null)
+                               stringFormat = new StringFormat ();
+
                        Status status = GDIPlus.GdipMeasureString (nativeObject, text, text.Length, 
-                               font.NativeObject, ref rect, stringFormat.NativeObject,
-                               out boundingBox, out charactersFitted, out linesFilled);
+                                                                  font.NativeObject, ref rect,
+                                                                  stringFormat.NativeObject,
+                                                                  out boundingBox,
+                                                                  out charactersFitted,
+                                                                  out linesFilled);
                        GDIPlus.CheckStatus (status);
 
                        return new SizeF (boundingBox.Width, boundingBox.Height);
@@ -1520,7 +1579,9 @@ namespace System.Drawing
 
                public void MultiplyTransform (Matrix matrix, MatrixOrder order)
                {
-                       Status status = GDIPlus.GdipMultiplyWorldTransform (nativeObject, matrix.nativeMatrix, order);
+                       Status status = GDIPlus.GdipMultiplyWorldTransform (nativeObject,
+                                                                           matrix.nativeMatrix,
+                                                                           order);
                        GDIPlus.CheckStatus (status);
                }
 
@@ -1533,6 +1594,7 @@ namespace System.Drawing
 
                [MonoTODO]
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                public void ReleaseHdcInternal (IntPtr hdc)
                {
                        throw new NotImplementedException ();
@@ -1552,8 +1614,7 @@ namespace System.Drawing
                }
 
                public void Restore (GraphicsState gstate)
-               {
-                       Transform = gstate.matrix.Clone ();
+               {                       
                        Status status = GDIPlus.GdipRestoreGraphics (nativeObject, gstate.nativeState);
                        GDIPlus.CheckStatus (status);
                }
@@ -1572,13 +1633,12 @@ namespace System.Drawing
                }
 
                public GraphicsState Save ()
-               {
-                       GraphicsState state = new GraphicsState ();
-                       state.matrix = Transform.Clone ();
+               {                                               
                        uint saveState;
                        Status status = GDIPlus.GdipSaveGraphics (nativeObject, out saveState);
                        GDIPlus.CheckStatus (status);
 
+                       GraphicsState state = new GraphicsState ();
                        state.nativeState = saveState;
                        return state;
                }