Skip to content
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

Use nearby fonts for font fallback #11764

Merged
3 commits merged into from
Nov 16, 2021
Merged

Conversation

lhecker
Copy link
Member

@lhecker lhecker commented Nov 15, 2021

This commit is a minimal fix in order to pass the
IDWriteFontCollection we create out of .ttf files residing next to our
binaries to the IDWriteFontFallback::MapCharacters call. The
IDWriteTextFormat is used in order to carry the font collection over
into CustomTextLayout.

Validation

  • Put JetBrainsMono-Regular.ttf into the binary output directory
  • Modify HKCU:\Console\*\FaceName to JetBrains Mono
  • Launch OpenConsole.exe
  • OpenConsole uses JetBrains Mono ✔️

Closes #11032
Closes #11648

@lhecker lhecker requested a review from miniksa November 15, 2021 18:07
@ghost ghost added Area-Fonts Related to the font Issue-Bug It either shouldn't be doing this or needs an investigation. Priority-1 A description (P1) Priority-3 A description (P3) Product-Terminal The new Windows Terminal. labels Nov 15, 2021
@lhecker
Copy link
Member Author

lhecker commented Nov 15, 2021

With this PR finally open I'll go back into suspension vacation.

I have a branch that fixes this issue much more thoroughly, by getting rid of the entire DxFontInfo class as well as most of the font features and axes code and some other bits altogether (removes about 10-15% of DxEngine).
But I felt like that's pure overkill so I'm saving that one for later. 😈

I realize I didn't test it with WT under Windows Server 2022, but I had to uninstall Hyper-V in order to test Windows 7 rendering stuff, so... Yeah let me know if you think my testing methodology is enough. Otherwise I'll reinstall Hyper-V soon and test it again.
IMO it's enough, since I didn't touch DxFontInfo::s_GetNearbyFonts at all. As such the only way my change can work, is by fixing it fundamentally for all cases (including app packages on Windows Server 2022).

@ianjoneill
Copy link
Contributor

This does address the underlying problem on Server 2022.

Windows2022

However, it doesn't make any changes to the settings UI. As I noted in #11032 the SUI uses the system font collection, so the font isn't displayed in the dropdown. This leads to a bit of a weird UI - the dropdown looks like it's empty. If you click on it, you can select a font, but not Cascadia. If you select e.g. Courier New, then decide you want to switch back, you need to use the reset button. Under the debugger clicking it causes an exception to be raised, but without the debugger attached, the button just disappears. Clicking save does revert the font successfully.

Demo:

Windows2022.mp4

@lhecker
Copy link
Member Author

lhecker commented Nov 15, 2021

@ianjoneill I pushed the code for the settings UI just now.

@github-actions

This comment has been minimized.

@@ -3,13 +3,62 @@

#include "pch.h"
#include "Profiles.h"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Member Author

@lhecker lhecker Nov 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah this is just me following the most common C++ style guide for imports... It breaks them up into the following order:

  • "pch.h"
  • "class.h"
  • blank line
  • <system headers>
  • blank line
  • <stdlib headers>
  • blank line
  • <other global headers>
  • blank line
  • "local headers.h"

(Google has a good explanation here.)

This ordering helps with clarity as you know immediately where some file resides at. This is especially helpful with MSVC, which for whatever reason has decided to not actually implement C++ and treats #include "foo" and #include <foo> synonymous. With the above order such imports cannot be confused anymore under msvc, which is nice. ¹ You'll find that most projects follow this style and in fact even in this project most code follows this style already.

But in short: Considering that our project already does this for most files, I feel like it's alright to modify files that don't do this yet.

¹ Turns out every compiler does that. The only thing msvc does differently is that it searches in the parent directories of all previously included files in a unit as well.``

// The convenience interfaces for loading fonts from files
// are only available on Windows 10+.
wil::com_ptr<IDWriteFactory6> factory6;
// wil's query() facilities don't work inside WinRT land at the moment.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this filed against microsoft/wil and/or are we just behind on updating our copy of wil?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got a TODO item to open a PR for that when I'm back at work. Since it's an easy fix that seemed better to me than opening an issue. 🙂

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC that's an ordering issue - something about including wil before winrt, or vice-versa, or something like that. My memory's hazy on this...

@@ -107,8 +156,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
reinterpret_cast<::IUnknown**>(factory.put())));

// get the font collection; subscribe to updates
com_ptr<IDWriteFontCollection> fontCollection;
THROW_IF_FAILED(factory->GetSystemFontCollection(fontCollection.put(), TRUE));
const auto fontCollection = NearbyCollection(factory.get());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will recreate it every time the page reloads the view model? Not a perf issue?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I could tell this only loads once when the settings page is opened. Navigating back and forth between views didn't call this function again.

Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm only worried about the Win10 comment there. Otherwise this is a ✅ from me

// The convenience interfaces for loading fonts from files
// are only available on Windows 10+.
wil::com_ptr<IDWriteFactory6> factory6;
// wil's query() facilities don't work inside WinRT land at the moment.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC that's an ordering issue - something about including wil before winrt, or vice-versa, or something like that. My memory's hazy on this...


// The convenience interfaces for loading fonts from files
// are only available on Windows 10+.
// Don't try to look up if below that OS version.
static const bool s_isWindows10OrGreater = IsWindows10OrGreater();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to this check? Are these available on Win7 now? (If so, we should get rid of the comment, or update to say that it doesn't matter)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I had to guess, it's because we switched to using QueryInterface to determine whether the factory supported the requisite interface.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is always better to do live detection of features (think backports!) instead of version number checks.

Copy link
Member Author

@lhecker lhecker Nov 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, version checks (including the entirety of IsWindowsXOrGreater() functions) are basically deprecated. We're supposed to do feature checks nowadays instead.

This is especially so since the current code has a bug. Can you spot it? 😄
It's this line:

        // Builder2 has a convenience to just feed in paths to font files.
        ::Microsoft::WRL::ComPtr<IDWriteFontSetBuilder2> fontSetBuilder2;
        THROW_IF_FAILED(fontSetBuilder.As(&fontSetBuilder2));

This will throw if you don't have Windows 10 Build 20348 or newer installed, which lead to #10211 and got solved somewhat "by accident" in a way, since the problem wasn't just corrupted fonts per se.

Copy link
Member Author

@lhecker lhecker Nov 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh btw: Let's not store results from VersionHelpers.h into statics. The data it uses comes from the PEB (process environment block) and while the version check isn't trival (since you can set a ton of fields and flags when calling VerifyVersionInfoW), it's not a syscall and can read the version straight from process-local memory (the PEB is local to each process).
The overhead of using a static is likely greater than just calling the function. 😅

Copy link
Member

@DHowett DHowett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know who "wins" in this font collection? Ideally, if a user installs a newer version of Cascadia on their system the nearby version would be ignored.

@DHowett DHowett added zPreview-Service-Queued-1.13 A floating label that tracks the current Preview version for servicing purposes. zStable-Service-Queued-1.12 A floating label that tracks the current Stable version for servicing purposes. labels Nov 16, 2021
@lhecker
Copy link
Member Author

lhecker commented Nov 16, 2021

I suspect that the font set builder is an ordered list. @miniksa mentioned that it always prefers the system font collection if the code is written this way.

@zadjii-msft zadjii-msft added the AutoMerge Marked for automatic merge by the bot when requirements are met label Nov 16, 2021
@ghost
Copy link

ghost commented Nov 16, 2021

Hello @zadjii-msft!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit 131f5d2 into main Nov 16, 2021
@ghost ghost deleted the dev/lhecker/issue-11032-font-fallback branch November 16, 2021 23:22
@miniksa
Copy link
Member

miniksa commented Nov 22, 2021

I suspect that the font set builder is an ordered list. @miniksa mentioned that it always prefers the system font collection if the code is written this way.

I believe that's what @fdwr told me.

DHowett pushed a commit that referenced this pull request Dec 13, 2021
This commit is a minimal fix in order to pass the
`IDWriteFontCollection` we create out of .ttf files residing next to our
binaries to the `IDWriteFontFallback::MapCharacters` call. The
`IDWriteTextFormat` is used in order to carry the font collection over
into `CustomTextLayout`.

## Validation
* Put `JetBrainsMono-Regular.ttf` into the binary output directory
* Modify `HKCU:\Console\*\FaceName`  to `JetBrains Mono`
* Launch OpenConsole.exe
* OpenConsole uses JetBrains Mono ✔️

Closes #11032
Closes #11648

(cherry picked from commit 131f5d2)
DHowett pushed a commit that referenced this pull request Dec 13, 2021
This commit is a minimal fix in order to pass the
`IDWriteFontCollection` we create out of .ttf files residing next to our
binaries to the `IDWriteFontFallback::MapCharacters` call. The
`IDWriteTextFormat` is used in order to carry the font collection over
into `CustomTextLayout`.

## Validation
* Put `JetBrainsMono-Regular.ttf` into the binary output directory
* Modify `HKCU:\Console\*\FaceName`  to `JetBrains Mono`
* Launch OpenConsole.exe
* OpenConsole uses JetBrains Mono ✔️

Closes #11032
Closes #11648

(cherry picked from commit 131f5d2)
@DHowett DHowett removed zStable-Service-Queued-1.12 A floating label that tracks the current Stable version for servicing purposes. zPreview-Service-Queued-1.13 A floating label that tracks the current Preview version for servicing purposes. labels Dec 13, 2021
@ghost
Copy link

ghost commented Dec 14, 2021

🎉Windows Terminal Preview v1.12.3472.0 has been released which incorporates this pull request.:tada:

Handy links:

@ghost
Copy link

ghost commented Dec 14, 2021

🎉Windows Terminal v1.11.3471.0 has been released which incorporates this pull request.:tada:

Handy links:

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Fonts Related to the font AutoMerge Marked for automatic merge by the bot when requirements are met Issue-Bug It either shouldn't be doing this or needs an investigation. Priority-1 A description (P1) Priority-3 A description (P3) Product-Terminal The new Windows Terminal.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Terminal suddenly can't find the font Cascadia Mono Weird fonts on Windows Server 2022
5 participants