So this is a workaround for a buggy font that doesn't play well with GDI ?

It does rely on the fonts always being different sizes which is highly likely if not guaranteed.
I suppose it is OK so long as we aren't getting any "false" positives.

What I mean is that almost no one will have these Roboto fonts installed, so the fix is solving a problem they don't have, but if it is wrong in some way, then they could lose
GDI rendering of LCD glyphs and that could affect a lot of people.

So have you tested this with the full set of Windows 10 fonts - including Indic, CJK, etc  - to be sure
there are no cases where it fails for these or other spurious failures.

> As for performance impact, during testing I didn't observe average glyph generation time increase of more than 15%.

Since you aren't retrieving the data, just asking what the size is, I'd expect it to be unmeasurable.

-phil.

On 1/13/20 1:25 AM, Dmitry Batrak wrote:
Hello,

I'd like to submit a patch for JDK-8236996. I'm not a Committer, so I'll need someone to sponsor this change.

Issue: https://bugs.openjdk.java.net/browse/JDK-8236996
Webrev: http://cr.openjdk.java.net/~dbatrak/8236996/webrev.00/

The problem described in JDK-8236996 is from a group of issues (see also e.g. JDK-8078382 and JDK-8192972), where JDK uses one font to perform char-to-glyph conversion, but GDI, when asked to render the glyph is picking a different font, leading to completely random glyphs being rendered, as char-to-glyph mapping obviously differs for different fonts.

Specific version of Roboto font, mentioned in JDK-8236996, is most probably causing the issue because it's not following the naming guidelines from OpenType specification (https://docs.microsoft.com/en-us/typography/opentype/spec/name), having more than 4 variants (regular, bold, italic and bold italic) with the same 'Font Family name' (name ID = 1). So, GDI gets confused and picks Roboto Black for rendering, when asked to choose a regular font from Roboto family (Roboto Black having weight of 400, just like Roboto Regular, probably adds to the confusion).

But the reasoning, given above, about the issue cause is only a guess. GDI is not an open-source subsystem, so we cannot know for sure how it selects the font for rendering, and cannot implement matching logic in JDK. Ideally, we'd want to select the font by specifying its file path, but that's not possible with GDI. Luckily, it allows us to query file data
for the selected font using GetFontData function
(https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getfontdata), which we can use to validate that the
selected font is the one we need.

The proposed solution is to check the file size of the font, selected by GDI, before using it for rendering. If a mismatch is detected, fallback to FreeType is performed. It can produce a somewhat different glyph representation, but, at least, the correct glyph will be rendered. For members of font collections, file size for validation is calculated in a special way, in accordance with GetFontData logic described in the documentation. I've verified that it works for font collections
bundled with Windows 10.

As for performance impact, during testing I didn't observe average glyph generation time increase of more than 15%. Taking glyph caching into account, it shouldn't be that significant for typical UI applications, I think. Performance impact can be made even smaller - by performing the validation only once per font, but, I believe, having a Java application always render correct glyphs (even if fonts are added or removed while application is running) is more
important.

Proposed patch doesn't add any tests, as reproducing the issue requires installation of fonts. Existing automated OpenJDK tests pass after the fix. Proposed approach has been used in JetBrains Runtime without known issues for about 3
months in testing and for about 1 month in production.

Best regards,
Dmitry Batrak

Reply via email to