CPF/CPF.Mac/Mac/CoreGraphics/CGFunction.cs
2023-11-21 23:05:03 +08:00

107 lines
3.0 KiB
C#

using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.CoreGraphics
{
public class CGFunction : INativeObject, IDisposable
{
private unsafe delegate void CGFunctionEvaluateCallback(IntPtr info, double* data, double* outData);
private struct CGFunctionCallbacks
{
public uint version;
public CGFunctionEvaluateCallback evaluate;
public IntPtr release;
}
public unsafe delegate void CGFunctionEvaluate(double* data, double* outData);
internal IntPtr handle;
private GCHandle gch;
private CGFunctionEvaluate evaluate;
public IntPtr Handle => handle;
internal CGFunction(IntPtr handle)
: this(handle, owns: false)
{
this.handle = handle;
}
[Preserve(Conditional = true)]
internal CGFunction(IntPtr handle, bool owns)
{
this.handle = handle;
if (!owns)
{
CGFunctionRetain(handle);
}
}
~CGFunction()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/CoreGraphics")]
private static extern void CGFunctionRelease(IntPtr handle);
[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/CoreGraphics")]
private static extern void CGFunctionRetain(IntPtr handle);
protected unsafe virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CGFunctionRelease(handle);
handle = IntPtr.Zero;
gch.Free();
evaluate = null;
}
}
[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/CoreGraphics")]
private static extern IntPtr CGFunctionCreate(IntPtr data, IntPtr domainCount, double[] domain, IntPtr rangeDomain, double[] range, ref CGFunctionCallbacks callbacks);
public unsafe CGFunction(double[] domain, double[] range, CGFunctionEvaluate callback)
{
if (domain != null && domain.Length % 2 != 0)
{
throw new ArgumentException("The domain array must consist of pairs of values", "domain");
}
if (range != null && range.Length % 2 != 0)
{
throw new ArgumentException("The range array must consist of pairs of values", "range");
}
if (callback == null)
{
throw new ArgumentNullException("callback");
}
evaluate = callback;
CGFunctionCallbacks callbacks = default(CGFunctionCallbacks);
callbacks.version = 0u;
callbacks.evaluate = EvaluateCallback;
callbacks.release = IntPtr.Zero;
gch = GCHandle.Alloc(this);
handle = CGFunctionCreate(GCHandle.ToIntPtr(gch), (domain != null) ? new IntPtr(domain.Length / 2) : IntPtr.Zero, domain, (range != null) ? new IntPtr(range.Length / 2) : IntPtr.Zero, range, ref callbacks);
}
private unsafe static void EvaluateCallback(IntPtr info, double* input, double* output)
{
((CGFunction)GCHandle.FromIntPtr(info).Target).evaluate(input, output);
}
}
}