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

Italics & Bold not rendering properly if they are the final character - text looks "cut off" #9381

Closed
Nosamdaman opened this issue Mar 4, 2021 · 58 comments · Fixed by #14959
Labels
Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Help Wanted We encourage anyone to jump in on these. Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Tag-Fix Doesn't match tag requirements Priority-2 A description (P2) Product-Terminal The new Windows Terminal.

Comments

@Nosamdaman
Copy link

Nosamdaman commented Mar 4, 2021

Environment

Windows build number: [Version 10.0.19042.844]
Windows Terminal version: 1.6.10571.0

Any other software?
Ubuntu using WSL 1
Fish Shell

Steps to reproduce

Print any italic text to the terminal

Expected behavior

All characters should be italicized and fully visible.

Actual behavior

The last character before a newline is cut-off where the italic character would bleed into the next character. Note this occurs when using both Cascadia Code and FiraCode in my testing.

After further testing, we've determined that the issue is related to the cleartype antialiasing setting. Using grayscale eliminates the issue.

image

@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Mar 4, 2021
@Nosamdaman
Copy link
Author

Interestingly, switching the font back and forth actually fixes the issue for anything that has already been printed.

@zadjii-msft
Copy link
Member

Huh. Good catch!

@zadjii-msft zadjii-msft added Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Help Wanted We encourage anyone to jump in on these. Issue-Bug It either shouldn't be doing this or needs an investigation. Priority-3 A description (P3) Product-Terminal The new Windows Terminal. labels Mar 4, 2021
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Mar 4, 2021
@zadjii-msft zadjii-msft added this to the Terminal v2.0 milestone Mar 4, 2021
@vefatica
Copy link

vefatica commented Mar 4, 2021

What is "set_color"?

I have no problem doing it manually (in TCSH).

image

@Nosamdaman
Copy link
Author

It's a function in Fish that makes colorizing output a little easier. And not every character crosses over into the next spot, I found that '0' did it a lot.
image

@237dmitry
Copy link

Everything seems to be fine:

aaa

@Nosamdaman
Copy link
Author

Huh. I've noticed that any action that would cause a re-render like changing the font or font size fixes the issue for anything that's already been printed.

@vefatica
Copy link

vefatica commented Mar 4, 2021

Thanks. I was using Consolas. I switch to Cascadia Code and tried a few characters that are tycically wide, and a few font sizes. I'm still OK (though the lowercase w's are a bit weird).

image

@j4james
Copy link
Collaborator

j4james commented Mar 4, 2021

I believe this only happens when you're changing colors. So in most cases you wouldn't see it at the end of a line, but I'm guessing the OP is actually writing out text with a black background while the rest of the screen is using the default color (which just happens to be the same value as black), so there is actually an invisible transition from black to default where the characters get clipped.

I'm was aware this could happen when I implemented italics, but I didn't think there was much we could do about it.

@Nosamdaman
Copy link
Author

That makes sense, except I'm not changing the background color as far as I know

@j4james
Copy link
Collaborator

j4james commented Mar 4, 2021

Hmm... you're right. The test case you did with the escape sequence is clearly using the default background, so it can't be that. I'm not sure what is triggering it for you then. I wonder if the acrylic background is the issue.

@Nosamdaman
Copy link
Author

Turning off acrylic didn't fix the issue ... but switching my anti-aliasing mode from "cleartype" to "grayscale" did. It seems like that's what's causing it.

@237dmitry
Copy link

this only happens when you're changing colors

bbb

May be this is "fish"-behavior

@Nosamdaman
Copy link
Author

I've confirmed it happens in bash as well

@j4james
Copy link
Collaborator

j4james commented Mar 4, 2021

switching my anti-aliasing mode from "cleartype" to "grayscale" did. It seems like that's what's causing it.

Yep, that's it. I can reproduce it now too.

@DHowett
Copy link
Member

DHowett commented Mar 4, 2021

So, when we render individual "runs" of text we clip the rendering region to the estimated space to avoid characters overhanging their boxes. The italics and the spaces are logically two units . . . at first.

I suspect that when we re-render the line containing the italic text (in response to a selection, cursor blink, etc.), we decide that the italic text plus the spaces after it are a single run and don't clip it. Probably due to our "identical visual representation for space characters" "optimization" ;P

@DHowett DHowett removed the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Mar 13, 2021
@Antonio-Bennett
Copy link

Antonio-Bennett commented Apr 3, 2021

@DHowett So for me in the shell (fish) and on Ubuntu 20.10 it is fine
image
But in Neovim comments that are italic has this issue for some reason
image

@xbb
Copy link

xbb commented Apr 19, 2021

I'm having the same issue, which I notice only with neovim so far and fonts without italic variant

@Gee19
Copy link

Gee19 commented May 24, 2021

I'm also seeing this issue in vim/neovim regardless of "antialiasingMode": "cleartype" or "antialiasingMode": "grayscale". Especially noticeable when 0 or { are the ending characters.

grayscale_vim

Although, grayscale seemingly fixes it in the shell, zsh in this case.

echo -e "\e[3m foo {{{ \e[23m"
grayscale_shell

Windows Terminal Preview
Version: 1.8.1032.0

@chrisdcao
Copy link

chrisdcao commented Jun 24, 2021

might I add that the behavior is not consistent though, on certain lines the last character will not be cut out.. while on some it will be?...

Screenshot_34

Windows Terminal version (or Windows build number)

10.0.19042.1052

Other Software

Ubuntu WSL, using Vim inside the terminal

Font Used

Ubuntu Mono (which has true italic)

@jiashun0011

This comment was marked as spam.

@zadjii-msft zadjii-msft added Priority-2 A description (P2) and removed Priority-3 A description (P3) labels Jun 9, 2022
@yueyingjuesha

This comment was marked as spam.

@miversen33
Copy link

miversen33 commented Jul 25, 2022

I'm noticing this issue regardless of the text antialiser I am using (I tried Grayscale, ClearType and Alisased).
Another interesting thing I noticed, this issue is only present on one of my machines. My other (using an identical profile) is not experiencing the same issue.

I have attached the profile as well as whatever info I can provide about the terminal for each machine
not-broken-italics-settings.txt
broken-italics-settings.txt
(Note, I had to upload them as .txt files because github hates real code. But you're all smart cookies)

Edit: Both versions are running the same Microsoft Terminal version: 1.13.11431.0

Edit 2: This appears to be an issue with monospace font rendering.
Using MesloLGS NF works perfectly, however using MesloLGM NF results in the cutoff italics. See

image

@scallaway
Copy link

scallaway commented Jul 28, 2022

I'm seeing something related when rendering text (code comments) with italics;
image

As I type across the line, the cursor seems to move further and further to the right, and become disjointed from where the text is actually getting displayed;
image

image

When in insert mode in Vim, you can see clearly where the cursor is pointing to (the vertical bar) vs. where the letter is actually going to be inserted (to the left of that black box).

This looks to be some sort of mathematical pixelling issue?

@DHowett
Copy link
Member

DHowett commented Jul 28, 2022

You're right. This is sort of the opposite of the original report, but the root cause is the same. Text will be cut off on the right side when the italic or bold version is wider than the normal version, and it will spring back (for lack of a better term) and squeeze over to the left when it's narrower.

The root cause here is that our current text rendering engine tries to batch text into identical runs--that is, groups of characters with the same display attributes--and render them all at once. It helps us combine things like a base character and a combining diacritic (e + acute), but it also means that the font's native sizing and sometimes kerning take effect. When you do something that splits the display attributes (like, in your case you have cursorcolumn enabled), we end up doing this:

[One big render containing most of the text                 ] [e]

... and that one big render follows the font's native sizing.

At the end of the day, this isn't going to get better until we make the cell-by-cell rendering engine the default; the work to complete it is being tracked in #9999. I believe this case already works over there, but I haven't validated it with all fonts.

That's probably going to be the most complete solution to this issue, so I'm tempted to close this as a duplicate and recommend testing out the "new experimental text rendering engine" in the meantime.

What do you think? (Both the team and the community!)

@Nosamdaman
Copy link
Author

What do you think? (Both the team and the community!)

I kinda like the idea of leaving this open for now. It will likely make it easier for those trying to see if this problem is reported and being looked. People sometimes don't read the whole thread (I know, not our problem), and may think that the issue was closed because it was resolved.

@jfaz1
Copy link

jfaz1 commented Sep 6, 2022

Hey all, tried using the new experimental text rendering engine and it still cuts off italics (using Dina Remaster). Just checking if it's supposed to be working already or not since @DHowett mentioned that this case already works over there, but I may be misunderstanding. If anything it's actually worse with it enabled (more than just the last italicized character is removed):
image

@DHowett
Copy link
Member

DHowett commented Sep 6, 2022

Huh. @lhecker, should we measure cell extents in Atlas by checking all three fonts (bold, italic, regular) that the user could encounter? This will make the window wider IN MOST CASES for poorly-behaved fonts like the one @jfaz1 is using, but it would resolve this issue once and for all.

@lhecker
Copy link
Member

lhecker commented Sep 6, 2022

In 1.16 those glyphs won't be cut off anymore. But to retain a proper monospace grid we should implement your suggestion @DHowett.

@j4james
Copy link
Collaborator

j4james commented Sep 6, 2022

@lhecker If we're going to force the cells to be wide enough to completely fit italic characters, I suspect that's going to make the letter spacing unnecessarily large for quite a few fonts. That will be particularly annoying for users that aren't even using italics.

I thought at one point that you had planned to allow characters to overflow their cell, which I assumed would largely solve this problem (at leat if we're also rendering the background in a separate pass - I'm not sure if that's true yet).

I can't say for definite that's what everyone else does, but I know at least some terminals do something like this. For example this is a screenshot from Mintty rendering italics with the background changing between characters.

image

@scallaway
Copy link

@lhecker
I thought at one point that you had planned to allow characters to overflow their cell, which I assumed would largely solve this problem (at leat if we're also rendering the background in a separate pass - I'm not sure if that's true yet).

This would be the way I'd expect this to be implemented?

I'm not sure, however, whether this uncovers other issues surrounding obscure placement of characters, especially with other glyphs.

I haven't had a chance to test the latest myself yet, but will try to give it a go for my use case in the next day.

@lhecker
Copy link
Member

lhecker commented Sep 6, 2022

I thought at one point that you had planned to allow characters to overflow their cell, which I assumed would largely solve this problem (at leat if we're also rendering the background in a separate pass - I'm not sure if that's true yet).

Yeah I still do, but it's not trivial to decide on a proper heuristic here. What I was planning to solve in the near term is joining ambiguous emojis with a trailing whitespace to make Windows Terminal behave like other terminals in that regard. Implementing the heuristic for that is pretty simple after all.

Implementing a glyph atlas with arbitrarily sized glyphs correctly and properly is a lot more annoying. This will require the use of a bin packing algorithm to store glyph textures. Then during rendering you have to render each glyph on its own rectangular polygon (quad). This is how most text renderers including Direct2D do it. It's easy to do this sloppy and hard to do correctly.

After all, you can't just draw each glyph on its own quad. What if the overlapping glyphs intentionally form a ligature? Overlapping them by simply alpha-blending them would mean that the anti-aliased border of the glyph ends up too opaque at the point of the overlap. It also doesn't work with ClearType which a lot of our users use (ClearType doesn't support alpha blending). Joining overlapping glyphs and rasterizing them as one large glyph solves the problem.

But what is the heuristic here? If you simply join all overlapping glyphs you might get a perfect result, but now a screen full of slanted/italic text would all be rendered as one huge glyph with effectively no caching at all. The performance would end up being terrible. Given that Direct2D already handles this perfectly, it might be easier to port our text rendering improvements to Direct2D than it is to replicate Direct2Ds text renderer in Windows Terminal in full.

I'm not a text rendering expert and I've always considered our custom text renderer ("AtlasEngine") to be a "hack" which just works around our immediate performance problems we had. It's a nice bonus that it performs much much faster than Direct2D ever could, thanks to us assuming that each glyph fits into the terminal's raster grid, but clearly this isn't a perfect solution either.

If anyone is knowledgeable about text rendering and has ideas how to improve ours I'd be happy to hear about it.

I haven't had a chance to test the latest myself yet, but will try to give it a go for my use case in the next day.

1.16 hasn't been released yet, but will be most likely this week.

@j4james
Copy link
Collaborator

j4james commented Sep 6, 2022

But what is the heuristic here? If you simply join all overlapping glyphs you might get a perfect result, but now a screen full of slanted/italic text would all be rendered as one huge glyph

But you surely don't need to join overlapping glyphs just because they're slanted? I would have thought the only time you really care about joining is if you've got an actual ligature, which I assumed you'd know from the font metrics somehow. Or am I wrong about that?

I accept you might still have a situation where you've got something like an italic W overlapping a non-italic H, with artifacts where the characters intersect, but it seems like that should be fairly rare, and even when it happens I suspect it would be less jarring than having excessive letter spacing everywhere.

I'm not super concerned about any of this stuff though. Just wanted to offer my thoughts on the subject. But I know very little about text rendering, so if I'm not making any sense, feel free to disregard.

@lhecker
Copy link
Member

lhecker commented Sep 6, 2022

But you surely don't need to join overlapping glyphs just because they're slanted? I would have thought the only time you really care about joining is if you've got an actual ligature, which I assumed you'd know from the font metrics somehow. Or am I wrong about that?

For text rendering with grayscale antialiasing this would mostly work, apart from an uneven appearance when glyphs do intersect. This is the approach I would choose if I had to make this change in the near-ish future, because it provides 80% of the value (overlapping glyphs mostly appear to work) for 20% of the cost (only a minor performance impact). If ClearType is enabled I'd probably force glyphs into the cell grid the way it works now, due to the lack of an alpha channel for ClearType glyphs.

But in either case this does require a non-trivial amount of work (due to the bin packing with conservative memory management & quad layout for each glyph) and and I still need to work on a lot of other rendering improvements which IMO add just as much value to Windows Terminal (looking at you, sixel support in AtlasEngine, our 4th biggest issue). Until then I'm hoping that the new cell-fitting algorithm (#13549) which ships in 1.16 next week improves the situation around italic/bold glyphs so much so that it's far less of an issue for most users, most of the time.

Edit: The cell-fitting thing didn't work out. 🥲

lhecker added a commit that referenced this issue Feb 14, 2023
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 absolute
sizes 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
* Setting `height` to `1` creates 12pt tall rows ✅
* Setting `height` to `1ch` creates square cells ✅
* Setting `width` to `1` creates square cells ✅
* Setting `width` or `height` to `Npx` or `Npt` works ✅
* Trailing zeroes are trimmed properly during serialization ✅
* Patching the PR to allow >100 line heights and entering "100.123456"
  displays 6 fractional digits ✅
@zadjii-msft
Copy link
Member

Hey this might have been fixed by #14959. I haven't been following this thread as closely, but I'm pretty sure this thread ended up being one of the more central premises of that approach.

Talking with @lhecker, there's still the chance that text will be cut off on the right side of the window, by the margins, but that seems like a much smaller subset of this thread.

@Nosamdaman
Copy link
Author

I agree, text getting cutoff at the edge is pretty outside of the scope of my original complaint, thanks for getting this one sorted out guys!

spenserlee added a commit to spenserlee/.dotfiles that referenced this issue Jun 23, 2023
Windows terminal has a font rendering bug for the last character in a
line if it is italic. This issue claims it's resolved, but it is not:

<microsoft/terminal#9381>

Confirmed this issue doesn't occur in XFCE terminal with the same
JetBrains NF.
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. Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Tag-Fix Doesn't match tag requirements Priority-2 A description (P2) Product-Terminal The new Windows Terminal.
Projects
None yet
Development

Successfully merging a pull request may close this issue.