Skip to content

Commit 2e610f5

Browse files
stanioaivanov-jdk
andcommitted
8260687: Inherited font size is smaller than expected when using StyleSheet to add styles
Co-authored-by: Alexey Ivanov <aivanov@openjdk.org> Reviewed-by: psadhukhan, aivanov, kizune
1 parent 3882fda commit 2e610f5

File tree

3 files changed

+211
-13
lines changed

3 files changed

+211
-13
lines changed

src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -2813,7 +2813,10 @@ public Object getAttribute(Object key) {
28132813
((StyleConstants)key);
28142814
if (cssKey != null) {
28152815
Object value = doGetAttribute(cssKey);
2816-
if (value instanceof CSS.CssValue) {
2816+
if (value instanceof CSS.FontSize) {
2817+
return ((CSS.FontSize)value)
2818+
.getValue(this, StyleSheet.this);
2819+
} else if (value instanceof CSS.CssValue) {
28172820
return ((CSS.CssValue)value).toStyleConstants
28182821
((StyleConstants)key, host);
28192822
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.BorderLayout;
25+
import java.util.ArrayList;
26+
import java.util.Arrays;
27+
import java.util.List;
28+
import javax.swing.JEditorPane;
29+
import javax.swing.JFrame;
30+
import javax.swing.JScrollPane;
31+
import javax.swing.SwingUtilities;
32+
import javax.swing.text.AbstractDocument.AbstractElement;
33+
import javax.swing.text.Document;
34+
import javax.swing.text.GlyphView;
35+
import javax.swing.text.View;
36+
import javax.swing.text.html.HTMLEditorKit;
37+
import javax.swing.text.html.StyleSheet;
38+
39+
/*
40+
* @test
41+
* @bug 8260687
42+
* @summary Tests inherited font-size is the same as explicitly specified
43+
* @run main BodyInheritedFontSize
44+
*/
45+
public class BodyInheritedFontSize {
46+
private static final String HTML_TEXT = """
47+
<html>
48+
<body>
49+
<p style="font-size: 100%">100% from body</p>
50+
<p>16pt inherited from body</p>
51+
<p style="font-size: 16pt">16pt paragraph</p>
52+
</body>
53+
</html>
54+
""";
55+
56+
private static JEditorPane createEditorPane(boolean w3cUnits, boolean showFrame) {
57+
JEditorPane htmlPane = new JEditorPane();
58+
htmlPane.setEditable(false);
59+
60+
if (w3cUnits) {
61+
htmlPane.putClientProperty(JEditorPane.W3C_LENGTH_UNITS, Boolean.TRUE);
62+
}
63+
64+
HTMLEditorKit kit = new HTMLEditorKit();
65+
htmlPane.setEditorKit(kit);
66+
67+
StyleSheet styleSheet = kit.getStyleSheet();
68+
styleSheet.addRule("body { font-family: sans-serif; font-size: 16pt; }");
69+
70+
Document doc = kit.createDefaultDocument();
71+
htmlPane.setDocument(doc);
72+
htmlPane.setText(HTML_TEXT);
73+
74+
if (showFrame) {
75+
JFrame frame = new JFrame("HtmlFontSizeGUITest: "
76+
+ (w3cUnits ? "w3c" : "std"));
77+
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
78+
frame.add(new JScrollPane(htmlPane), BorderLayout.CENTER);
79+
frame.setLocationRelativeTo(null);
80+
frame.pack();
81+
frame.setVisible(true);
82+
}
83+
84+
// Ignore the result but perform layout
85+
htmlPane.getPreferredSize();
86+
87+
return htmlPane;
88+
}
89+
90+
public static void main(String[] args) throws Exception {
91+
final List<String> argsList = Arrays.asList(args);
92+
final boolean showFrame = toShowFrame(argsList);
93+
final boolean debugPrint = toDebugPrint(argsList);
94+
95+
final List<Exception> exceptions = new ArrayList<>(2);
96+
SwingUtilities.invokeAndWait(() -> {
97+
for (boolean w3cUnits : new boolean[] {true, false}) {
98+
JEditorPane htmlPane = createEditorPane(w3cUnits, showFrame);
99+
try {
100+
checkFontSize(htmlPane, w3cUnits, debugPrint);
101+
} catch (Exception e) {
102+
exceptions.add(e);
103+
}
104+
}
105+
});
106+
if (exceptions.size() > 0) {
107+
exceptions.forEach(System.err::println);
108+
throw new RuntimeException(
109+
"Test failed: " + exceptions.get(0).getMessage(),
110+
exceptions.get(0));
111+
}
112+
}
113+
114+
private static boolean toShowFrame(final List<String> argsList) {
115+
return argsList.contains("-show");
116+
}
117+
118+
private static boolean toDebugPrint(final List<String> argsList) {
119+
return argsList.contains("-print");
120+
}
121+
122+
private static void checkFontSize(JEditorPane htmlPane,
123+
boolean w3cUnits,
124+
boolean debugPrint) {
125+
final View rootView = htmlPane.getUI().getRootView(htmlPane);
126+
final View boxView = rootView.getView(0);
127+
final View bodyView = boxView.getView(1);
128+
129+
int fontSizePercentage = getViewFontSize(bodyView.getView(0), debugPrint);
130+
int fontSizeInherited = getViewFontSize(bodyView.getView(1), debugPrint);
131+
int fontSizeExplicit = getViewFontSize(bodyView.getView(2), debugPrint);
132+
if (debugPrint) {
133+
System.out.println("w3cUnits: " + w3cUnits + "\n"
134+
+ "Percentage: " + fontSizePercentage + "\n"
135+
+ "Inherited: " + fontSizeInherited + "\n"
136+
+ "Explicit: " + fontSizeExplicit + "\n");
137+
}
138+
if (fontSizeInherited != fontSizeExplicit
139+
|| fontSizePercentage != fontSizeExplicit) {
140+
throw new RuntimeException("The font size is different with "
141+
+ (w3cUnits ? "w3cUnits" : "stdUnits") + ": "
142+
+ "Percentage: " + fontSizePercentage + " vs. "
143+
+ "Inherited: " + fontSizeInherited + " vs. "
144+
+ "Explicit: " + fontSizeExplicit);
145+
}
146+
}
147+
148+
private static int getViewFontSize(View paragraphView, boolean debugPrint) {
149+
GlyphView inlineView = findFirstTextRun(paragraphView);
150+
int fontSize = inlineView.getFont().getSize();
151+
if (debugPrint) {
152+
((AbstractElement) inlineView.getElement()).dump(System.out, 1);
153+
}
154+
return fontSize;
155+
}
156+
157+
private static GlyphView findFirstTextRun(View view) {
158+
if (view instanceof GlyphView) {
159+
return (GlyphView) view;
160+
}
161+
for (int i = 0; i < view.getViewCount(); i++) {
162+
GlyphView textRun = findFirstTextRun(view.getView(i));
163+
if (textRun != null) {
164+
return textRun;
165+
}
166+
}
167+
return null;
168+
}
169+
}

test/jdk/javax/swing/text/html/StyleSheet/TestWrongCSSFontSize.java

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.awt.image.BufferedImage;
2727
import java.io.File;
2828
import java.io.IOException;
29+
import java.util.Arrays;
2930
import java.util.concurrent.atomic.AtomicReference;
3031
import java.util.function.Consumer;
3132
import javax.imageio.ImageIO;
@@ -39,10 +40,11 @@
3940
* @bug 8257664
4041
* @summary Tests inherited font-size with parent percentage specification.
4142
* @run main TestWrongCSSFontSize
43+
* @run main TestWrongCSSFontSize -w3cUnits
4244
*/
4345
public class TestWrongCSSFontSize {
4446

45-
private static String text =
47+
private static final String TEXT =
4648
"<html><head><style>" +
4749
"body { font-size: 14 }" +
4850
"div span { font-size: 150% }" +
@@ -61,23 +63,33 @@ public class TestWrongCSSFontSize {
6163

6264
"</body></html>";
6365

64-
private static int expectedFontSize = 21;
65-
private static int expectedAssertions = 8;
66+
private static final int expectedFontSize = 21;
67+
private static final int expectedAssertions = 8;
68+
69+
private final boolean w3cUnits;
6670

6771
private JEditorPane editor;
6872

73+
public TestWrongCSSFontSize(boolean w3cUnits) {
74+
this.w3cUnits = w3cUnits;
75+
}
76+
6977
public void setUp() {
7078
editor = new JEditorPane();
7179
editor.setContentType("text/html");
72-
editor.setText(text);
80+
if (w3cUnits) {
81+
editor.putClientProperty(JEditorPane.W3C_LENGTH_UNITS, Boolean.TRUE);
82+
}
83+
editor.setText(TEXT);
7384
editor.setSize(editor.getPreferredSize()); // layout
7485
}
7586

7687
public void run() {
7788
int count = forEachTextRun(editor.getUI()
7889
.getRootView(editor), this::assertFontSize);
7990
if (count != expectedAssertions) {
80-
throw new AssertionError("assertion count expected ["
91+
throw new AssertionError((w3cUnits ? "w3cUnits - " : "")
92+
+ "assertion count expected ["
8193
+ expectedAssertions + "] but found [" + count + "]");
8294
}
8395
}
@@ -104,7 +116,8 @@ private void assertFontSize(GlyphView child) {
104116
printSource(child);
105117
int actualFontSize = child.getFont().getSize();
106118
if (actualFontSize != expectedFontSize) {
107-
throw new AssertionError("font size expected ["
119+
throw new AssertionError((w3cUnits ? "w3cUnits - " : "")
120+
+ "font size expected ["
108121
+ expectedFontSize + "] but found [" + actualFontSize +"]");
109122
}
110123
}
@@ -119,22 +132,24 @@ private void printSource(View textRun) {
119132
}
120133
}
121134

122-
private static void captureImage(Component comp, String path) {
135+
private static void captureImage(Component comp, String suffix) {
123136
try {
124137
BufferedImage capture = new BufferedImage(comp.getWidth(),
125138
comp.getHeight(), BufferedImage.TYPE_INT_ARGB);
126139
Graphics g = capture.getGraphics();
127140
comp.paint(g);
128141
g.dispose();
129142

130-
ImageIO.write(capture, "png", new File(path));
143+
ImageIO.write(capture, "png",
144+
new File(TestWrongCSSFontSize.class
145+
.getSimpleName() + suffix + ".png"));
131146
} catch (IOException e) {
132147
e.printStackTrace();
133148
}
134149
}
135150

136151
public static void main(String[] args) throws Throwable {
137-
TestWrongCSSFontSize test = new TestWrongCSSFontSize();
152+
TestWrongCSSFontSize test = new TestWrongCSSFontSize(argW3CUnits(args));
138153
AtomicReference<Throwable> failure = new AtomicReference<>();
139154
SwingUtilities.invokeAndWait(() -> {
140155
try {
@@ -143,8 +158,11 @@ public static void main(String[] args) throws Throwable {
143158
} catch (Throwable e) {
144159
failure.set(e);
145160
} finally {
146-
if (args.length == 1) {
147-
captureImage(test.editor, args[0]);
161+
String suffix = test.w3cUnits ? "-w3cUnits" : "";
162+
if (failure.get() != null) {
163+
captureImage(test.editor, suffix + "-failure");
164+
} else if (argCapture(args)) {
165+
captureImage(test.editor, suffix + "-success");
148166
}
149167
}
150168
});
@@ -153,4 +171,12 @@ public static void main(String[] args) throws Throwable {
153171
}
154172
}
155173

174+
private static boolean argW3CUnits(String[] args) {
175+
return Arrays.asList(args).contains("-w3cUnits");
176+
}
177+
178+
private static boolean argCapture(String[] args) {
179+
return Arrays.asList(args).contains("-capture");
180+
}
181+
156182
}

0 commit comments

Comments
 (0)