[OpenJDK 2D-Dev] [PATCH] 8236996: Incorrect Roboto font rendering on Windows with subpixel antialiasing

Phil Race philip.race at oracle.com
Tue Jan 14 17:57:51 UTC 2020


Ok approved. Seems it is making a few things better if not ideal, but 
nothing worse.

-phil.

On 1/14/20 8:14 AM, Dmitry Batrak wrote:
> > So this is a workaround for a buggy font that doesn't play well with 
> GDI ?
>
> This is a workaround for all cases (or the vast majority of them) of 
> broken
> rendering reported by our customers. The case with Roboto is just the 
> one we
> have steps to reproduce for. There can be other cases where GDI's 
> logic is not
> matched by JDK. Even if all of them are caused by 'mis-constructed' 
> fonts, I'm
> afraid, this will not be considered as a good excuse by our customers, 
> as only
> Java applications have such problems with these fonts.
>
> See JDK-8192972, still unsolved in OpenJDK, as an example of the 
> problems which
> will be, at least partially, solved with this fix (correct glyphs will be
> rendered, albeit using FreeType).
>
> I did test the fix with fonts preinstalled in Windows 10. Fallback was 
> actually
> triggered for one font (bold italic 'Segoe UI Semibold'), which is not 
> a 'false'
> positive, but actually a manifestation of another JDK bug from the 
> same family -
> I've just raised https://bugs.openjdk.java.net/browse/JDK-8237085 for 
> it. That's
> yet another example of an issue which will be (mostly) solved by the 
> proposed
> fix.
>
> Using file length as a 'checksum' certainly doesn't guarantee we 
> choose the
> right font, but the probability of error is very low, and this value 
> seems to be
> the best candidate in our circumstances in terms of cost vs. benefit. 
> Even if
> the validation mistreats a different font (having the same length) as 
> a correct
> one, we'll not be in a worse position than before.
>
> Of course, there's a certain risk that rendering for unaffected fonts 
> might
> change, but, given quite straightforward contract of GetFontData 
> function, I
> would consider it very low.
>
> > Since you aren't retrieving the data, just asking what the size is, 
> I'd expect
> > it to be unmeasurable.
>
> Well, we don't know how GetFontData works exactly, but it does seem to 
> add some
> overhead. On my Windows 10 machine OpenJDK with the proposed fix 
> yields about 7%
> larger result for the following benchmark program. The reported value does
> fluctuate from run to run, but the impact of the fix seems to be 
> larger than the
> fluctuations.
>
> --- Benchmark source code ----
> import java.awt.*;
> import java.awt.font.GlyphVector;
> import java.awt.image.BufferedImage;
>
> public class PerfTestOneFont {
>     private static final Font FONT = new Font("Segoe UI", Font.PLAIN, 12);
>
>     public static void main(String[] args) {
>         FONT.getFamily(); // preload font
>
>         BufferedImage image = new BufferedImage(1, 1, 
> BufferedImage.TYPE_INT_RGB);
>         Graphics2D g = image.createGraphics();
> g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
> RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
>         int glyphCount = FONT.getNumGlyphs();
>         long startTime = System.currentTimeMillis();
>         for (int glyphCode = 0; glyphCode < glyphCount; glyphCode++) {
>             GlyphVector gv = 
> FONT.createGlyphVector(g.getFontRenderContext(),
>                                        new int[]{glyphCode});
>             g.drawGlyphVector(gv, 0, 0);
>         }
>         long endTime = System.currentTimeMillis();
>         g.dispose();
>         System.out.println(endTime - startTime);
>     }
> }
> ------------------------------
>
> Best regards,
> Dmitry Batrak
>
> On Mon, Jan 13, 2020 at 11:09 PM Phil Race <philip.race at oracle.com 
> <mailto:philip.race at oracle.com>> wrote:
>
>     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
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/2d-dev/attachments/20200114/b3e5de4e/attachment-0001.htm>


More information about the 2d-dev mailing list