Listing 4
118: /**
119: * Class: Document <p>
120: *
121: * This class is the painter for the document content.<p>
122: *
123: *
124: * @author Jean-Pierre Dube <jpdube@videotron.ca>
125: * @version 1.0
126: * @since 1.0
127: * @see Printable
128: */
129: private class Document implements Printable {
130:
131:
132: /**
133: * Method: print <p>
134: *
135: * @param g a value of type Graphics
136: * @param pageFormat a value of type PageFormat
137: * @param page a value of type int
138: * @return a value of type int
139: */
140: public int print (Graphics g, PageFormat pageFormat, int page) {
141:
142:
143: //--- Create the Graphics2D object
144: Graphics2D g2d = (Graphics2D) g;
145:
146: //--- Translate the origin to 0,0 for the top left corner
147: g2d.translate (pageFormat.getImageableX (), pageFormat.getImageableY ());
148:
149: //--- Set the drawing color to black
150: g2d.setPaint (Color.black);
151:
152: //--- Draw a border around the page using a 12 point border
153: g2d.setStroke (new BasicStroke (4));
154: Rectangle2D.Double border = new Rectangle2D.Double (0,
155: 0,
156: pageFormat.getImageableWidth (),
157: pageFormat.getImageableHeight ());
158:
159: g2d.draw (border);
160:
161:
162: //--- Create a string and assign the text
163: String text = new String ();
164: text += "Manipulating raw fonts would be too complicated to render paragraphs of ";
165: text += "text. Trying to write an algorithm to fully justify text using ";
166: text += "proportional fonts is not trivial. Adding support for international ";
167: text += "characters adds to the complexity. That's why we will use the ";
168: text += "TextLayout and the LineBreakMeasurer class to ";
169: text += "render text. The TextLayout class offers a lot of ";
170: text += "functionality to render high quality text. This class is capable of ";
171: text += "rendering bidirectional text such as Japanese text where the alignment ";
172: text += "is from right to left instead of the North American style which is left ";
173: text += "to right. The TextLayout class offers some additional ";
174: text += "functionalities that we will not use in the course of this ";
175: text += "series. Features such as text input, caret positioning and hit ";
176: text += "testing will not be of much use when printing documents, but it's good ";
177: text += "to know that this functionality exists. ";
178:
179: text += "The TextLayout class will be used to layout ";
180: text += "paragraphs. The TextLayout class does not work alone. To ";
181: text += "layout text within a specified width it needs the help of the ";
182: text += "LineBreakMeasurer class. This class will wrap a string of ";
183: text += "text to fit a predefined width. Since it's a multi-lingual class, it ";
184: text += "knows exactly where to break a line of text according to the rules ";
185: text += "of the language. Then again the LineBreakMeasurer does ";
186: text += "not work alone. It needs information from the ";
187: text += "FontRenderContext class. This class' main function is to ";
188: text += "return accurate font metrics. To measure text effectively, this class ";
189: text += "needs to know the rendering hints for the targeted device and the font ";
190: text += "type being used. ";
191:
192:
193: //--- Create a point object to set the top left corner of the TextLayout object
194: Point2D.Double pen = new Point2D.Double (0.25 * POINTS_PER_INCH, 0.25 * POINTS_PER_INCH);
195:
196: //--- Set the width of the TextLayout box
197: double width = 7.5 * POINTS_PER_INCH;
198:
199:
200: //--- Create an attributed string from the text string. We are creating an
201: //--- attributed string because the LineBreakMeasurer needs an Iterator as
202: //--- parameter.
203: AttributedString paragraphText = new AttributedString (text);
204:
205: //--- Set the font for this text
206: paragraphText.addAttribute (TextAttribute.FONT, new Font ("serif", Font.PLAIN, 12));
207:
208: //--- Create a LineBreakMeasurer to wrap the text for the TextLayout object
209: //--- Note the second parameter, the FontRendereContext. I have set the second
210: //--- parameter antiAlised to true and the third parameter useFractionalMetrics
211: //--- to true to get the best possible output
212: LineBreakMeasurer lineBreaker = new LineBreakMeasurer (paragraphText.getIterator(),
213: new FontRenderContext (null, true, true));
214:
215: //--- Create the TextLayout object
216: TextLayout layout;
217:
218: //--- LineBreakMeasurer will wrap each line to correct length and
219: //--- return it as a TextLayout object
220: while ((layout = lineBreaker.nextLayout ((float) width)) != null) {
221:
222: //--- Align the Y pen to the ascend of the font, remember that
223: //--- the ascend is origin (0, 0) of a font. Refer to Figure 1
224: pen.y += layout.getAscent ();
225:
226: //--- Draw the line of text
227: layout.draw (g2d, (float) pen.x, (float) pen.y);
228:
229: //--- Move the pen to the next position adding the descent and
230: //--- the leading of the font
231: pen.y += layout.getDescent () + layout.getLeading ();
232: }
233:
234: //--- Validate the page
235: return (PAGE_EXISTS);
236: }
237: }
238:
239: } // Example4