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