diff --git a/CHANGELOG.md b/CHANGELOG.md index a5292a67..f780a26f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,25 @@ # Changelog -All notable changes to this project will be documented in this file. +All notable changes to NetVips will be documented in this file. See [here](CHANGELOG.native.md) for the changes to the [pre-compiled binaries of libvips](https://www.nuget.org/packages/NetVips.Native/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.1.0] - ??? +## [1.1.0] - Unreleased ### Added -- Pre-compiled libvips binaries for a few distros ([#21](https://github.com/kleisauke/net-vips/issues/21)): - - [NetVips.Native.linux-x64](https://www.nuget.org/packages/NetVips.Native.linux-x64) - Linux x64 glibc (Ubuntu, Debian, etc). - - [NetVips.Native.linux-musl-x64](https://www.nuget.org/packages/NetVips.Native.linux-musl-x64) - Linux x64 musl (Alpine, Gentoo Linux, etc). - - [NetVips.Native.osx-x64](https://www.nuget.org/packages/NetVips.Native.osx-x64) - macOS x64. +- A new [NetVips.Native](https://www.nuget.org/packages/NetVips.Native/) package containing the pre-compiled libvips binaries for Linux, macOS and Windows ([#21](https://github.com/kleisauke/net-vips/issues/21)). + - Changes to the [NetVips.Native.*](https://www.nuget.org/packages?q=id%3ANetVips.Native) packages will be documented [here](CHANGELOG.native.md). +- Add `Base.GetSuffixes()` to get a list of all the filename suffixes supported by libvips ([libvips/ruby-vips#186](https://github.com/libvips/ruby-vips/issues/186)). +- Add support for progress feedback (`image.SetProgress()`) and signal handling (`image.SignalConnect()`) ([#31](https://github.com/kleisauke/net-vips/issues/31)). +- Add `image.SetKill()` and `image.IsKilled()` ([#31](https://github.com/kleisauke/net-vips/issues/31), [libvips/libvips@91d0e7e](https://github.com/libvips/libvips/commit/91d0e7e3d06fe6293f8e7513f30fd21585ea4305)). ### Changed - Improve memory management ([#26](https://github.com/kleisauke/net-vips/issues/26)). -- The bundled libvips Windows binaries were split into different NuGet packages: - - [NetVips.Native.win-x64](https://www.nuget.org/packages/NetVips.Native.win-x64) - Windows 64-bit. - - [NetVips.Native.win-x86](https://www.nuget.org/packages/NetVips.Native.win-x86) - Windows 32-bit. +- The bundled libvips Windows binaries were moved to the [NetVips.Native](https://www.nuget.org/packages/NetVips.Native/) package. - Update the [NetVips.Benchmarks](https://github.com/kleisauke/net-vips/tree/master/tests/NetVips.Benchmarks). -- A statically linked libvips binary is build for Windows. This reduces the number of DLLs from 37 to 3 ([libvips/build-win64#21](https://github.com/libvips/build-win64/issues/21#issuecomment-458112440)). +- The overloadable operators `==` and `!=` have been changed to `Equal` and `NotEqual` to avoid conflicts with `null` checks. +- Some methods are overloaded instead of defining the parameters as `object` type. ### Removed -- The `UseGlobalLibvips` property since the bundled libvips binaries are split into different NuGet packages. +- The `UseGlobalLibvips` property since the bundled libvips binaries were moved to the [NetVips.Native](https://www.nuget.org/packages/NetVips.Native/) package. ## [1.0.7] - 2019-01-18 ### Changed @@ -85,7 +85,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Added - First release! -[1.1.0]: https://github.com/kleisauke/net-vips/compare/v1.0.7...v1.1.0 +[1.1.0]: https://github.com/kleisauke/net-vips/compare/v1.0.7...1.1.0 [1.0.7]: https://github.com/kleisauke/net-vips/compare/v1.0.6...v1.0.7 [1.0.6]: https://github.com/kleisauke/net-vips/compare/v1.0.5...v1.0.6 [1.0.5]: https://github.com/kleisauke/net-vips/compare/v1.0.4...v1.0.5 diff --git a/CHANGELOG.native.md b/CHANGELOG.native.md new file mode 100644 index 00000000..fc5ce1b8 --- /dev/null +++ b/CHANGELOG.native.md @@ -0,0 +1,33 @@ +# Changelog +All notable changes to the pre-compiled binaries of libvips will be documented in this file. The version number of these NuGet packages is in sync with libvips' version number. +The changes of libvips are documented [here](https://github.com/libvips/libvips/blob/master/ChangeLog). + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [8.8.0] - Unreleased +### Note +If you would like to see a complete list of all the new features, changes and bug fixes, please visit the the release notes of libvips: +https://github.com/libvips/libvips/releases + +## [8.7.4] - 2019-04-10 +### Added +- A [NetVips.Native](https://www.nuget.org/packages/NetVips.Native/) package which depends on the other [NetVips.Native.*](https://www.nuget.org/packages?q=id%3ANetVips.Native) packages. + +### Changed +- The OS X binaries are now distributed with [`jpeg-turbo`](https://github.com/libjpeg-turbo/libjpeg-turbo) instead than [`jpeg`](https://www.ijg.org/) ([lovell/package-libvips-darwin#3](https://github.com/lovell/package-libvips-darwin/pull/3)). + +## [8.7.4 beta 1] - 2019-02-25 +### Added +- Pre-compiled libvips binaries for a few distros ([#21](https://github.com/kleisauke/net-vips/issues/21)): + - [NetVips.Native.linux-x64](https://www.nuget.org/packages/NetVips.Native.linux-x64) - Linux x64 glibc (Ubuntu, Debian, etc). + - [NetVips.Native.linux-musl-x64](https://www.nuget.org/packages/NetVips.Native.linux-musl-x64) - Linux x64 musl (Alpine, Gentoo Linux, etc). + - [NetVips.Native.osx-x64](https://www.nuget.org/packages/NetVips.Native.osx-x64) - macOS x64. + - [NetVips.Native.win-x64](https://www.nuget.org/packages/NetVips.Native.win-x64) - Windows 64-bit. + - [NetVips.Native.win-x86](https://www.nuget.org/packages/NetVips.Native.win-x86) - Windows 32-bit. + +### Changed +- A statically linked libvips binary is build for Windows. This reduces the number of DLLs from 37 to 3 ([libvips/build-win64#21](https://github.com/libvips/build-win64/issues/21#issuecomment-458112440)). + +[8.8.0]: https://github.com/kleisauke/libvips-packaging/compare/v8.7.4...HEAD +[8.7.4]: https://github.com/kleisauke/libvips-packaging/compare/v8.7.4-beta1...v8.7.4 +[8.7.4 beta 1]: https://github.com/kleisauke/libvips-packaging/releases/tag/v8.7.4-beta1 diff --git a/documentation/docfx.json b/documentation/docfx.json index b7b8a5d9..ff1a1dfb 100644 --- a/documentation/docfx.json +++ b/documentation/docfx.json @@ -30,6 +30,10 @@ "files": "CHANGELOG.md", "src": ".." }, + { + "files": "CHANGELOG.native.md", + "src": ".." + }, { "files": [ "tutorial/**/*.{md,yml}", diff --git a/src/NetVips/ExtensionMethods.cs b/src/NetVips/ExtensionMethods.cs index 39efbfc6..c34ad4fd 100644 --- a/src/NetVips/ExtensionMethods.cs +++ b/src/NetVips/ExtensionMethods.cs @@ -252,28 +252,5 @@ internal static string ToReadableBytes(this ulong value) return $"{dValue:n2} {sizeSuffixes[i]}"; } - - /// - /// Connects a callback function () - /// to a signal for a particular . - /// - /// The instance to connect to. - /// A string of the form "signal-name::detail". - /// The to connect. - /// Data to pass to handler calls. - /// The handler id. - /// If it failed to connect the signal. - internal static uint Connect(this GObject instance, string detailedSignal, GCallback callback, - IntPtr data = default) - { - var ret = GSignal.ConnectData(instance, detailedSignal, callback, data, null, default); - - if (ret == 0) - { - throw new Exception("Failed to connect signal."); - } - - return ret; - } } } \ No newline at end of file diff --git a/src/NetVips/GObject.cs b/src/NetVips/GObject.cs index 6d8eb2f6..908f72d6 100644 --- a/src/NetVips/GObject.cs +++ b/src/NetVips/GObject.cs @@ -2,6 +2,8 @@ namespace NetVips { using System; using System.Runtime.InteropServices; + using System.Collections.Generic; + using NetVips.Internal; /// /// Manage lifetime. @@ -10,6 +12,12 @@ public class GObject : SafeHandle { // private static Logger logger = LogManager.GetCurrentClassLogger(); + /// + /// We have to record all of the delegates to + /// prevent them from being re-located or disposed of by the garbage collector. + /// + private readonly List _handles = new List(); + // Handy for debugging // public static int NObjects; @@ -32,6 +40,35 @@ internal GObject(IntPtr pointer) // logger.Debug($"GObject = {pointer}"); } + /// + /// Connects a callback function () to a signal on this object. + /// + /// + /// The callback will be triggered every time this signal is issued on this instance. + /// + /// A string of the form "signal-name::detail". + /// The callback to connect. + /// Data to pass to handler calls. + /// The handler id. + /// If it failed to connect the signal. + public uint SignalConnect(string detailedSignal, Delegate callback, IntPtr data = default) + { + // prevent the delegate from being re-located or disposed of by the garbage collector + var delegateHandle = GCHandle.Alloc(callback); + _handles.Add(delegateHandle); + + // get the pointer for the delegate which can be passed to the native code + var callbackPtr = Marshal.GetFunctionPointerForDelegate(callback); + var ret = GSignal.ConnectData(this, detailedSignal, callbackPtr, data, null, default); + + if (ret == 0) + { + throw new Exception("Failed to connect signal."); + } + + return ret; + } + /// /// Decreases the reference count of object. /// When its reference count drops to 0, the object is finalized (i.e. its memory is freed). @@ -44,6 +81,14 @@ protected override bool ReleaseHandle() if (!IsInvalid) { Internal.GObject.Unref(handle); + + // release all handles recorded by this object + foreach (var gcHandle in _handles) + { + gcHandle.Free(); + } + + _handles.Clear(); } // NObjects--; diff --git a/src/NetVips/Image.cs b/src/NetVips/Image.cs index 1b240491..35a4634b 100644 --- a/src/NetVips/Image.cs +++ b/src/NetVips/Image.cs @@ -21,11 +21,6 @@ public sealed partial class Image : VipsObject /// private GCHandle _dataHandle; - /// - /// Ref for . - /// - private GCHandle _progressHandle; - /// internal Image(IntPtr pointer) : base(pointer) @@ -1426,7 +1421,7 @@ public void SetKill(bool kill) return; } - VipsImage.SetKill(this, kill ? 1 : 0); + VipsImage.SetKill(this, kill ? 1 : 0); } /// @@ -1456,11 +1451,15 @@ public void SetKill(bool kill) public void SetProgress(IProgress progress, CancellationToken token = default) { VipsImage.SetProgress(this, progress == null ? 0 : 1); + if (progress == null) + { + return; + } var lastPercent = 0; var isKilled = false; - GCallback evalCallback = (imagePtr, progressPtr, userDataPtr) => + EvalCallback evalCallback = (imagePtr, progressPtr, userDataPtr) => { // Block evaluation on this image if a cancellation // has been requested for this token. @@ -1483,15 +1482,12 @@ public void SetProgress(IProgress progress, CancellationToken token = defau var progressStruct = progressPtr.Dereference(); if (progressStruct.Percent != lastPercent) { - progress?.Report(progressStruct.Percent); + progress.Report(progressStruct.Percent); lastPercent = progressStruct.Percent; } }; - // prevent it from being re-located or disposed of by the garbage collector - _progressHandle = GCHandle.Alloc(evalCallback); - - this.Connect(Internal.Enums.VipsEvaluation.Eval, evalCallback); + SignalConnect(Internal.Enums.VipsEvaluation.Eval, evalCallback); } #endregion @@ -1630,17 +1626,12 @@ public override int GetHashCode() /// protected override void Dispose(bool disposing) { - // release references to delegates / data objects + // release reference to our secret ref if (_dataHandle.IsAllocated) { _dataHandle.Free(); } - if (_progressHandle.IsAllocated) - { - _progressHandle.Free(); - } - // Call our base Dispose method base.Dispose(disposing); } diff --git a/src/NetVips/Internal/GObject.cs b/src/NetVips/Internal/GObject.cs index a979ae4b..d1b6cd2e 100644 --- a/src/NetVips/Internal/GObject.cs +++ b/src/NetVips/Internal/GObject.cs @@ -163,16 +163,13 @@ internal struct Struct [SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void GClosureNotify(IntPtr data, IntPtr closure); - [SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void GCallback(IntPtr gobjectPtr, IntPtr pspecPtr, IntPtr userDataPtr); - internal static class GSignal { [SuppressUnmanagedCodeSecurity] [DllImport(Libraries.GObject, CallingConvention = CallingConvention.Cdecl, EntryPoint = "g_signal_connect_data")] internal static extern uint ConnectData(NetVips.GObject instance, - [MarshalAs(UnmanagedType.LPStr)] string detailedSignal, GCallback cHandler, IntPtr data, + [MarshalAs(UnmanagedType.LPStr)] string detailedSignal, IntPtr cHandler, IntPtr data, GClosureNotify destroyData, Enums.GConnectFlags connectFlags); } } \ No newline at end of file diff --git a/src/NetVips/Internal/Vips.cs b/src/NetVips/Internal/Vips.cs index 583de79b..5802ce47 100644 --- a/src/NetVips/Internal/Vips.cs +++ b/src/NetVips/Internal/Vips.cs @@ -295,6 +295,9 @@ internal static extern void SetArrayInt(ref GValue.Struct value, internal static extern void SetArrayImage(ref GValue.Struct value, int n); } + [SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void EvalCallback(IntPtr imagePtr, IntPtr progressPtr, IntPtr userDataPtr); + internal static class VipsImage { [SuppressUnmanagedCodeSecurity] diff --git a/tests/NetVips.Tests/IoFuncsTests.cs b/tests/NetVips.Tests/IoFuncsTests.cs index 6f37d9b2..6b1657d2 100644 --- a/tests/NetVips.Tests/IoFuncsTests.cs +++ b/tests/NetVips.Tests/IoFuncsTests.cs @@ -162,15 +162,13 @@ public void TestSetProgress() var progress = new Progress(percent => { - // Tests whether the actual percentage is higher - // than the last percentage received. - Assert.True(percent > lastPercent); lastPercent = percent; }); im.SetProgress(progress); var buf = im.DzsaveBuffer("image-pyramid"); Assert.True(buf.Length > 0); + Assert.True(lastPercent <= 100); } [Fact]