Skip to content

Commit 7fc7d69

Browse files
committed
[mac_fonts] Replace CFURLGetFileSystemRepresentation to CFURLCopyFileSystemPath
I thought it would be a bit faster to use CFURLCopyFileSystemPath instead of CFURLGetFileSystemRepresentation since the buffer isn't always 1024, but after some performance testing, it reveal that CFURLGetFileSystemRepresentation is actually faster. So, this is totally useless, but it might be good to keep it.
1 parent c6620f9 commit 7fc7d69

1 file changed

Lines changed: 46 additions & 16 deletions

File tree

find_system_fonts_filename/mac_fonts.py

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
1-
from ctypes import c_bool, c_char_p, c_long, c_void_p, cdll, create_string_buffer, util
2-
from os import pathconf
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
33
from pathlib import Path
44
from platform import mac_ver
55
from typing import Set
66
from .exceptions import OSNotSupported
77
from .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+
1017
class MacFonts(SystemFonts):
1118
_core_foundation = None
1219
_core_text = None
1320
# CoreText has an API to get the format of the font: https://developer.apple.com/documentation/coretext/ctfontformat
1421
# 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.
1522
# So, we only check the file extension and see if it is valid.
1623
VALID_FONT_FORMATS = ["ttf", "otf", "ttc"]
24+
kCFStringEncodingUTF8 = 0x08000100 # https://developer.apple.com/documentation/corefoundation/cfstringbuiltinencodings/kcfstringencodingutf8?language=objc
1725

1826
def get_system_fonts_filename() -> Set[str]:
1927
if MacVersionHelpers.is_mac_version_or_greater(10, 6):
@@ -25,28 +33,37 @@ def get_system_fonts_filename() -> Set[str]:
2533
font_urls = MacFonts._core_text.CTFontManagerCopyAvailableFontURLs()
2634
font_count = MacFonts._core_foundation.CFArrayGetCount(font_urls)
2735

28-
max_length = pathconf("/", "PC_PATH_MAX")
29-
3036
for i in range(font_count):
3137
url = MacFonts._core_foundation.CFArrayGetValueAtIndex(font_urls, i)
3238

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()
39+
filename = MacFonts._cfstring_to_string(MacFonts._core_text.CFURLCopyFileSystemPath(url, CFURLPathStyle.kCFURLPOSIXPathStyle))
3840

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.")
41+
if Path(filename).suffix.lstrip(".").strip().lower() in MacFonts.VALID_FONT_FORMATS:
42+
fonts_filename.add(filename)
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+
5067
@staticmethod
5168
def _load_core_library():
5269
core_foundation_library_name = util.find_library("CoreFoundation")
@@ -64,6 +81,8 @@ def _load_core_library():
6481
MacFonts._core_text = cdll.LoadLibrary(core_text_library_name)
6582

6683
CFIndex = c_long
84+
CFStringEncoding = c_uint32
85+
CFURLPathStyle = c_int
6786

6887
# https://developer.apple.com/documentation/corefoundation/1521153-cfrelease
6988
MacFonts._core_foundation.CFRelease.restype = c_void_p
@@ -77,14 +96,25 @@ def _load_core_library():
7796
MacFonts._core_foundation.CFArrayGetValueAtIndex.restype = c_void_p
7897
MacFonts._core_foundation.CFArrayGetValueAtIndex.argtypes = [c_void_p, CFIndex]
7998

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]
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]
83110

84111
# https://developer.apple.com/documentation/coretext/1499478-ctfontmanagercopyavailablefontur?language=objc
85112
MacFonts._core_text.CTFontManagerCopyAvailableFontURLs.restype = c_void_p
86113
MacFonts._core_text.CTFontManagerCopyAvailableFontURLs.argtypes = []
87114

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]
88118

89119
class MacVersionHelpers:
90120
@staticmethod

0 commit comments

Comments
 (0)