[OpenJDK 2D-Dev] FontMetrics differ between OracleJDK 8 and OpenJDK 11

Tredinnick, Jacob jacob_tredinnick at mentor.com
Wed Jan 2 18:37:59 UTC 2019


The result with the latest OpenJDK 12 EA (25) looks the same as OpenJDK 11:

[cid:image001.jpg at 01D4A2CA.46F26050]

Thanks for your help so far.  Any more on your return would be gratefully received!

--
Jake

From: Philip Race [mailto:philip.race at oracle.com]
Sent: 02 January 2019 17:44
To: Tredinnick, Jacob <jacob_tredinnick at mentor.com>
Cc: 2d-dev at openjdk.java.net
Subject: Re: [OpenJDK 2D-Dev] FontMetrics differ between OracleJDK 8 and OpenJDK 11

I am on vacation for (another) week but it is possible that what
you are describing is a bug whereby a transformation that is in effect
was not inverted before returning metrics to the application.
https://bugs.openjdk.java.net/browse/JDK-8139178

This notably affected rotations but could be in play here too although
I haven't tested this. It was fixed very recently so you will need to try a
JDK 12 EA build here : https://jdk.java.net/12/

-phil.

On 1/2/19, 8:44 AM, Tredinnick, Jacob wrote:
Philip,

Default scaling options are "Medium - 125%" on Windows 7.  You are correct this does affect things but read on...
Basically, we are using these FontMetrics values to determine a scale transformation to apply to a size 12 font.  HDPI might be playing in somewhere here, but the problem we know about is with our use of FontMetrics.

I wrote some code to demonstrate our problem (source at the end of this message).  The application shows:

*        An example string drawn using java.awt.Graphics#drawString(java.lang.String, int, int) with a "normal" font object: Calibri plain, size 12

*        The same string drawn based on a Font that is "scaled" (nothing to do with HDPI) using a simplified version of what our application does with the FontMetrics object (we also have zoom levels and users may specify their font sizes in various ways)

*        2 rectangles with sizes hard-coded to wrap these texts when run on my system with OracleJDK 8 (what our applications currently use), for use when comparing the screenshots

For OracleJDK 8:

[cid:image003.jpg at 01D4A2CA.46F26050]


*        The "normal" text is at the top at the "scaled" text at the bottom

*        The application window is 300x400 as in the code

For OpenJDK 8:

[cid:image005.jpg at 01D4A2CA.46F26050]


*        The "scaled" text is much larger, obviously because java.awt.FontMetrics#getMaxAscent() returns a significantly smaller value than it used to

*        The application window is the same size as for OracleJDK 8

For OracleJDK 9 & 10:

[cid:image007.jpg at 01D4A2CA.46F26050]


*        The "normal" text is now smaller than the rectangle

*        The "scaled" text is smaller than with OpenJDK 8 but larger than the rectangle

*        The application window is now 575x400 suggesting that it has been scaled according to my Windows preferences.

*        The rectangles both remain the same size with respect to the application window

For OpenJDK 11:

[cid:image009.jpg at 01D4A2CA.46F26050]


*        The application window and rectangles as scaled as for OracleJDK 9 & 10

*        The "normal" text looks the same as with OracleJDK 9 & 10

*        The "scaled" text is much larger again due to the FontMetrics change

*        The application window is the same size as for OracleJDK 9 & 10

I can do some more work e.g. switch my windows scaling setting to 100% or trying our application against JDK 9 & 10, but I have some questions for now if I may:

Is it wrong of our application code to depend on FontMetrics values remaining consistent between Java versions or even just between different systems?
The FontMetrics changes are affecting our calculation for this font scaling and also a number of other places.

Any advice on how we can work around this to make our text appear roughly the same as it used to  (a few pixel diffs on glyphs and character spacing are OK)?
So far we have tried applying corrections based on what the FontMetrics class used to return in Java 8.  We have some promising results but I suspect that there must be a better way...

Is there any prospect of the FontMetrics values being "corrected" in OpenJDK 11?
I think I know what the answer to that will be :)   But can you explain why for the same font the metrics can be so significantly different between T2K and FreeType?

Example code:

package demo;

import java.awt.*;
import java.awt.geom.AffineTransform;

public class FontScaleProblemDemo extends Frame {

    private static final Font CALIBRI_PLAIN_12 = new Font("Calibri", Font.PLAIN, 12);
    private static final FontMetrics CALIBRI_PLAIN_12_METRICS = Toolkit.getDefaultToolkit().getFontMetrics(CALIBRI_PLAIN_12);
    private static final String EXAMPLE_STRING = "The quick brown fox jumps over the lazy dog";

    // application-specific height setting
    private static final double HEIGHT = 15;

    private FontScaleProblemDemo() {
        super("Font problem - " + System.getProperty("java.version"));
    }

    @Override

    public void paint(Graphics g) {
        // rectangles are hard-coded to neatly surround the strings drawn in OracleJDK 8
        g.setColor(Color.BLACK);
       drawRectangles(g);

        // just draw the string with the raw size 12 font inside the first rectangle
        drawStringSimple(g);

        // draw the string scaled to some application-specific size
        // this calculation is based on the font metrics getMaxAscent which differs in OpenJDK 8
        drawStringScaled(g);
    }

    private void drawRectangles(Graphics g) {
        g.drawRect(48, 90, 241, 13);  // surrounds the simple example in OracleJDK 8
        g.drawRect(48, 187, 290, 17); // surrounds the scaled example in OracleJDK 8
    }

    private void drawStringSimple(Graphics g) {
        g.setFont(CALIBRI_PLAIN_12);
        g.drawString(EXAMPLE_STRING, 50, 100);
    }

    private void drawStringScaled(Graphics g) {

        // in reality the scaling calculation in our app is not this simple (e.g. a transform will be applied for zoom level etc)
        // but it basically depends on the font metrics to determine the font to be applied on the Graphics2D before drawing the string
        double scale = HEIGHT / CALIBRI_PLAIN_12_METRICS.getMaxAscent();
        AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
        Font font = CALIBRI_PLAIN_12.deriveFont(at);

        g.setFont(font);
        g.drawString(EXAMPLE_STRING, 50, 200);
    }

    public static void main(String[] args) {
        FontScaleProblemDemo problemDemo = new FontScaleProblemDemo();
        problemDemo.setSize(new Dimension(400, 300));
        problemDemo.setVisible(true);
    }
}

Thanks
--
Jake

From: Philip Race [mailto:philip.race at oracle.com]
Sent: 31 December 2018 18:23
To: Tredinnick, Jacob <jacob_tredinnick at mentor.com><mailto:jacob_tredinnick at mentor.com>
Cc: 2d-dev at openjdk.java.net<mailto:2d-dev at openjdk.java.net>
Subject: Re: [OpenJDK 2D-Dev] FontMetrics differ between OracleJDK 8 and OpenJDK 11



On 12/31/18, 3:29 AM, Tredinnick, Jacob wrote:
> This is Windows ? What is your Windows desktop DPI setting ?
> If its greater than 100% (aka 96 dpi) you will see a difference in JDK 9+
This particular test was done on my laptop on Windows 7 with default scaling options and a 1920x1080 (maximum) screen resolution.

"default scaling options" can be > 100% so that  is not answering the question.



I don't believe that it is due to HDPI scaling as the rectangle graphic would also have been affected?

Perhaps. It depends how you drew it.




> because of hidpi .. have you tried running on Oracle JDK 9 or JDK 10 ?
> If you see similar there then you can rule out t2k->freetype.
We haven't yet tried this test on OracleJDK 9 or 10 but we will look into this.
We will also check the behaviour with OpenJDK 8 vs OracleJDK 8 as I believe we will see the same problem there.

>From our debugging it is fairly clear that change in rendering comes from the different font metrics coming from the removal of T2K.
We will work this week on some sample code demonstrating the problem...

Ok but different font metrics don't make the glyph images 30% bigger ..
which is how your image looks.
Maybe you are using that somehow to determine the font size to use in
a way that I can't divine.

-phil.



From: Philip Race [mailto:philip.race at oracle.com]
Sent: 30 December 2018 22:41
To: Tredinnick, Jacob <jacob_tredinnick at mentor.com><mailto:jacob_tredinnick at mentor.com>
Cc: 2d-dev at openjdk.java.net<mailto:2d-dev at openjdk.java.net>
Subject: Re: [OpenJDK 2D-Dev] FontMetrics differ between OracleJDK 8 and OpenJDK 11

This is Windows ? What is your Windows desktop DPI setting ?
If its greater than 100% (aka 96 dpi) you will see a difference in JDK 9+
because of hidpi .. have you tried running on Oracle JDK 9 or JDK 10 ?
If you see similar there then you can rule out t2k->freetype.

-phil.

On 12/30/18, 4:43 AM, Tredinnick, Jacob wrote:
Thank you Philip!
(Someone else in our team had submitted the bug report before going on vacation & I didn't realize that we couldn't search based on the original ID).

Looking at your comment on the bug, you are seeing differences of only a pixel, but in our application we are getting very large differences in the size of text.
For example here is a "diff" that one of our tests generated for the Calibri "text object" in Java 8:

[cid:image011.jpg at 01D4A2CA.46F26050]

The blue text is from a golden reference generated with Java 8 and the red text is from the test running in Java 11.
The rectangle is just a rectangle graphic which remains unchanged between Java versions.
(I hope that the image in this mail makes it through to the mail list...)

I believe that the calculation of the bounding box for the text is based on the result of FontMetrics.getMaxAscent() and other FontMetrics methods, so the difference that we see is very significant indeed.
Are you saying that we should not be relying on these font metrics for scaling of text in our applications?
Unfortunately I cannot share our application code that results in these large differences, but we will work next week on making an example that we can share here...

Thanks
--
Jake

From: Philip Race [mailto:philip.race at oracle.com]
Sent: 29 December 2018 17:56
To: Tredinnick, Jacob <jacob_tredinnick at mentor.com><mailto:jacob_tredinnick at mentor.com>
Cc: 2d-dev at openjdk.java.net<mailto:2d-dev at openjdk.java.net>
Subject: Re: [OpenJDK 2D-Dev] FontMetrics differ between OracleJDK 8 and OpenJDK 11

You can't find your report since it was mapped into this public report :
https://bugs.openjdk.java.net/browse/JDK-8215290

You should have received an email to that effect.

-phil.

On 12/29/18, 7:50 AM, Tredinnick, Jacob wrote:
Hello,

My team is currently working on migrating some of our (mostly Desktop & Swing-based) applications from OracleJDK 8 to OpenJDK 11 and we have discovered that some fonts in our application are getting drawn significantly differently e.g. significantly larger, differences with spaces between characters.

When debugging, we found that the FontMetrics for the Font obtained as follows:
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);

Returns significantly different values:
For example a plain, size 12 Calibri font:
In OracleJDK 8 metrics.getMaxAscent() returns 11, while in OracleJDK 11 it returns 9.

I understand that the proprietary "T2K" font engine was replaced by "FreeType" in OpenJDK but I'm surprised at the very noticeable differences that we now see in some of our text objects.
Is it expected that FontMetrics would be so significantly different between OracleJDK 8 and OpenJDK 11?

Note: I can share the code that generates the font metrics as well as a file describing all the diffs for fonts on my laptop if needed.

Note also:
We did attempt to submit a bug for this behaviour via https://bugreport.java.com/bugreport/
But when we search for our bug ID 9058505 there are no results, presumably meaning that no-one has accepted this as a bug so far.
I'm not sure if anyone here is able to find out what happened to our report?

Thanks
--
Jake

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/2d-dev/attachments/20190102/4ffb9e53/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image001.jpg
Type: image/jpeg
Size: 17145 bytes
Desc: image001.jpg
URL: <https://mail.openjdk.java.net/pipermail/2d-dev/attachments/20190102/4ffb9e53/image001-0001.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image003.jpg
Type: image/jpeg
Size: 12178 bytes
Desc: image003.jpg
URL: <https://mail.openjdk.java.net/pipermail/2d-dev/attachments/20190102/4ffb9e53/image003-0001.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image005.jpg
Type: image/jpeg
Size: 13229 bytes
Desc: image005.jpg
URL: <https://mail.openjdk.java.net/pipermail/2d-dev/attachments/20190102/4ffb9e53/image005-0001.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image007.jpg
Type: image/jpeg
Size: 16188 bytes
Desc: image007.jpg
URL: <https://mail.openjdk.java.net/pipermail/2d-dev/attachments/20190102/4ffb9e53/image007-0001.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image009.jpg
Type: image/jpeg
Size: 17061 bytes
Desc: image009.jpg
URL: <https://mail.openjdk.java.net/pipermail/2d-dev/attachments/20190102/4ffb9e53/image009-0001.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image011.jpg
Type: image/jpeg
Size: 12825 bytes
Desc: image011.jpg
URL: <https://mail.openjdk.java.net/pipermail/2d-dev/attachments/20190102/4ffb9e53/image011-0001.jpg>


More information about the 2d-dev mailing list