diff --git a/test/jdk/java/awt/font/TestDevanagari.java b/test/jdk/java/awt/font/TestDevanagari.java new file mode 100644 index 0000000000000..f4424b32b6b96 --- /dev/null +++ b/test/jdk/java/awt/font/TestDevanagari.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Font; +import java.awt.GraphicsEnvironment; + +import javax.swing.JFrame; +import javax.swing.JTextArea; + +/* + * @test + * @bug 5014727 + * @summary Display Devanagari text and make sure the character + * that appears after the nukta (dot) isn't duplicated. + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException + * @run main/manual TestDevanagari + */ + +public class TestDevanagari { + + private static final String text = """ + Ra Nukta Ra + \u0930\u093c\u0930"""; + private static final Font font = getPhysicalFontForText(text, Font.PLAIN, 20); + + public static void main(String[] args) throws Exception { + if (font == null) { + throw new jtreg.SkippedException("No Devanagari font found. Test Skipped."); + } + + final String INSTRUCTIONS = """ + You should see two Devanagari Letters 'Ra': + The first with Nukta sign (dot under it), the second without. + The second character (after the Nukta sign) shouldn't be visible twice + + Pass the test if this is true. + """; + + PassFailJFrame.builder() + .title("TestDevanagari Instruction") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(TestDevanagari::createUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame frame = new JFrame("TestDevanagari UI"); + JTextArea textArea = new JTextArea(); + textArea.setFont(font); + textArea.setText(text); + + frame.add(textArea); + frame.setSize(300, 200); + return frame; + } + + private static Font getPhysicalFontForText(String text, int style, int size) { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String[] names = ge.getAvailableFontFamilyNames(); + + for (String n : names) { + switch (n.toLowerCase()) { + case "dialog": + case "dialoginput": + case "serif": + case "sansserif": + case "monospaced": + break; + default: + Font f = new Font(n, style, size); + if (f.canDisplayUpTo(text) == -1) { + return f; + } + } + } + return null; + } +} diff --git a/test/jdk/java/awt/font/TextLayout/TestControls.java b/test/jdk/java/awt/font/TextLayout/TestControls.java new file mode 100644 index 0000000000000..ee15038a84590 --- /dev/null +++ b/test/jdk/java/awt/font/TextLayout/TestControls.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; + +/* + * @test + * @bug 4517298 + * @summary Display special control characters using both TextLayout.draw and + * Graphics.drawString. In no case should a missing glyph appear. + * Also display the advance of the control characters, in all cases + * these should be 0. The space character is also displayed as a reference. + * Note, the character is rendered between '><' but owing to the directional + * properties of two of the characters, the second '<' is rendered as '>'. + * This is correct behavior. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestControls + */ + +public class TestControls { + private static String fontName = Font.DIALOG; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + A number of control characters are displayed, one per line. + Each line displays the hex value of the character, the character + between '><' as rendered by TextLayout, the character between '><' + as rendered by drawString, and the advance of the character. + The first line renders the space character, as a reference. + The following lines all render the controls. + All controls should not render (even as space) and report a zero advance. + + Pass the test if this is true. + + Note: two of the control characters have the effect of changing the '<' + following the control character so that it renders as '>'. + This is not an error."""; + + PassFailJFrame.builder() + .title("TestControls Instruction") + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TestControls::createUI) + .build() + .awaitAndCheck(); + } + + private static Frame createUI() { + Frame f = new Frame("TestControls Test UI"); + Panel panel = new ControlPanel(fontName); + ScrollPane sp = new ScrollPane(); + sp.add("Center", panel); + f.add(sp); + f.setSize(450, 400); + return f; + } + + static class ControlPanel extends Panel { + + static final char[] chars = { + (char)0x0020, (char)0x0009, + (char)0x000A, (char)0x000D, (char)0x200C, (char)0x200D, (char)0x200E, + (char)0x200F, (char)0x2028, (char)0x2029, (char)0x202A, (char)0x202B, + (char)0x202C, (char)0x202D, (char)0x202E, (char)0x206A, (char)0x206B, + (char)0x206C, (char)0x206D, (char)0x206E, (char)0x206F + }; + + ControlPanel(String fontName) { + Font font = new Font(fontName, Font.PLAIN, 24); + System.out.println("using font: " + font); + setFont(font); + setForeground(Color.BLACK); + setBackground(Color.WHITE); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(400, 750); + } + + @Override + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + FontRenderContext frc = g2d.getFontRenderContext(); + Font font = g2d.getFont(); + FontMetrics fm = g2d.getFontMetrics(); + Insets insets = getInsets(); + + String jvmString = System.getProperty("java.version"); + String osString = System.getProperty("os.name") + " / " + + System.getProperty("os.arch") + " / " + + System.getProperty("os.version"); + + int x = insets.left + 10; + int y = insets.top; + + y += 30; + g2d.drawString("jvm: " + jvmString, x, y); + + y += 30; + g2d.drawString("os: " + osString, x, y); + + y += 30; + g2d.drawString("font: " + font.getFontName(), x, y); + + for (int i = 0; i < chars.length; ++i) { + String s = ">" + chars[i] + "<"; + x = insets.left + 10; + y += 30; + + g2d.drawString(Integer.toHexString(chars[i]), x, y); + x += 100; + + new TextLayout(s, font, frc).draw(g2d, x, y); + x += 100; + + g2d.drawString(s, x, y); + x += 100; + + g2d.drawString(Integer.toString(fm.charWidth(chars[i])), x, y); + } + } + } +} diff --git a/test/jdk/java/awt/font/TextLayout/TestGraphicOutline.java b/test/jdk/java/awt/font/TextLayout/TestGraphicOutline.java new file mode 100644 index 0000000000000..42efd4185f4ca --- /dev/null +++ b/test/jdk/java/awt/font/TextLayout/TestGraphicOutline.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GraphicAttribute; +import java.awt.font.ShapeGraphicAttribute; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; + +import javax.swing.JPanel; + +/* + * @test + * @bug 4915565 4920820 4920952 + * @summary Display graphics (circles) embedded in text, and draw both the outline (top) + * and black box bounds (bottom) of the result. The circles should each display at a + * different height. The outline and frames should approximately (within a pixel + * or two) surround each character. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestGraphicOutline + */ + +public class TestGraphicOutline { + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + Display graphics (circles) embedded in text, and draw both the + outline (top) and black box bounds (bottom) of the result. + + The circles should each display at a different height. + The outline and frames should approximately (within a pixel or two) + surround each character. + + Pass the test if these conditions hold. + + 'Black box bounds' is a term that refers to the bounding rectangles + of each glyph, see the TextLayout API getBlackBoxBounds. It does not + mean that the rendered outlines in the test are supposed to be black. + The color of the outlines does not matter and is not part of the test + conditions. Since there is no API for embedded graphics to return an + outline that matches the shape of the graphics, the outlines of the + graphics are their visual bounding boxes, which are rectangles. + + This is not an error. These outlines, as stated, should surround each + character's graphic."""; + + PassFailJFrame.builder() + .title("TestGraphicOutline Instruction") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(TestGraphicsPanel::new) + .build() + .awaitAndCheck(); + } + + private static final class TestGraphicsPanel extends JPanel { + + TextLayout tl; + + public TestGraphicsPanel() { + setBackground(Color.white); + setPreferredSize(new Dimension(650, 300)); + setName("2D Text"); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + int w = getSize().width; + int h = getSize().height; + + g2.setColor(getBackground()); + g2.fillRect(0, 0, w, h); + + Font f1 = new Font(Font.SANS_SERIF, Font.BOLD, 60); + Font f2 = new Font(Font.SERIF, Font.ITALIC, 80); + String str = "The Starry Night ok?"; + + AttributedString ats = new AttributedString(str); + + Shape s = new Ellipse2D.Float(0, -10, 12, 12); + GraphicAttribute iga1 = new ShapeGraphicAttribute(s, GraphicAttribute.TOP_ALIGNMENT, false); + GraphicAttribute iga2 = new ShapeGraphicAttribute(s, GraphicAttribute.HANGING_BASELINE, false); + GraphicAttribute iga3 = new ShapeGraphicAttribute(s, GraphicAttribute.CENTER_BASELINE, false); + GraphicAttribute iga4 = new ShapeGraphicAttribute(s, GraphicAttribute.ROMAN_BASELINE, false); + GraphicAttribute iga5 = new ShapeGraphicAttribute(s, GraphicAttribute.BOTTOM_ALIGNMENT, false); + + ats.addAttribute(TextAttribute.CHAR_REPLACEMENT, iga1, 1, 2); + ats.addAttribute(TextAttribute.CHAR_REPLACEMENT, iga2, 3, 4); + ats.addAttribute(TextAttribute.CHAR_REPLACEMENT, iga3, 7, 8); + ats.addAttribute(TextAttribute.CHAR_REPLACEMENT, iga4, 10, 11); + ats.addAttribute(TextAttribute.CHAR_REPLACEMENT, iga5, 14, 15); + ats.addAttribute(TextAttribute.FONT, f1, 0, 20); + ats.addAttribute(TextAttribute.FONT, f2, 4, 10); + AttributedCharacterIterator iter = ats.getIterator(); + + FontRenderContext frc = g2.getFontRenderContext(); + tl = new TextLayout(iter, frc); + Rectangle2D bounds = tl.getBounds(); + float sw = (float) bounds.getWidth(); + float sh = (float) bounds.getHeight(); + + g2.translate((w - sw) / 2f, h / 2f - sh + tl.getAscent() - 2); + + g2.setColor(Color.blue); + tl.draw(g2, 0, 0); + g2.draw(bounds); + + g2.setColor(Color.black); + Shape shape = tl.getOutline(null); + g2.draw(shape); + + g2.translate(0, sh + 5); + + g2.setColor(Color.blue); + tl.draw(g2, 0, 0); + g2.draw(bounds); + + g2.setColor(Color.red); + shape = tl.getBlackBoxBounds(0, tl.getCharacterCount()); + g2.draw(shape); + } + } +}