* System.Drawing/Image.cs: On win32, when cloning images initialized from
authorAndreia Gaita <avidigal@novell.com>
Fri, 21 Nov 2008 05:39:11 +0000 (05:39 -0000)
committerAndreia Gaita <avidigal@novell.com>
Fri, 21 Nov 2008 05:39:11 +0000 (05:39 -0000)
  resources, also clone the underlying stream, since it needs to stay
  around for the life of the image (gdi doesn't clone the underlying
  stream when cloning images, so when the gc disposes the original, it
  will also dispose the stream, which invalidates the clone).

* System.Drawing/Bitmap.cs: Save the underlying stream when creating bitmaps from a
  clone under win32

* System.Drawing.Imaging/Metafile.cs: Save the underlying stream when creating from a
  clone under win32

  [fixes #438886]

2008-11-21  Andreia Gaita  <shana@jitted.com>

svn path=/trunk/mcs/; revision=119580

mcs/class/System.Drawing/System.Drawing.Imaging/ChangeLog
mcs/class/System.Drawing/System.Drawing.Imaging/Metafile.cs
mcs/class/System.Drawing/System.Drawing/Bitmap.cs
mcs/class/System.Drawing/System.Drawing/ChangeLog
mcs/class/System.Drawing/System.Drawing/Image.cs

index 80c244e6cdfc5ccea86337f0381326ec1beb453f..c4bf92b1ae7fe341f26cd637632c31978bf5f9f9 100644 (file)
@@ -1,3 +1,8 @@
+2008-11-21  Andreia Gaita  <shana@jitted.com>
+
+       * Metafile.cs: Save the underlying stream when creating from a
+       clone under win32 (fixes #438886)
+
 2008-10-12  Sebastien Pouliot  <sebastien@ximian.com>
 
        * ColorPalette.cs, ImageFormat.cs: Remove unneeded field 
index 0f89d2c784efe6ae17c1838bfb356a699a6f6d7e..db519eda9019eda259dc18047bb2123d35caa124 100644 (file)
@@ -51,6 +51,17 @@ namespace System.Drawing.Imaging {
                        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 Metafile (IntPtr ptr, Stream stream)
+               {
+                       // under Win32 stream is owned by SD/GDI+ code
+                       if (GDIPlus.RunningOnWindows ())
+                               this.stream = stream;
+                       nativeObject = ptr;
+               }
+
                public Metafile (Stream stream) 
                {
                        if (stream == null)
index a500086e9b9e2bdb05dc99cb3debe0a062086219..d88c3e129f51b24ae3f22a485c32b3e5d8cdaf91 100644 (file)
@@ -64,6 +64,17 @@ namespace System.Drawing
                        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)
                {
                }
index 9af525598a5fae4eec724f374f4d6b5208591a0e..4f4119642e3973cc252f4f08689d48fe67de2344 100644 (file)
@@ -1,3 +1,15 @@
+2008-11-21  Andreia Gaita  <shana@jitted.com>
+
+       * Image.cs: On win32, when cloning images initialized from
+       resources, also clone the underlying stream, since it needs to stay
+       around for the life of the image (gdi doesn't clone the underlying
+       stream when cloning images, so when the gc disposes the original, it
+       will also dispose the stream, which invalidates the clone).
+
+       * Bitmap.cs: Save the underlying stream when creating bitmaps from a
+       clone under win32
+       [fixes #438886]
+
 2008-11-01  Sebastien Pouliot  <sebastien@ximian.com>
 
        * Font.cs: Add comment on .ctor(Font,FontStyle) about the lack of
index 9c8eed41949b6ac23189a6f7293617399ae2b966..0c9a0694db0d05463a57d4ff6c04e0c820eb27ff 100644 (file)
@@ -811,15 +811,43 @@ public abstract class Image : MarshalByRefObject, IDisposable , ICloneable, ISer
        
        public object Clone ()
        {
+               if (GDIPlus.RunningOnWindows () && stream != null)
+                       return CloneFromStream ();
+
                IntPtr newimage = IntPtr.Zero;
-               Status status = GDIPlus.GdipCloneImage (NativeObject, out newimage);                    
-               GDIPlus.CheckStatus (status);                   
+               Status status = GDIPlus.GdipCloneImage (NativeObject, out newimage);
+               GDIPlus.CheckStatus (status);
 
                if (this is Bitmap)
                        return new Bitmap (newimage);
                else
                        return new Metafile (newimage);
        }
+
+       // On win32, when cloning images that were originally created from a stream, we need to
+       // clone both the image and the stream to make sure the gc doesn't kill it
+       // (when using MS GDI+ and IStream we must ensure the stream stays alive for all the life of the Image)
+       object CloneFromStream ()
+       {
+               byte[] bytes = new byte [stream.Length];
+               MemoryStream ms = new MemoryStream (bytes);
+               int count = (stream.Length < 4096 ? (int) stream.Length : 4096);
+               byte[] buffer = new byte[count];
+               stream.Position = 0;
+               do {
+                       count = stream.Read (buffer, 0, count);
+                       ms.Write (buffer, 0, count);
+               } while (count == 4096);
+
+               IntPtr newimage = IntPtr.Zero;
+               newimage = InitFromStream (ms);
+
+               if (this is Bitmap)
+                       return new Bitmap (newimage, ms);
+               else
+                       return new Metafile (newimage, ms);
+       }
+
 }
 
 }