-
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
Implement cell size customizations #14255
Conversation
3660b47
to
aaec2a5
Compare
IncrementNumberRounder rounder; | ||
rounder.Increment(1e-6); |
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.
Before you get too excited, I have to mention again that this PR doesn't work great by itself. Neither the old/stable nor new/preview text renderer work correctly with line heights less than approx. 1.2, which is what a significant portion of people in #3498 have asked for though. I'm working on that separately, but that will unfortunately take another couple months to complete on the side. |
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.
Mainly concerned about inheritance being done properly. It feels weird to introduce two settings in the cellSize
object but then store them as two different members in the settings model.
Also confused why this isn't going in the FontConfig.
This comment has been minimized.
This comment has been minimized.
0c945b6
to
9554470
Compare
This comment has been minimized.
This comment has been minimized.
I've moved the two fields into the font config object now. With the primary target being the line height customization, the resulting config might look something like this to the user: {
"profiles":
{
"defaults":
{
"font":
{
"face": "Consolas",
"size": 13,
"cellHeight": "1.4"
}
}
}
} |
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 have to trust the math in AtlasEngine.api.cpp. I did however check the math in Dx :)
@@ -39,6 +39,7 @@ namespace Microsoft.Terminal.Settings.Editor | |||
|
|||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, FontFace); | |||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Single, FontSize); | |||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Double, LineHeight); |
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.
one's a single, one's a double!
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.
Double
is technically the better one, because that's what WinUI's setters and getters use. But we use float
and Single
throughout the project (which is alright - we don't need more than 2-3 decimal places for anything), including for the FontSize
property. LineHeight
on the other hand is a custom getter/setter and I felt like it'd be better to use Double
if we can when interfacing with WinUI.
@@ -219,7 +219,6 @@ | |||
Visibility="{x:Bind Appearance.IsDefault, Mode=OneWay}"> | |||
<muxc:NumberBox x:Name="_fontSizeBox" | |||
x:Uid="Profile_FontSizeBox" | |||
AcceptsExpression="False" |
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.
Does it accept expressions now?
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.
false is the default!
<comment>A description for what the "line height" setting does. Presented near "Profile_LineHeight".</comment> | ||
</data> | ||
<data name="Profile_LineHeightBox.PlaceholderText" xml:space="preserve"> | ||
<value>1.2</value> |
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.
will users be confused that it says 1.2 but the default is not 1.2?
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 felt like a placeholder made the input feel a little less confusing. 1.2 is reasonably close to the line height of most fonts (I've seen anything between about 1.15 and 1.35).
// Font settings | ||
const auto fontInfoImpl = winrt::get_self<FontConfig>(_FontInfo); | ||
if (fontInfoImpl->HasAnyOptionSet()) | ||
if (auto fontJSON = winrt::get_self<FontConfig>(_FontInfo)->ToJson(); !fontJSON.empty()) |
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.
interesting. serialize first, then check!
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! I felt like that it made the code a lot simpler.
|
||
CSSLengthPercentage CSSLengthPercentage::FromString(const wchar_t* str) | ||
{ | ||
auto& errnoRef = errno; // Nonzero cost, pay it once. |
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 is the cost and how does this ensure we pay it only once? Is it the thread safety?
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 think it's because errno
is a thread-local variable and this gets the reference to the actual storage early. I took the code and the comment from the STL.
} | ||
else | ||
{ | ||
return {}; |
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.
silent discard - OK?
i notice we have no way of expressing a failure to parse this via the settings warning dialog
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.
It's not okay, but I tried the alternative by implementing a WinRT runtimeclass for CSSLengthPercentage
and using that as the value for CellWidth/Height and that was quite the mess. I would not mind adding an extra check during the settings loading. I could call CSSLengthPercentage::FromString
inside the FontConfig::LayerJson
to check if it's valid since wcstof
and wcscmp
aren't /that/ expensive. But I wasn't personally convinced it's worth it (by asking myself "Would anyone notice if I don't check this?"). Would you say I should do it?
|
||
float CSSLengthPercentage::Resolve(float factor) const noexcept | ||
{ | ||
return _value * factor; |
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 don't love how we have two functions, same name, one of which uses the local reference frame and one of which doesn't. Gotta look more to see what it means
@@ -11,6 +11,7 @@ | |||
<Import Project="$(SolutionDir)src\common.build.pre.props" /> | |||
<Import Project="$(SolutionDir)src\common.nugetversions.props" /> | |||
<ItemGroup> | |||
<ClCompile Include="..\CSSLengthPercentage.cpp" /> |
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 you need to add this to sources
, or will it be okay to not link anything related to CSSLengthPercentage inside Windows?
const auto lineHeight = desired.GetCellHeight().Resolve(defaultHeight, dpiF, heightDesired, widthAdvanceInPx); | ||
const auto baseline = fullPixelAscent + (lineHeight - defaultHeight) / 2.0f; | ||
|
||
lineSpacing.height = roundf(lineHeight); |
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.
This isn't going to result in a different outcome for users who haven't customized cellHeight, right?
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.
Yeah, because defaultHeight
is an integer and that's what Resolve()
returns if no cellHeight is set.
Just for the sake of clarity; while a lot of the vocal majority are wanting smaller line heights- there are folk like me out there who want the opposite. I want more distance between my lines. As such, I speak for us all when I say- thank you for doing this. It's the small QoL stuff like this that honestly adds up. |
I would love to have access to this feature. Is 1.18 on the horizon? |
Yep, probably not for a couple months though. We're working on some... bigger... features that might take longer to bake. We're still discussing the finer points of our plan here though. |
This is practically a from scratch rewrite of AtlasEngine. The initial approach used a very classic monospace text renderer, where the viewport is subdivided into cells and each cell is assigned one glyph texture, just like how real terminals used to work. While we knew that it would have problems with overly large glyphs, like those found in less often used languages, we didn't expect the absolutely massive number of fonts that this approach would break. For one, the assumption that monospace fonts are actually mostly monospace has turned out to be a complete lie and we can't force users to use better designed fonts. But more importantly, we can't just design an entire Unicode fallback font collection from scratch where every major glyph is monospace either. This is especially problematic for vertical overhangs which are extremely difficult to handle in a way that outperforms the much simpler alternative approach: Just implementing a bog-standard, modern, quad-based text renderer. Such an approach is both, less code and runs faster due to a less complex CPU-side. The text shaping engine (in our case DirectWrite) has to resolve text into glyph indices anyways, so using them directly for text rendering allows reduces the effort of turning it back into text ranges and hashing those. It's memory overhead is also reduced, because we can now break up long ligatures into their individual glyphs. Especially on AMD APUs I found this approach to run much faster. A list of issues I think are either obsolete (and could be closed) or resolved with this PR in combination with #14255: Closes #6864 Closes #6974 Closes #8993 Closes #9940 Closes #10128 Closes #12537 Closes #13064 Closes #13527 Closes #13662 Closes #13700 Closes #13989 Closes #14022 Closes #14057 Closes #14094 Closes #14098 Closes #14117 Closes #14533 Closes #14877 ## PR Checklist * Enabling software rendering enables D2D mode ✅ * Both D2D and D3D: * Background appears correctly ✅✅ * Text appears correctly * Cascadia Code Regular ✅✅ * Cascadia Code Bold ✅✅ * Cascadia Code Italic ✅✅ * Cascadia Code block chars leave (almost) no gaps ✅✅ * Terminus TTF at 13.5pt leaves no gaps between block chars ✅✅ * ``"`u{e0b2}`u{e0b0}"`` in Fira Code Nerd Font forms a square ✅✅ * Cursor appears correctly * Legacy small/medium/large ✅✅ * Vertical bar ✅✅ * Underscore ✅✅ * Empty box ✅✅ * Full box ✅✅ * Double underscore ✅✅ * Changing the cursor color works ✅✅ * Selection appears correctly ✅✅ * Scrolling in various manners always renders correctly ✅✅ * Changing the text antialising mode works ✅✅ * Semi-transparent backgrounds work ✅✅ * Scroll-zooming the font size works ✅✅ * Double-size characters work ✅✅ * Resizing while text is printing works ✅✅ * DWM `+Heatmap_ShowDirtyRegions` shows that only the cursor region is dirty when it's blinking ✅✅ * D2D * Margins are filled with background color ❌ They're filled with the neighboring's cell background color for convenience, as D2D doesn't support `D3D11_TEXTURE_ADDRESS_BORDER` * D3D * Margins are filled with background color ✅ * Soft fonts work ✅ * Custom shaders enable continous redraw if time constant is used ✅ * Retro shader appears correctly ✅ * Resizing while a custom shader is running works ✅
Does what it says in the title. After this commit you can customize the height
and width of the terminal's cells. This commit supports parts of CSS'
<length-percentage>
data type: Font-size relative sizes as multiples (1.2
),percentage (
120%
), or advance-width relative (1.2ch
), as well as absolutesizes in CSS pixels (
px
) or points (pt
).This PR is neither bug free in DxEngine, nor in AtlasEngine.
The former fails to implement glyph advance corrections (for instance #9381),
as well as disallowing glyphs to overlap rows. The latter has the same
overlap issue, but more severely as it tries to shrink glyphs to fit in.
Closes #3498
Closes #14068
Validation Steps Performed
height
to1
creates 12pt tall rows ✅height
to1ch
creates square cells ✅width
to1
creates square cells ✅width
orheight
toNpx
orNpt
works ✅displays 6 fractional digits ✅