diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 59d86c646d2..5f78fc06abd 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -806,6 +806,7 @@ java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx- java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all java/awt/Frame/FrameStateTest/FrameStateTest.java 8203920 macosx-all,linux-all java/awt/print/PrinterJob/ScaledText/ScaledText.java 8231226 macosx-all +java/awt/print/PrinterJob/PrintTextTest.java 8148334 generic-all java/awt/font/TextLayout/TestJustification.java 8250791 macosx-all java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all diff --git a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java index 95bf177aa2f..f2ec4e15a8a 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java +++ b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -21,193 +21,207 @@ * questions. */ -/** +/* * @test * @bug 6425068 7157659 8132890 * @key printer * @summary Confirm that text prints where we expect to the length we expect. - * @run main/manual=yesno PrintTextTest + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PrintTextTest */ -import java.awt.*; -import java.awt.event.*; -import java.text.*; -import java.util.*; -import java.awt.font.*; -import java.awt.geom.*; -import java.awt.print.*; -import javax.swing.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.RenderingHints; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.print.Book; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.HashMap; -public class PrintTextTest extends Component implements Printable { +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JTabbedPane; - static int preferredSize; - Font textFont; - AffineTransform gxTx; - String page; - boolean useFM; +public class PrintTextTest { - public static void main(String args[]) { - String[] instructions = - { - "This tests that printed text renders similarly to on-screen", - "under a variety of APIs and graphics and font transforms", - "Print to your preferred printer. Collect the output.", - "Refer to the onscreen buttons to cycle through the on-screen", - "content", - "For each page, confirm that the printed content corresponds to", - "the on-screen rendering for that *same* page.", - "Some cases may look odd but its intentional. Verify", - "it looks the same on screen and on the printer.", - "Note that text does not scale linearly from screen to printer", - "so some differences are normal and not a bug.", - "The easiest way to spot real problems is to check that", - "any underlines are the same length as the underlined text", - "and that any rotations are the same in each case.", - "Note that each on-screen page is printed in both portrait", - "and landscape mode", - "So for example, Page 1/Portrait, and Page 1/Landscape when", - "rotated to view properly, should both match Page 1 on screen.", - }; - Sysout.createDialogWithInstructions(instructions); + static final String INSTRUCTIONS = """ + This tests that printed text renders similarly to on-screen under a variety + of APIs and graphics and font transforms. + 1. Print to your preferred printer. + 2. Collect the output. + 3. Refer to the onscreen buttons to cycle through the on-screen content. + 4. For each page, confirm that the printed content corresponds to the + on-screen rendering for that *same* page. Some cases may look odd but + its intentional. Verify it looks the same on screen and on the printer. + Note that text does not scale linearly from screen to printer so some + differences are normal and not a bug. + The easiest way to spot real problems is to check that any underlines are + the same length as the underlined text and that any rotations are the same + in each case. + Note that each on-screen page is printed in both portrait and landscape mode. + So for example, Page 1/Portrait, and Page 1/Landscape when rotated to view + properly, should both match Page 1 on screen. + """; + public static void main(String[] args) throws Exception { PrinterJob pjob = PrinterJob.getPrinterJob(); PageFormat portrait = pjob.defaultPage(); portrait.setOrientation(PageFormat.PORTRAIT); - preferredSize = (int)portrait.getImageableWidth(); + int preferredSize = (int) portrait.getImageableWidth(); PageFormat landscape = pjob.defaultPage(); landscape.setOrientation(PageFormat.LANDSCAPE); Book book = new Book(); - JTabbedPane p = new JTabbedPane(); + JTabbedPane pane = new JTabbedPane(); int page = 1; - Font font = new Font("Dialog", Font.PLAIN, 18); - String name = "Page " + new Integer(page++); - PrintTextTest ptt = new PrintTextTest(name, font, null, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + Font font = new Font(Font.DIALOG, Font.PLAIN, 18); + String name = "Page " + page++; + PrintText pt = new PrintText(name, font, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); - font = new Font("Dialog", Font.PLAIN, 18); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, null, true); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + font = new Font(Font.DIALOG, Font.PLAIN, 18); + name = "Page " + page++; + pt = new PrintText(name, font, null, true, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); font = getPhysicalFont(); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, null, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, font, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); font = getPhysicalFont(); AffineTransform rotTx = AffineTransform.getRotateInstance(0.15); - rotTx.translate(60,0); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, rotTx, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + rotTx.translate(60, 0); + name = "Page " + page++; + pt = new PrintText(name, font, rotTx, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); - font = new Font("Dialog", Font.PLAIN, 18); + font = new Font(Font.DIALOG, Font.PLAIN, 18); AffineTransform scaleTx = AffineTransform.getScaleInstance(1.25, 1.25); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, scaleTx, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, font, scaleTx, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); - font = new Font("Dialog", Font.PLAIN, 18); + font = new Font(Font.DIALOG, Font.PLAIN, 18); scaleTx = AffineTransform.getScaleInstance(-1.25, 1.25); - scaleTx.translate(-preferredSize/1.25, 0); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, scaleTx, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + scaleTx.translate(-preferredSize / 1.25, 0); + name = "Page " + page++; + pt = new PrintText(name, font, scaleTx, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); - font = new Font("Dialog", Font.PLAIN, 18); + font = new Font(Font.DIALOG, Font.PLAIN, 18); scaleTx = AffineTransform.getScaleInstance(1.25, -1.25); - scaleTx.translate(0, -preferredSize/1.25); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, scaleTx, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + scaleTx.translate(0, -preferredSize / 1.25); + name = "Page " + page++; + pt = new PrintText(name, font, scaleTx, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); font = font.deriveFont(rotTx); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, null, false); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, font, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); - font = new Font("Monospaced", Font.PLAIN, 12); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, null, false); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + font = new Font(Font.MONOSPACED, Font.PLAIN, 12); + name = "Page " + page++; + pt = new PrintText(name, font, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); Font xfont = font.deriveFont(AffineTransform.getScaleInstance(1.5, 1)); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, xfont, null, false); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, xfont, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); Font yfont = font.deriveFont(AffineTransform.getScaleInstance(1, 1.5)); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, yfont, null, false); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, yfont, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); if (System.getProperty("os.name").startsWith("Windows")) { font = new Font("MS Gothic", Font.PLAIN, 12); - name = "Page " + new Integer(page++); - ptt = new PrintJAText(name, font, null, true); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintJapaneseText(name, font, null, true, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); font = new Font("MS Gothic", Font.PLAIN, 12); - name = "Page " + new Integer(page++); + name = "Page " + page++; rotTx = AffineTransform.getRotateInstance(0.15); - ptt = new PrintJAText(name, font, rotTx, true); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + pt = new PrintJapaneseText(name, font, rotTx, true, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); } pjob.setPageable(book); - JFrame f = new JFrame(); - f.add(BorderLayout.CENTER, p); - f.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) {System.exit(0);} - }); - f.pack(); - f.show(); - - try { - if (pjob.printDialog()) { - pjob.print(); + JButton printButton = new JButton("Print"); + printButton.addActionListener(event -> { + try { + if (pjob.printDialog()) { + pjob.print(); + } + } catch (PrinterException e) { + throw new RuntimeException(e.getMessage(), e); } - } catch (PrinterException e) { - throw new RuntimeException(e.getMessage()); - } + }); + + JFrame f = new JFrame("PrintTextTest"); + f.add(BorderLayout.CENTER, pane); + f.add(BorderLayout.SOUTH, printButton); + f.pack(); + + PassFailJFrame.builder() + .title("PrintTextTest") + .instructions(INSTRUCTIONS) + .testTimeOut(10) + .columns(60) + .testUI(f) + .build() + .awaitAndCheck(); } // The test needs a physical font that supports Latin. @@ -221,338 +235,228 @@ public class PrintTextTest extends Component implements Printable { String[] names = ge.getAvailableFontFamilyNames(); for (String n : names) { - switch (n.toLowerCase()) { - case "dialog": - case "dialoginput": - case "serif": - case "sansserif": - case "monospaced": - break; + switch (n) { + case Font.DIALOG: + case Font.DIALOG_INPUT: + case Font.SERIF: + case Font.SANS_SERIF: + case Font.MONOSPACED: + continue; default: Font f = new Font(n, Font.PLAIN, 18); if (f.canDisplayUpTo("AZaz09") == -1) { physicalFont = f; return f; } - } + } } physicalFont = new Font(Font.DIALOG, Font.PLAIN, 18); return physicalFont; } - public PrintTextTest(String page, Font font, AffineTransform gxTx, - boolean fm) { - this.page = page; - textFont = font; - this.gxTx = gxTx; - this.useFM = fm; - setBackground(Color.white); - } + private static class PrintText extends Component implements Printable { - public static AttributedCharacterIterator getIterator(String s) { - return new AttributedString(s).getIterator(); - } + protected final Font textFont; + protected final AffineTransform gxTx; + protected final String page; + protected final boolean useFM; + protected final int preferredSize; - static String orient(PageFormat pf) { - if (pf.getOrientation() == PageFormat.PORTRAIT) { - return "Portrait"; - } else { - return "Landscape"; - } - } - - public int print(Graphics g, PageFormat pf, int pageIndex) { - - Graphics2D g2d = (Graphics2D)g; - g2d.translate(pf.getImageableX(), pf.getImageableY()); - g.drawString(page+" "+orient(pf),50,20); - g.translate(0, 25); - paint(g); - return PAGE_EXISTS; - } - - public Dimension getMinimumSize() { - return getPreferredSize(); - } - - public Dimension getPreferredSize() { - return new Dimension(preferredSize, preferredSize); - } - - public void paint(Graphics g) { - - /* fill with white before any transformation is applied */ - g.setColor(Color.white); - g.fillRect(0, 0, getSize().width, getSize().height); - - - Graphics2D g2d = (Graphics2D) g; - if (gxTx != null) { - g2d.transform(gxTx); - } - if (useFM) { - g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, - RenderingHints.VALUE_FRACTIONALMETRICS_ON); + public PrintText(String page, Font font, AffineTransform gxTx, boolean fm, int size) { + this.page = page; + this.textFont = font; + this.gxTx = gxTx; + this.useFM = fm; + this.preferredSize = size; + setBackground(Color.WHITE); } - g.setFont(textFont); - FontMetrics fm = g.getFontMetrics(); - - String s; - int LS = 30; - int ix=10, iy=LS+10; - g.setColor(Color.black); - - s = "drawString(String str, int x, int y)"; - g.drawString(s, ix, iy); - if (!textFont.isTransformed()) { - g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); + private static AttributedCharacterIterator getIterator(String s) { + return new AttributedString(s).getIterator(); } - iy += LS; - s = "drawString(AttributedCharacterIterator iterator, int x, int y)"; - g.drawString(getIterator(s), ix, iy); - - iy += LS; - s = "\tdrawChars(\t\r\nchar[], int off, int len, int x, int y\t)"; - g.drawChars(s.toCharArray(), 0, s.length(), ix, iy); - if (!textFont.isTransformed()) { - g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); - } - - iy += LS; - s = "drawBytes(byte[], int off, int len, int x, int y)"; - byte data[] = new byte[s.length()]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) s.charAt(i); - } - g.drawBytes(data, 0, data.length, ix, iy); - - Font f = g2d.getFont(); - FontRenderContext frc = g2d.getFontRenderContext(); - - iy += LS; - s = "drawString(String s, float x, float y)"; - g2d.drawString(s, (float) ix, (float) iy); - if (!textFont.isTransformed()) { - g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); - } - - iy += LS; - s = "drawString(AttributedCharacterIterator iterator, "+ - "float x, float y)"; - g2d.drawString(getIterator(s), (float) ix, (float) iy); - - iy += LS; - s = "drawGlyphVector(GlyphVector g, float x, float y)"; - GlyphVector gv = f.createGlyphVector(frc, s); - g2d.drawGlyphVector(gv, ix, iy); - Point2D adv = gv.getGlyphPosition(gv.getNumGlyphs()); - if (!textFont.isTransformed()) { - g.drawLine(ix, iy+1, ix+(int)adv.getX(), iy+1); - } - - iy += LS; - s = "GlyphVector with position adjustments"; - - gv = f.createGlyphVector(frc, s); - int ng = gv.getNumGlyphs(); - adv = gv.getGlyphPosition(ng); - for (int i=0; i(), frc); + tl.draw(g2d, ix, iy); + + iy += LS; + s = "TextLayout 2: \u0924\u094d\u0930 \u0915\u0948\u0930\u0947 End."; + tl = new TextLayout(s, f, frc); + tl.draw(g2d, ix, iy); + } } - private static final String TEXT = - "\u3042\u3044\u3046\u3048\u304a\u30a4\u30ed\u30cf" + - "\u30cb\u30db\u30d8\u30c8\u4e00\u4e01\u4e02\u4e05\uff08"; + private static class PrintJapaneseText extends PrintText { - - public void paint(Graphics g) { - - /* fill with white before any transformation is applied */ - g.setColor(Color.white); - g.fillRect(0, 0, getSize().width, getSize().height); - - - Graphics2D g2d = (Graphics2D) g; - if (gxTx != null) { - g2d.transform(gxTx); - } - if (useFM) { - g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, - RenderingHints.VALUE_FRACTIONALMETRICS_ON); + public PrintJapaneseText(String page, Font font, AffineTransform gxTx, boolean fm, int size) { + super(page, font, gxTx, fm, size); } - String text = TEXT + TEXT + TEXT; - g.setColor(Color.black); - int y = 20; - float origSize = 7f; - for (int i=0;i<11;i++) { - float size = origSize+(i*0.1f); - g2d.translate(0, size+6); - Font f = textFont.deriveFont(size); - g2d.setFont(f); - FontMetrics fontMetrics = g2d.getFontMetrics(); - int stringWidth = fontMetrics.stringWidth(text); - g.drawLine(0, y+1, stringWidth, y+1); - g.drawString(text, 0, y); - y +=10; + private static final String TEXT = + "\u3042\u3044\u3046\u3048\u304a\u30a4\u30ed\u30cf" + + "\u30cb\u30db\u30d8\u30c8\u4e00\u4e01\u4e02\u4e05\uff08"; + + @Override + public void paint(Graphics g) { + + g.setColor(Color.WHITE); + g.fillRect(0, 0, getSize().width, getSize().height); + + Graphics2D g2d = (Graphics2D) g; + if (gxTx != null) { + g2d.transform(gxTx); + } + if (useFM) { + g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); + } + + String text = TEXT + TEXT + TEXT; + g.setColor(Color.BLACK); + int y = 20; + float origSize = 7f; + for (int i = 0; i < 11; i++) { + float size = origSize + (i * 0.1f); + g2d.translate(0, size + 6); + Font f = textFont.deriveFont(size); + g2d.setFont(f); + FontMetrics fontMetrics = g2d.getFontMetrics(); + int stringWidth = fontMetrics.stringWidth(text); + g.drawLine(0, y + 1, stringWidth, y + 1); + g.drawString(text, 0, y); + y += 10; + } } } } - -class Sysout - { - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - - }// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog - { - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 20, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("South", messageText); - - pack(); - - show(); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - } - -}// TestDialog class