JDK-8146035 : Windows - With LCD antialiasing, some glyphs are not rendered correctly
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 8u66
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-12-22
  • Updated: 2016-07-21
  • Resolved: 2016-04-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u102Fixed 9 b117Fixed
Related Reports
Duplicate :  
Description
On Windows, when LCD antialiasing is enabled, glyphs of some fonts can be rendered only partially by JRE (or not rendered at all). For example, only one bar can be rendered for 'equals' character (=) instead of two.

The same behavior is not observed in native applications.
Comments
The suggested fix is posted to 2d-dev mailing list: http://mail.openjdk.java.net/pipermail/2d-dev/2016-April/006674.html The patch is available here: ��� http://adm-12504.intellij.net/ ��� http://cr.openjdk.java.net/~aivanov/dmitry.batrak/8146035/jdk9/webrev.00/ The suggested fix creates a dummy compatible bitmap and selects into hMemoryDC before GetGlyphOutline is called. It makes sure, Windows uses ClearType antialiasing for measuring the dimensions of the glyph. This situation was also mentioned in MSDN blog post comments: https://blogs.msdn.microsoft.com/oldnewthing/20060614-00/?p=30873#comment-392143 I will sponsor integrating the patch into the codebase as soon as code review is complete.
14-04-2016

I am guessing that Microsoft have very distinct rasterisation paths for CFF and TT fonts. Perhaps they licensed the CFF code from Adobe and it has never been augmented to handle ClearType. I don't *think* it can be a hinting issue since in that case they would probably say they need hints even in the TrueType case.
12-04-2016

EqualsGlyph.java is a test case which demonstrates the problem. The test case is based on the test case from JDK-8146097. If you don't have Inconsolata, it will show a message. See http://www.levien.com/type/myfonts/inconsolata.html for more information on the font. You can download the font from Google Fonts: https://www.google.com/fonts/specimen/Inconsolata
12-04-2016

Changing lfQuality member of LOGFONT structure does not affect the result if monochrome bitmap is selected into the DC. Yet if you use NONANTIALIASED_QUALITY when compatible bitmap is selected, you'll get the same results as if the monochrome bitmap is selected. If you render the test string '=' to compatible bitmap with NONANTIALIASED_QUALITY, you can see 'minus' instead of '=' in native Win32 app too. With font size of 12px, the lower line of the pair is rendered; with font size of 15px, the upper line is rendered. If you set the font size to 10px, nothing is rendered at all: equals sign looks like a space.
11-04-2016

Windows does not use ClearType with this font, Inconsolata, because it has PostScript outlines. MSDN explicitly mentions that ClearType antialiasing is not possible with PostScript OpenType fonts. See Remarks section in LOGFONT structure documentation: https://msdn.microsoft.com/en-us/library/dd145037%28v=vs.85%29.aspx Although it's not spelt out in the documentation, the result of GetGlyphOutline depends on the bitmap selected into the DC. In Java native code, a compatible DC is created. It is used for measuring the glyph size. Then a compatible bitmap is created with the correct size, and the glyph is rendered. Remarks section of CreateCompatibleDC function documentation https://msdn.microsoft.com/en-us/library/vs/alm/dd183489%28v=vs.85%29.aspx states: ���When the memory DC is created, its display surface is exactly one monochrome pixel wide and one monochrome pixel high. Before an application can use a memory DC for drawing operations, it must select a bitmap of the correct width and height into the DC.��� That is when GetGlyphOutline is called, a monochrome bitmap is selected into the DC. GetGlyphOutline does not perform any drawing, yet its result is affected by the selected bitmap: antialiasing is not possible in black-and-white mode. For Inconsolata font with the size of 12, GetGlyphOutline returns the glyph size is 4��1. It corresponds to what we see: one line is rendered, in this case it is the lower of two. If you select a compatible bitmap into the DC before calling GetGlyphOutline, the result changes to 6��4, and equals sign becomes distinguishable from minus sign. For this particular font, the height of glyphs for 'a' and 'b' in the sample is also affected. With monochrome bitmap, the height of 'a' and 'b' is 6 and 8 correspondingly; with compatible bitmap, the height is 1px greater: 7 and 9.
11-04-2016

Windows bug, not a JDK bug.
22-12-2015

The bug report references a font called Inconsolata available from http://www.levien.com/type/myfonts/inconsolata.html This is an Opentype/CFF font. What I see is that "native apps" do not attempt to use LCD text with this font. They instead use greyscale. When we request the glyph from Windows in LCD mode it seems to do a bad job on it which is probably why it is not something windows does unless you ask it to. Note that if I use "-Dsun.java2d.font.scaler=t2k", the glyph renders perfectly. So this is a Windows bug, not a JDK one. Since this is a Windows bug then I suspect only Microsoft can fix it. We can only work around it. The workaround above is one possibility but you then lose the native rendering completely. Of course since this is not a standard Windows font probably the better way of doing it is to load the font via Font.createFont(..) since in that case JDK will automatically go the T2K route, but for just that font.
22-12-2015