iText PDF 系列文章之一: continued, page 2

--------------------------------------------------------------------------------------

原著:Bruno Lowagie  翻译:吴晓明 kfc@seu.edu.cn 东南大学

--------------------------------------------------------------------------------------

PDF 页面的内部元素

在上述将  PDF 写入 System.out 的事例中,你可以看到 PDF 许多特定的语法格式,例如 objendobj,  /Type  和  /Font 等等。你不会找到 'Hello World' 这个段落在哪里,但是如果你了解了 PDF 语法的话,就能从 PDF 的内容中追踪到下一个对象。'页面字典( page dictionary)' 对象被压缩了。如果我们解压缩,那么它就几乎类似于下面的内容:

2 0 obj <</Length 55>>stream

q

BT

36 788 Td

/F1 12 Tf

(Hello World)Tj

ET

Q

endstream

endobj

你所看到的就是 PDF 的操作符和操作数。每一对 q 和 Q 之间的所有内容定义了图形(Graphics)的状态,在 BT 和 ET 之间的代码定义了文本(Text) 的状态。至于 Td , 表示移动到页面的某一个坐标。Tf 表示选择一种字体(/F1) 和字号(12)。Tj 在当前位置写入字符串 'Hello World' 。

直接内容(Direct Content)

使用高层对象很容易,如果你一再要求这样的的话可能就显得太容易了。 如果你想要将文本和图形放在某个绝对位置,或者要罄尽 PDF 语法的功能,你可以使用'直接内容(direct content)' 功能。下面的代码与上面的 Hello World 事例的输出相同,但是没有在第四步使用 paragraph 对象,而是使用了生成 PDF 语法的方法。我在 iText 每一行代码的注释部分加入了相应的操作符(以及可能的操作数): 

Document document = new Document();
try {
PdfWriter writer =
PdfWriter.getInstance(document,
new FileOutputStream("HelloWorld2.pdf"));
document.open();
PdfContentByte cb = writer.getDirectContent();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.saveState(); // q
cb.beginText(); // BT
cb.moveText(36, 788); // 36 788 Td
cb.setFontAndSize(bf, 12); // /F1 12 Tf
cb.showText("Hello World"); // (Hello World)Tj
cb.endText(); // ET
cb.restoreState(); // Q
} catch (Exception e) {
System.err.println(e.getMessage());
}
document.close();

java.awt.Graphics2D

PDF 参考文献超过了1200页,并且 PDF 语法的学习也是永无止境的。然而,如果你熟悉 java.awt.Graphics2D ,你就是幸运儿了。下面我们再一次将生成 PDF 过程的第四步替换一下,同时来看看第三种生成 Hello World 的 PDF 文件的方法。

Document document = new Document();
try {
PdfWriter writer =
PdfWriter.getInstance(document,
new FileOutputStream("HelloWorld3.pdf"));
document.open();
PdfContentByte cb = writer.getDirectContent();
Graphics2D graphics2D = cb.createGraphics(
PageSize.A4.width(), PageSize.A4.height());
graphics2D.drawString("Hello World", 36, 54);
graphics2D.dispose();
} catch (Exception e) {
System.err.println(e.getMessage());
}
document.close();

发生的情况是这样的,createGraphics 方法返回了抽象类 Graphics2D 的一个特定实现。iText 的 PdfGraphics2D 对象将所有的方法从标准的 Java API 翻译成了 PdfContentByte 对象的调用。如果你拥有某个存在的 Java Swing 应用程序,并且它带有 JTable、JPane对象l……,那么你就可以很容易将 iText 作为一个 PDF 引擎集成到你的软件当中去。

其他文档格式

与其他库相比,iText 的优异之处是它的性能、灵活性以及也是非常重要的一个特点:方便性。高层对象为你提供了一个抽象层,从而让你无需知道 PDF 的任何语法。但是更显著的效果是:因为该层是抽象的,你还可以用它来生成其他格式的文档; iText 也能够生成 HTML 文档和 RTF 文档。出于调试方面的原因, HTML package 与 PDF package 的开发放在了一起。如果你生成了一个损坏的 PDF 文档,那么将很难调试。然而 HTML 却很容易理解。为了能够跟踪问题所在,下面这两行代码就可以加入到 Hello World 事例中:

HtmlWriter.getInstance(document,

new FileOutputStream("HelloWorld.html"));

你将会看到,HTML 与 PDF 文件同时创建。RTF package 由 Mark Hall 开发。将以下代码添加到 Hello World 测试一下:

RtfWriter.getInstance(document,

new FileOutputStream("HelloWorld.rtf"));

在 PDF 中生成报表

你可能从 CD 上找到这个 Hello World 事例,但是我打赌你肯定需要一些更为复杂的PDF文件。

图 3. 使用 iText 生成报表 

原文地址:http://www.pdfdev.com/page/articles_1_2/

posted on 2006-08-20 11:52  OrientalDragon  阅读(930)  评论(0)    收藏  举报