Skip to content

Commit ff05795

Browse files
committed
Move conversion methods to correct places and use convenient constructors
1 parent e3757e1 commit ff05795

File tree

6 files changed

+113
-53
lines changed

6 files changed

+113
-53
lines changed

osu.Framework/Platform/Apple/Native/Interop.cs

-47
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@
22
// See the LICENCE file in the repository root for full licence text.
33

44
using System;
5-
using System.IO;
65
using System.Runtime.InteropServices;
7-
using osu.Framework.Platform.MacOS.Native;
8-
using SixLabors.ImageSharp;
9-
using SixLabors.ImageSharp.Formats.Tiff;
10-
using SixLabors.ImageSharp.PixelFormats;
116

127
namespace osu.Framework.Platform.Apple.Native
138
{
@@ -100,48 +95,6 @@ static Interop()
10095
AppKitLibrary = dlopen(LIB_APPKIT, RTLD_NOW);
10196
}
10297

103-
private static readonly IntPtr sel_utf8_string = Selector.Get("UTF8String");
104-
private static readonly IntPtr sel_tiff_representation = Selector.Get("TIFFRepresentation");
105-
106-
public static string? FromNSString(IntPtr handle) => Marshal.PtrToStringUTF8(SendIntPtr(handle, sel_utf8_string));
107-
108-
public static Image<TPixel>? FromNSImage<TPixel>(IntPtr handle)
109-
where TPixel : unmanaged, IPixel<TPixel>
110-
{
111-
if (handle == IntPtr.Zero)
112-
return null;
113-
114-
var tiffRepresentation = new NSData(SendIntPtr(handle, sel_tiff_representation));
115-
return Image.Load<TPixel>(tiffRepresentation.ToBytes());
116-
}
117-
118-
public static unsafe IntPtr ToNSString(string? str)
119-
{
120-
if (str == null)
121-
return IntPtr.Zero;
122-
123-
fixed (char* ptrFirstChar = str)
124-
{
125-
IntPtr handle = SendIntPtr(Class.Get("NSString"), Selector.Get("alloc"));
126-
return SendIntPtr(handle, Selector.Get("initWithCharacters:length:"), (IntPtr)ptrFirstChar, str.Length);
127-
}
128-
}
129-
130-
public static IntPtr ToNSImage(Image? image)
131-
{
132-
if (image == null)
133-
return IntPtr.Zero;
134-
135-
using (var stream = new MemoryStream())
136-
{
137-
image.Save(stream, TiffFormat.Instance);
138-
byte[] array = stream.ToArray();
139-
140-
IntPtr handle = SendIntPtr(Class.Get("NSImage"), Selector.Get("alloc"));
141-
return SendIntPtr(handle, Selector.Get("initWithData:"), NSData.FromBytes(array));
142-
}
143-
}
144-
14598
public static IntPtr GetStringConstant(IntPtr handle, string symbol)
14699
{
147100
IntPtr ptr = dlsym(handle, symbol);

osu.Framework/Platform/Apple/Native/NSData.cs

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77

88
namespace osu.Framework.Platform.Apple.Native
99
{
10-
internal readonly struct NSData
10+
internal readonly struct NSData : IDisposable
1111
{
1212
internal IntPtr Handle { get; }
1313

1414
private static readonly IntPtr class_pointer = Class.Get("NSData");
15+
private static readonly IntPtr sel_release = Selector.Get("release");
1516
private static readonly IntPtr sel_data_with_bytes = Selector.Get("dataWithBytes:length:");
1617
private static readonly IntPtr sel_bytes = Selector.Get("bytes");
1718
private static readonly IntPtr sel_length = Selector.Get("length");
@@ -21,6 +22,8 @@ internal NSData(IntPtr handle)
2122
Handle = handle;
2223
}
2324

25+
public static implicit operator NSData(NSMutableData data) => new NSData(data.Handle);
26+
2427
internal byte[] ToBytes()
2528
{
2629
IntPtr pointer = Interop.SendIntPtr(Handle, sel_bytes);
@@ -31,6 +34,14 @@ internal byte[] ToBytes()
3134
return bytes;
3235
}
3336

37+
internal void Release() => Interop.SendVoid(Handle, sel_release);
38+
39+
public void Dispose()
40+
{
41+
if (Handle != IntPtr.Zero)
42+
Release();
43+
}
44+
3445
internal static unsafe NSData FromBytes(ReadOnlySpan<byte> bytes)
3546
{
3647
fixed (byte* ptr = bytes)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2+
// See the LICENCE file in the repository root for full licence text.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using osu.Framework.Platform.MacOS.Native;
7+
8+
namespace osu.Framework.Platform.Apple.Native
9+
{
10+
internal readonly struct NSString
11+
{
12+
internal IntPtr Handle { get; }
13+
14+
private static readonly IntPtr class_pointer = Class.Get("NSString");
15+
private static readonly IntPtr sel_string_with_characters = Selector.Get("stringWithCharacters:length:");
16+
private static readonly IntPtr sel_utf8_string = Selector.Get("UTF8String");
17+
18+
internal NSString(IntPtr handle)
19+
{
20+
Handle = handle;
21+
}
22+
23+
public override string ToString() => Marshal.PtrToStringUTF8(Interop.SendIntPtr(Handle, sel_utf8_string))!;
24+
25+
internal static unsafe NSString FromString(string str)
26+
{
27+
fixed (char* strPtr = str)
28+
return new NSString(Interop.SendIntPtr(class_pointer, sel_string_with_characters, (IntPtr)strPtr, str.Length));
29+
}
30+
}
31+
}

osu.Framework/Platform/MacOS/MacOSClipboard.cs

+24-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// See the LICENCE file in the repository root for full licence text.
33

44
using System;
5+
using System.IO;
56
using osu.Framework.Platform.Apple.Native;
67
using osu.Framework.Platform.MacOS.Native;
78
using SixLabors.ImageSharp;
@@ -12,13 +13,32 @@ public class MacOSClipboard : Clipboard
1213
{
1314
private readonly NSPasteboard generalPasteboard = NSPasteboard.GeneralPasteboard();
1415

15-
public override string? GetText() => Interop.FromNSString(getFromPasteboard(Class.Get("NSString")));
16+
public override string GetText()
17+
{
18+
var nsString = new NSString(getFromPasteboard(Class.Get("NSString")));
19+
return nsString.ToString();
20+
}
21+
22+
public override Image<TPixel>? GetImage<TPixel>()
23+
{
24+
var nsImage = new NSImage(getFromPasteboard(Class.Get("NSImage")));
25+
if (nsImage.Handle == IntPtr.Zero)
26+
return null;
1627

17-
public override Image<TPixel>? GetImage<TPixel>() => Interop.FromNSImage<TPixel>(getFromPasteboard(Class.Get("NSImage")));
28+
return Image.Load<TPixel>(nsImage.TiffRepresentation.ToBytes());
29+
}
30+
31+
public override void SetText(string text) => setToPasteboard(NSString.FromString(text).Handle);
1832

19-
public override void SetText(string text) => setToPasteboard(Interop.ToNSString(text));
33+
public override bool SetImage(Image image)
34+
{
35+
using var stream = new MemoryStream();
36+
image.SaveAsTiff(stream);
2037

21-
public override bool SetImage(Image image) => setToPasteboard(Interop.ToNSImage(image));
38+
using var nsData = NSData.FromBytes(stream.ToArray());
39+
using var nsImage = NSImage.LoadFromData(nsData);
40+
return setToPasteboard(nsImage.Handle);
41+
}
2242

2343
private IntPtr getFromPasteboard(IntPtr @class)
2444
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2+
// See the LICENCE file in the repository root for full licence text.
3+
4+
using System;
5+
using JetBrains.Annotations;
6+
using osu.Framework.Platform.Apple.Native;
7+
8+
namespace osu.Framework.Platform.MacOS.Native
9+
{
10+
internal readonly struct NSImage : IDisposable
11+
{
12+
internal IntPtr Handle { get; }
13+
14+
internal NSImage(IntPtr handle)
15+
{
16+
Handle = handle;
17+
}
18+
19+
private static readonly IntPtr class_pointer = Class.Get("NSImage");
20+
private static readonly IntPtr sel_alloc = Selector.Get("alloc");
21+
private static readonly IntPtr sel_release = Selector.Get("release");
22+
private static readonly IntPtr sel_init_with_data = Selector.Get("initWithData:");
23+
private static readonly IntPtr sel_tiff_representation = Selector.Get("TIFFRepresentation");
24+
25+
internal NSData TiffRepresentation => new NSData(Interop.SendIntPtr(Handle, sel_tiff_representation));
26+
27+
[MustDisposeResource]
28+
internal static NSImage LoadFromData(NSData data)
29+
{
30+
var image = alloc();
31+
Interop.SendIntPtr(image.Handle, sel_init_with_data, data);
32+
return image;
33+
}
34+
35+
internal void Release() => Interop.SendVoid(Handle, sel_release);
36+
37+
private static NSImage alloc() => new NSImage(Interop.SendIntPtr(class_pointer, sel_alloc));
38+
39+
public void Dispose()
40+
{
41+
if (Handle != IntPtr.Zero)
42+
Release();
43+
}
44+
}
45+
}

osu.Framework/Platform/MacOS/Native/NSWorkspace.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ internal NSWorkspace(IntPtr handle)
2121

2222
internal static NSWorkspace SharedWorkspace() => new NSWorkspace(Interop.SendIntPtr(class_pointer, sel_shared_workspace));
2323

24-
internal bool SelectFile(string file) => Interop.SendBool(Handle, sel_select_file, Interop.ToNSString(file));
24+
internal bool SelectFile(string file) => Interop.SendBool(Handle, sel_select_file, NSString.FromString(file).Handle);
2525
}
2626
}

0 commit comments

Comments
 (0)