-
Notifications
You must be signed in to change notification settings - Fork 36
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
Rework windows font collector #107
Rework windows font collector #107
Conversation
This replaces all the logic of using the Windows registry to obtain the font path by using DirectWrite. The goal is simply to improve the quality of the code. This doesn't change any functionality
Uniscribe was only used for the FontCollector. Since we now use DirectWrite, we don't need it anymore.
…raise On Windows, the initialization of the FontCollector can raise an exception
The CI failure for MacOS seems unrelated to this PR.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I finally had time to look through this - thanks a lot for the PR!
Looking through it, everything seems to be correct as long as I trust you on the DirectWrite/GDI wrangling (and barring the IDWriteLocalFontLoader
question on Discord). I do have a few comments regarding general code style and conventions, though.
…se to std::wstring
I did a bunch of test with the user. |
In some specific cases, the FontCollector can make a mistake in obtaining the font weight and italic style. FontCollector will return the font path to "AliviaRegular_Weight31961.ttf" (which is correct), but it will select the weight and italic style from "Alivia.otf." Because of this problem, the I tried to see if there is a way to avoid this problem, but I didn't find one.
Conclusion: |
…ect fake_italic/fake_bold See this comment: arch1t3cht#107 (comment)
336647f
to
83f8c7f
Compare
…correctly verify if font has character(s) With the Visual Studio 2019 toolchain on Windows 7, it installs the Windows 10 SDK by default. Because of this, ``HAVE_DWRITE_3`` is true, so the ``QueryInterface`` always fails. Now, if the ``QueryInterface`` fails, we try to verify if the font has characters with a Windows Vista SP2 compatible code.
…ect fake_italic/fake_bold See this comment: arch1t3cht#107 (comment)
…pace AND truncated facename Problem 1: Previously, if a user wrote "\fn ", it would return the font Arial, which is not what we want. This is because when we request EnumFontFamiliesEx with whitespace or an empty lfFaceName, it will enumerate all the installed fonts. Solution 1: To resolve this issue, let's implement a solution similar to libass to determine if the selected facename exists: https://github.com/libass/libass/blob/649a7c2e1fc6f4188ea1a89968560715800b883d/libass/ass_directwrite.c#L737-L747 Problem 2: GDI truncates font names to 31 characters. See: libass/libass#459 However, since I changed the method to determine if a facename exists, I ensured that we still support this "feature". To test this, I used the font in: libass/libass#710
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates. Just a couple more nitpicks left. Once those are addressed, you can squash everything onto one commit and I'll merge it (or if you want to keep the commit history on your branch I'll squash it myself when merging).
src/font_file_lister_gdi.cpp
Outdated
LOGFONTW lf{}; | ||
lf.lfCharSet = DEFAULT_CHARSET; | ||
lf.lfCharSet = DEFAULT_CHARSET; // we should use the one specified in the ass file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's probably better to treat encodings different from 1 as "unsupported". What I really meant here, though, is that currently this comment is a bit confusing. You can remove it or reword it to something like "note that this currently ignores the font encoding specified in the ass file".
I will let you squash them. I would like to conserve the commits. Some of them contain relevant information that may be useful if a problem is discovered in the future. |
[src\meson.build] Add DirectWrite has dependency [src\font_file_lister_gdi] Rework GDI FontCollector to use DirectWrite This replaces all the logic of using the Windows registry to obtain the font path by using DirectWrite. The goal is simply to improve the quality of the code. This doesn't change any functionality [src\meson.build] Remove Uniscribe has dependency Uniscribe was only used for the FontCollector. Since we now use DirectWrite, we don't need it anymore. [src\dialog_fonts_collector] Catch exceptions that FontCollector may raise On Windows, the initialization of the FontCollector can raise an exception [src\font_file_lister] Document the exception that GdiFontFileLister can throw [src\font_file_lister_gdi] Correct possible memory leak when an error occur Fix error caused by AddFontResource on Windows 10 or higher [meson.build] Replace add_project_arguments with conf.set for HAVE_DWRITE_3 [src\dialog_fonts_collector] Update message error and optimisation [src\font_file_lister_gdi] Correct documentation typo [src\font_file_lister_gdi] Cosmetic nit - Initialize hfont in one line [src\font_file_lister_gdi] Cosmetic nit - Remove if statements brace [src\font_file_lister_gdi] Replace WCHAR param of normalizeFilePathCase to std::wstring [src\font_file_lister_gdi] Replace WCHAR by std::wstring [src\font_file_lister_gdi] Use IDWriteFontFace::GetSimulations to detect fake_italic/fake_bold See this comment: #107 (comment) [src\font_file_lister_gdi] If Win7/8 has Win 10 SDK on compile time, correctly verify if font has character(s) With the Visual Studio 2019 toolchain on Windows 7, it installs the Windows 10 SDK by default. Because of this, ``HAVE_DWRITE_3`` is true, so the ``QueryInterface`` always fails. Now, if the ``QueryInterface`` fails, we try to verify if the font has characters with a Windows Vista SP2 compatible code. [src\font_file_lister_gdi] Support facename that contains only whitespace AND truncated facename Problem 1: Previously, if a user wrote "\fn ", it would return the font Arial, which is not what we want. This is because when we request EnumFontFamiliesEx with whitespace or an empty lfFaceName, it will enumerate all the installed fonts. Solution 1: To resolve this issue, let's implement a solution similar to libass to determine if the selected facename exists: https://github.com/libass/libass/blob/649a7c2e1fc6f4188ea1a89968560715800b883d/libass/ass_directwrite.c#L737-L747 Problem 2: GDI truncates font names to 31 characters. See: libass/libass#459 However, since I changed the method to determine if a facename exists, I ensured that we still support this "feature". To test this, I used the font in: libass/libass#710 [src\font_file_lister_gdi] Add a FIXME comment regarding the utilization of std::wstring over WCHAR [src\font_file_lister_gdi] Add FIXME comment about charset
Thanks! Now squashed and merged in 7543060. |
The main goal of this PR is to replace the "hack" in the Windows FontCollector which involves using the Windows registry to obtain the font filename. Now, we use DirectWrite which can interop with GDI, so we are 100% sure it use the same font has VSFilter.
I have also removed Uniscribe, which was used to determine if a font has a specific character.
The sole objective of this PR is to enhance the code quality in the Windows FontCollector.
Now, the user can request a font by a fullname or postscript name like said in libass/libass#203. Previously, on windows, the user could only request a family name.
Should I move the method
normalizeFilePathCase
toAegisub/libaegisub/windows/fs.cpp
?Edit:
The commit de1d3e3 ensures that fonts installed via AddFontResource are detected by FontCollector. Previously, they were not recognized.
However, please note that this detection only works on Windows 10 or later. It's uncertain whether this behavior is a bug in the Windows API, but the fonts installed via AddFontResource aren't added to the IDWriteFontCollection. Consequently, we cannot convert IDWriteFontFace to IDWriteFont which impeding the ability to verify the presence of certain characters.