using CPF.Mac.CoreFoundation; using CPF.Mac.Foundation; using CPF.Mac.ObjCRuntime; using System; using System.Runtime.InteropServices; namespace CPF.Mac.CoreText { [Since(3, 2)] public class CTFontDescriptor : INativeObject, IDisposable { internal IntPtr handle; public IntPtr Handle => handle; internal CTFontDescriptor(IntPtr handle) : this(handle, owns: false) { } internal CTFontDescriptor(IntPtr handle, bool owns) { if (handle == IntPtr.Zero) { throw ConstructorError.ArgumentNull(this, "handle"); } this.handle = handle; if (!owns) { CFObject.CFRetain(handle); } } ~CTFontDescriptor() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (handle != IntPtr.Zero) { CFObject.CFRelease(handle); handle = IntPtr.Zero; } } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCreateWithNameAndSize(IntPtr name, double size); public CTFontDescriptor(string name, double size) { if (name == null) { throw ConstructorError.ArgumentNull(this, "name"); } using (CFString cFString = (CFString)name) { handle = CTFontDescriptorCreateWithNameAndSize(cFString.Handle, size); } if (handle == IntPtr.Zero) { throw ConstructorError.Unknown(this); } } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCreateWithAttributes(IntPtr attributes); public CTFontDescriptor(CTFontDescriptorAttributes attributes) { if (attributes == null) { throw ConstructorError.ArgumentNull(this, "attributes"); } handle = CTFontDescriptorCreateWithAttributes(attributes.Dictionary.Handle); if (handle == IntPtr.Zero) { throw ConstructorError.Unknown(this); } } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCreateCopyWithAttributes(IntPtr original, IntPtr attributes); public CTFontDescriptor WithAttributes(NSDictionary attributes) { if (attributes == null) { throw new ArgumentNullException("attributes"); } return CreateDescriptor(CTFontDescriptorCreateCopyWithAttributes(handle, attributes.Handle)); } private static CTFontDescriptor CreateDescriptor(IntPtr h) { if (h == IntPtr.Zero) { return null; } return new CTFontDescriptor(h, owns: true); } public CTFontDescriptor WithAttributes(CTFontDescriptorAttributes attributes) { if (attributes == null) { throw new ArgumentNullException("attributes"); } return CreateDescriptor(CTFontDescriptorCreateCopyWithAttributes(handle, attributes.Dictionary.Handle)); } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCreateCopyWithVariation(IntPtr original, IntPtr variationIdentifier, double variationValue); public CTFontDescriptor WithVariation(uint variationIdentifier, double variationValue) { using (NSNumber nSNumber = new NSNumber(variationIdentifier)) { return CreateDescriptor(CTFontDescriptorCreateCopyWithVariation(handle, nSNumber.Handle, variationValue)); } } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCreateCopyWithFeature(IntPtr original, IntPtr featureTypeIdentifier, IntPtr featureSelectorIdentifier); [Advice("Use WithFeature with specific selector")] public CTFontDescriptor WithFeature(NSNumber featureTypeIdentifier, NSNumber featureSelectorIdentifier) { if (featureTypeIdentifier == null) { throw new ArgumentNullException("featureTypeIdentifier"); } if (featureSelectorIdentifier == null) { throw new ArgumentNullException("featureSelectorIdentifier"); } return CreateDescriptor(CTFontDescriptorCreateCopyWithFeature(handle, featureTypeIdentifier.Handle, featureSelectorIdentifier.Handle)); } public CTFontDescriptor WithFeature(CTFontFeatureAllTypographicFeatures.Selector featureSelector) { return WithFeature(FontFeatureGroup.AllTypographicFeatures, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureLigatures.Selector featureSelector) { return WithFeature(FontFeatureGroup.Ligatures, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureCursiveConnection.Selector featureSelector) { return WithFeature(FontFeatureGroup.CursiveConnection, (int)featureSelector); } [Obsolete("Deprecated")] public CTFontDescriptor WithFeature(CTFontFeatureLetterCase.Selector featureSelector) { return WithFeature(FontFeatureGroup.LetterCase, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureVerticalSubstitutionConnection.Selector featureSelector) { return WithFeature(FontFeatureGroup.VerticalSubstitution, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureLinguisticRearrangementConnection.Selector featureSelector) { return WithFeature(FontFeatureGroup.LinguisticRearrangement, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureNumberSpacing.Selector featureSelector) { return WithFeature(FontFeatureGroup.NumberSpacing, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureSmartSwash.Selector featureSelector) { return WithFeature(FontFeatureGroup.SmartSwash, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureDiacritics.Selector featureSelector) { return WithFeature(FontFeatureGroup.Diacritics, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureVerticalPosition.Selector featureSelector) { return WithFeature(FontFeatureGroup.VerticalPosition, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureFractions.Selector featureSelector) { return WithFeature(FontFeatureGroup.Fractions, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureOverlappingCharacters.Selector featureSelector) { return WithFeature(FontFeatureGroup.OverlappingCharacters, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureTypographicExtras.Selector featureSelector) { return WithFeature(FontFeatureGroup.TypographicExtras, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureMathematicalExtras.Selector featureSelector) { return WithFeature(FontFeatureGroup.MathematicalExtras, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureOrnamentSets.Selector featureSelector) { return WithFeature(FontFeatureGroup.OrnamentSets, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureCharacterAlternatives.Selector featureSelector) { return WithFeature(FontFeatureGroup.CharacterAlternatives, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureDesignComplexity.Selector featureSelector) { return WithFeature(FontFeatureGroup.DesignComplexity, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureStyleOptions.Selector featureSelector) { return WithFeature(FontFeatureGroup.StyleOptions, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureCharacterShape.Selector featureSelector) { return WithFeature(FontFeatureGroup.CharacterShape, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureNumberCase.Selector featureSelector) { return WithFeature(FontFeatureGroup.NumberCase, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureTextSpacing.Selector featureSelector) { return WithFeature(FontFeatureGroup.TextSpacing, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureTransliteration.Selector featureSelector) { return WithFeature(FontFeatureGroup.Transliteration, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureAnnotation.Selector featureSelector) { return WithFeature(FontFeatureGroup.Annotation, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureKanaSpacing.Selector featureSelector) { return WithFeature(FontFeatureGroup.KanaSpacing, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureIdeographicSpacing.Selector featureSelector) { return WithFeature(FontFeatureGroup.IdeographicSpacing, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureUnicodeDecomposition.Selector featureSelector) { return WithFeature(FontFeatureGroup.UnicodeDecomposition, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureRubyKana.Selector featureSelector) { return WithFeature(FontFeatureGroup.RubyKana, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureCJKSymbolAlternatives.Selector featureSelector) { return WithFeature(FontFeatureGroup.CJKSymbolAlternatives, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureIdeographicAlternatives.Selector featureSelector) { return WithFeature(FontFeatureGroup.IdeographicAlternatives, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureCJKVerticalRomanPlacement.Selector featureSelector) { return WithFeature(FontFeatureGroup.CJKVerticalRomanPlacement, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureItalicCJKRoman.Selector featureSelector) { return WithFeature(FontFeatureGroup.ItalicCJKRoman, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureCaseSensitiveLayout.Selector featureSelector) { return WithFeature(FontFeatureGroup.CaseSensitiveLayout, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureAlternateKana.Selector featureSelector) { return WithFeature(FontFeatureGroup.AlternateKana, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureStylisticAlternatives.Selector featureSelector) { return WithFeature(FontFeatureGroup.StylisticAlternatives, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureContextualAlternates.Selector featureSelector) { return WithFeature(FontFeatureGroup.ContextualAlternates, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureLowerCase.Selector featureSelector) { return WithFeature(FontFeatureGroup.LowerCase, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureUpperCase.Selector featureSelector) { return WithFeature(FontFeatureGroup.UpperCase, (int)featureSelector); } public CTFontDescriptor WithFeature(CTFontFeatureCJKRomanSpacing.Selector featureSelector) { return WithFeature(FontFeatureGroup.CJKRomanSpacing, (int)featureSelector); } private CTFontDescriptor WithFeature(FontFeatureGroup featureGroup, int featureSelector) { using (NSNumber nSNumber = new NSNumber((int)featureGroup)) { using (NSNumber nSNumber2 = new NSNumber(featureSelector)) { return CreateDescriptor(CTFontDescriptorCreateCopyWithFeature(handle, nSNumber.Handle, nSNumber2.Handle)); } } } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCreateMatchingFontDescriptors(IntPtr descriptor, IntPtr mandatoryAttributes); public CTFontDescriptor[] GetMatchingFontDescriptors(NSSet mandatoryAttributes) { IntPtr cfArrayRef = CTFontDescriptorCreateMatchingFontDescriptors(handle, mandatoryAttributes?.Handle ?? IntPtr.Zero); if (cfArrayRef == IntPtr.Zero) { return new CTFontDescriptor[0]; } CTFontDescriptor[] result = NSArray.ArrayFromHandle(cfArrayRef, (IntPtr fd) => new CTFontDescriptor(cfArrayRef, owns: false)); CFObject.CFRelease(cfArrayRef); return result; } public CTFontDescriptor[] GetMatchingFontDescriptors(params NSString[] mandatoryAttributes) { NSSet mandatoryAttributes2 = NSSet.MakeNSObjectSet(mandatoryAttributes); return GetMatchingFontDescriptors(mandatoryAttributes2); } public CTFontDescriptor[] GetMatchingFontDescriptors() { NSSet mandatoryAttributes = null; return GetMatchingFontDescriptors(mandatoryAttributes); } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCreateMatchingFontDescriptor(IntPtr descriptor, IntPtr mandatoryAttributes); public CTFontDescriptor GetMatchingFontDescriptor(NSSet mandatoryAttributes) { return CreateDescriptor(CTFontDescriptorCreateMatchingFontDescriptors(handle, mandatoryAttributes?.Handle ?? IntPtr.Zero)); } public CTFontDescriptor GetMatchingFontDescriptor(params NSString[] mandatoryAttributes) { NSSet mandatoryAttributes2 = NSSet.MakeNSObjectSet(mandatoryAttributes); return GetMatchingFontDescriptor(mandatoryAttributes2); } public CTFontDescriptor GetMatchingFontDescriptor() { NSSet mandatoryAttributes = null; return GetMatchingFontDescriptor(mandatoryAttributes); } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCopyAttributes(IntPtr descriptor); public CTFontDescriptorAttributes GetAttributes() { IntPtr intPtr = CTFontDescriptorCopyAttributes(handle); if (intPtr == IntPtr.Zero) { return null; } NSDictionary obj = (NSDictionary)Runtime.GetNSObject(intPtr); obj.Release(); return new CTFontDescriptorAttributes(obj); } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCopyAttribute(IntPtr descriptor, IntPtr attribute); public NSObject GetAttribute(NSString attribute) { if (attribute == null) { throw new ArgumentNullException("attribute"); } return Runtime.GetNSObject(CTFontDescriptorCopyAttribute(handle, attribute.Handle)); } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCopyLocalizedAttribute(IntPtr descriptor, IntPtr attribute, IntPtr language); public NSObject GetLocalizedAttribute(NSString attribute) { return Runtime.GetNSObject(CTFontDescriptorCopyLocalizedAttribute(handle, attribute.Handle, IntPtr.Zero)); } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern IntPtr CTFontDescriptorCopyLocalizedAttribute(IntPtr descriptor, IntPtr attribute, out IntPtr language); public NSObject GetLocalizedAttribute(NSString attribute, out NSString language) { IntPtr language2; NSObject nSObject = Runtime.GetNSObject(CTFontDescriptorCopyLocalizedAttribute(handle, attribute.Handle, out language2)); language = (NSString)Runtime.GetNSObject(language2); if (language2 != IntPtr.Zero) { CFObject.CFRelease(language2); } return nSObject; } [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/CoreText")] private static extern bool CTFontDescriptorMatchFontDescriptorsWithProgressHandler(IntPtr descriptors, IntPtr mandatoryAttributes, Func progressHandler); [Since(6, 0)] public static bool MatchFontDescriptors(CTFontDescriptor[] descriptors, NSSet mandatoryAttributes, Func progressHandler) { IntPtr mandatoryAttributes2 = mandatoryAttributes?.Handle ?? IntPtr.Zero; using (CFArray cFArray = CFArray.FromNativeObjects(descriptors)) { return CTFontDescriptorMatchFontDescriptorsWithProgressHandler(cFArray.Handle, mandatoryAttributes2, progressHandler); } } } }