-
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
Use active font metrics for grid line rendering #6911
Comments
I should mention that I tried to see what the grid lines looked like in the legacy console, but I couldn't get any of the |
This one probably needs @miniksa's input. I think the gridlines were intended to be 1 px or 1 dip (pixel * scale). Personally, I'm fine with making them scale based on font size at a fixed em proportion. What's the optimization you're thinking about for 3? Niksa's knocking about in rendering recently, and I poked at it for #6193 (never landed, but might inform future direction). Idly, I wonder if we're getting closer to the time when we need to decouple underline/overline from gridlines and render them differently (per the callout in #2916)... |
OK, I'll wait to see what he says. I'm not in any rush to submit anything yet - I'm still looking into the GDI side of things.
My main objective was to change the grid line rendering from this pattern:
to this sort of thing:
So in the primary use case of a top or bottom line, you only need a single line being drawn, instead of a loop with lots of little strokes joined together. And pulling the conditions out of the loops in the left and right cases make those a little more efficient too (you can also pull up several of the offset calculations). These things probably aren't going to be a big deal in terms of performance, but I thought it was worth trying to clean it up a bit if I was going to be extending it anyway to support varying line widths (which is what we'll need for the underline and crossed-out attributes). Oh and I also noticed an off-by-one error in the top line rendering which needed fixing.
If you want me to wait for you guys to finish anything there, just let me know. Most of what I'm looking at is in the
That was one my reasons for proposing this refactoring. Even if we keep the current grid lines at 1px, I'd still like to get the code to a state where it's easy to add lines of different widths and at different offsets, and also get the metadata in place for the other line types. If you prefer, we could just include this work as part of the PR for the crossed-out attribute, or the underline decoupling, but I thought it might be cleaner to do it as a separate, preparatory step. |
Bold grid lines for instance, would benefit from changeable widths |
I actually really like this as it harnesses the style imparted by each font author. That was one of the reasons why I tried scaling on the box/line characters instead of ignoring them and drawing our own like some Terminals do. I am willing to be overridden, though, by the rest of you if you believe that I'm crazypants and we should do a specific pixel or em count (scaled by font and DPI) for all fonts.
You have to use the
Per
I'm fine with this.
Given that the decision came from We probably should preserve that 1px for the GDI side though (and the other oddball renderers, if they even handle grid lines) and only change the DX one to some other proportion.
Yes, I like this. Fewer draw commands is always better.
No, don't wait. Go ahead.
I also agree with having them go in their own pass if necessary. I am OK with refactoring going in its own preparatory step to be cleaner. |
I'm not thrilled by this idea. At the moment DX is only used in Windows Terminal, and that doesn't actually use grid lines other than as a way to emulate underline and overline. Underline we're going to replace with a real underline with font-specific position and width. But overline isn't covered by font metrics, so it would be convenient if we could just leave it an alias for the top grid line. But if we go with that plan, then I'd expect the grid line width to be consistent, so that overline looked the same in both renderers. The other option would be for overline to get its own attribute bit, but then the DX renderer has no need to show grid lines at all, so there's still no point in making it render things differently. Bottom line is I don't really care what width we use, but I do think it would be preferable if it were consistent across renderers. |
Well, okay. We can make it consistent across renderers. I just try to avoid changing any of the other ones when possible because leaving them alone is a 0% chance of bugs/regression where as changing them in any way is now non-zero. I feel it's easier to avoid the problem. But if you are passionate about it being consistent, that's fine with me. |
First off, I just want to be clear that I am happy to let you guys make the final decision here - don't let me push you into doing something you're not comfortable with. That said, I've been playing around with a couple of different renderings to see how they feel, and think this might help with the decision making. In the image below you can see some test cases with three different fonts (Cascadia Mono, Consolas, and MS Gothic) in a range of "normal" font sizes (12pt to 18pt). It's rendered on a high DPI display (at 200%) so you'll want to scale the image to 50% in the browser to get an accurate feel for the size. In each case I'm rendering both top and bottom grid lines as well as a proper underline and strikethrough line. The grid lines are rendered in 3 different ways: 1 physical pixel (on the left); 1 device-independent pixel, i.e. 2 physical pixels (in the centre); and using the underline width (on the right). I found the middle one a bit odd, because with Cascadia you end up with grid lines wider than the standard underline, which just seems wrong. And then if you scale the font size up far enough the opposite happens - the underline becomes wider than the grid lines - so it's not even consistent. The one on the right (using the underline width) is nice in some ways, but with MS Gothic if feels like the grid lines are smothering the text, and this is one of the fonts I suspect is most likely to be used with grid lines. And in the case of Cascadia, the underline width is so narrow that's it's no different from a 1 pixel grid line anyway, at least for most "normal" font sizes. So after all that I'm starting to think our current rendering (i.e. 1 physical pixel) may well be the best option. However, I'd be a little happier with something like 0.025 em. That's still going to be 1 pixel for most normal font sizes (i.e. it'll look exactly like the left column), but if you did happen to zoom in a large amount, it would feel more natural to see the grid lines scaling. In short: first preference 0.025 em, second preference 1 physical pixel, but I'll leave it to you guys to make the final choice (and DX and GDI being different is not the end of the world for me). The way the code is now written it's essentially a one line change in each renderer to switch between widths, so it's not a big deal to play around with the different options if you change your mind. |
You're right, MS Gothic is most likely to be used with gridlines so that's the one we should probably make look the best with them. I'm alright with doing the 0.025em option across all the renderers. If it's that close to how it already is in a majority of cases, I can't see it causing me much if any trouble with the other renderers also changing. Also, I think I like the way the left most column of these looks as the best option. I'd rather it be based on a text metric though like a fractional em than on a pixel though, so I agree with your priority ranking. |
Yeah, I agree with that order as well. 👍
|
This is a refactoring of the grid line renderers, adjusting the line widths to scale with the font size, and optimising the implementation to cut down on the number of draw calls. It also extends the supported grid line types to include true underlines and strike-through lines in the style of the active font. The main gist of the optimisation was to render the horizontal lines with a single draw call, instead of a loop with lots of little strokes joined together. In the case of the vertical lines, which still needed to be handled in a loop, I've tried to move the majority of static calculations outside the loop, so there is bit of optimisation there too. At the same time this code was updated to support a variable stroke width for the lines, instead of having them hardcoded to 1 pixel. The width is now calculated as a fraction of the font size (0.025 "em"), which is still going to be 1 pixel wide in most typical usage, but will scale up appropriately if you zoom in far enough. And in preparation for supporting the SGR strike-through attribute, and true underlines, I've extended the grid line renders with options for handling those line types as well. The offset and thickness of the lines is obtained from the font metrics (rounded to a pixel width, with a minimum of one pixel), so they match the style of the font. VALIDATION For now we're still only rendering grid lines, and only the top and bottom lines in the case of the DirectX renderer in Windows Terminal. So to test, I hacked in some code to force the renderer to use all the different options, confirming that they were working in both the GDI and DirectX renderers. I've tested the output with a number of different fonts, comparing it with the same text rendered in WordPad. For the most part they match exactly, but there can be slight differences when we adjust the font size for grid alignment. And in the case of the GDI renderer, where we're working with pixel heights rather than points, it's difficult to match the sizes exactly. This is a first step towards supporting the strike-through attribute (#6205) and true underlines (#2915). Closes #6911
🎉This issue was addressed in #7107, which has now been successfully released as Handy links: |
Description of the new feature/enhancement
I was looking at adding support for the crossed-out attribute, but found that it doesn't look very good without getting the font metrics to draw the line in the right position, and ideally the right size. And I know there have also been discussions before about the need to draw the underline in the right position and size.
So as a first step, I thought it might be good idea to put together a PR just gathering the font line metrics, and updating the grid line code to take those metrics into account. This is not about drawing the underline in the right position yet - just getting the existing grid lines to scale with the font size.
Proposed technical implementation details (optional)
My first thought was to use the underline thickness metric for the width of all grid lines, and you can see an example of what that might look like below:
But based on those results, I'm now more inclined to think a hard coded size might be preferable. Either option would be better than the current single pixel width, though, which is almost invisible on high dpi displays. If we do go with a hard coded value, I think something around the thickness of Cascadia or Fira Code would be reasonable (that's about 0.025em).
And while looking at this area of the code, I also wanted to propose some refactoring of the grid line renderer to be more efficient. In the current implementation, if you're drawing an underline across 20 cells, it actually renders it with 20 separate strokes, when it could easily be done in one. The left and right grid lines still need to be rendered one cell at a time, but that's a much less common occurrence.
So just to summarize:
The text was updated successfully, but these errors were encountered: