-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[MNT]: findSystemFonts - Use system API instead to look into folder #24001
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
Comments
So I've been working on the Windows part of this (it turns out it was slightly more complex than the functions you highlighted, but that gave me the pointers I needed):
(I'm planning to release this as a stand-alone python module as I actually need it for a separate project) |
I am sorry. I thought it was the right logic. By curiosity, which method have you used?
|
@moi15moi You had the right functions, but the issue was that GetFilePathFromKey needs to be called on an instance of And I think I've used the Vista+ approach. |
Ok, then, i think you could have called GetLoader from the object you have with GetFiles Here is the updated version Logic for Windows Vista to this day:
Here is the pseudo-code font_collection = GetSystemFontCollection()
for i in range(font_collection.GetFontFamilyCount()):
font_family = font_collection.GetFontFamily(i)
matching_fonts = GetMatchingFonts(ANY_WEIGHT, ANY_STRETCH, ANY_STYLE)
for j in range(matching_fonts.GetFontCount()):
font = matching_fonts.GetFont(j)
font_face = font.CreateFontFace()
files = font_face.GetFiles()
loader = files.GetLoader()
reference_key, reference_key_size = files.GetReferenceKey()
path = loader.GetFilePathFromKey(reference_key, reference_key_size) Edit: GetLoader return an instance of IDWriteFontFileLoader. It doesn't return of instance of IDWriteLocalFontFileLoader. Sorry, i missread that. But, i just found this: https://social.msdn.microsoft.com/Forums/vstudio/en-US/8f57b186-9cf6-417a-8923-092b406d94ea/obtain-filename-from-directwrite-font?forum=windowsuidevelopment |
Yup, that's what I used to get it working :) |
First alpha release available at https://pypi.org/project/windows-fonts/0.1.0a1/ |
Hey is anybody working on the mac portion of this? If not I'd like to have a crack. |
@kostyafarber, it doesn't look like anyone is working on the mac side of this and in general we have very few people looking into the objective c portion of the code, so I would say go for it! You can also find other mac issues with this label: GUI: MacOSX |
For the windows version would we need to write up the code in c++ and write a Python binding and use it in For the Mac version are we happy to explore using https://pypi.org/project/pyobjc-framework-CoreText/ or would we prefer to use a binding as well? |
I would much rather have bindings in Matplotlib than pick up a dependency for this. If it is so complex that we need a dependency rather than just implementing it, than I think that continuing to search the directories is fine. |
I decided to do a repos to show you how I implemented it: https://github.com/moi15moi/FindSystemFontsFilename I haven't open an PR here since font_manager can search for .afm file which cannot be done with DirectWrite and CoreText (it may be possible with FontConfig, but I haven't check) |
Summary
Currently, findSystemFonts look at all the file in the specified folders for macos and windows.
This is not a very good method, because a font in a "Font folder" does not necessarily need to be picked up.
A very good example of that is in this issue: #22859
This is why I propose to use CoreText (for mac) and DirectWrite (for Windows).
These are API provided by Apple and Microsoft.
Proposed fix
CoreText - For MAC
In this example, I use this library: https://pypi.org/project/pyobjc-framework-CoreText/
DirectWrite - For Windows
I don't know much C/C++, so I can't give an good example.
On recent Windows build, it is pretty simple to get the font path with DirectWrite, but since matplotlib seems to support Windows 7, we would maybe need to use the "complex" solution.
But, here is how I understand it (I have no proof that it works):
Logic for to support only Windows 10:
Here is an "pseudo-code" of how I see it.
Logic for Windows Vista to this day:
I have try to see if the GDI api could help us to get the path of the fonts, but from what I can see, it is not an available feature: https://learn.microsoft.com/en-us/windows/win32/gdi/font-and-text-functions
FontConfig (Bonus) - For Linux
Currently, matplotlib parse the result from subprocess.
It would be an good idea to directly use FontConfig. See this answer from stackoverflow to know how to do it: https://stackoverflow.com/a/14634033
I did not found any FontConfig bindings library that are still maintained, so it would need to be implemented with Cython.
The text was updated successfully, but these errors were encountered: