iText Tutorial
|
|
iText, a Free Java-PDF library
by Bruno Lowagie
|
[Home] |
|
[TOC] |
[Next] |
[PDF] |
Part I: Simple iText
Chapter 1: Creating a document
|
Creation of a document in 5 steps: Hello World
Download the source code of the first example: Chap0101.java.
This example contains the 5 most important steps to create a PDF file using iText:
Step 1:
Creates an instance of the com.lowagie.text.Document-object:
Document document = new Document();
Step 2:
Creates a Writer that listens to this document and writes the document to the OutputStream of your choice:
PdfWriter.getInstance(document, new FileOutputStream("Chap0101.pdf"));
Step 3:
Opens the document:
document.open();
Step 4:
Adds content to the document:
document.add(new Paragraph("Hello World"));
Step 5:
Closes the document:
document.close();
Check the result here: Chap0101.pdf.
|
Examining step 1: the Document-object
The com.lowagie.text.Document-object has 3 constructors:
public Document();
public Document(Rectangle pageSize);
public Document(Rectangle pageSize,
int marginLeft,
int marginRight,
int marginTop,
int marginBottom);
The first constructor calls the second one, with
PageSize.A4 as parameter.
The second constructor calls the third one, with
36 as value for each margin.
PageSize
You could create your own Rectangle-object in a certain
color and use this as pageSize.
In example Chap0102.java, we create a long, narrow
document with a yellowish backgroundcolor:
Rectangle pageSize = new Rectangle(144, 720);
pageSize.setBackgroundColor(new java.awt.Color(0xFF, 0xFF, 0xDE));
Document document = new Document(pageSize);
This is the result: Chap0102.pdf.
Normally, you don't have to worry about creating this rectangle, since
you can use one of the statics in class
PageSize.java.
These are the pagesizes that are provided: A0-A10, LEGAL, LETTER, HALFLETTER, _11x17, LEDGER, NOTE, B0-B5, ARCH_A-ARCH_E, FLSA and FLSE.
Most these pageSizes are in PORTRAIT-format. If you want them to be in LANDSCAPE, all you have to do is rotate()
the Rectangle:
Document document = new Document(PageSize.A4.rotate());
Check out example Chap0103.java and its result.
Margins
When creating a document, you can also define left, right, upper and lower margins:
Document document = new Document(PageSize.A5, 36, 72, 108, 180);
In example Chap0104.java (and its result: Chap0104.pdf),
you will see that this document has a left margin of 0.5 inch and a right margin of 1 inch.
The upper margin is 1.5 inch, the lower 2.5 inch.
Measurements When creating a rectangle or choosing a margin, you might wonder what measurement unit
is used: centimeters, inches or pixels. In fact, the default measurement system
roughly corresponds to the various definitions of the typographic unit of
measurement known as the point. There are 72 points in 1 inch.
If you want to create a rectangle in PDF that has the size of an A4-page,
you have to calculate the number of points:
21 cm / 2.54 = 8.2677 inch
8.2677 * 72 = 595 points
29.7 cm / 2.54 = 11.6929 inch
11.6929 * 72 = 842 points
The default border of 36 points corresponds with half an inch.
|
Remark: if you change the page size, this only has effect on the next page (see page initialisations).
If you change the margins, this has an immediate effect, so be careful!
|
Examining step 2: the Writer-object
Once our document is created, we can create one or more instances of writers
that listen to this document. All writers should be derived from the abstract class
com.lowagie.text.DocWriter. For the moment there are two
possibilities: you can use com.lowagie.text.pdf.PdfWriter
to generate documents in the Portable Document Format, or you can use
com.lowagie.text.html.HtmlWriter to generate documents
in HTML. If for instance you want to generate TeX-documents as well, you could write
a package: com.lowagie.text.TeX.TeXWriter.
Remark:
I wrote the HTML classes only for testing purposes. You really shouldn't
use them in a production environment. The resulting HTML isn't very
nice and there are lots of better tools around. The iText HTML-package
can be useful for debugging reasons. HTML is a lot more straightforward
than PDF. When an error occurs while generating a PDF file, it is very hard
to find what bug caused the error. The resulting PDF-file is too damaged
to examin its contents. So while testing I always generate an HTML file
at the same time in order to retrieve the exact place where the error occurs
or the exact object that throws the exception.
There is also a package com.lowagie.text.xml
and a package com.lowagie.text.rtf,
but the XML and RTF generation functionality isn't that stable yet
(see Chapter 7 and Chapter 8).
|
The constructor of these writer-classes is made private. You can only create an
instance with the following method:
public static xxxWriter getInstance(Document document, OutputStream os) throws DocumentException
(xxx being Pdf or Html)
You can create an instance this way:
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("Chap01xx.pdf"));
but you will hardly ever need the object writer (except if you want to create Advanced PDF
or if you want to use some very specific functionalities such as ViewerPreferences or
Encryption).
So it's sufficient to just get the instance:
PdfWriter.getInstance(document, new FileOutputStream("Chap01xx.pdf"));
It's trivial that the first parameter should be the document you created in step 1.
The second parameter can be an outputStream of any kind.
Until now, we have always used a java.io.FileOutputStream to write the document to a file,
but in example Chap0105, the outputStream is a javax.servlet.ServletOutputStream.
(This is not a standalone example; you will have to test this code on a Servlet Engine).
If you use MSIE as browser, you will only see a blank page due to a bug in some specific versions of MicroSofts browser (see the
FAQ). This has been discussed over and over in the mailing list archives and even
in the newsgroup comp.text.pdf. If you want to try a more difficult example (using the workaround in the FAQ), try the
following code: Calendar.java and Month.java.
A JSP example was provided by Tal Liron: pdf.jsp.
|
Examining step 3: Meta data + opening the document
Metadata
Before you add any actual data (= content), you might want to add some metadata
about the document with one of these methods:
public boolean addTitle(String title)
public boolean addSubject(String subject)
public boolean addKeywords(String keywords)
public boolean addAuthor(String author)
public boolean addCreator(String creator)
public boolean addProducer()
public boolean addCreationDate()
public boolean addHeader(String name, String content)
You can choose your own title, subject, keywords, author and creator, but the method that
adds the producerdata should always add: iText (or a reference to iText)
and the method that adds the creation date always add the current system time
(as a matter of fact, these two methods are called automatically).
You can also add a header with a custom name, but this will have no effect on the
PdfWriter (for the moment it is only used in the HtmlWriter).
If we look at the example in step 1: Chap0101.pdf,
we see that only the producer and date are shown in the infobox. If we run
Chap0106.java, the result is a similar document:
Chap0106.pdf, but there are more items added to
the infobox:
As an additional illustration of the fact that you can send documents to any
outputstream; example 6 sends HTML to System.out.
You can see that a custom header was used to add an 'Expires' META-tag. There is 1 exception:
if you add a custom header with as name HtmlWriter.STYLESHEET,
you get a link to a stylesheet:
document.add(new Header(HtmlWriter.STYLESHEET, "my.css"));
results in:
<link rel="STYLESHEET" type="text/css" href="my.css">
Things to do BEFORE you open the document
You can only add metadata BEFORE the open-method
is invoked. This is a choice made by the developer of iText. In HTML meta-information is
put between the HEAD-tags at the beginning of the document
(the header section). Invoking the open-method causes the writer
to write this header to the OutputStream.
So there is no way to change this data once the document is 'opened'.
The PDF header doesn't contain any metadata, it looks like this:
%PDF-1.2
%рсту
The first line indicates the generated document is a file in the Portable Document Format version 1.2.
The meaning of the second line is explained in the reference manual.
Portable Document Format Reference Manual Version 1. 3 (section 2.3.2 'Portability' page 22):
A PDF file is a binary file; the entire 8-bit range of characters may be used.
Unfortunately, some agents treat files that happen to use only the printable subset
of the 7-bit ASCII code and whitespace characters as text, and take unreasonable
liberties with the contents. For example, mail-transmission systems may not
preserve certain 7-bit characters and may change line endings. This can cause
damage to PDF files.
Therefore, in situations where it is possible to label PDF files as binary, we
recommend that this be done. One method for encouraging such treatment is to
include a few binary characters (codes greater than 127) in a comment near the
beginning of the file.
|
In PDF, the metadata is kept in a PdfInfo-object,
written to the PdfWriter when the document is closed. So there is no technical reason why one
couldn't alter the library to be able to add or change the metadata at any time. It's a design choice that
was made.
Page initialisations
The open-method also triggers some initialisations
in the different writers. For instance if you want a Watermark
or a HeaderFooter-object to appear starting on the FIRST page
of the document, you have to add it BEFORE you open the document.
The same goes for setting watermark, headers, footers, pagenumbers and sizes for the rest
of the pages in the document.
When you invoke methods such as:
public boolean setPageSize(Rectangle pageSize)
public boolean add(Watermark watermark)
public void removeWatermark()
public void setHeader(HeaderFooter header)
public void resetHeader()
public void setFooter(HeaderFooter footer)
public void resetFooter()
public void resetPageCount()
public void setPageCount(int pageN)
the result of these methods will only be seen on the next new page (when the
initialisation methods of this page are called). This is illustrated in
example 7. If you want to try this example,
you will need an image file called watermark.jpg.
The result should look like Chap0107.pdf.
Viewerpreferences
For PDF files you can also set some viewer preferences with the method:
public void setViewerPreferences(int preferences)
In example 8, some
of the possibilities are demonstrated:
writerA.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft); (see Chap0108a.pdf)
writerB.setViewerPreferences(PdfWriter.HideMenubar | PdfWriter.HideToolbar); (see Chap0108b.pdf)
writerC.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft | PdfWriter.PageModeFullScreen | PdfWriter.NonFullScreenPageModeUseThumbs); (see Chap0108c.pdf)
As you can see, the preferences can be set by ORing some of these constants:
- The page layout to be used when the document is opened (choose one).
- PdfWriter.PageLayoutSinglePage - Display one page at a time.
- PdfWriter.PageLayoutOneColumn - Display the pages in one column.
- PdfWriter.PageLayoutTwoColumnLeft - Display the pages in two columns, with
oddnumbered pages on the left.
- PdfWriter.PageLayoutTwoColumnRight - Display the pages in two columns, with
oddnumbered pages on the right.
- The page mode how the document should be displayed
when opened (choose one).
- PdfWriter.PageModeUseNone - Neither document outline nor thumbnail images visible.
- PdfWriter.PageModeUseOutlines - Document outline visible.
- PdfWriter.PageModeUseThumbs - Thumbnail images visible.
- PdfWriter.PageModeFullScreen - Full-screen mode, with no menu bar, window
controls, or any other window visible.
- PdfWriter.HideToolbar - A flag specifying whether to hide the viewer application's tool
bars when the document is active.
- PdfWriter.HideMenubar - A flag specifying whether to hide the viewer application's
menu bar when the document is active.
- PdfWriter.HideWindowUI - A flag specifying whether to hide user interface elements in
the document's window (such as scroll bars and navigation controls),
leaving only the document's contents displayed.
- PdfWriter.FitWindow - A flag specifying whether to resize the document's window to
fit the size of the first displayed page.
- PdfWriter.CenterWindow - A flag specifying whether to position the document's window
in the center of the screen.
- The document's page mode, specifying how to display the
document on exiting full-screen mode. It is meaningful only
if the page mode is PageModeFullScreen (choose one).
- PdfWriter.NonFullScreenPageModeUseNone - Neither document outline nor thumbnail images
visible
- PdfWriter.NonFullScreenPageModeUseOutlines - Document outline visible
- PdfWriter.NonFullScreenPageModeUseThumbs - Thumbnail images visible
Remark: you can invoke this method only on a class of type PdfWriter.
Encryption
Another thing to do BEFORE you open the document, is to set the encryption (that is: if you want the
PDF file to be encrypted). To achieve this, you use the method:
public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions);
- The strength is one of these two constants:
- PdfWriter.STRENGTH40BITS: 40 bits
- PdfWriter.STRENGTH128BITS: 128 bits (only with Acrobat Reader 5.0 or higher)
- The userPassword and ownerPassword can be null or have zero length. In this case the ownerPassword is
replaced by a random string.
- Permissions are set by ORing some of these constants:
- PdfWriter.AllowPrinting
- PdfWriter.AllowModifyContents
- PdfWriter.AllowCopy
- PdfWriter.AllowModifyAnnotations
- PdfWriter.AllowFillIn
- PdfWriter.AllowScreenReaders
- PdfWriter.AllowAssembly
- PdfWriter.AllowDegradedPrinting
This functionality is demonstrated in example 9
and example 10.
writer.setEncryption(PdfWriter.STRENGTH40BITS, null, null, PdfWriter.AllowCopy);
Chap0109.pdf can be opened without using a password,
but the user is not allowed to Print, Modify,... the document.
writer.setEncryption(PdfWriter.STRENGTH128BITS, "userpass", "ownerpass", PdfWriter.AllowCopy | PdfWriter.AllowPrinting);
When you try to open Chap0110.pdf, you
are asked for a password (type in 'userpass'). Because the AllowPrinting-preference was added, you can
print this document without any problem.
|
Examining step 4: adding content
In the different examples explaining step 1 to 3, you have already encountered objects
such as Phrase, Paragraph,... In the next 5 chapters all these objects will be explained
more thoroughly.
It is very important to realize that not all types of objects are supported in all types
of writers. For instance: the Graphic-object isn't supported
in HTML. If you add a graphic to a Document, the listening
HtmlWriter will ignore this.
Sometimes you may want a writer to deliberately ignore actions performed on a document.
This is shown in example 11.
If we create two writers: writerA and writerB (this is an exception to what was said in
step 2):
PdfWriter writerA = PdfWriter.getInstance(document, new FileOutputStream("Chap0111a.pdf"));
PdfWriter writerB = PdfWriter.getInstance(document, new FileOutputStream("Chap0111b.pdf"));
We can create two documents that are slightly different:
writerA.pause();
document.add(new Paragraph("This paragraph will only be added to Chap0111b.pdf, not to Chap0111a.pdf"));
writerA.resume();
You can compare the results of example 11 here: Chap0111a.pdf vs.
Chap0111b.pdf.
|
Examining step 5: closing the document
Closing the document is very important, because it flushes and closes the outputstream to which
the writer is writing. The close-method is called in the finalize-method, but you shouldn't count
on that. You should always close the document yourself!
|
[Top] |
|
[TOC] |
[Next] |
[PDF] |
Page Updated: $Date: 2003/06/25 07:36:34 $
Copyright © 2000, 2001 by Bruno Lowagie
|
Adolf Baeyensstraat 121, 9040 Gent, BELGIUM,
tel +00 32 92 28 10 97 mailto:itext-questions@lists.sourceforge.net
|
|