Cocoa Font File

I am trying to resolve the font the user is using down to the particular font file so I can read some data from that file. In carbon this was resolved though ATSFontFindFromName, getting the Handle, and then resolving the folderitem through ATSFontGetFileSpecification.

I presume I would use NSFont and/or NSFontManager but I’m not seeing anything direct. Any ideas on how to get the file ref in Cocoa?

FYI: I am aware of NSFontMBS.file but for this project I am not allowed to use plugins. :slight_smile:

[code]Private Function FindFontFile(name As String, size As Double) As FolderItem
#If Target32Bit
Declare Function CTFontDescriptorCreateWithNameAndSize Lib “CoreText” ( name As CFStringRef, size As Single ) As Ptr
#ElseIf Target64Bit
Declare Function CTFontDescriptorCreateWithNameAndSize Lib “CoreText” ( name As CFStringRef, size As Double ) As Ptr
#endif
Declare Function CTFontDescriptorCopyAttribute Lib “CoreText” ( descriptor As Ptr, attribute As Ptr ) As Ptr
Declare Function CFURLGetString Lib “CoreFoundation” ( anURL As Ptr ) As CFStringRef
Declare Function dlopen Lib “System” ( path As CString, mode As Integer ) As ptr
Declare Function dlsym Lib “System” ( handle As Ptr, name As CString ) As ptr
Const RTLD_LAZY = 1
Const RTLD_GLOBAL = 8

// First look up kCTFontURLAttribute
Dim libPtr As ptr = dlopen( “/System/Library/Frameworks/CoreText.framework/CoreText”, RTLD_LAZY Or RTLD_GLOBAL )
If libPtr = Nil Then Return Nil

Dim symPtr As ptr = dlsym( libPtr, “kCTFontURLAttribute” )
If symPtr = Nil Then Return Nil

// Now see if we can get the font descriptor and grab the URL
Dim descriptor As Ptr = CTFontDescriptorCreateWithNameAndSize( name, size )
Dim attr As Ptr = CTFontDescriptorCopyAttribute( descriptor, symPtr.Ptr )
If attr = Nil Then Return Nil

Return GetFolderItem( CFURLGetString( attr ), FolderItem.PathTypeURL )
End Function[/code]

Joe’s code did not release the CoreText objects per CoreFoundation Create Rule. If you used the code above, please update to fix memory leaks:

Private Function FindFontFileMacOS(name As String, size As Double = 0) as FolderItem
  #If TargetMacOS
    
    Declare Function CTFontDescriptorCreateWithNameAndSize Lib "CoreText" (name As CFStringRef, size As Double) As Ptr
    
    Declare Function CTFontDescriptorCopyAttribute Lib "CoreText" (descriptor As Ptr, attribute As Ptr) As Ptr
    
    Declare Function CFURLGetString Lib "CoreFoundation" (anURL As Ptr) As CFStringRef
    
    Declare Function dlopen Lib "System" (path As CString, mode As Integer) As Ptr
    
    Declare Function dlsym Lib "System" (handle As Ptr, name As CString) As Ptr
    
    Declare Sub CFRelease Lib "CoreFoundation" (handle As Ptr) 
    
    Const RTLD_LAZY = 1
    Const RTLD_GLOBAL = 8
    
    ' First look up kCTFontURLAttribute
    Var libPtr As ptr = dlopen("/System/Library/Frameworks/CoreText.framework/CoreText", RTLD_LAZY Or RTLD_GLOBAL)
    If libPtr = Nil Then Return Nil
    
    Var symPtr As ptr = dlsym(libPtr, "kCTFontURLAttribute")
    If symPtr = Nil Then Return Nil
    
    ' Now see if we can get the font descriptor and grab the URL
    Var descriptor As Ptr = CTFontDescriptorCreateWithNameAndSize(name, size)
    If descriptor = Nil Then Return Nil      
    Var attr As Ptr = CTFontDescriptorCopyAttribute(descriptor, symPtr.Ptr)
    If attr = Nil Then 
       CFRelease descriptor // see below
       Return Nil
    End If
    
    Var Result As New FolderItem(CFURLGetString(attr), FolderItem.PathModes.URL)
    CFRelease attr // CoreText is based on CoreFoundation, so objects initialized 
    CFRelease descriptor // with "Create" or "Copy" methods need to be released manually.
    
    Return Result
  #EndIf
End Function
2 Likes