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

ClearType TextRenderingMode uses incorrect DWrite rendering mode #2025

Closed
rladuca opened this issue Oct 9, 2019 · 9 comments · Fixed by #2668
Closed

ClearType TextRenderingMode uses incorrect DWrite rendering mode #2025

rladuca opened this issue Oct 9, 2019 · 9 comments · Fixed by #2668
Assignees
Labels
Bug Product bug (most likely)
Milestone

Comments

@rladuca
Copy link
Member

rladuca commented Oct 9, 2019

  • .NET Core Version: All
  • Windows version: All
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes

When rendering text, CGlyphRunResource::GetDWriteRenderingMode is called in order to get the appropriate rendering mode to pass to DWrite in CGlyphRunResource::CreateRealization for a call to pIDWriteFactoryNoRef->CreateGlyphRunAnalysis.

The analysis is what gives WPF the glyph bitmap(s) it uses to render to the screen. The problem comes in some special cases in CGlyphRunResource::GetDWriteRenderingMode. In this function, WPF overrides what the recommended rendering mode would be from DWrite with DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL. DWrite, if given the choice, would use DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC for this font and emsize.

What this means is the algorithm used to render the font is not symmetric, as in the anti-aliasing algorithm is only performed in the horizontal and not the vertical direction. Due to this, fine features in the horizontal can be sampled out if the font itself is optimized for symmetric anti-aliasing.

This bug was originally found while investigating an issue with the rendering of MS Mincho after the installation of KB4482887. The application was setting TextOptions.TextRenderingMode to ClearType. According to the documentation:

Text is rendered with the most appropriate `ClearType` rendering algorithm based on the layout mode that was used to format the text.

This is simply not true for all fonts as described above. WPF should, in this case, simply ask DWrite what the appropriate rendering mode is and use the closest ClearType equivalent to that (see here). There are other special cases that should be preserved, but this particular one needs fixing.

Note that applications that do not set TextOptions.TextRenderingMode to ClearType will not see this problem as the default mode is Auto. In Auto, WPF will ask DWrite what the appropriate mode to use is.

EDIT: Since wpfgfx_cor3 has been open sourced, here is the offending code:

CGlyphRunResource::GetDWriteRenderingMode(__in IDWriteFontFace *pIDWriteFontFace,

Original internal bug for reference

@grubioe grubioe added this to the Future milestone Oct 16, 2019
@grubioe grubioe added the Bug Product bug (most likely) label Oct 16, 2019
@AmadeusW
Copy link

Visual Studio developers have received multiple feedback Windows Terminal, VS Code and JetBrains all render the text better than Visual Studio, which uses the WPF renderer. Text rendered by WPF is less crisp than other technologies; horizontal lines are thinner, and vertical lines are thicker.

image

Some of the user feedback:
https://www.reddit.com/r/VisualStudio/comments/ev5b2u/is_there_an_editor_text_readability_fix_already/
https://developercommunity.visualstudio.com/content/problem/44061/some-programming-ligatures-do-not-work.html
https://developercommunity.visualstudio.com/content/problem/899361/editor-readability.html?childToView=904574#comment-904574

@alexhajdu
Copy link

alexhajdu commented Feb 19, 2020

Thanks @AmadeusW to bring the issue here. Guys, we are reading a text like 99% of our time. Please make this experience more pleasant. Thanks!!!

@rladuca
Copy link
Member Author

rladuca commented Feb 19, 2020

@AmadeusW Is Visual Studio setting TextOptions.TextRenderingMode to ClearType in the editor?

@AmadeusW
Copy link

Yes, it does.

Up to VS 16.4, text formatting mode was Display at 100% zoom and Ideal at other zoom levels. Text rendering mode was set to ClearType for Consolas font and Automatic for other fonts. It appeared that Automatic looked the same as ClearType.

In VS 16.5 preview (you can check it out now), rendering mode is always set to ClearType. User may go to Tools - Options - Text Editor - Advanced and set both the formatting method and rendering method.
Choices for formatting method are Automatic (= 16.4 behavior), Display, Ideal
Choices for rendering method are Automatic, ClearType, Grayscale, Aliased.

In my experience, rendering method affected whether anti-aliasing is colored, grayscale or does not exist. Formatting method was the one which affected the shape of the characters.

@rladuca
Copy link
Member Author

rladuca commented Feb 21, 2020

Now that wpfgfx_cor3 is open sourced, I can link the offending code.

CGlyphRunResource::GetDWriteRenderingMode(__in IDWriteFontFace *pIDWriteFontFace,

As you can see in that function, if ClearType is set, WPF chooses one of two rendering modes based on whether the TextFormattingMode is Display or Ideal. In the Ideal case, we always choose DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL as the rendering mode. In cases where fonts are designed for symmetric anti-aliasing this can lead to issues like you are stating. The anti-aliasing is only performed on the horizontal axis, so vertical lines would appear thicker. Horizontal features would be much thinner since we are not adding surrounding pixels due to anti-aliasing on the vertical axis.

EDIT: I guess you don't need to be designed for symmetric to see the axis thickness differential. The original bug was losing fine features due to only using vertical anti-aliasing, but you'd see this in generally all fonts if a symmetric mode wasn't chosen.

The only real way around this is to ensure you don't set the mode to ClearType since, as you can see, WPF will then choose (barring an error) whatever DWrite suggests.

Like I said in the original post, this isn't great and we should be asking DWrite in every case and attempting to use the appropriate ClearType mode in DWrite if ClearType is on (generally DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC).

@zhuman
Copy link

zhuman commented Feb 25, 2020

@rladuca were you around for the great WPF text controversy of Visual Studio 2010? When VS switched to WPF, there were lots of complaints about the text rendering being fuzzier, possibly as a result of using the symmetric rendering style. It's possible this code was updated at the time to handle these complaints.

Link to VS 2010 blog post

@rladuca
Copy link
Member Author

rladuca commented Feb 25, 2020

@zhuman I wasn't around during that period (I was chugging away on emacs doing Linux and vxWorks dev at the time : - )). I came at this from a reported bug where features in MS Mincho were actually missing due to the asymmetric anti-aliasing. So it was more than just fuzzy, it destroyed the meaning/readability of the text itself.

From what I can tell, this code pathway has been in place since the implementation of TextFormattingMode/TextRenderingMode was completed. There don't seem to be any tweaks to this function since its creation. So I believe that ClearType has always selected DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL based on that. Prior to that function there may have been some preview where things were different, but I am not sure.

Fonts have also changed quite a lot since then. So it is possible that issues that arose from symmetric anti-aliasing in 2010 are no longer applicable due to improved support for that at the font level itself. I'm not an expert on that for sure and any change will have to be carefully evaluated.

@AmadeusW
Copy link

The only real way around this is to ensure you don't set the mode to ClearType since, as you can see, WPF will then choose (barring an error) whatever DWrite suggests.

@rladuca does it mean that setting TextRenderingMode.Auto will use desired anti aliasing? In my experience, and on my machine, Auto looks just like ClearType.

@rladuca
Copy link
Member Author

rladuca commented Feb 25, 2020

@AmadeusW Yes, this should use the correct anti-aliasing. You should see a difference as far as I know. That was definitely the case for the internal bug regarding MS Mincho, disabling ClearType immediately resolved the issue with missing features in the font. This could be specific to the font itself.

Remember that the TextFormattingMode also influences this. If you're not in Ideal mode, you will get GDI rendering.

See:

case TextFormattingMode::Display : return DWRITE_MEASURING_MODE_GDI_CLASSIC;

and

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Product bug (most likely)
Projects
None yet
5 participants