microsoft / terminal

The new Windows Terminal and the original Windows console host, all in the same place!
MIT License
95.25k stars 8.27k forks source link

awful font rendering quality #10353

Closed manxorist closed 2 years ago

manxorist commented 3 years ago

Windows Terminal version (or Windows build number)

1.8.1521.0

Other Software

No response

Steps to reproduce

Use "Liberation Mono" font, size 8pt. (https://github.com/liberationfonts/liberation-fonts/files/2926169/liberation-fonts-ttf-2.00.5.tar.gz)

Expected Behavior

Proper font rendering like any other program.

Actual Behavior

See screenshot (comparing with PuTTY and oldschool Console window).

broken-font

The respective settings are:

Setting experimental.rendering.software or changing font size or weight does not improve anything.

skyline75489 commented 3 years ago

Can you try this https://github.com/microsoft/terminal/issues/10074#issuecomment-837708983 ?

manxorist commented 3 years ago

Can you try this #10074 (comment) ?

According to documentation "grayscale" should be the default. Anyway, setting either "grayscale" or "cleartype" does not fix anything. "aliased" makes it even worse.

DHowett commented 3 years ago

I'm surprised the old console renders like that: requesting a size of 8 from the vintage console gets you eight pixels, whereas in WT you're getting eight points.

Assuming you're using a 100% scale display, it would be more equitable to compare 6pt in Windows Terminal against 8px in conhost. This will impact hinting, which can make a huge difference in the appearance of a font.

That's not to say that we don't render fonts differently than conhost, of course.

DHowett commented 3 years ago

Ugh, that should teach me to read the report. Sorry, I totally missed that you did use pixels in conhost. Feel free to ignore me.

manxorist commented 3 years ago

Assuming you're using a 100% scale display

Yes, I am using a 100% scale display with as far as I know completely default font scaling and display scaling settings.

Ignoring the rest :smirk:

Graphics driver is NVidia, however I assume that does not matter, given that enforcing software rendering did not change anything.

FWIW, I am also using Liberation Mono 8pt as the font in Visual Studio. Also works properly there.

j4james commented 3 years ago

It almost looks to me like Windows Terminal is picking up a different font. For example, look at the lowercase c and s letters in the word "accusam". They look completely different on Windows Terminal compared to putty and conhost. Maybe that's just detail that was lost because the letters are smaller, but it's weird. The size ratio between uppercase and lowercase letters is different too.

I'm curious whether there are still obvious differences when comparing at larger sizes. Perhaps it's some kind of rounding issue in the DX renderer's size calculation when trying to align a small font size to an exact pixel boundary.

manxorist commented 3 years ago

I'm curious whether there are still obvious differences when comparing at larger sizes.

To me, it looks like the problem is less pronounced with larger font sizes.

If I had to guess what's going wrong, I would say it looks like in Windows Terminal, some kind of spacing between the lines gets added and the font size gets changed smaller a bit to compensate. As to why, I have no idea.

Neither additional line spacing alone nor in combination with adjusted smaller font size is acceptable font rendering in my opinion. I have been using Liberation Mono 8pt for about 10 years in various Windows programs (Console Window, Notepad, Notepad++, Visual Studio, PuTTY, ...) as well as in Linux (Mate Terminal, Mate Pluma). Apart from minor differences in anti-aliasing between Cleartype on Windows and Freetype on Linux, it looks identical everywhere except in Windows Terminal.

zadjii-msft commented 3 years ago

I'm gonna /cc @miniksa. He's the font expert, he might have some idea.

miniksa commented 3 years ago

Actually... I think @lhecker was working on a resolution for this already.

lhecker commented 3 years ago

I'll put this on my backlog and test my theoretical fix on the above font. If it fixes it, I'll submit a PR right away.

lhecker commented 3 years ago

My change makes some things a bit better and some things a bit worse: image

I think the issue here is that we use natural scaling for fonts, whereas GDI (which is what "console" and "putty" use) tries to always fit fonts into the pixel grid. I believe DirectWrite can do the same, but it's not as trivial. We need to look into this more.

manxorist commented 2 years ago

Reading about a new experimental text rendering engine in 1.13-preview (https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-13-release/#new-rendering-engine), I retested this issue with the current preview version. In my opinion, the rendering quality is significantly improved up to the point I would consider it almost fixed. The only remaining problem is that the line spacing is bigger than old Console Window.

The screenshot shows Windows Terminal 1.11.3471.0 / Windows Terminal Preview 1.13.10336.0 (with experimental atlas engine) / Console Window (Windows 10 21H2 19044.1469) side by side. terminal-1 11-terminal-1 13-preview-console

lhecker commented 2 years ago

@manxorist What happens if you enable ClearType? Does that further improve things?

This is what I get: image

I'm glad that the font quality could improved this much! Our line spacing algorithm is surprisingly difficult. You can find it here (cellHeight/Width are the resulting values per grid cell): https://github.com/microsoft/terminal/blob/5238235268e32dc6ad1bf2c62b44a28eb16a272b/src/renderer/atlas/AtlasEngine.api.cpp#L565-L579

I used to use a different algorithm with reduced space for ascenders and descenders, but that lead to cut off glyphs for various asian scripts. Furthermore those asian scripts are often a bit taller in Windows Terminal, which improves their legibility. For instance if you try to paste georgian script in those programs you'll find that they're 10px tall in Windows Terminal 1.13 and only 9px tall in conhost. But the algorithm is only the first version. If someone has an idea how to improve it I'll happily merge it as long as it doesn't cut off glyphs (because, to be honest, I'd also like to reduce the line height). Maybe it's already enough to remove the halfGap parameter. 🙂

manxorist commented 2 years ago

@manxorist What happens if you enable ClearType? Does that further improve things?

Cleartype only changes things very subtly.

1.11 | 1.13 altas greyscale | 1,13 atlas cleartype | conhost 1 11-1 13atlas-greyscale-1 13atlas-cleartype-console

I used to use a different algorithm with reduced space for ascenders and descenders, but that lead to cut off glyphs for various asian scripts. Furthermore those asian scripts are often a bit taller in Windows Terminal, which improves their legibility. For instance if you try to paste georgian script in those programs you'll find that they're 10px tall in Windows Terminal 1.13 and only 9px tall in conhost. But the algorithm is only the first version. If someone has an idea how to improve it I'll happily merge it as long as it doesn't cut off glyphs (because, to be honest, I'd also like to reduce the line height). Maybe it's already enough to remove the halfGap parameter. 🙂

I understand that it is important to also support all glyphs from non-western scripts properly, and thus rendering that takes these into account looks like a sensible default to me. However, traditional terminal usage probably mostly deals with only ASCII, at least for some users. Maybe an additional advanced setting could be added that lets the user choose between compatible and condensed line spacing?

j4james commented 2 years ago

Maybe an additional advanced setting could be added that lets the user choose between compatible and condensed line spacing?

There's already an issue for customizing the line spacing - see #3498.

lhecker commented 2 years ago

I think I'll take the liberty to close this issue. My personal understanding is that the font rendering we get in AtlasEngine is as good as it gets with Direct2D and DirectWrite (which we'd like to continue to use) and line spacing will be tackled as part of #3498.

manxorist commented 2 years ago

@lhecker Well, if Windows Terminal cannot achieve the same rendering quality and line density as other terminals, this currently is and will continue to be a major issue for me. The fact that you "like to use" some particular rendering techniques does not invalidate the problem itself.

Please, either tag it as wontfix, or leave it open until Line Spacing can be configured properly. I cannot consider this fixed or closed at all in the current state of things.

zadjii-msft commented 2 years ago

leave it open until Line Spacing can be configured properly

We're already tracking that in #3498. Feel free to go give that thread a 👍

manxorist commented 2 years ago

Also, with Windows Terminal 1.14.1962.0, I cannot even get the improved rendering output that I did see with 1.13 preview any more:

Console 12px: windows-console-12px

PuTTY 8pt: putty-8pt

Windows Terminal 1.14.1962.0 8pt: windows-terminal-1 14 1962 0-8pt-greyscale

Windows Terminal 1.14.1962.0 9pt: windows-terminal-1 14 1962 0-9pt-greyscale

So, nothing fixed. Now it is confused about what 8pt means (compared to every other program).

You could maybe at least try the provided test case before closing issues.

lhecker commented 2 years ago

@manxorist Correct me if I'm wrong, but I believe Windows Terminal 1.14.1962.0 is a non-Preview version. It doesn't have the new text renderer, so it can't have the improved font rendering. Can you please try a Preview version (currently 1.15)? The new text renderer is feature gated and has stayed in Preview ever since. 1.16 will be the first non-Preview version which gets the new text renderer.

manxorist commented 2 years ago

@lhecker Thanks, I might be confused by the versioning and preview/release management that Windows Terminal uses.

Seriously, what's the point of versioning preview versions in a way that does not relate at all to release versions?

If the new renderer is still experimental and deemed unfit for a release version, then even more so this issue should not get closed, as it is (from my perspective) totally uncertain whether it will ever hit a release version at all.

1.15.2002.0 Preview Atlas 8pt: windows-terminal-1 15 2002 0-8pt-greyscale

That's 1.13 Preview Atlas level performance.

lhecker commented 2 years ago

Here's a comparison between existing conhost/cmd.exe on the left and the latest AtlasEngine with all changes on main on the right; 100% display scale, Liberation Mono, 12px/8pt: image

From what I can tell, the result from the new renderer is pretty good and wouldn't qualify as "awful" anymore like it did before. The line spacing thing is being tackled in another issue.

If the new renderer is still experimental and deemed unfit for a release version, then even more so this issue should not get closed, as it is (from my perspective) totally uncertain whether it will ever hit a release version at all.

The PR making it available in non-Preview has already merged. 🙂 It stayed in Preview a bit longer than other features, because it's a fairly large feature. BTW I heard someone might be working on the line spacing / glyph advance thing already... *wink*

manxorist commented 2 years ago

The PR making it available in non-Preview has already merged. 🙂

OK, I guess closing is fine then.

DHowett commented 2 years ago

Seriously, what's the point of versioning preview versions in a way that does not relate at all to release versions?

I can answer this one! For most features, we follow a pretty linear development cycle. Something is checked into main. Between 0 and 6 weeks later (depending on when it was checked in), main is branched for release and the new branch is named release-$N.

That release branch is compiled with Preview settings (icon, app name, app ID, and "feature flags".) The previous release branch, release-$N-1, is then compiled with Stable settings (icon, app name, ...).

Everything is roughly linear. These 6-week snapshots of main are frozen in time, and specific fixes are backported.

Now, I keep saying "roughly" and "most" and stuff. That's where feature flags come in. For the vast majority of changes, they'll be swept into the next release. Some, however, require a little longer than six weeks to bake. Some, more than 12. It's all about feeling out how stable they are, and whether they're ready for the 9+ million population user base running Stable. So, we use feature flags to turn those things off at build time, depending on whether it's a Stable, Preview or Dev build. Those flags are governed by an XML file here.

Atlas was recently promoted to being "available in Stable, on-by-default in Preview". That commit, like all others, will wait between 0 and 6 weeks before becoming part of the next release branch. It will come out first in Preview (where it will be on-by-default), and six weeks after that it will be compiled into Stable (where it will be available but off by default.)

All that to say: we slow down certain features to make sure that our huge user base doesn't get broken stuff before it's done, but all the code is still there waiting to be turned on if we find that it's ready for them. :)

manxorist commented 2 years ago

@DHowett Thanks for the explanation.

I can understand that from a developer perspective (even though I would not use such a scheme myself).

From a user perspective, it still ends up looking confusing though, especially if one is not following the development too closely.