Sei sulla pagina 1di 32

Optimized Printing in Java

By
Anand John
Programmer,
Department of Computer Applications
Christ College, Rajkot

TERMINOLOGY
USED
IN
PRINTING
Definition of a page
Gutenberg invented the first printing press. At that time, he had to create a
terminology to describe the layout of a page.

Figure 1 Layout of a Landscape view

Figure 2 Layout of a Portrait view

In Figures 1 and 2, the page


is divided into several areas.
The printer margins make up
the page's periphery. They
are printer-dependent and
define the minimum area
that the printer needs to feed
the page. Printer margins are
not user-definable.

In Java, you do not need to


know these measurements;
the
API
(Application
Programming
Interface)
returns the dimensions of the
printable area. Just inside the
printer margins are the
margins that define the
contour of the page.

The left and right margins extend the length of the page minus
the top and bottom printer margins.
The gutter on the left side of the page provides an additional
margin that is used primarily for binding the pages in a book.
The printing API in java itself does not support the gutter.
The print API in java also fails to support margins.
We can design a print framework that will enable us to provide
gutter spacing.
Finally, the area in the middle of the page is called the
printable area.
At first glance, the page layout might look similar to the
BorderLayout that we are accustomed to in java.
However, in the BorderLayout, both top and bottom
components extend the width of the display area, whereas in
the physical page layout, the top and bottom margins are
contained between the left and right margins.

In Java, when working with the Graphics2D class, it is


important to understand the difference between device space
and user space.
In the device space, you work in pixels using the resolution of
the device.
A square of 100 pixels by 100 pixels drawn on a device that
has a resolution of 1,024 pixels by 768 pixels will not be the
same size as it is when rendered on a device that has a
resolution of 1,600 pixels by 1,400 pixels.
Because the second device features more pixels per inch, the
square will appear smaller.

User space, on the other hand, allows us to think in terms of


measurement units, regardless of the device's resolution.

When you create a Graphics2D object for a given device


(screen or printer), a default transform is generated to map the
user space to the device space.

In user space, the default is set to 72 coordinates per inch.


Instead of thinking in terms of pixels, you think in terms of
units. A 1-by-1-inch square is 72 units by 72 units.

A letter-size page (8.5 by 11 inches) is 612 by 792 points.


When using the print API, you must set your mind to work
with units because all the classes work in the user space.

A method and system for printing documents based on Java


commands.
A Java program receives page layout requests and converts the
requests into a rasterized image which is transferred to a
printer.
Page layout can be interactively modified. The Java printer
also monitors print requests and is configurable using a World
Wide Web interface.
The rendering process was not optimized at all. Printing a
simple page required a great deal of memory and was very
slow.

To simplify the concept, let's say that your program has a contract
with the printing subsystem to supply a given page at a given time.
The printing subsystem may request that your application render a
page more than once, or render pages out of sequence.
This model provides several advantages. First, by sending strips of
the page instead of the whole page to the printer, it allows the
application to print complex documents that would require more
printer memory than is available.
The application does not have to know how to print each strip; it only
needs to know how to render a given page. The API will take care of
the rest.
In this case, the printing subsystem might request that a page be
rendered several times depending on the number of strips required to
completely print the page.
Second, if the paper tray on a particular printer outputs the pages in
reverse order, then your application might be asked to print the
document in reverse order, so it will appear in the right order in the
output tray.

The print system in Java has two distinct models: the Printable
and the Pageable.
Though Printable can print simple documents, it features
several limitations, the major one being that all pages must
share the same format.
The Pageable model, on the other hand, offers much more
flexibility. It can create multipage documents, with each page
formatted differently.

The steps required for printing with the Printable model:


1.

Create a PrinterJob object. This object controls the print process by


displaying page and print dialogs, and initiating the print action.

2.

Display the proper dialogs, either print or page dialogs.

3.

Create a class that implements the Printable interface's print()


method.

4.

Validate the page number to be rendered.

5.

Render your page using the Graphics parameter.

6.

If the page renders, return the PAGE_EXISTS value; if the page


does not render, return the NO_SUCH_PAGE value.

Interface Printable
public interface Printable
The Printable interface is implemented by the print methods of the
current page painter, which is called by the printing system to
render
a
page.
When
building
a Pageable,
pairs
of PageFormat instances and instances that implement this interface
are
used
to
describe
each
page.
The
instance
implementing Printable is called to print the page's graphics.
A Printable(..) may be set on a PrinterJob. When the client
subsequently initiates printing by calling PrinterJob.print(..)
control is handed to the printing system until all pages have been
printed.
It does this by calling Printable.print(..) until all pages in the
document have been printed. In using the Printable interface the
printing commits to image the contents of a page whenever
requested by the printing system.

You can display either the


print or the page dialog. This
enables you to create unattended
print jobs, an ability that becomes
useful when you want to set a
server to print documents.
With the print dialog box, the
user can select a printer and
modify its configuration. The user
can also set the number of copies
to print and select the page range.
Using this dialog, you transfer
control of the print job to the user.
The dialog box provides the only
place where the user can decide to
proceed with the print job or
cancel it.

if (printJob.printDialog()) {
try {
printJob.print();
}
catch (Exception
PrintException)
{ PrintException.printStackTrac
e();
}

The printDialog() method, part of the PrinterJob class, shows the


print dialog to the user. This method returns a Boolean value.
The print method returns an integer value as shown below:
public int print(Graphics g, PageFormat pf, int page_index)
throws PrinterException {
if (page_index > 0) {
return NO_SUCH_PAGE;
}
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/* Now we perform our rendering */
g.drawString("Print same like this", 400, 400);
return PAGE_EXISTS;
}

The second dialog is the page dialog.


With this dialog, the user can change
the page setup. Figure 2 illustrates an
example of a page dialog:
Using this dialog, the user can choose
all the parameters of the PageFormat
object, including the paper size, the
paper source, the orientation of the
page, and the margins.

Figure 2
PageFormat documentPageFormat = new PageFormat ();
documentPageFormat = printJob.pageDialog (documentPageFormat);
book.append (new Document (), documentPageFormat);

To render attractive text, you must first understand the structure of a font.
Characters align along a line called the baseline, which is the vertical point
of reference for positioning a font.
The ascend is the distance between the baseline and the top of the tallest
character in a string.
The space between the baseline and a string's lowest glyph is the descend.
The leading represents the vertical distance between two characters, and the
font height is the ascend plus the leading plus the descend. Finally, we call a
string's length the advance.
All of these parameters are font dependent, meaning that text rendered
using an Arial font will not occupy the same physical space as the same text
rendered using a Lucida font.

Two styles of fonts are available:


Serif fonts feature short lines stemming from and at an angle to the upper
and lower ends of a letter. Times New Roman is an example of a serif font.
Sans serif fonts do not have any decorative elements. The Arial font is a
sans serif font.

Java offers eight default fonts: Serif, Sans Serif, Dialog, Dialog Input,
Lucida Sans, Lucida Sans Typewriter, Lucida Bright, and Monospace.
Java uses logical font names. These names automatically map to an
operating system's fonts.
The mapping occurs in the JDK directory's jre/lib/font.properties file.
If your application needs access to more fonts, set the java.awt.fonts
parameters of the Java command as in java D java.awt.fonts=[fonts
directory] ... -- to point to a font directory of Type 1 (Postscript) fonts or
True Type fonts.
The Java Graphics API supplies many classes that alleviate the task of
manipulating fonts.
TextLayout offers a great deal of functionality in rendering high quality
text. This class can render bidirectional text such as Japanese text, where
figures align right to left instead of the North American style, which flows
left to right.

Name

Type

Font

Class

FontMetrics

This class contains information about a


font and the rendering device.
FontMetrics features many utilities, one
of which obtains a string's width. Note
that this class is abstract; to acquire an
Class (Abstract)
instance, you must call
Graphics.getFontMetrics(). Use
FontMetrics to learn a font's basic metric
information, such as its descend, ascend,
leading, or advance.

FontRenderContext Class

Description
The Font class represents an instance of a
font face. Use this class to create a new
font based on the available fonts on the
target system.

This class provides information about a


font related to the rendering device and
the rules required to render such a font.
Rules define the quality of the rendering.

Example
Font normalFont = new Font ("serif", Font.PLAIN, 12);
Font boldFont = new Font ("serif", Font.BOLD, 12);
g2.setFont (normalFont);
g2.drawString ("This is a normal font ");
g2.setFont (boldFont);
g2.drawString ("bold ");
g2.setFont (normalFont);
g2.drawString ("attribute", 72, 72);
If we had to render an entire paragraph! We can simplify this example with an
AttributedString object.
AttributedString attributedString = new AttributedString ("This is a Bold attribute");
attributedString.addAttribute (TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD,
11, 14);
g2.drawString (attributeString.getIterator (), 72, 72);
Output will be:
This is a Bold Attribute

Printing images
Printing an image is as straightforward as loading it in an Image object
and invoking the Graphics2D.drawImage() method.
The process of printing an image is divided into three easy steps.
1. Create a URL that will point to the image you want to print.
2. Load the image using a MediaTracker class. With this class, you can
load GIF, JPEG, and PNG files. If you want to load other image types,
use the Advance Imaging API.
3. Draw the image using the drawImage() method of the Graphics2D class.
drawImage() needs six parameters. The first is the Image object to print;
the second and third parameters are coordinates for the image's top left
position, and the fourth and fifth parameters specify the image's width
and height. The last parameter is for the ImageObserver. The Document
extends the Component class. All Component classes implement the
ImageObserver interface.

Purpose of the print framework

1.
2.
3.

4.
5.
6.
7.

We are now able to evaluate its strengths and weaknesses of Java Print API
and so we can build a framework on top of it.
The print framework or print model will :
Be easy to use.
Provide the high-level functionality required to efficiently render pages.
Loosely couple with the Print API. Because the framework has no direct
ties to the Java Print API, it will allow greater support for other output
formats, such as PDF or HTML.
Provide a structure that clearly defines each component involved in
creating documents (document, page, paragraph, and so on).
Use an abstract measurement system. Developers will thus be able to work
with the measurement system of their choice or even create their own.
Provide a print-preview facility. The Java Print API has no support for
previewing the output before you print.
Support a standard and portable page-setup dialog. The print framework
will provide one page-setup dialog that will be uniform across all
platforms, but its functionality varies from platform to platform.

8. Offer export features. Although the framework will support several


output formats (PDF, HTML, Postscript).
9. Offer text handling, which is of primary importance. The
framework will provide all the functionality needed to effectively
render text, including right justification, left justification, full
justification, and support for the AttributedString class.
10. Support graphics primitives such as rectangles, circles, and lines.
11. Support GIF and JPEG image types.
12. Support headers and footers. These can be set at the document or
the page level, and the first page can feature a different
header/footer.
13. Support sticky position, which easily sticks a component to a
specific location. Since all print objects are containers, the sticky
values would be applied within the boundaries of the parent object.
14. Support dimensions, with which you can set a component's width
and/or height to the parent container's width and/or height.
15. Support tables, though their implementation will be limited.

Implement the measurement system classes


Start building the framework design by implementing the measurement
classes.
The PFUnit class forms the heart of the measurement system; only the
getPoints() and setPoints() methods are left abstract.
Place your code that converts the measurement unit to points in getPoints(),
and the code that converts from points to the measurement unit, in the
setPoints() method.
All the basic math operations have been implemented in PFUnit. The math
methods support either a double value or a PFUnit class as their input.
When you pass a double value in parameters, the method assumes that the
value is in the measurement unit represented by the class.
For example, a double value passed to one of the math methods in the
PFInchUnit class is assumed to be in inches.
PFUnit provides the foundation; by extending PFUnit, you can create
custom measurement systems like PFInchUnit and PFCmUnit. In addition,
the PFPoint, PFSize, and the PFRectangle represent geometrical
coordinates.

The PFPage class


The PFPage class represents a page entity. A document is a collection of
pages; a page is a collection of print objects.
In the print framework, you must create an instance of PFPage for each
page in your document.
PFPage uses a Vector object to store print objects and supports several
methods of adding and removing print objects.
To store page parameters like margins, page size, and page orientation, use
a PFPageFormat class, which offers various functionalities.
It allows the PFPageSetupDialog to obtain and return the page parameters
in one full swoop.
If the user selects a different page format, the PFDocument print() method
can assign the new parameters using a single line of code.
All the PFPrintObject classes render themselves with a Graphics2D
object.
The getHeader()/getFooter() methods will make the final decision based
on the rule: The page header/footer is used if it is not null, else the
methods ask PFDocument for a non-null header/footer value.

PFPage class
The PFPage defines a page and acts as a container of PFPrintObject
objects.
When the print() method invokes, it renders each object in the page.
The PFPage class does not store the page parameters directly; it uses a
PFPageFormat class for storage
Use the PFPageFormat class to set and store the page format data.
PFPageFormat computes the page area origin with the
getPageAreaOrigin() method, and the page area size using the
getPageAreaSize() method.
Use getPageFormat() to obtain a java.awt.PageFormat object.
Before returning a PageFormat object, getPageFormat() must first
evaluate the page orientation and set the page's margins and size
accordingly.
FPrintObject's rendering process is a bit more complex than PFPage's,
because each object must be rendered in relation to its parent object. The
parent object can be either the PFPage object onto which the print object
was added or another PFPrintObject.

The steps for using the print framework


Create a PFDocument object
2.
Create a PFPage object and add it to the PFDocument class
3.
Create all the print objects that will appear in your page and add them to the
PFPage object
4.
Invoke the document's print() method to print it
Repeat steps 2 and 3 until all the pages in your document have been created.
1.

PFDocument document = new PFDocument ();


PFPage page = new PFPage ();
PFFrame rectangle = new PFFrame ();
document.addPage (page);
rectangle.setHeight (new PFInchUnit (5.0));
rectangle.setHorizontalSticky (PFPrintObject.STICKY_LEFT);
rectangle.setHorizontalFill (true);
rectangle.setFillColor (Color.black);
rectangle.setLineColor (Color.red);
page.add (rectangle);
document.print ();

Printing AWT/Swing components


Because visual components rely on layout managers, printing those
components can be tricky.

You can more easily position and resize an image on a canvas.


The component is asked to render itself on the double-buffer image.

And finally, the image of the component renders on the page.

Swing Component
Demonstration
Link to Printing Jar

JasperReports
Optional Libraries and Tools
There are a number of libraries that are required only if we wish to take advantage of
some of JasperReports' features. These optional libraries and their uses are listed next.
Apache ANT
JasperReports comes bundled with some custom ANT targets for previewing report
designs and for viewing reports serialized in JasperReports' native format. Although
not mandatory, it is very helpful to have ANT available to take advantage of these
custom targets.
We can use JasperReports-specific ANT targets. Therefore, ANT is required when
following the examples. ANT can be downloaded from http://ant.apache.org/ .
JDT Compiler
JDT stands for Java Development Tools. The JDT compiler is the Java compiler
included with the Eclipse IDE (Integrated Development Environment). The JDT
compiler is needed only when the JasperReports application is running under a Java
Runtime Environment (JRE), and not under a full JDK.

JDBC Driver
When using a JDBC datasource, the appropriate JDBC driver for our
specific RDBMS is needed. The following table lists popular relational
database systems and the required JAR files to be added to the
CLASSPATH (exact file names may vary depending on the version). The
names shown in the table reflect the latest stable versions at the time of
writing:
RDBMS Driver JAR Files
Firebird firebirdsql-full.jar
HSQLDBhsqldb.jar
MySQL mysql-connector-java-3.1.10-bin.jar
Oracle
classes12dms.jar
DB2 db2java.zip
PostgreSQL postgresql-8.0-312.jdbc3.jar
SQL Server mssqlserver.jar
msbase.jar
msutil.jar
Sybase
j conn3.jar

iText
iText is an open-source library for creation and manipulation of PDF files.
iText is needed only if you want to export your reports to PDF or RTF
format. Version 1.2.2 of the JasperReports project ZIP file includes iText
version 1.3.1. The file to be added to your CLASSPATH is itext-1.3.1.jar.
iText can be downloaded separately from http://www.lowagie.com/iText/.
JFreeChart
JFreeChart is an open-source library for creating professional-looking
charts including, but not limited to 2-D and 3-D pie charts, 2-D and 3-D
bar charts, and line charts. JFreeChart is needed in our CLASSPATH only
if you intend to add charts to your reports. JFreeChart version 1.0 RC1
can be found in the lib directory inside the JasperReports project ZIP file
version 1.1. The file to be added to the CLASSPATH is jfreechart-1.0.0rc1.jar.
JFreeChart
can
be
downloaded
separately
from
http://www.jfree.org/jfreechart/.

Thank you

Potrebbero piacerti anche