From: Andreia Gaita Date: Fri, 21 Nov 2008 05:39:11 +0000 (-0000) Subject: * System.Drawing/Image.cs: On win32, when cloning images initialized from X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=0605c47f81b64506d24a11415a2e72381b71e8e1;p=mono.git * System.Drawing/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). * 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 svn path=/trunk/mcs/; revision=119580 --- diff --git a/mcs/class/System.Drawing/System.Drawing.Imaging/ChangeLog b/mcs/class/System.Drawing/System.Drawing.Imaging/ChangeLog index 80c244e6cdf..c4bf92b1ae7 100644 --- a/mcs/class/System.Drawing/System.Drawing.Imaging/ChangeLog +++ b/mcs/class/System.Drawing/System.Drawing.Imaging/ChangeLog @@ -1,3 +1,8 @@ +2008-11-21 Andreia Gaita + + * Metafile.cs: Save the underlying stream when creating from a + clone under win32 (fixes #438886) + 2008-10-12 Sebastien Pouliot * ColorPalette.cs, ImageFormat.cs: Remove unneeded field diff --git a/mcs/class/System.Drawing/System.Drawing.Imaging/Metafile.cs b/mcs/class/System.Drawing/System.Drawing.Imaging/Metafile.cs index 0f89d2c784e..db519eda901 100644 --- a/mcs/class/System.Drawing/System.Drawing.Imaging/Metafile.cs +++ b/mcs/class/System.Drawing/System.Drawing.Imaging/Metafile.cs @@ -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) diff --git a/mcs/class/System.Drawing/System.Drawing/Bitmap.cs b/mcs/class/System.Drawing/System.Drawing/Bitmap.cs index a500086e9b9..d88c3e129f5 100644 --- a/mcs/class/System.Drawing/System.Drawing/Bitmap.cs +++ b/mcs/class/System.Drawing/System.Drawing/Bitmap.cs @@ -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) { } diff --git a/mcs/class/System.Drawing/System.Drawing/ChangeLog b/mcs/class/System.Drawing/System.Drawing/ChangeLog index 9af525598a5..4f4119642e3 100644 --- a/mcs/class/System.Drawing/System.Drawing/ChangeLog +++ b/mcs/class/System.Drawing/System.Drawing/ChangeLog @@ -1,3 +1,15 @@ +2008-11-21 Andreia Gaita + + * 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 * Font.cs: Add comment on .ctor(Font,FontStyle) about the lack of diff --git a/mcs/class/System.Drawing/System.Drawing/Image.cs b/mcs/class/System.Drawing/System.Drawing/Image.cs index 9c8eed41949..0c9a0694db0 100644 --- a/mcs/class/System.Drawing/System.Drawing/Image.cs +++ b/mcs/class/System.Drawing/System.Drawing/Image.cs @@ -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); + } + } }