Repository navigation
Use CoreText to find macOS fonts #31977
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
50cbd1e
aa947c8
0122e2d
dbbcd59
058dfc0
a592719
a980e73
aca9614
22e92ce
f76a6ed
7a279ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,10 @@ | |
| #else | ||
| #define UNUSED_ON_NON_WINDOWS Py_UNUSED | ||
| #endif | ||
| #ifdef __APPLE__ | ||
| #include <CoreFoundation/CoreFoundation.h> | ||
| #include <CoreText/CoreText.h> | ||
| #endif | ||
|
|
||
| namespace py = pybind11; | ||
| using namespace pybind11::literals; | ||
|
|
@@ -95,6 +99,62 @@ mpl_display_is_valid(void) | |
| #endif | ||
| } | ||
|
|
||
| static py::object | ||
| mpl_GetAvailableFonts(void) | ||
|
iccir marked this conversation as resolved.
Outdated
|
||
| { | ||
| #if defined(__APPLE__) | ||
| py::set fonts; | ||
|
|
||
| auto cfStringToPyStr = [](CFStringRef str) -> py::str { | ||
| auto cstr = CFStringGetCStringPtr(str, kCFStringEncodingUTF8); | ||
| if (cstr) { | ||
| return py::str(cstr); | ||
| } | ||
| auto length = CFStringGetLength(str); | ||
| auto maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; | ||
| auto buffer = new char[maxSize]; | ||
|
iccir marked this conversation as resolved.
Outdated
|
||
| py::str result; | ||
| if (CFStringGetCString(str, buffer, maxSize, kCFStringEncodingUTF8)) { | ||
| result = py::str(buffer); | ||
| } | ||
| delete[] buffer; | ||
| return result; | ||
| }; | ||
|
|
||
| auto collection = CTFontCollectionCreateFromAvailableFonts(NULL); | ||
| auto descriptors = collection ? | ||
| CTFontCollectionCreateMatchingFontDescriptors(collection) : NULL; | ||
| auto count = descriptors ? CFArrayGetCount(descriptors) : 0; | ||
| for (CFIndex i = 0; i < count; i++) { | ||
| auto descriptor = static_cast<CTFontDescriptorRef>( | ||
| CFArrayGetValueAtIndex(descriptors, i)); | ||
| auto url = static_cast<CFURLRef>( | ||
| CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute)); | ||
| CFStringRef path = NULL; | ||
|
iccir marked this conversation as resolved.
Outdated
|
||
| if (url) { | ||
| path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); | ||
| CFRelease(url); | ||
| } | ||
| if (path) { | ||
| auto pyStr = cfStringToPyStr(path); | ||
| if (pyStr) { | ||
| fonts.add(pyStr); | ||
| } | ||
| CFRelease(path); | ||
| } | ||
| } | ||
| if (descriptors) { | ||
| CFRelease(descriptors); | ||
| } | ||
| if (collection) { | ||
| CFRelease(collection); | ||
| } | ||
| return fonts; | ||
| #else | ||
| return py::none(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be a py::set() call so that you can iterate it on the returning item even on a non macos platform? It is private, so probably not a big deal either way, but you are calling it as
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was trying to mimic the "on other platforms, returns None" in I think I think raising |
||
| #endif | ||
| } | ||
|
|
||
| static py::object | ||
| mpl_GetCurrentProcessExplicitAppUserModelID(void) | ||
| { | ||
|
|
@@ -210,6 +270,13 @@ PYBIND11_MODULE(_c_internal_utils, m, py::mod_gil_not_used()) | |
| only (e.g., for Tkinter). | ||
|
|
||
| On other platforms, always returns True.)"""); | ||
| m.def( | ||
| "get_available_fonts", &mpl_GetAvailableFonts, | ||
| R"""( -- | ||
| On macOS, uses CoreText to find all fonts available to the current | ||
| process and returns the paths as a set of strings. | ||
|
|
||
| On other platforms, always returns None.)"""); | ||
| m.def( | ||
| "Win32_GetCurrentProcessExplicitAppUserModelID", | ||
| &mpl_GetCurrentProcessExplicitAppUserModelID, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.