From 00e8af10cccc66709fbcdffdf89bd1ac1c059c51 Mon Sep 17 00:00:00 2001 From: Mike Kestner Date: Sat, 23 Feb 2008 04:20:02 +0000 Subject: [PATCH] 2008-02-22 Mike Kestner * gdk/Pixbuf.custom: add destroy notification and pin byte[] to avoid GC complications. Add a couple new convenience ctors as well. svn path=/trunk/gtk-sharp/; revision=96460 --- ChangeLog | 6 ++++++ gdk/Pixbuf.custom | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b02c47ea7..68506dd8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-02-22 Mike Kestner + + * gdk/Pixbuf.custom: add destroy notification and pin byte[] to + avoid GC complications. Add a couple new convenience ctors as + well. + 2008-02-21 Mike Kestner * glib/Source.cs: rework proxy removal to avoid boxing profile. diff --git a/gdk/Pixbuf.custom b/gdk/Pixbuf.custom index 7cf3d5b9d..ad01b1895 100644 --- a/gdk/Pixbuf.custom +++ b/gdk/Pixbuf.custom @@ -175,6 +175,37 @@ return ret; } + class DestroyHelper { + + GCHandle gch; + GCHandle data_handle; + PixbufDestroyNotify notify; + + public DestroyHelper (byte[] data, PixbufDestroyNotify notify) + { + gch = GCHandle.Alloc (this); + data_handle = GCHandle.Alloc (data, GCHandleType.Pinned); + this.notify = notify; + } + + void ReleaseHandles (byte[] data) + { + data_handle.Free (); + if (notify != null) + notify (data); + gch.Free (); + } + + PixbufDestroyNotify handler; + public PixbufDestroyNotify Handler { + get { + if (handler == null) + handler = new PixbufDestroyNotify (ReleaseHandles); + return handler; + } + } + } + [DllImport("libgdk_pixbuf-2.0-0.dll")] static extern IntPtr gdk_pixbuf_new_from_data(byte[] data, int colorspace, bool has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkSharp.PixbufDestroyNotifyNative destroy_fn, IntPtr destroy_fn_data); @@ -183,7 +214,8 @@ if (GetType () != typeof (Pixbuf)) { throw new InvalidOperationException ("Can't override this constructor."); } - GdkSharp.PixbufDestroyNotifyWrapper destroy_fn_wrapper = new GdkSharp.PixbufDestroyNotifyWrapper (destroy_fn); + DestroyHelper helper = new DestroyHelper (data, destroy_fn); + GdkSharp.PixbufDestroyNotifyWrapper destroy_fn_wrapper = new GdkSharp.PixbufDestroyNotifyWrapper (helper.Handler); Raw = gdk_pixbuf_new_from_data(data, (int) colorspace, has_alpha, bits_per_sample, width, height, rowstride, destroy_fn_wrapper.NativeDelegate, IntPtr.Zero); PersistentData ["new_from_data_destroy_fn_wrapper"] = destroy_fn_wrapper; } @@ -191,6 +223,10 @@ // overload to default the colorspace public Pixbuf(byte [] data, bool has_alpha, int bits_per_sample, int width, int height, int rowstride, Gdk.PixbufDestroyNotify destroy_fn) : this (data, Gdk.Colorspace.Rgb, has_alpha, bits_per_sample, width, height, rowstride, destroy_fn) {} + public Pixbuf(byte [] data, bool has_alpha, int bits_per_sample, int width, int height, int rowstride) : this (data, Gdk.Colorspace.Rgb, has_alpha, bits_per_sample, width, height, rowstride, null) {} + + public Pixbuf(byte [] data, Gdk.Colorspace colorspace, bool has_alpha, int bits_per_sample, int width, int height, int rowstride) : this (data, colorspace, has_alpha, bits_per_sample, width, height, rowstride, null) {} + public unsafe Pixbuf(byte[] data, bool copy_pixels) : base (IntPtr.Zero) { IntPtr error = IntPtr.Zero;