1- from ctypes import c_bool , c_char_p , c_int , c_long , c_uint32 , c_void_p , cdll , create_string_buffer , util
2- from enum import IntEnum
1+ from ctypes import c_bool , c_char_p , c_long , c_void_p , cdll , create_string_buffer , util
2+ from os import pathconf
33from pathlib import Path
44from platform import mac_ver
55from typing import Set
66from .exceptions import OSNotSupported
77from .system_fonts import SystemFonts
88
99
10- class CFURLPathStyle (IntEnum ):
11- # https://developer.apple.com/documentation/corefoundation/cfurlpathstyle?language=objc
12- kCFURLPOSIXPathStyle = 0
13- kCFURLHFSPathStyle = 1
14- kCFURLWindowsPathStyle = 2
15-
16-
1710class MacFonts (SystemFonts ):
1811 _core_foundation = None
1912 _core_text = None
2013 # CoreText has an API to get the format of the font: https://developer.apple.com/documentation/coretext/ctfontformat
2114 # But, the API is "semi-broken" since it says .dfont are TrueType. This is kinda true, but it is not a behaviour that we want.
2215 # So, we only check the file extension and see if it is valid.
2316 VALID_FONT_FORMATS = ["ttf" , "otf" , "ttc" ]
24- kCFStringEncodingUTF8 = 0x08000100 # https://developer.apple.com/documentation/corefoundation/cfstringbuiltinencodings/kcfstringencodingutf8?language=objc
2517
2618 def get_system_fonts_filename () -> Set [str ]:
2719 if MacVersionHelpers .is_mac_version_or_greater (10 , 6 ):
@@ -33,37 +25,28 @@ def get_system_fonts_filename() -> Set[str]:
3325 font_urls = MacFonts ._core_text .CTFontManagerCopyAvailableFontURLs ()
3426 font_count = MacFonts ._core_foundation .CFArrayGetCount (font_urls )
3527
28+ max_length = pathconf ("/" , "PC_PATH_MAX" )
29+
3630 for i in range (font_count ):
3731 url = MacFonts ._core_foundation .CFArrayGetValueAtIndex (font_urls , i )
3832
39- filename = MacFonts ._cfstring_to_string (MacFonts ._core_text .CFURLCopyFileSystemPath (url , CFURLPathStyle .kCFURLPOSIXPathStyle ))
33+ file_name_ptr = create_string_buffer (max_length )
34+ no_error = MacFonts ._core_foundation .CFURLGetFileSystemRepresentation (url , True , file_name_ptr , max_length )
35+
36+ if no_error :
37+ filename = file_name_ptr .value .decode ()
4038
41- if Path (filename ).suffix .lstrip ("." ).strip ().lower () in MacFonts .VALID_FONT_FORMATS :
42- fonts_filename .add (filename )
39+ if Path (filename ).suffix .lstrip ("." ).strip ().lower () in MacFonts .VALID_FONT_FORMATS :
40+ fonts_filename .add (filename )
41+ else :
42+ raise Exception ("An unexpected error has occurred while decoded the CFURL." )
4343
4444 MacFonts ._core_foundation .CFRelease (font_urls )
4545 else :
4646 raise OSNotSupported ("FindSystemFontsFilename only works on Mac 10.6 or more" )
4747
4848 return fonts_filename
4949
50- @staticmethod
51- def _cfstring_to_string (cfstring : c_void_p ) -> str :
52- """
53- Parameters:
54- cfstring (c_void_p): An CFString instance.
55- Returns:
56- The decoded CFString.
57- """
58- length = MacFonts ._core_foundation .CFStringGetLength (cfstring )
59- size = MacFonts ._core_foundation .CFStringGetMaximumSizeForEncoding (length , MacFonts .kCFStringEncodingUTF8 )
60- buffer = create_string_buffer (size + 1 )
61- result = MacFonts ._core_foundation .CFStringGetCString (cfstring , buffer , len (buffer ), MacFonts .kCFStringEncodingUTF8 )
62- if result :
63- return str (buffer .value , 'utf-8' )
64- else :
65- raise Exception ("An unexpected error has occurred while decoded the CFString." )
66-
6750 @staticmethod
6851 def _load_core_library ():
6952 core_foundation_library_name = util .find_library ("CoreFoundation" )
@@ -81,8 +64,6 @@ def _load_core_library():
8164 MacFonts ._core_text = cdll .LoadLibrary (core_text_library_name )
8265
8366 CFIndex = c_long
84- CFStringEncoding = c_uint32
85- CFURLPathStyle = c_int
8667
8768 # https://developer.apple.com/documentation/corefoundation/1521153-cfrelease
8869 MacFonts ._core_foundation .CFRelease .restype = c_void_p
@@ -96,25 +77,14 @@ def _load_core_library():
9677 MacFonts ._core_foundation .CFArrayGetValueAtIndex .restype = c_void_p
9778 MacFonts ._core_foundation .CFArrayGetValueAtIndex .argtypes = [c_void_p , CFIndex ]
9879
99- # https://developer.apple.com/documentation/corefoundation/1542853-cfstringgetlength?language=objc
100- MacFonts ._core_foundation .CFStringGetLength .restype = CFIndex
101- MacFonts ._core_foundation .CFStringGetLength .argtypes = [c_void_p ]
102-
103- # https://developer.apple.com/documentation/corefoundation/1542143-cfstringgetmaximumsizeforencodin?language=objc
104- MacFonts ._core_foundation .CFStringGetMaximumSizeForEncoding .restype = CFIndex
105- MacFonts ._core_foundation .CFStringGetMaximumSizeForEncoding .argtypes = [c_void_p , CFStringEncoding ]
106-
107- # https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring?language=objc
108- MacFonts ._core_foundation .CFStringGetCString .restype = c_bool
109- MacFonts ._core_foundation .CFStringGetCString .argtypes = [c_void_p , c_char_p , CFIndex , CFStringEncoding ]
80+ # https://developer.apple.com/documentation/corefoundation/1541515-cfurlgetfilesystemrepresentation?language=objc
81+ MacFonts ._core_foundation .CFURLGetFileSystemRepresentation .restype = c_bool
82+ MacFonts ._core_foundation .CFURLGetFileSystemRepresentation .argtypes = [c_void_p , c_bool , c_char_p , CFIndex ]
11083
11184 # https://developer.apple.com/documentation/coretext/1499478-ctfontmanagercopyavailablefontur?language=objc
11285 MacFonts ._core_text .CTFontManagerCopyAvailableFontURLs .restype = c_void_p
11386 MacFonts ._core_text .CTFontManagerCopyAvailableFontURLs .argtypes = []
11487
115- # https://developer.apple.com/documentation/corefoundation/1541581-cfurlcopyfilesystempath?language=objc
116- MacFonts ._core_text .CFURLCopyFileSystemPath .restype = c_void_p
117- MacFonts ._core_text .CFURLCopyFileSystemPath .argtypes = [c_void_p , CFURLPathStyle ]
11888
11989class MacVersionHelpers :
12090 @staticmethod
0 commit comments