Printing in Java, Part 5

Discover the print framework's support classes

Welcome to the fifth and final installment of "Printing in Java." In Part 1 you learned about the different models that the Java API uses to produce printed output, and Part 2 presented code examples of those models. Part 3 introduced you to the print framework. Most recently, in Part 4, you learned about the base classes that form the print framework, as I explained the PFDocument, PFPage, PFPrintObject, and all the measurement classes. In Part 5 I will focus my explanations on what I call the support classes of the print framework. I will start with the PFParagraph class.

Handling text

The PFParagraph class is essential to the print framework. It provides all the basic functions needed to render text. By using PFParagraph, you will be able to render text with the following alignments: left, right, center, and fully justified. In addition, the class enables you to set the text color and the font size. PFParagraph also supports two text input methods. You can use either the standard String class, or if you need a more elaborate way of inputting text, you can use an AttributedString.

PFParagraph also provides all the previously explained functions of the PFPrintObject. Although PFParagraph does not provide direct support for margins, you can use the implementation provided by the PFPrintObject. You will find PFParagraph's code in Listing 1.

Listing 1: PFParagraph As most of PFParagraph is pretty straightforward, I will focus only on its rendering methods. The rendering process starts in the print method located at line 179 in Listing 1. First, the method sets the text color and the text font. Then, depending on the horizontal alignment, the method calls the proper text renderer. When finished with the rendering process, the print method calls the printChilds() method to render any child object that it may contain.

There are four private methods available to render text: renderLeftJustfied(), renderRightJustified(), renderCenterJustified(), and renderFullyJustified(). The renderLeftJustified() method (line 387) uses nearly the same code as that presented in Part 2, Listing 4.

Line 325 shows how renderCenterJustified() differs from renderLeftJustified(). To calculate the object's center, divide the width of the object by two. Then divide the width of the string -- which the layout.getAdvance() method obtains -- by two. Next, subtract the object's center from the string's center to obtain the position where the string will be rendered.

The renderRightJustified() method resembles renderLeftJustified() except that you subtract the string's width from the object's width (i.e., you compute the same math without the divisions).

The renderFullyJustified() method differs from the other private rendering methods. With renderLeftJustfied(), renderRightJustified(), and renderCenterJustified(), all paragraph lines are justified, whereas in a fully justified paragraph, the last line should not be justified. Since the LineBreakMeasurer class cannot determine when it has reached the last line in a paragraph, you must implement that function yourself. Fortunately, the solution to the problem is simple: just scan and store each line in the paragraph in a Vector object (lines 423-449). Then, the method enters into a for loop to render each line stored in the previously created Vector. Use an if statement (line 459) to trap the last line and render it as left justified. At line 460, note the use of the getJustifiedLayout() method; it fully justifies a line of text, a useful feature of the TextLayout class.

To ease the layout of paragraphs on a page, I implemented the following two methods in PFParagraph: getTextHeight(), which obtains the height of a paragraph, and getNextParagraphPosition(), which obtains the next paragraph location.

Use the getNextParagraphPosition() method when you want to lay out several paragraphs one after the other, as shown in Figure 1:

Figure 1. Paragraph layout using the getNextParagraphPosition method

To achieve the result in Figure 1, I used the following code excerpt:

 1|PFParagraph paragraph = new PFParagraph ();
 2|PFParagraph paragraph1 = new PFParagraph ();
 4|page.add (paragraph);
 5|paragraph.setText (text);
 6|paragraph.setHorizontalAlignment (PFParagraph.FULL_JUSTIFIED);
 7|paragraph.setSize (new PFSize (page.getPrintableAreaSize ().getWidth (), new PFInchUnit (6)));
 9|page.add (paragraph1);
10|paragraph1.setText (text1);
11|paragraph1.setHorizontalAlignment (PFParagraph.FULL_JUSTIFIED);
12|paragraph1.setSize (new PFSize (page.getPrintableAreaSize ().getWidth (), new PFInchUnit (6)));
13|paragraph1.setPosition (paragraph.getNextParagraphPosition ());

For the sake of clarity, assume that the text was assigned to




. The trick resides at line 13, where




method calls


to obtain the next paragraph's position. Suppose you want to print a file using the framework. To do that, create a


instance for each line and use the


method to lay out each line. To know when it's time to create another page, use the


method. Let's review what you have learned so far about rendering text using the print framework. The


class enables you to render text with the following justifications: left, center, right, and full. The class will accept text as either a


or an


object. The


will also provide metrics to help you lay out text objects. Next, I will introduce the drawing primitives available in the framework.

1 2 Page 1
Page 1 of 2