JavaWorldPrintExample4.java Source code

Java tutorial

Introduction

Here is the source code for JavaWorldPrintExample4.java

Source

/**
 * Class: Example4
 * <p>
 * 
 * Example of using the TextLayout class to format a text paragraph.
 * <p>
 * 
 * @author Jean-Pierre Dube <jpdube@videotron.ca>
 * @version 1.0
 * @since 1.0
 */

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterJob;
import java.text.AttributedString;

public class JavaWorldPrintExample4 {
    public static void main(String[] args) {

        JavaWorldPrintExample4 example = new JavaWorldPrintExample4();
        System.exit(0);
    }

    //--- Private instances declarations
    private final static int POINTS_PER_INCH = 72;

    /**
     * Constructor: Example4
     * <p>
     *  
     */
    public JavaWorldPrintExample4() {

        //--- Create a new PrinterJob object
        PrinterJob printJob = PrinterJob.getPrinterJob();

        //--- Create a new book to add pages to
        Book book = new Book();

        //--- Add the cover page using the default page format for this print
        // job
        book.append(new IntroPage(), printJob.defaultPage());

        //--- Add the document page using a landscape page format
        PageFormat documentPageFormat = new PageFormat();
        documentPageFormat.setOrientation(PageFormat.LANDSCAPE);
        book.append(new Document(), documentPageFormat);

        //--- Tell the printJob to use the book as the pageable object
        printJob.setPageable(book);

        //--- Show the print dialog box. If the user click the
        //--- print button we then proceed to print else we cancel
        //--- the process.
        if (printJob.printDialog()) {
            try {
                printJob.print();
            } catch (Exception PrintException) {
                PrintException.printStackTrace();
            }
        }
    }

    /**
     * Class: IntroPage
     * <p>
     * 
     * This class defines the painter for the cover page by implementing the
     * Printable interface.
     * <p>
     * 
     * @author Jean-Pierre Dube <jpdube@videotron.ca>
     * @version 1.0
     * @since 1.0
     * @see Printable
     */
    private class IntroPage implements Printable {

        /**
         * Method: print
         * <p>
         * 
         * @param g
         *            a value of type Graphics
         * @param pageFormat
         *            a value of type PageFormat
         * @param page
         *            a value of type int
         * @return a value of type int
         */
        public int print(Graphics g, PageFormat pageFormat, int page) {

            //--- Create the Graphics2D object
            Graphics2D g2d = (Graphics2D) g;

            //--- Translate the origin to 0,0 for the top left corner
            g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

            //--- Set the default drawing color to black
            g2d.setPaint(Color.black);

            //--- Draw a border arround the page
            Rectangle2D.Double border = new Rectangle2D.Double(0, 0, pageFormat.getImageableWidth(),
                    pageFormat.getImageableHeight());
            g2d.draw(border);

            //--- Print the title
            String titleText = "Printing in Java Part 2, Example 4";
            Font titleFont = new Font("helvetica", Font.BOLD, 18);
            g2d.setFont(titleFont);

            //--- Compute the horizontal center of the page
            FontMetrics fontMetrics = g2d.getFontMetrics();
            double titleX = (pageFormat.getImageableWidth() / 2) - (fontMetrics.stringWidth(titleText) / 2);
            double titleY = 3 * POINTS_PER_INCH;
            g2d.drawString(titleText, (int) titleX, (int) titleY);

            return (PAGE_EXISTS);
        }
    }

    /**
     * Class: Document
     * <p>
     * 
     * This class is the painter for the document content.
     * <p>
     * 
     * 
     * @author Jean-Pierre Dube <jpdube@videotron.ca>
     * @version 1.0
     * @since 1.0
     * @see Printable
     */
    private class Document implements Printable {

        /**
         * Method: print
         * <p>
         * 
         * @param g
         *            a value of type Graphics
         * @param pageFormat
         *            a value of type PageFormat
         * @param page
         *            a value of type int
         * @return a value of type int
         */
        public int print(Graphics g, PageFormat pageFormat, int page) {

            //--- Create the Graphics2D object
            Graphics2D g2d = (Graphics2D) g;

            //--- Translate the origin to 0,0 for the top left corner
            g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

            //--- Set the drawing color to black
            g2d.setPaint(Color.black);

            //--- Draw a border arround the page using a 12 point border
            g2d.setStroke(new BasicStroke(4));
            Rectangle2D.Double border = new Rectangle2D.Double(0, 0, pageFormat.getImageableWidth(),
                    pageFormat.getImageableHeight());

            g2d.draw(border);

            //--- Create a string and assign the text
            String text = new String();
            text += "Manipulating raw fonts would be too complicated to render paragraphs of ";
            text += "text. Trying to write an algorithm to fully justify text using ";
            text += "proportional fonts is not trivial. Adding support for international ";
            text += "characters adds to the complexity. That's why we will use the ";
            text += "<code>TextLayout</code> and the <code>LineBreakMeasurer<code> class to ";
            text += "render text. The <code>TextLayout<code> class offers a lot of ";
            text += "functionality to render high quality text. This class is capable of ";
            text += "rendering bidirectional text such as Japanese text where the alignment ";
            text += "is from right to left instead of the North American style which is left ";
            text += "to right. The <code>TextLayout<code> class offers some additional ";
            text += "functionalities that we will not use in the course of this ";
            text += "series. Features such as text input, caret positionning and hit ";
            text += "testing will not be of much use when printing documents, but it's good ";
            text += "to know that this functionality exists. ";

            text += "The <code>TextLayout</code> class will be used to layout ";
            text += "paragraphs. The <code>TextLayout</code> class does not work alone. To ";
            text += "layout text within a specified width it needs the help of the ";
            text += "<code>LineBreakMeasurer</code> class. This class will wrap a string of ";
            text += "text to fit a predefined width. Since it's a multi-lingual class, it ";
            text += "knows exactly where to break a line of text according to the rules ";
            text += "of the language.  Then again the <code>LineBreakMeasurer</code> does ";
            text += "not work alone. It needs information from the ";
            text += "<code>FontRenderContext</code> class. This class' main function is to ";
            text += "return accurate font metrics. To measure text effectively, this class ";
            text += "needs to know the rendering hints for the targeted device and the font ";
            text += "type being used. ";

            //--- Create a point object to set the top left corner of the
            // TextLayout object
            Point2D.Double pen = new Point2D.Double(0.25 * POINTS_PER_INCH, 0.25 * POINTS_PER_INCH);

            //--- Set the width of the TextLayout box
            double width = 7.5 * POINTS_PER_INCH;

            //--- Create an attributed string from the text string. We are
            // creating an
            //--- attributed string because the LineBreakMeasurer needs an
            // Iterator as
            //--- parameter.
            AttributedString paragraphText = new AttributedString(text);

            //--- Set the font for this text
            paragraphText.addAttribute(TextAttribute.FONT, new Font("serif", Font.PLAIN, 12));

            //--- Create a LineBreakMeasurer to wrap the text for the
            // TextLayout object
            //--- Note the second parameter, the FontRendereContext. I have set
            // the second
            //--- parameter antiAlised to true and the third parameter
            // useFractionalMetrics
            //--- to true to get the best possible output
            LineBreakMeasurer lineBreaker = new LineBreakMeasurer(paragraphText.getIterator(),
                    new FontRenderContext(null, true, true));

            //--- Create the TextLayout object
            TextLayout layout;

            //--- LineBreakMeasurer will wrap each line to correct length and
            //--- return it as a TextLayout object
            while ((layout = lineBreaker.nextLayout((float) width)) != null) {

                //--- Align the Y pen to the ascend of the font, remember that
                //--- the ascend is origin (0, 0) of a font. Refer to figure 1
                pen.y += layout.getAscent();

                //--- Draw the line of text
                layout.draw(g2d, (float) pen.x, (float) pen.y);

                //--- Move the pen to the next position adding the descent and
                //--- the leading of the font
                pen.y += layout.getDescent() + layout.getLeading();
            }

            //--- Validate the page
            return (PAGE_EXISTS);
        }
    }

} // Example4