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

Investigate alternative ways to handle box drawing/block elements #5897

Closed
3 tasks
DHowett-MSFT opened this issue May 13, 2020 · 38 comments · Fixed by #16729
Closed
3 tasks

Investigate alternative ways to handle box drawing/block elements #5897

DHowett-MSFT opened this issue May 13, 2020 · 38 comments · Fixed by #16729
Assignees
Labels
Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Help Wanted We encourage anyone to jump in on these. In-PR This issue has a related PR Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Needs-Tag-Fix Doesn't match tag requirements Priority-1 A description (P1) Product-Terminal The new Windows Terminal.

Comments

@DHowett-MSFT
Copy link
Contributor

DHowett-MSFT commented May 13, 2020

There've been some concerns about how we scale glyphs in the Box Drawing character block.

Other terminal emulators do interesting things:

  • Gnome-terminal uses little 5x5 bitmaps and stretches them to fill the entire cell (shout-out to @egmontkob for telling me this!)
    • This results in pixel perfect lines and shading.
  • [Other popular terminal] uses line-drawing primitives at the graphics layer to mimic box drawing and rect-filling primitives with opacity to mimic block elements
    • This also results in pixel-perfect lines and cool blended shading glyphs.

We chose not to do these things for v1.0 because we learned that certain fonts (monofur is a good one) have their own unique styles for box drawing and block elements that we wanted to preserve.

Proposed solution

  • Add a setting for "Let Windows Terminal handle block / powerline drawing"
    • This is a per-profile setting. profile::compatibility.builtinBlockDrawing
    • When enabled, Terminal will manually draw box-drawing and powerline glyphs, replacing the glyph from the font
    • Enable this by default
      • Obviously, users will be able to opt out
      • This will give us the benefit of getting PL glyphs even for fonts without them!
    • We should probably start with a few of the glyphs as higher pri:
      image
      • Green: Definitely, in v0
      • Yellow: okay probably yea
      • Orange: meh
      • red: probably too expensive (engineering wise)
      • white: I can't imagine we'll actually need to draw these
  • Add a secondary setting for "Replace filled rectangles with transparent glyphs"
    • Only enable if compatibility.builtinBlockDrawing is enabled

Links

@DHowett-MSFT DHowett-MSFT added Help Wanted We encourage anyone to jump in on these. Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Product-Terminal The new Windows Terminal. Issue-Task It's a feature request, but it doesn't really need a major design. labels May 13, 2020
@DHowett-MSFT DHowett-MSFT added this to the Terminal Backlog milestone May 13, 2020
@ghost ghost added the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label May 13, 2020
@DHowett-MSFT DHowett-MSFT changed the title Investigate alternative ways to handle box/line drawing Investigate alternative ways to handle box drawing/block elements May 13, 2020
@DHowett-MSFT DHowett-MSFT removed the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label May 13, 2020
@benc-uk
Copy link

benc-uk commented May 14, 2020

The shaded/hatched boxes now look really bad since the last update.
A lot of themes like Powerlevel10k use these

This is my prompt now in Windows Terminal
image

This is what it should look like (In VS Code)
image

@DHowett-MSFT
Copy link
Contributor Author

yikes.

@DHowett-MSFT
Copy link
Contributor Author

Though, that looks like Cascadia Code. The version released yesterday with the new metrics works properly with Terminal. You may need to update.

@benc-uk
Copy link

benc-uk commented May 14, 2020

Hi, I just updated to CascadiaCode_2004.30, and I didn't see any difference :(
image

Weirdly if I set my font size to 15, the shading disappears altogether, and at font size 19 it looks perfect, but that's just too huge to use!

@benc-uk
Copy link

benc-uk commented May 14, 2020

Some further tests with Cascadia Code.

At font size 14 the line elements are super thin and the curved corner lacks any antialiasing/smoothing
image

At font size 13 they look much better
image

@mdtauk
Copy link

mdtauk commented May 14, 2020

I think if this is added, it should be behind a setting. Something like

☑ Let Windows Terminal handle block character drawing

Cascadia code has an interesting approach to the character of some of it's Block Characters, and other fonts will also. That character is lost by Terminal doing it itself - so it should be optional IMO

@ionut-botizan
Copy link

I'd really love to see those "rect-filling primitives with opacity" make it into the Windows Terminal:

  1. top left - Windows Terminal with Fira Code 12px
  2. bottom left - Windows Terminal with Fira Code 15 px
  3. top right - [Other popular terminal] with Fira Code 12px

(the filling char I'm using is $([char]0x2592) or "░")

image

Obviously, the best looking one is the one on the right and the second best one is the one with the 15px font size. Sadly, 15px is way too big, so I'm stuck with the ugly looking one for now. 🙂

@DHowett
Copy link
Member

DHowett commented May 19, 2020

(that's a nice prompt line)

@j4james
Copy link
Collaborator

j4james commented May 19, 2020

Obviously, the best looking one is the one on the right and the second best one is the one with the 15px font size. Sadly, 15px is way too big, so I'm stuck with the ugly looking one for now. 🙂

I understand the desire for a better rendering of theses characters, but the terminal on the right is just displaying a solid block in a different color as far I can see. If that's what you want, you should really be using U+2588. U+2591 to U+2593 are distinct characters where the cell is filled with a pattern to produce a degree of shading. The latest version of Unicode has even added an inverse version of U+2592. That would be impossible to distinguish from U+2592 if you're just renderning them as solid blocks.

@egmontkob
Copy link

the terminal on the right is just displaying a solid block in a different color

This is what VTE does, too. It's a heavily debated feature/bug: https://bugzilla.gnome.org/show_bug.cgi?id=778122.

@j4james
Copy link
Collaborator

j4james commented May 19, 2020

I can understand choosing to render those characters with a solid block as a compromise solution if that's the best we can do - it's probably better than the scaling artifacts. But it is a compromise - it's not what we should be aiming for as the ideal solution.

For me the ideal would be appropriately designed fill patterns, possibly scaled to account for the DPI (as long as the pattern can be retained). Those fill patterns would then be rendered to align with the coordinate system, rather than the character boundaries, so they can repeat perfectly across a range of cells.

It's possible something like that just isn't feasible for performance reasons, or API limitations, but I think we should at least consider ways to do this correctly before resorting to a compromise solution.

Edit: I've just read the whole VTE thread and I see you were proposing the same sort of thing there.

@egmontkob
Copy link

Yup this also occurred to us at VTE, but this method also has a drawback: as these glyphs scroll, the pattern changes. This is again hardly the expected user behavior.

This is clearly a field with contradicting requirements, and thus no single perfect solution. A compromise has to be made somewhere. It's really hard to decide or argue which solution is better or worse.

@PhMajerus
Copy link

PhMajerus commented May 24, 2020

There seems to be something wrong with both how Windows Terminal 1.0.1401.0 scales glyphs for shading blocks and how these glyphs appear in Cascadia Code 2005.15.

And because I know you like nice test files, here's a new one for this issue (I probably spent way too long on this one) : https://github.com/PhMajerus/ANSI-art/blob/master/Sonic%20Green%20Hill%20Zone.ans
(Edit: Added a 256 colors one so you don't have to stare at the base 16 colors all the time : https://github.com/PhMajerus/ANSI-art/blob/master/Sonic%20Green%20Hill%20Zone%20(256%20colors).ans )

Windows Terminal seems to scale shading blocks without anti-aliasing, to me it looks like a nearest neighbor that loses some pixels in pattern that depend on single pixel regularity:

Windows Terminal with Consolas, see the irregular patterns in the clouds:
image

Windows Terminal with Cascadia Code, see how shading blocks do not fill their cells heights (clouds and waterfall):
image

It seems that the issue is only at some font sizes, as if the terminal is zoomed a bit, the shading blocks are then rendered properly (I believe this is equivalent to fontSize:13):
image

Conhost with Cascadia Code, see how all block drawing and shading blocks heights are wrong:
image

And same file in conhost with Consolas as a reference of how it is supposed to look:
image

@mdtauk
Copy link

mdtauk commented May 24, 2020

What would the consensus be with the halftone filled shapes? Should they be rendered with some kind of crosshatching like with fonts, or just an opacity fill?

This is if Terminal was to offer the ability to "handle" or "override" the box drawing.

@j4james
Copy link
Collaborator

j4james commented May 25, 2020

What would the consensus be with the halftone filled shapes? Should they be rendered with some kind of crosshatching like with fonts, or just an opacity fill?

I don't understand why anyone would ask for the patterned characters to rendered with an opacity fill, unless there was no other option. You can already get an opacity effect - with much finer control - just using the existing block characters with appropriate colors. All you'd be doing is preventing other people from using patterns, which seems a spiteful sort of thing to want.

I could understand if the current rendering was the best we could achieve, and the question was do you prefer that or an opacity fill. But we haven't even tried other rendering techniques yet.

@mdtauk
Copy link

mdtauk commented May 25, 2020

What would the consensus be with the halftone filled shapes? Should they be rendered with some kind of crosshatching like with fonts, or just an opacity fill?

I don't understand why anyone would ask for the patterned characters to rendered with an opacity fill, unless there was no other option. You can already get an opacity effect - with much finer control - just using the existing block characters with appropriate colors. All you'd be doing is preventing other people from using patterns, which seems a spiteful sort of thing to want.

I could understand if the current rendering was the best we could achieve, and the question was do you prefer that or an opacity fill. But we haven't even tried other rendering techniques yet.

My thinking is that the intention behind those characters would originally have substituted for a gradient or semi-transparent element. Back with 16 colours or monochrome terminals.

Some fonts use half-tone dots/squares, others (like Cascadia) use a diagonal hatching getting progressively heavier/darker.

If Windows Terminal is going to include an option to override the font's characters, and to get proper horizontal, vertical, and diagonal connecting glyphs - as well as rounded corners etc - there should perhaps be a neutral design approach, so they don't stand out as odd amongst different fonts.

So do you go for the intent behind the characters, a simulation of different shades - by actually using shades of the glyph colour - or pick a particular approach and run with it?

@PhMajerus
Copy link

I guess it started as a way to do intermediate colors and gradients, but over the years shading blocks got used for their texturing features as well. Now that we can use 256 and RGB colors, the pattern they provide is more interesting than the color mix.
I might agree that for a built-in rendering of blocks and lines not based on a font, a pure color mix could work as a default, but it is critical to get the ability to use patterns provided by fonts. And once fonts with blocks work correctly, why would you want to return to a built-in rendering?

Even if some fonts work properly and other don't, the ability to configure a set of fonts for different blocks of Unicode characters, which will probably be required to properly handle a mix of latin, asian (CJK) and technical characters (Math, powerline, nerd font,...), would make it possible to simply specify a font that works for the block and line characters while using other fonts for everything else, so no other fallback required.
See my suggestion at #455 (comment)

@j4james
Copy link
Collaborator

j4james commented May 25, 2020

I guess it started as a way to do intermediate colors and gradients

Did it though? I haven't seen any evidence to suggest that was the only intended usage. People use patterned fills in graphing all the time, both with and without the availability of RGB colors. It's just as reasonable to suppose that these patterned characters were intended to be used as actual patterns. Emulating gradients is just one of the things you could do with those patterns.

And note that the comments on U+2592 in the Unicode standard actually includes the description "speckles fill, dotted fill". The reference glyphs, while not prescriptive, are clearly rendered with patterned fills.

Even ignoring all of the above, I've yet to hear anyone explain how they would render U+1FB90 with an opacity fill. It's the exact same shade as U+2592, only the pixels are "inverted". How do we achieve that with a solid block?

simply specify a font that works for the block and line characters while using other fonts for everything else, so no other fallback required.

In theory I like this idea, but that assumes there are fonts capable of rendering all of these patterns and things like diagonals (e.g. see #6161) while still lining up perfectly with different font sizes and DPI scaling. However, if it could be achieved with a well-designed font, that would be preferable I think.

@egmontkob
Copy link

I've yet to hear anyone explain how they would render U+1FB90 with an opacity fill. It's the exact same shade as U+2592, only the pixels are "inverted". How do we achieve that with a solid block?

In VTE these two are manually rendered as exactly the same solid blocks.

I'm not saying it's great, nor that it's my preferred approach, nor that this is what WT should do. But these are not the first pair of homoglyphs, so I don't think this approach is inherently wrong either.

@felipecrs

This comment was marked as off-topic.

@DHowett

This comment was marked as off-topic.

@he3als
Copy link

he3als commented Jun 15, 2022

Are there any ways to fix this issue at the moment? I am using the default font.

@jaminthorns
Copy link

I'd really love to see this implemented as it can provide a much nicer TUI experience. If this ends up happening, it'd be great if the Powerline symbols were implemented as well (don't forget the slants/triangles!).

Here's some further reading for anyone interested in how some other terminals handle rendering of box drawing characters:

@ShelpAm

This comment was marked as off-topic.

@Mystic8b
Copy link

Mystic8b commented Feb 6, 2024

Well, #16664 was closed, so I'm writing here.
I and tens of thousands of other people use zsh + p10k. And AtlasEngine breaks the prompt in p10k by cutting off the bottom pixel or something like that. In the last release you enabled Atlas by default, which means you are sure there are no problems, but this is not the case! This is a huge problem. Pay attention to this. Thank you!

Old engine:
image

New engine:
image

And no, it's not a font problem, I've tried every variation of Nerd Fonts. I asked the developer of p10k, he also said that it was a terminal problem.


  • Terminal ver: 1.19.10302.0
  • ZSH
  • p10k (rainbow theme)
  • MesloLGS Nerd Font (from p10k repo)
  • 9pt font size
  • 100% scale screen (1080p 2560x1080)

@zadjii-msft
Copy link
Member

zadjii-msft commented Feb 6, 2024

To loop back on this: I've updated the OP with our plan-of-record. Adding a setting to force Terminal to draw pixel-perfect glyphs seems like the right plan. It'll be a setting, so users can always feel free to opt-out if they want the glyph from their font instead.

Adding the setting itself is trivial.
Figuring out how to get the renderer to draw each of those shapes: that's a little more work. Hence why we've tried to group them by priority.

We'd probably appreciate help here, if someone's willing to figure out the glyph drawing 😉

@lhecker
Copy link
Member

lhecker commented Feb 16, 2024

Box drawing and block element glyphs are done:
image

Powerline glyphs are much more difficult to do, because a user's font may not have powerline glyphs in the first place and so there's nothing to MapCharacters to. This made me realize that I need to do my own MapCharacters in addition to what DWrite is doing and that will take some time because it requires additional work on the text renderer - work that isn't trivial unfortunately since DWrite is a little unwieldy.

@microsoft-github-policy-service microsoft-github-policy-service bot added the In-PR This issue has a related PR label Feb 17, 2024
DHowett pushed a commit that referenced this issue Feb 23, 2024
This adds support for drawing our own box drawing, block element,
and basic Powerline (U+E0Bx) glyphs in AtlasEngine.

This PR consists of 4 parts:
* AtlasEngine was refactored to simplify `_drawGlyph` because I've
  wanted to do that for ~1 year now and never got a chance.
  Well, now I'm doing it and you all will review it muahahaha.
  The good news is that it removes a goto usage that even for my
  standards was rather dangerous. Now it's gone and the risk with it.
* AtlasEngine was further refactored to properly parse out text that
  we want to handle different from regular text. Previously, we only
  did that for soft fonts, but now we want to do that for a lot more,
  so a refactor was in order. The new code is still extremely
  disgusting, because I now stuff `wchar_t`s into an array that's
  intended for glyph indices, but that's the best way to make it fast
  and not blow up the complexity of the code even further.
* Finally this adds a huge LUT for all the aforementioned glyphs.
  The LUT has 4 "drawing instruction" entries per glyph which describe
  the shape (rectangle, circle, lines, etc.) and the start/end coord.
  With a lot of bit packing each entry is only 4 bytes large.
* Finally-finally a `builtinGlyphs` setting was added to the font
  object and it defaults to `true`.

Closes #5897

## Validation Steps Performed
* RenderingTests with soft fonts ✅
* All the aforementioned glyphs ✅
* ...with color ✅
* `customGlyphs` setting can be toggled on and off ✅
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Tag-Fix Doesn't match tag requirements label Feb 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Help Wanted We encourage anyone to jump in on these. In-PR This issue has a related PR Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Needs-Tag-Fix Doesn't match tag requirements Priority-1 A description (P1) Product-Terminal The new Windows Terminal.
Projects
Status: Mini-spec in thread
Development

Successfully merging a pull request may close this issue.