<Swing Dev> RFR: 8231286: HTML font size too large with high-DPI scaling and W3C_LENGTH_UNITS
Alexey Ivanov
aivanov at openjdk.java.net
Fri Jan 29 19:49:46 UTC 2021
On Wed, 27 Jan 2021 11:40:10 GMT, Matthias Perktold <github.com+7334069+mperktold at openjdk.org> wrote:
> This PR supersedes #2223.
> The original PR was created from master, whereas this PR is created from a fresh branch.
>
> Below is a copy of the original description, but as @mrserb correctly [pointed out](https://github.com/openjdk/jdk/pull/2223#issuecomment-767048399), there is actually no relevant change from CSS 2.1 to CSS 2.2, so I <strike>striked out</strike> that part.
>
> ### Original Description
>
> @prsadhuk asked me to take over his pull request #1628, since I filed the bug an suggested this fix.
>
> I thought the current behavior would be buggy, but actually the units are quite precise. I checked the size of a text in font-size of 1 in, and it really was approximately 1 inch. The problem is just that browsers behave differently.
>
> <strike>
> Swing follows the CSS 2.1 spec: https://www.w3.org/TR/CSS21/syndata.html#length-units.
> But in CSS 2.2, length units where redefined: https://www.w3.org/TR/CSS22/syndata.html#length-units.
> Now px is also an absolute unit, and there are constant conversion factors between all absolute units.
>
> The CSS 2.2 spec includes the following two notes regarding this change:
>
> Note that if the anchor unit is the pixel unit, the physical units might not match their physical measurements. Alternatively if the anchor unit is a physical unit, the pixel unit might not map to a whole number of device pixels.
>
> Note that this definition of the pixel unit and the physical units differs from previous versions of CSS. In particular, in previous versions of CSS the pixel unit and the physical units were not related by a fixed ratio: the physical units were always tied to their physical measurements while the pixel unit would vary to most closely match the reference pixel. (This change was made because too much existing content relies on the assumption of 96dpi, and breaking that assumption breaks the content.)
>
> So the spec changed the behavior to better support high-DPI devices with existing content, and that is exactly my intention with this PR as well.
> </strike>
Changes requested by aivanov (Reviewer).
src/java.desktop/share/classes/javax/swing/text/html/CSS.java line 2864:
> 2862: lengthMapping.put("pc", 12f);
> 2863: lengthMapping.put("in", 72f);
> 2864: // mapping according to the CSS2.2 spec
> Should we not put the latest CSS link here in addition/instead of in JEditorPane?
I agree the link to Length Units should also be added here:
Suggestion:
// Mapping according to the CSS2.2 spec
// https://www.w3.org/TR/CSS22/syndata.html#length-units
Or https://www.w3.org/TR/CSS22/syndata.html#x39 which leads directly to _Absolute length units_.
src/java.desktop/share/classes/javax/swing/text/html/CSS.java line 2870:
> 2868: w3cLengthMapping.put("cm", 37.7952f); //96px/2.54
> 2869: w3cLengthMapping.put("pc", 16f); //1/6 of 1in
> 2870: w3cLengthMapping.put("in", 96f); //96px
I suggest adding a space after `//`.
Align the comments?
As for *px*, CSS defines, “1px is equal to 0.75pt”, then 1pt is 4/3px — this is where 1.3f comes from (=96/72).
test/jdk/javax/swing/text/html/HtmlFontSizeTest.java line 79:
> 77: frame.setLocationRelativeTo(null);
> 78:
> 79: return frame.getBounds();
`frame` is redundant, `htmlPane.getPreferredSize()` does the job.
test/jdk/javax/swing/text/html/HtmlFontSizeTest.java line 94:
> 92:
> 93: float ratio = (float)w3cFrameSize.width / (float)stdFrameSize.width;
> 94: System.out.println("w3cFrameSize.width/stdFrameSize.width " + ratio);
Shall the ratio be `(float)w3cFrameSize.height / (float)stdFrameSize.height`?
You measure the font size so height seems a better candidate. However, the width does change as well.
test/jdk/javax/swing/text/html/HtmlFontSizeTest.java line 98:
> 96: String str = String.format("%.1g%n", ratio);
> 97: if (str.compareTo(String.format("%.1g%n", 1.3f)) != 0) {
> 98: throw new RuntimeException("HTML font size too large with high-DPI scaling and W3C_LENGTH_UNITS");
The test passes for me with the fresh build of JDK, even without the fix applied.
Indeed, I get the same frame dimensions in both cases: 150×42.
However, the test fails when run with JDK 11.0.10 or JDK 15, the dimension of `htmlPane` is 409×76.
The formatted string, `str`, contains only the number before the decimal point. I mean for `1.3f`, the formatted string is `"1"`. I'd expect the formatted string to have at least one digit after the decimal point but there's none.
Does
if ("1.3".equals(String.format("%1.1", ratio))
look clearer?
I guess the test does not fail if the system scaling (of the main monitor) is set to 100% because `res` value read from `Toolkit.getDefaultToolkit().getScreenResolution()` is 96/72 which is 1.3.
In my testing, `sun.java2d.uiScale` has no effect on the result.
-------------
PR: https://git.openjdk.java.net/jdk/pull/2256
More information about the swing-dev
mailing list