1/* 2 * Copyright (c) 2007, 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/* 25 @test 26 @bug 4291373 27 @summary Printing of scaled text is wrong / disappearing 28 @author prr: area=PrinterJob 29 @run main/manual ScaledText 30*/ 31import java.awt.*; 32import java.awt.event.*; 33import java.awt.print.*; 34 35 36public class ScaledText implements Printable { 37 38 private Image opaqueimg,transimg; 39 40 private static void init() { 41 42 //*** Create instructions for the user here *** 43 44 String[] instructions = { 45 "On-screen inspection is not possible for this printing-specific", 46 "test therefore its only output is two printed pages.", 47 "To be able to run this test it is required to have a default", 48 "printer configured in your user environment.", 49 "", 50 "Visual inspection of the printed pages is needed. A passing", 51 "test will print a page on which 6 lines of text will be", 52 "printed, all of the same size. The test fails only if the sizes", 53 "are different, or not all of the sizes labelled 1.0, 2.0, 4.0", 54 "8.0, 16.0, 32.0 appear." 55 }; 56 57 Sysout.createDialog( ); 58 Sysout.printInstructions( instructions ); 59 60 PrinterJob pjob = PrinterJob.getPrinterJob(); 61 62 Book book = new Book(); 63 64 PageFormat portrait = pjob.defaultPage(); 65 book.append(new ScaledText(),portrait); 66 67 pjob.setPageable(book); 68 69 if (pjob.printDialog()) { 70 try { 71 pjob.print(); 72 } catch (PrinterException e) { 73 System.err.println(e); 74 e.printStackTrace(); 75 } 76 } 77 System.out.println("Done Printing"); 78 79 }//End init() 80 81 82 public ScaledText() { 83 } 84 85 public int print(Graphics g, PageFormat pgFmt, int pgIndex) { 86 87 Graphics2D g2D = (Graphics2D) g; 88 g2D.translate(pgFmt.getImageableX(), pgFmt.getImageableY()); 89 90 g2D.setColor(Color.black); 91 Font font = new Font("serif", Font.PLAIN, 1); 92 93 float scale; 94 float x; 95 float y; 96 97 scale = 1.0f; 98 x = 3.0f; 99 y = 3.0f; 100 printScale(g2D, font, scale, x, y); 101 102 scale = 2.0f; 103 x = 3.0f; 104 y = 3.5f; 105 printScale(g2D, font, scale, x, y); 106 107 scale = 4.0f; 108 x = 3.0f; 109 y = 4.0f; 110 printScale(g2D, font, scale, x, y); 111 112 scale = 8.0f; 113 x = 3.0f; 114 y = 4.5f; 115 printScale(g2D, font, scale, x, y); 116 117 scale = 16.0f; 118 x = 3.0f; 119 y = 5.0f; 120 printScale(g2D, font, scale, x, y); 121 122 scale = 32.0f; 123 x = 3.0f; 124 y = 5.5f; 125 printScale(g2D, font, scale, x, y); 126 127 return Printable.PAGE_EXISTS; 128 } 129 130 /** 131 * The graphics is scaled and the font and the positions 132 * are reduced in respect to the scaling, so that all 133 * printing should be the same. 134 * 135 * @param g2D graphics2D to paint on 136 * @param font font to paint 137 * @param scale scale for the painting 138 * @param x x position 139 * @param y y position 140 */ 141 private void printScale(Graphics2D g2D, Font font, 142 float scale, float x, float y) { 143 144 int RES = 72; 145 146 g2D.scale(scale, scale); 147 148 g2D.setFont (font.deriveFont(10.0f / scale)); 149 g2D.drawString("This text is scaled by a factor of " + scale, 150 x * RES / scale, y * RES / scale); 151 152 g2D.scale(1/scale, 1/scale); 153 154} 155 156 /***************************************************** 157 Standard Test Machinery Section 158 DO NOT modify anything in this section -- it's a 159 standard chunk of code which has all of the 160 synchronisation necessary for the test harness. 161 By keeping it the same in all tests, it is easier 162 to read and understand someone else's test, as 163 well as insuring that all tests behave correctly 164 with the test harness. 165 There is a section following this for test-defined 166 classes 167 ******************************************************/ 168 private static boolean theTestPassed = false; 169 private static boolean testGeneratedInterrupt = false; 170 private static String failureMessage = ""; 171 172 private static Thread mainThread = null; 173 174 private static int sleepTime = 300000; 175 176 public static void main( String args[] ) throws InterruptedException 177 { 178 mainThread = Thread.currentThread(); 179 try 180 { 181 init(); 182 } 183 catch( TestPassedException e ) 184 { 185 //The test passed, so just return from main and harness will 186 // interepret this return as a pass 187 return; 188 } 189 //At this point, neither test passed nor test failed has been 190 // called -- either would have thrown an exception and ended the 191 // test, so we know we have multiple threads. 192 193 //Test involves other threads, so sleep and wait for them to 194 // called pass() or fail() 195 try 196 { 197 Thread.sleep( sleepTime ); 198 //Timed out, so fail the test 199 throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); 200 } 201 catch (InterruptedException e) 202 { 203 if( ! testGeneratedInterrupt ) throw e; 204 205 //reset flag in case hit this code more than once for some reason (just safety) 206 testGeneratedInterrupt = false; 207 if ( theTestPassed == false ) 208 { 209 throw new RuntimeException( failureMessage ); 210 } 211 } 212 213 }//main 214 215 public static synchronized void setTimeoutTo( int seconds ) 216 { 217 sleepTime = seconds * 1000; 218 } 219 220 public static synchronized void pass() 221 { 222 Sysout.println( "The test passed." ); 223 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 224 //first check if this is executing in main thread 225 if ( mainThread == Thread.currentThread() ) 226 { 227 //Still in the main thread, so set the flag just for kicks, 228 // and throw a test passed exception which will be caught 229 // and end the test. 230 theTestPassed = true; 231 throw new TestPassedException(); 232 } 233 //pass was called from a different thread, so set the flag and interrupt 234 // the main thead. 235 theTestPassed = true; 236 testGeneratedInterrupt = true; 237 mainThread.interrupt(); 238 }//pass() 239 240 public static synchronized void fail() 241 { 242 //test writer didn't specify why test failed, s fail( "it just plain failed! :-)" ); 243 } 244 245 public static synchronized void fail( String whyFailed ) 246 { 247 Sysout.println( "The test failed: " + whyFailed ); 248 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 249 //check if this called from main thread 250 if ( mainThread == Thread.currentThread() ) 251 { 252 //If main thread, fail now 'cause not sleeping 253 throw new RuntimeException( whyFailed ); 254 } 255 theTestPassed = false; 256 testGeneratedInterrupt = true; 257 failureMessage = whyFailed; 258 mainThread.interrupt(); 259 }//fail() 260 261}// class ScaledText 262 263//This exception is used to exit from any level of call nesting 264// when it's determined that the test has passed, and immediately 265// end the test. 266class TestPassedException extends RuntimeException 267 { 268 } 269 270 271//************** End classes defined for the test ******************* 272 273 274 275 276/**************************************************** 277 Standard Test Machinery 278 DO NOT modify anything below -- it's a standard 279 chunk of code whose purpose is to make user 280 interaction uniform, and thereby make it simpler 281 to read and understand someone else's test. 282 ****************************************************/ 283 284/** 285 This is part of the standard test machinery. 286 It creates a dialog (with the instructions), and is the interface 287 for sending text messages to the user. 288 To print the instructions, send an array of strings to Sysout.createDialog 289 WithInstructions method. Put one line of instructions per array entry. 290 To display a message for the tester to see, simply call Sysout.println 291 with the string to be displayed. 292 This mimics System.out.println but works within the test harness as well 293 as standalone. 294 */ 295 296class Sysout 297 { 298 private static TestDialog dialog; 299 300 public static void createDialogWithInstructions( String[] instructions ) 301 { 302 dialog = new TestDialog( new Frame(), "Instructions" ); 303 dialog.printInstructions( instructions ); 304 dialog.show(); 305 println( "Any messages for the tester will display here." ); 306 } 307 308 public static void createDialog( ) 309 { 310 dialog = new TestDialog( new Frame(), "Instructions" ); 311 String[] defInstr = { "Instructions will appear here. ", "" } ; 312 dialog.printInstructions( defInstr ); 313 dialog.show(); 314 println( "Any messages for the tester will display here." ); 315 } 316 317 318 public static void printInstructions( String[] instructions ) 319 { 320 dialog.printInstructions( instructions ); 321 } 322 323 324 public static void println( String messageIn ) 325 { 326 dialog.displayMessage( messageIn ); 327 } 328 329 }// Sysout class 330 331/** 332 This is part of the standard test machinery. It provides a place for the 333 test instructions to be displayed, and a place for interactive messages 334 to the user to be displayed. 335 To have the test instructions displayed, see Sysout. 336 To have a message to the user be displayed, see Sysout. 337 Do not call anything in this dialog directly. 338 */ 339class TestDialog extends Dialog implements ActionListener { 340 341 TextArea instructionsText; 342 TextArea messageText; 343 int maxStringLength = 80; 344 Panel buttonP = new Panel(); 345 Button passB = new Button( "pass" ); 346 Button failB = new Button( "fail" ); 347 348 //DO NOT call this directly, go through Sysout 349 public TestDialog( Frame frame, String name ) 350 { 351 super( frame, name ); 352 int scrollBoth = TextArea.SCROLLBARS_BOTH; 353 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 354 add( "North", instructionsText ); 355 356 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 357 add("Center", messageText); 358 359 passB = new Button( "pass" ); 360 passB.setActionCommand( "pass" ); 361 passB.addActionListener( this ); 362 buttonP.add( "East", passB ); 363 364 failB = new Button( "fail" ); 365 failB.setActionCommand( "fail" ); 366 failB.addActionListener( this ); 367 buttonP.add( "West", failB ); 368 369 add( "South", buttonP ); 370 pack(); 371 372 show(); 373 }// TestDialog() 374 375 //DO NOT call this directly, go through Sysout 376 public void printInstructions( String[] instructions ) 377 { 378 //Clear out any current instructions 379 instructionsText.setText( "" ); 380 381 //Go down array of instruction strings 382 383 String printStr, remainingStr; 384 for( int i=0; i < instructions.length; i++ ) 385 { 386 //chop up each into pieces maxSringLength long 387 remainingStr = instructions[ i ]; 388 while( remainingStr.length() > 0 ) 389 { 390 //if longer than max then chop off first max chars to print 391 if( remainingStr.length() >= maxStringLength ) 392 { 393 //Try to chop on a word boundary 394 int posOfSpace = remainingStr. 395 lastIndexOf( ' ', maxStringLength - 1 ); 396 397 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 398 399 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 400 remainingStr = remainingStr.substring( posOfSpace + 1 ); 401 } 402 //else just print 403 else 404 { 405 printStr = remainingStr; 406 remainingStr = ""; 407 } 408 409 instructionsText.append( printStr + "\n" ); 410 411 }// while 412 413 }// for 414 415 }//printInstructions() 416 417 //DO NOT call this directly, go through Sysout 418 public void displayMessage( String messageIn ) 419 { 420 messageText.append( messageIn + "\n" ); 421 } 422 423 //catch presses of the passed and failed buttons. 424 //simply call the standard pass() or fail() static methods of 425 //ScaledText 426 public void actionPerformed( ActionEvent e ) 427 { 428 if( e.getActionCommand() == "pass" ) 429 { 430 ScaledText.pass(); 431 } 432 else 433 { 434 ScaledText.fail(); 435 } 436 } 437 438 }// TestDialog class 439