-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Allow FontInfo{,Base,Desired} to store a font name > 32 wch #3107
Conversation
We now truncate the font name as it goes out to GDI APIs, in console API servicing, and in the propsheet. Fixes #602.
I also tested with my font set to |
argh, I used the wrong browser profile to submit this PR |
I think #2674 might be resolved or close to resolved with this too. Can you check that? |
Closer, but not there yet. It's suppressed in two places, one of which still has some static wstrings (font, padding, starting directory, delimiters) |
I think so, yes.
I think so, yes.
Here if it's possible. I would love for conhost to get the benefits of this too.
It's not for interop. It was just shared between the
I also think font weight is 100-900 so |
src/renderer/gdi/state.cpp
Outdated
@@ -396,7 +396,8 @@ GdiEngine::~GdiEngine() | |||
// NOTE: not using what GDI gave us because some fonts don't quite roundtrip (e.g. MS Gothic and VL Gothic) | |||
lf.lfPitchAndFamily = (FIXED_PITCH | FF_MODERN); | |||
|
|||
wcscpy_s(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FontDesired.GetFaceName()); | |||
// NOTE: GDI cannot support font faces > 32 characters in length. THIS TRUNCATES THE FONT. |
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.
Do we have any idea if GDI will accept the first 31-32 characters of a font whose name is too long and still resolve the correctish one?
src/renderer/gdi/state.cpp
Outdated
@@ -396,7 +396,8 @@ GdiEngine::~GdiEngine() | |||
// NOTE: not using what GDI gave us because some fonts don't quite roundtrip (e.g. MS Gothic and VL Gothic) | |||
lf.lfPitchAndFamily = (FIXED_PITCH | FF_MODERN); | |||
|
|||
wcscpy_s(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FontDesired.GetFaceName()); | |||
// NOTE: GDI cannot support font faces > 32 characters in length. THIS TRUNCATES THE FONT. | |||
wcscpy_s(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FontDesired.GetFaceName().data()); |
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.
StringCchCopy maybe? It has an HRESULT failure code...
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.
- Should we log truncation at the API boundary to telemetry?
I think so, yes.
K.
- Should the "launch face name" get the same treatment as the face name in Settings?
I think so, yes.
K.
- Should we fix Settings here, or later?
Here if it's possible. I would love for conhost to get the benefits of this too.
This one is a far bigger workitem, so I filed #3123 as a followup. I looked into doing this to TrueTypeFontList, and it cascades up through all the dialog procedure code, so I'm scared off of doing it for this pR.
TrueTypeFontList
is built out of things in winconp, the private console header. That fills me with dread that those structures are used for interop -- so I didn't bubble these fixes all the way up through the "default font" list, even though nominally the font list is also unbounded strings.It's not for interop. It was just shared between the
conhost
andpropsheet
code which used to live in different depots and were both written in just plain C. Now that both of them can use C++ and live in the same depot, you're welcome to bubble it the whole way throughTrueTypeFontList
(and half rewrite that bugger if you like to use modern collections and stuff). Or set it as a TODO for someone else to do.
Roger, but as above: propsheet needs more modernization than conhost today to get this bootstrapped.
- Is
unsigned int
right for codepage? For width?
Int
might be a bit too big for codepage. I think Codepage is actually anunsigned short
. But I'm fine withunsigned int
if that fits better in things.I also think font weight is 100-900 so
unsigned short
might be more appropriately sized there too. (Width translated to weight via asking you what "width" was all about in Teams.)
I was going to say "bah i'll stick with int
", but then I decided to use short
and use gsl's throwing narrower so that we can root out anybody who doesn't comply.
It looks like SetCurrentConsoleFont lets you pass an int for weight, but the docs say it ranges from 0-1000 so maybe this is fine? That one's getting a non-throwing narrow.
Actually, on the telemetry front: we'll get a log and fail to service the API call when the font name is too long. Right now, there's no way to get a font name that's too long... so I'm going to tag this with #3123 as well. |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
Okay, clearly I regressed this. |
src/host/getset.cpp
Outdated
@@ -269,7 +269,8 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept | |||
consoleFontInfoEx.FontFamily = fontInfo.GetFamily(); | |||
consoleFontInfoEx.FontWeight = fontInfo.GetWeight(); | |||
|
|||
RETURN_IF_FAILED(StringCchCopyW(consoleFontInfoEx.FaceName, ARRAYSIZE(consoleFontInfoEx.FaceName), fontInfo.GetFaceName())); | |||
// GH#3123: We will fail to service the API if the font name is longer than 32 characters. |
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.
Ehhh can we just truncate it to safely fit? I feel that's better than failing.
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.
Maybe we want a method that's like "GetNameGdiCompatible()" that fills an LF_FACESIZE size array.
src/host/settings.cpp
Outdated
@@ -404,13 +403,13 @@ void Settings::SetFilterOnPaste(const bool fFilterOnPaste) | |||
_fFilterOnPaste = fFilterOnPaste; | |||
} | |||
|
|||
const WCHAR* const Settings::GetLaunchFaceName() const | |||
const std::wstring& Settings::GetLaunchFaceName() const |
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.
What? Why? Why not just a std::wstring_view?
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.
/shrug no real reason, i went with your first suggestion instead of your second
src/renderer/gdi/state.cpp
Outdated
@@ -374,7 +374,7 @@ GdiEngine::~GdiEngine() | |||
// Because the API is affected by the raster/TT status of the actively selected font, we can't have | |||
// GDI choosing a TT font for us when we ask for Raster. We have to settle for forcing the current system | |||
// Terminal font to load even if it doesn't have the glyphs necessary such that the APIs continue to work fine. | |||
if (0 == wcscmp(FontDesired.GetFaceName(), L"Terminal")) | |||
if (FontDesired.GetFaceName() == L"Terminal") |
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 know it didn't have a whole lot to do with you here, but should the magic string L"Terminal"
be a constexpr at the top instead of here?
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.
Yep, good enough. Thanks.
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
ec32aca
to
83fcb6c
Compare
I'm extremely confused/alarmed. The selection tests were failing because the Time travel tracing indicates that the constructor for Why do they share storage? |
It turns out that there's an ODR violation! This bug only exists in our tests. The fix in 83fcb6c moves the trampled global out of the way... but just fixes the symptom. :| |
Followup filed in #3170. |
🎉 Handy links: |
Summary of the Pull Request
We now truncate the font name as it goes out to GDI APIs, in console API
servicing, and in the propsheet.
I attempted to defer truncating the font to as far up the stack as possible, so as to make FontInfo usable for the broadest set of cases.
PR Checklist
Detailed Description of the Pull Request / Additional comments
There are a couple things I have questions about, actually. I know that
Settings
gets memset (memsat?) by the registry deserializer, and perhaps that's another place for us to tackle. Right now, this pull request enables fonts whose names are >= 32 characters in Windows Terminal only, but the underpinnings are there for conhost as well. We'd need to explicitly break at the API, or perhaps return a failure or log something to telemetry.TrueTypeFontList
is built out of things in winconp, the private console header. That fills me with dread that those structures are used for interop -- so I didn't bubble these fixes all the way up through the "default font" list, even though nominally the font list is also unbounded strings.unsigned int
right for codepage? For width?I left some comments about truncating font faces around, but they could be tantamount to noise.