JDK-8231286 : HTML font size too large with high-DPI scaling and W3C_LENGTH_UNITS
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 8,11,12,13,14
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2019-09-04
  • Updated: 2021-02-16
  • Resolved: 2021-02-08
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 17
17 b09Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Windows 10 version 1903, 64 bit

A DESCRIPTION OF THE PROBLEM :
This issue appears on Windows 10 with high DPI monitors when using display scaling above 100%, e.g. 150% or 200%.
Therefore, this is related to JDK-8187367 : Numerous swing display problems with scaled displays on Windows.

When using a JEditorPane to render HTML views with W3C_LENGTH_UNITS enabled, font-sizes set using CSS are much larger than the same font size outside the HTML.

The difference in size appears to be proportional to the display scaling factor.
If the factor is 100%, the font sizes are roughly equal.
The more the scaling factor is increased, the more the font size of HTML and non HTML texts differs.

This makes it impossible to use W3C_LENGTH_UNITS when combining HTML and non HTML views.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the provided source code on a Windows machine.
Compare the HTML Paragraphs with the text in the JLabel.
Repeat the process with different display scaling factors.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
All texts should have equal size, or at least roughly equal.
In particular, the display scaling should be applied equally to HTML and non-HTML texts.
ACTUAL -
The ratio between the font sizes of HTML and non-HTML texts should remain constant for different display scaling factors.

---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Font;

import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;

public class HtmlFontSize extends JFrame {

    public HtmlFontSize() {
        JLabel label = new JLabel("This is 16 pt.");
        label.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 16));

        JEditorPane htmlPane = new JEditorPane();
        htmlPane.setEditable(false);

        htmlPane.putClientProperty(JEditorPane.W3C_LENGTH_UNITS, Boolean.TRUE);

        HTMLEditorKit kit = new HTMLEditorKit();
        htmlPane.setEditorKit(kit);

        StyleSheet styleSheet = kit.getStyleSheet();
        styleSheet.addRule("body { font-family: SansSerif; font-size: 16pt; }");

        String htmlString = "<html>\n"
                          + "<body>\n"
                          + "<p>This should be 16 pt.</p>\n"
                          + "<p style=\"font-size:16pt\">And this as well.</p>\n"
                          + "</body>\n"
                          + "</html>";

        Document doc = kit.createDefaultDocument();
        htmlPane.setDocument(doc);
        htmlPane.setText(htmlString);

        setLayout(new BorderLayout());

        add(label, BorderLayout.NORTH);
        add(htmlPane, BorderLayout.CENTER);
        pack();
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    }

    public static void main(String[] args) {
        HtmlFontSize frame = new HtmlFontSize();
        frame.setVisible(true);
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
One option is to disable W3C_LENGTH_UNITS, but that leads to other sizing issues.
Another option is to hard-code a smaller font-size style, but this requires knowledge of the actual scaling setting.

FREQUENCY : always



Comments
This fix requires update to javax/swing/text/html/CSS/4765271/bug4765271.java It's being handled under JDK-8261094.
09-02-2021

Changeset: 48c932e1 Author: Matthias Perktold <7334069+mperktold@users.noreply.github.com> Committer: Alexey Ivanov <aivanov@openjdk.org> Date: 2021-02-08 14:32:07 +0000 URL: https://git.openjdk.java.net/jdk/commit/48c932e1
08-02-2021

Additional Information from submitter: ========================== I managed to find the source of this problem: It's the static initializer of javax.swing.text.html.CSS.LengthUnit, copied here for convenience: static { lengthMapping.put("pt", Float.valueOf(1f)); // Not sure about 1.3, determined by experiementation. lengthMapping.put("px", Float.valueOf(1.3f)); lengthMapping.put("mm", Float.valueOf(2.83464f)); lengthMapping.put("cm", Float.valueOf(28.3464f)); lengthMapping.put("pc", Float.valueOf(12f)); lengthMapping.put("in", Float.valueOf(72f)); int res = 72; try { res = Toolkit.getDefaultToolkit().getScreenResolution(); } catch (HeadlessException e) { } // mapping according to the CSS2 spec w3cLengthMapping.put("pt", Float.valueOf(res/72f)); w3cLengthMapping.put("px", Float.valueOf(1f)); w3cLengthMapping.put("mm", Float.valueOf(res/25.4f)); w3cLengthMapping.put("cm", Float.valueOf(res/2.54f)); w3cLengthMapping.put("pc", Float.valueOf(res/6f)); w3cLengthMapping.put("in", Float.valueOf((float)res)); } For high DPI screens, the resolution is higher than 72, say 144. Then the mapping for "pt" becomes 2, so texts using a font-size given in pt are rendered about twice as large compared to when not using W3C_LENGTH_UNITS. Notice that "px" instead has a hardcoded value of 1 and so does not depend on the resolution. Indeed, when changing the provided example by replacing all font-sizes from "pt" to "px" units, everything works as expected (so there is a workaround). I guess this code was correct before Java became fully high DPI aware in Java 9, but now the scaling is applied twice: once by this code, and once by Java's hi-DPI engine. I suggest to not consider the screen resolution but to hardcode all values based on the official equivalences as defined here: https://drafts.csswg.org/css-values-3/#absolute-lengths For example, "px" should stay equal to 1, "pt" should be 0.75, "in" should be 96 etc.
23-11-2020

Additional information from submitter: ============================ I tried setting environment variable FREETYPE_PROPERTIES="truetype:interpreter-version=35" as suggested in related issue https://bugs.openjdk.java.net/browse/JDK-8217731, but the problem persists. Also, I misspelled the constant in the title and the description: it's W3C_LENGTH_UNITS, not W3C_UNIT_LENGTHS. Sorry for the inconvenience.
25-10-2019

On Windows 10 with High-DPI, the HTML font size appears larger then the non HTML font appears outside HTML. The issue does reproduce frequently with JDK 8u221, 12.0.2, 13 ea b24 and 14 ea b14. Result (Windows 10): ====================== 8u221: Fail 12.0.2: Fail 13ea b33: Fail 14ea b12: Fail To verify, run the attached test case with respective JDK versions. Also see attached screenshot as reference.
20-09-2019