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