diff --git a/src/CoreText/CTFont.Generator.cs b/src/CoreText/CTFont.Generator.cs index e6f64835f52b..7426e2bf125b 100644 --- a/src/CoreText/CTFont.Generator.cs +++ b/src/CoreText/CTFont.Generator.cs @@ -32,4 +32,6 @@ namespace CoreText { public partial class CTFont : NativeObject { } + public partial class CTFontDescriptor : NativeObject { + } } diff --git a/src/CoreText/CTFontDescriptor.cs b/src/CoreText/CTFontDescriptor.cs index 846c397ae580..511c9264908e 100644 --- a/src/CoreText/CTFontDescriptor.cs +++ b/src/CoreText/CTFontDescriptor.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Runtime.InteropServices; using ObjCRuntime; @@ -390,7 +391,7 @@ public CTFontDescriptorAttributes (NSDictionary dictionary) [SupportedOSPlatform ("macos")] [SupportedOSPlatform ("tvos")] #endif - public class CTFontDescriptor : NativeObject { + public partial class CTFontDescriptor : NativeObject { [Preserve (Conditional = true)] internal CTFontDescriptor (NativeHandle handle, bool owns) : base (handle, owns, true) @@ -738,17 +739,30 @@ public CTFontDescriptor (CTFontDescriptorAttributes attributes) [SupportedOSPlatform ("maccatalyst")] [SupportedOSPlatform ("tvos")] #endif -#if NET [DllImport (Constants.CoreTextLibrary)] - [return: MarshalAs (UnmanagedType.I1)] - static unsafe extern bool CTFontDescriptorMatchFontDescriptorsWithProgressHandler (IntPtr descriptors, IntPtr mandatoryAttributes, - delegate* unmanaged progressHandler); + static unsafe extern byte CTFontDescriptorMatchFontDescriptorsWithProgressHandler (IntPtr descriptors, IntPtr mandatoryAttributes, BlockLiteral* progressBlock); + + public delegate bool CTFontDescriptorProgressHandler (CTFontDescriptorMatchingState state, CTFontDescriptorMatchingProgress progress); + +#if !NET + delegate byte ct_font_desctiptor_progress_handler_t (IntPtr block, CTFontDescriptorMatchingState state, IntPtr progress); + static ct_font_desctiptor_progress_handler_t static_MatchFontDescriptorsHandler = MatchFontDescriptorsHandler; + + [MonoPInvokeCallback (typeof (ct_font_desctiptor_progress_handler_t))] #else - [DllImport (Constants.CoreTextLibrary)] - [return: MarshalAs (UnmanagedType.I1)] - static extern bool CTFontDescriptorMatchFontDescriptorsWithProgressHandler (IntPtr descriptors, IntPtr mandatoryAttributes, - Func progressHandler); + [UnmanagedCallersOnly] #endif + static byte MatchFontDescriptorsHandler (IntPtr block, CTFontDescriptorMatchingState state, IntPtr progress) + { + var del = BlockLiteral.GetTarget (block); + if (del is not null) { + var progressDictionary = Runtime.GetNSObject (progress)!; + var strongDictionary = new CTFontDescriptorMatchingProgress (progressDictionary); + var rv = del (state, strongDictionary); + return rv ? (byte) 1 : (byte) 0; + } + return 0; + } #if NET [SupportedOSPlatform ("macos")] @@ -756,16 +770,36 @@ public CTFontDescriptor (CTFontDescriptorAttributes attributes) [SupportedOSPlatform ("maccatalyst")] [SupportedOSPlatform ("tvos")] #endif - public static bool MatchFontDescriptors (CTFontDescriptor [] descriptors, NSSet mandatoryAttributes, Func progressHandler) + [BindingImpl (BindingImplOptions.Optimizable)] + public static bool MatchFontDescriptors (CTFontDescriptor [] descriptors, NSSet? mandatoryAttributes, CTFontDescriptorProgressHandler progressHandler) + { + if (descriptors is null) + ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (descriptors)); + + if (progressHandler is null) + ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (progressHandler)); + + unsafe { +#if NET + delegate* unmanaged trampoline = &MatchFontDescriptorsHandler; + using var block = new BlockLiteral (trampoline, progressHandler, typeof (CTFontDescriptor), nameof (MatchFontDescriptorsHandler)); +#else + using var block = new BlockLiteral (); + block.SetupBlockUnsafe (static_MatchFontDescriptorsHandler, progressHandler); +#endif + using var descriptorsArray = NSArray.FromNSObjects (descriptors); + var rv = CTFontDescriptorMatchFontDescriptorsWithProgressHandler (descriptorsArray.GetHandle (), mandatoryAttributes.GetHandle (), &block); + return rv != 0; + } + } + +#if !XAMCORE_5_0 + [EditorBrowsable (EditorBrowsableState.Never)] + [Obsolete ("Use 'MatchFontDescriptors (CTFontDescriptor[], NSSet, CTFontDescriptorProgressHandler)' instead.")] + public static bool MatchFontDescriptors (CTFontDescriptor [] descriptors, NSSet? mandatoryAttributes, Func progressHandler) { - // FIXME: the P/Invoke used below is wrong, it expects a block, not a function pointer. - // throwing a NIE instead of crashing until this is implemented properly. throw new NotImplementedException (); - // var ma = mandatoryAttributes is null ? IntPtr.Zero : mandatoryAttributes.Handle; - // // FIXME: SIGSEGV probably due to mandatoryAttributes mismatch - // using (var ar = CFArray.FromNativeObjects (descriptors)) { - // return CTFontDescriptorMatchFontDescriptorsWithProgressHandler (ar.Handle, ma, progressHandler); - // } } +#endif } } diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs index 3cda24b27877..ec6fa282dc7f 100644 --- a/src/bgen/Generator.cs +++ b/src/bgen/Generator.cs @@ -1951,6 +1951,9 @@ void GenerateStrongDictionaryTypes () } else if (elementType == TypeManager.System_String) { getter = "GetArray ({0}, (ptr) => CFString.FromHandle (ptr)!)"; setter = "SetArrayValue ({0}, value)"; + } else if (elementType.Name == "CTFontDescriptor") { + getter = "GetArray ({0}, (ptr) => new CTFontDescriptor (ptr, false))"; + setter = "SetArrayValue ({0}, value)"; } else { throw new BindingException (1033, true, pi.PropertyType, dictType, pi.Name); } @@ -1982,6 +1985,9 @@ void GenerateStrongDictionaryTypes () } else if (pi.PropertyType.Name == "CGImageSource") { getter = "GetNativeValue<" + pi.PropertyType + "> ({0})"; setter = "SetNativeValue ({0}, value)"; + } else if (pi.PropertyType.Name == "CTFontDescriptor") { + getter = "GetNativeValue<" + pi.PropertyType + "> ({0})"; + setter = "SetNativeValue ({0}, value)"; } else { throw new BindingException (1033, true, pi.PropertyType, dictType, pi.Name); } diff --git a/src/coretext.cs b/src/coretext.cs index 1e72615dfaf8..b385e27da5cf 100644 --- a/src/coretext.cs +++ b/src/coretext.cs @@ -325,6 +325,46 @@ interface CTFontCollectionOptionKey { } #endif + [Internal] + [Static] + interface CTFontDescriptorMatchingKeys { + [Field ("kCTFontDescriptorMatchingSourceDescriptor")] + NSString SourceDescriptorKey { get; } + + [Field ("kCTFontDescriptorMatchingDescriptors")] + NSString DescriptorsKey { get; } + + [Field ("kCTFontDescriptorMatchingResult")] + NSString ResultKey { get; } + + [Field ("kCTFontDescriptorMatchingPercentage")] + NSString PercentageKey { get; } + + [Field ("kCTFontDescriptorMatchingCurrentAssetSize")] + NSString CurrentAssetSizeKey { get; } + + [Field ("kCTFontDescriptorMatchingTotalDownloadedSize")] + NSString TotalDownloadedSizeKey { get; } + + [Field ("kCTFontDescriptorMatchingTotalAssetSize")] + NSString TotalAssetSizeKey { get; } + + [Field ("kCTFontDescriptorMatchingError")] + NSString ErrorKey { get; } + } + + [StrongDictionary ("CTFontDescriptorMatchingKeys")] + interface CTFontDescriptorMatchingProgress { + CTFontDescriptor SourceDescriptor { get; } + CTFontDescriptor [] Descriptors { get; } + CTFontDescriptor [] Result { get; } + double Percentage { get; } + long CurrentAssetSize { get; } + long TotalDownloadedSize { get; } + long TotalAssetSize { get; } + NSError Error { get; } + } + [Static] [Partial] interface CTStringAttributeKey { diff --git a/tests/cecil-tests/BlittablePInvokes.KnownFailures.cs b/tests/cecil-tests/BlittablePInvokes.KnownFailures.cs index 6cd1237099d6..244b4d7171e3 100644 --- a/tests/cecil-tests/BlittablePInvokes.KnownFailures.cs +++ b/tests/cecil-tests/BlittablePInvokes.KnownFailures.cs @@ -207,7 +207,6 @@ public partial class BlittablePInvokes { "System.Boolean CoreServices.FSEvent::FSEventsPurgeEventsForDeviceUpToEventId(System.UInt64,System.UInt64)", "System.Boolean CoreServices.FSEventStream::FSEventStreamStart(System.IntPtr)", "System.Boolean CoreText.CTFont::CTFontGetGlyphsForCharacters(System.IntPtr,System.Char[],System.UInt16[],System.IntPtr)", - "System.Boolean CoreText.CTFontDescriptor::CTFontDescriptorMatchFontDescriptorsWithProgressHandler(System.IntPtr,System.IntPtr,method System.Boolean *(CoreText.CTFontDescriptorMatchingState,System.IntPtr))", "System.Boolean CoreText.CTFontManager::CTFontManagerIsSupportedFont(System.IntPtr)", "System.Boolean CoreText.CTFontManager::CTFontManagerRegisterFontsForURL(System.IntPtr,CoreText.CTFontManagerScope,System.IntPtr&)", "System.Boolean CoreText.CTFontManager::CTFontManagerRegisterFontsForURLs(System.IntPtr,CoreText.CTFontManagerScope,System.IntPtr&)", diff --git a/tests/monotouch-test/CoreText/FontDescriptorTest.cs b/tests/monotouch-test/CoreText/FontDescriptorTest.cs index 11ca7e10670d..8aa2d6327300 100644 --- a/tests/monotouch-test/CoreText/FontDescriptorTest.cs +++ b/tests/monotouch-test/CoreText/FontDescriptorTest.cs @@ -8,6 +8,9 @@ // using System; +using System.Threading; +using System.Threading.Tasks; + using Foundation; using CoreText; #if MONOMAC @@ -71,5 +74,29 @@ public void WithFeature () Assert.That (set_feature.FeatureWeak, Is.EqualTo ((int) CTFontFeatureLigatures.Selector.RareLigaturesOn), "#2"); } } + + [Test] + public void MatchFontDescriptors () + { + var fda1 = new CTFontDescriptorAttributes () { + Name = "Helvetica", + }; + using var desc1 = new CTFontDescriptor (fda1); + var tcs = new TaskCompletionSource (); + var rv = CTFontDescriptor.MatchFontDescriptors (new CTFontDescriptor [] { desc1 }, null, (CTFontDescriptorMatchingState state, CTFontDescriptorMatchingProgress progress) => { + try { + if (state == CTFontDescriptorMatchingState.Finished) { + Assert.AreEqual (1, progress.Result.Length, "Result.Length"); + Assert.AreEqual (fda1.Name, progress.Result [0].GetAttributes ().Name, "Result[0].Name"); + tcs.TrySetResult (true); + } + } catch (Exception e) { + tcs.TrySetException (e); + } + return true; + }); + Assert.IsTrue (rv, "Return value"); + TestRuntime.RunAsync (TimeSpan.FromSeconds (30), tcs.Task); + } } } diff --git a/tests/xtro-sharpie/api-annotations-dotnet/common-CoreText.ignore b/tests/xtro-sharpie/api-annotations-dotnet/common-CoreText.ignore index abed0d85385d..58153965d318 100644 --- a/tests/xtro-sharpie/api-annotations-dotnet/common-CoreText.ignore +++ b/tests/xtro-sharpie/api-annotations-dotnet/common-CoreText.ignore @@ -4,14 +4,6 @@ !missing-enum! CTRubyAlignment not bound !missing-enum! CTRubyOverhang not bound !missing-enum! CTRubyPosition not bound -!missing-field! kCTFontDescriptorMatchingCurrentAssetSize not bound -!missing-field! kCTFontDescriptorMatchingDescriptors not bound -!missing-field! kCTFontDescriptorMatchingError not bound -!missing-field! kCTFontDescriptorMatchingPercentage not bound -!missing-field! kCTFontDescriptorMatchingResult not bound -!missing-field! kCTFontDescriptorMatchingSourceDescriptor not bound -!missing-field! kCTFontDescriptorMatchingTotalAssetSize not bound -!missing-field! kCTFontDescriptorMatchingTotalDownloadedSize not bound !missing-field! kCTFontDownloadableAttribute not bound !missing-field! kCTFontDownloadedAttribute not bound !missing-field! kCTFontManagerRegisteredFontsChangedNotification not bound diff --git a/tests/xtro-sharpie/common-CoreText.ignore b/tests/xtro-sharpie/common-CoreText.ignore index ad6875377fb1..f1e24da856de 100644 --- a/tests/xtro-sharpie/common-CoreText.ignore +++ b/tests/xtro-sharpie/common-CoreText.ignore @@ -24,14 +24,6 @@ !missing-field! kCTFontCollectionRemoveDuplicatesOption not bound !missing-field! kCTFontCopyrightNameKey not bound !missing-field! kCTFontDescriptionNameKey not bound -!missing-field! kCTFontDescriptorMatchingCurrentAssetSize not bound -!missing-field! kCTFontDescriptorMatchingDescriptors not bound -!missing-field! kCTFontDescriptorMatchingError not bound -!missing-field! kCTFontDescriptorMatchingPercentage not bound -!missing-field! kCTFontDescriptorMatchingResult not bound -!missing-field! kCTFontDescriptorMatchingSourceDescriptor not bound -!missing-field! kCTFontDescriptorMatchingTotalAssetSize not bound -!missing-field! kCTFontDescriptorMatchingTotalDownloadedSize not bound !missing-field! kCTFontDesignerNameKey not bound !missing-field! kCTFontDesignerURLNameKey not bound !missing-field! kCTFontDisplayNameAttribute not bound