[winforms] Style
[mono.git] / mcs / class / System.Drawing / System.Drawing / Bitmap.cs
old mode 100755 (executable)
new mode 100644 (file)
index 5f0156c..d88c3e1
@@ -13,7 +13,7 @@
 //
 
 //
-// 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
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
 using System.IO;
 using System.Drawing.Imaging;
 using System.Runtime.Serialization;
 using System.Runtime.InteropServices;
 using System.ComponentModel;
+using System.Security.Permissions;
 
 namespace System.Drawing
 {
@@ -51,22 +51,43 @@ namespace System.Drawing
        {
                #region constructors
                // constructors
+
+#if NET_2_0
+               // required for XmlSerializer (#323246)
+               private Bitmap ()
+               {
+               }
+#endif
+
                internal Bitmap (IntPtr ptr)
                {
                        nativeObject = ptr;
                }
 
+               // Usually called when cloning images that need to have
+               // not only the handle saved, but also the underlying stream
+               // (when using MS GDI+ and IStream we must ensure the stream stays alive for all the life of the Image)
+               internal Bitmap(IntPtr ptr, Stream stream)
+               {
+                       // under Win32 stream is owned by SD/GDI+ code
+                       if (GDIPlus.RunningOnWindows ())
+                               this.stream = stream;
+                       nativeObject = ptr;
+               }
+
                public Bitmap (int width, int height) : this (width, height, PixelFormat.Format32bppArgb)
                {
-                       
                }
 
                public Bitmap (int width, int height, Graphics g)
-               {               
+               {
+                       if (g == null)
+                               throw new ArgumentNullException ("g");
+
                        IntPtr bmp;
                        Status s = GDIPlus.GdipCreateBitmapFromGraphics (width, height, g.nativeObject, out bmp);
                        GDIPlus.CheckStatus (s);
-                       nativeObject = (IntPtr)bmp;                                             
+                       nativeObject = bmp;                                             
                }
 
                public Bitmap (int width, int height, PixelFormat format)
@@ -74,101 +95,64 @@ namespace System.Drawing
                        IntPtr bmp;
                        Status s = GDIPlus.GdipCreateBitmapFromScan0 (width, height, 0, format, IntPtr.Zero, out bmp);
                        GDIPlus.CheckStatus (s);
-                       nativeObject = (IntPtr) bmp;
+                       nativeObject = bmp;
                        
                }
 
-               public Bitmap (Image original) : this (original.Width, original.Height, PixelFormat.Format32bppArgb)
-               {
-                       BitmapFromImage(original, original.Size);
-               }
+               public Bitmap (Image original) : this (original, original.Width, original.Height) {}
 
                public Bitmap (Stream stream)  : this (stream, false) {} 
 
                public Bitmap (string filename) : this (filename, false) {}
 
-               public Bitmap (Image original, Size newSize)  : this (newSize.Width, newSize.Height, PixelFormat.Format32bppArgb)
-               {                       
-                       Status          status;
-                       Graphics        g;
-
-                       g=Graphics.FromImage(this);
-
-                       status = GDIPlus.GdipDrawImageRectRectI(g.nativeObject, original.nativeObject,
-                               0, 0, newSize.Width, newSize.Height,
-                               0, 0, original.Width, original.Height,
-                               GraphicsUnit.Pixel, IntPtr.Zero, null, IntPtr.Zero);
-                       GDIPlus.CheckStatus (status);
-
-                       g.Dispose();
-               }
-               
-               internal Bitmap (int width, int height, PixelFormat pixel, IntPtr bmp)
-               {                       
-                       nativeObject = (IntPtr)bmp;                                             
-               }
-               
-               internal Bitmap (float width, float height, PixelFormat pixel, IntPtr bmp)
-               {                       
-                       nativeObject = (IntPtr)bmp;                     
-                       
-               }
+               public Bitmap (Image original, Size newSize)  : this(original, newSize.Width, newSize.Height) {}
                
-               internal void BitmapFromImage(Image original, Size newSize){
-                       
-                       if (original is Bitmap) {
-                               
-                               if (nativeObject!=IntPtr.Zero) 
-                                       Dispose();
-                               
-                               Bitmap bmpOriginal = (Bitmap) original;
-                                       
-                               IntPtr bmp;
-                               Status s = GDIPlus.GdipCloneBitmapAreaI (0, 0, newSize.Width, newSize.Height, bmpOriginal.PixelFormat, bmpOriginal.nativeObject, out bmp);
-                               GDIPlus.CheckStatus (s);
-                               nativeObject = (IntPtr) bmp;
-                               
-                       }
-                       else {
-                               throw new NotImplementedException ();
-                       }
-               }
-
-               void InitFromFile (string filename)
-               {               
-                       IntPtr imagePtr;
-                       Status st = GDIPlus.GdipLoadImageFromFile (filename, out imagePtr);
-                       GDIPlus.CheckStatus (st);
-                       nativeObject = imagePtr;                        
-               }
-
                public Bitmap (Stream stream, bool useIcm)
                {
-                       InitFromStream (stream);
+                       // false: stream is owned by user code
+                       nativeObject = InitFromStream (stream);
                }
 
                public Bitmap (string filename, bool useIcm)
                {
-                       InitFromFile (filename);
+                       if (filename == null)
+                               throw new ArgumentNullException ("filename");
+
+                       IntPtr imagePtr;
+                       Status st;
+
+                       if (useIcm)
+                               st = GDIPlus.GdipCreateBitmapFromFileICM (filename, out imagePtr);
+                       else
+                               st = GDIPlus.GdipCreateBitmapFromFile (filename, out imagePtr);
+
+                       GDIPlus.CheckStatus (st);
+                       nativeObject = imagePtr;
                }
 
                public Bitmap (Type type, string resource)
                {
-                       using (Stream s = type.Assembly.GetManifestResourceStream (resource)){
-                               if (s == null)
-                                       throw new FileNotFoundException ("Resource name was not found: `" + resource + "'");
+                       if (resource == null)
+                               throw new ArgumentException ("resource");
 
-                               InitFromStream (s);
+                       Stream s = type.Assembly.GetManifestResourceStream (type, resource);
+                       if (s == null) {
+                               string msg = Locale.GetText ("Resource '{0}' was not found.", resource);
+                               throw new FileNotFoundException (msg);
                        }
+
+                       nativeObject = InitFromStream (s);
+                       // under Win32 stream is owned by SD/GDI+ code
+                       if (GDIPlus.RunningOnWindows ())
+                               stream = s;
                }
 
-               public Bitmap (Image original, int width, int heigth) 
+               public Bitmap (Image original, int width, int height)  : this(width, height, PixelFormat.Format32bppArgb)
                {
-                       Size newSize = new Size();
-                       newSize.Height=heigth;
-                       newSize.Width=width;
-                       
-                       BitmapFromImage(original,newSize);
+                       Graphics graphics = Graphics.FromImage(this);
+
+                       graphics.DrawImage(original, 0, 0, width, height);
+                       graphics.Dispose();
                }
 
                public Bitmap (int width, int height, int stride, PixelFormat format, IntPtr scan0)
@@ -177,27 +161,13 @@ namespace System.Drawing
                                
                        Status status = GDIPlus.GdipCreateBitmapFromScan0 (width, height, stride, format, scan0, out bmp);
                        GDIPlus.CheckStatus (status);   
-                       nativeObject = (IntPtr) bmp;                                                                                                            
+                       nativeObject = bmp;                                                                                                             
                }
 
                private Bitmap (SerializationInfo info, StreamingContext context)
+                       : base (info, context)
                {
-                       foreach (SerializationEntry serEnum in info) {
-                               if (String.Compare(serEnum.Name, "Data", true) == 0) {
-                                       byte[] bytes = (byte[]) serEnum.Value;
-               
-                                       if (bytes != null) {
-                                               InitFromStream(new MemoryStream(bytes));
-                                       }
-                               }
-                       }
                }
-               //The below function is not required. Call should resolve to base
-               //Moreover there is a problem with the declaration. Base class function
-               //is not declared as protected to access in descendent class
-               /*private Bitmap (SerializationInfo info, StreamingContext context) : base(info, context)
-               {
-               }*/
 
                #endregion
                // methods
@@ -212,61 +182,66 @@ namespace System.Drawing
                }
 
                public void SetPixel (int x, int y, Color color)
-               {                                                                       
-                       Status s = GDIPlus.GdipBitmapSetPixel(nativeObject, x, y, color.ToArgb());
+               {
+                       Status s = GDIPlus.GdipBitmapSetPixel (nativeObject, x, y, color.ToArgb ());
+                       if (s == Status.InvalidParameter) {
+                               // check is done in case of an error only to avoid another
+                               // unmanaged call for normal (successful) calls
+                               if ((this.PixelFormat & PixelFormat.Indexed) != 0) {
+                                       string msg = Locale.GetText ("SetPixel cannot be called on indexed bitmaps.");
+#if NET_2_0
+                                       throw new InvalidOperationException (msg);
+#else
+                                       throw new Exception (msg);
+#endif
+                               }
+                       }
                        GDIPlus.CheckStatus (s);
                }
 
-               public Bitmap Clone (Rectangle rect,PixelFormat format)
+               public Bitmap Clone (Rectangle rect, PixelFormat format)
                {                               
                        IntPtr bmp;                     
-                       Status status = GDIPlus.GdipCloneBitmapAreaI(rect.X, rect.Top, rect.Width, rect.Height,
-                               PixelFormat, nativeObject,  out bmp);
-                               
+                       Status status = GDIPlus.GdipCloneBitmapAreaI (rect.X, rect.Y, rect.Width, rect.Height,
+                               format, nativeObject, out bmp);
                        GDIPlus.CheckStatus (status);
-
-                       Bitmap bmpnew = new Bitmap (rect.Width, rect.Height,  PixelFormat, (IntPtr) bmp);
-                               return bmpnew;
+                       return new Bitmap (bmp);
                        }
                
                public Bitmap Clone (RectangleF rect, PixelFormat format)
                {
                        IntPtr bmp;                     
-                       Status status = GDIPlus.GdipCloneBitmapArea (rect.X, rect.Top, rect.Width, rect.Height,
-                               PixelFormat, nativeObject,  out bmp);
+                       Status status = GDIPlus.GdipCloneBitmapArea (rect.X, rect.Y, rect.Width, rect.Height,
+                               format, nativeObject, out bmp);
                        GDIPlus.CheckStatus (status);
-
-                       Bitmap bmpnew = new Bitmap (rect.Width, rect.Height,  PixelFormat, (IntPtr) bmp);
-                       return bmpnew;
+                       return new Bitmap (bmp);
                }
 
-               public static Bitmap FromHicon (IntPtr hicon)   //TODO: Untested
+               public static Bitmap FromHicon (IntPtr hicon)
                {       
                        IntPtr bitmap;  
-                               
                        Status status = GDIPlus.GdipCreateBitmapFromHICON (hicon, out bitmap);
                        GDIPlus.CheckStatus (status);
-
-                       return new Bitmap (0,0, PixelFormat.Format32bppArgb, bitmap);   // FIXME
+                       return new Bitmap (bitmap);
                }
 
                public static Bitmap FromResource (IntPtr hinstance, string bitmapName) //TODO: Untested
                {
                        IntPtr bitmap;  
-                               
                        Status status = GDIPlus.GdipCreateBitmapFromResource (hinstance, bitmapName, out bitmap);
                        GDIPlus.CheckStatus (status);
-
-                       return new Bitmap (0,0, PixelFormat.Format32bppArgb, bitmap); // FIXME
+                       return new Bitmap (bitmap);
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                public IntPtr GetHbitmap ()
                {
                        return GetHbitmap(Color.Gray);
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                public IntPtr GetHbitmap (Color background)
                {
                        IntPtr HandleBmp;
@@ -278,6 +253,7 @@ namespace System.Drawing
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                public IntPtr GetHicon ()
                {
                        IntPtr HandleIcon;
@@ -291,21 +267,19 @@ namespace System.Drawing
                public BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format)
                {
                        BitmapData result = new BitmapData();
+                       return LockBits (rect, flags, format, result);
+               }
 
-                       if (nativeObject == (IntPtr) 0)
-                               throw new Exception ("nativeObject is null");                   
-                       
-                       IntPtr lfBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(result));
-                       Marshal.StructureToPtr(result, lfBuffer, false);                                                
-               
-                       Status status = GDIPlus.GdipBitmapLockBits (nativeObject, ref rect, flags, format,  lfBuffer);
-                       
-                       result = (BitmapData) Marshal.PtrToStructure(lfBuffer,  typeof(BitmapData));                                                                                    
-                       Marshal.FreeHGlobal (lfBuffer);                 
+#if NET_2_0
+               public
+#endif
+               BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
+               {
+                       Status status = GDIPlus.GdipBitmapLockBits (nativeObject, ref rect, flags, format, bitmapData);
                        //NOTE: scan0 points to piece of memory allocated in the unmanaged space
                        GDIPlus.CheckStatus (status);
 
-                       return  result;
+                       return bitmapData;
                }
 
                public void MakeTransparent ()
@@ -319,18 +293,17 @@ namespace System.Drawing
                        // We have to draw always over a 32-bitmap surface that supports alpha channel
                        Bitmap  bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
                        Graphics gr = Graphics.FromImage(bmp);
-                       Rectangle destRect = new Rectangle(0,0, Width, Height);
+                       Rectangle destRect = new Rectangle(0, 0, Width, Height);
                        ImageAttributes imageAttr = new ImageAttributes();
                        
                        imageAttr.SetColorKey(transparentColor, transparentColor);
 
-                       gr.DrawImage (this, destRect, 0, 0, Width, Height,      GraphicsUnit.Pixel, imageAttr);                                 
-                       
-                       Size newSize = new Size();
-                       newSize.Height=Height;
-                       newSize.Width=Width;                    
-                       BitmapFromImage(bmp,newSize);                   
+                       gr.DrawImage (this, destRect, 0, 0, Width, Height, GraphicsUnit.Pixel, imageAttr);                                      
                        
+                       IntPtr oldBmp = nativeObject;
+                       nativeObject = bmp.nativeObject;
+                       bmp.nativeObject = oldBmp;
+
                        gr.Dispose();
                        bmp.Dispose();
                        imageAttr.Dispose();
@@ -342,9 +315,9 @@ namespace System.Drawing
                        GDIPlus.CheckStatus (status);
                }
 
-               public void UnlockBits (BitmapData bitmap_data)
+               public void UnlockBits (BitmapData bitmapdata)
                {
-                       Status status = GDIPlus.GdipBitmapUnlockBits (nativeObject, bitmap_data);
+                       Status status = GDIPlus.GdipBitmapUnlockBits (nativeObject, bitmapdata);
                        GDIPlus.CheckStatus (status);
                }
        }