微型机与应用
MICROCOMPUTER & ITS APPLICATIONS
1999年 第18卷 第2期 Vol.18 No.2 1999



多国语言PDF软件包的设计
——Java技术在电子商务领域的应用
徐　鹏　柳　菁　王克宏　孟　杰
　　摘　要：用Java语言进行PDF软件包的设计框架及实现此软件包中的关键技术，并对此软件在电子商务领域的应用前景做了分析。
　　关键词：电子数据交换　Java语言　PDF文件　电子商务
　　20多年以来，电子数据交换EDI(Electronic Data Interchange)在工商业界应用中不断得到发展和完善，在当前电子商务中占据重要的地位。EDI旨在实现票据传送的电子化，所以有人称EDI为无纸化贸易。但EDI的意义不在于节约纸张，而在于其快速(比如从邮寄的几天变成几分钟甚至实时)、避免重复劳动(不必反复打印和录入票据)、提高效率、降低成本等方面。
　　PDF可以在EDI的无纸化贸易中充当重要的角色。利用Java语言编写出实现电子票据填写功能的Applet程序，并将此程序嵌入HTML文件中，这样用户就可以通过浏览器访问此网页并填写票据。当填写完成后，服务程序将调用由Java语言编写的PDF软件包，将用户界面中的内容直接转换成PDF格式的文件，并从服务器中将生成的PDF文件传送到客户端。由于PDF文档能够集成多媒体信息，可移植性强并非常便于阅读，因此其成为最流行的网络文档格式。目前，国际上各大企业均采用PDF格式制作文档来介绍企业及其产品，并在各自的网页上建立了与这些文档的链接，供全球的访问者下载。而利用Java语言实现PDF软件包有助于程序员在网页上直接生成PDF文件，而不必再通过专用的PDF工具来编写PDF文件了，这样就实现了1种PDF文件的实时编写和传送过程。此软件包的实现将在电子商务飞速发展的时代发挥重要的作用，且是实现EDI的核心环节。本文在分析PDF文件结构的基础上，提出用Java语言实现PDF软件包的设计框架，并展望此软件包的应用前景。
1　PDF文件的基本结构
　　PDF(Portable Document Format)，即可移植的文档格式。用户可以以一种简便、可靠的方式来浏览PDF格式的电子文档，同时这种文档格式还独立于生成它的应用软件、硬件和操作系统，因此这种文档具有可移植性。PDF文件依靠PostScript语言来描述文字和图形。为了增强浏览的交互性，PDF还定义了比PostScript程序更多的结构化格式。PDF文档还包含了很多对象，例如注解、超文本链接等等。
　　与PostScript语言类似，PDF文档是通过一系列对象序列来构造的，而构成页面内容的文本、图形和图像是使用基于PostScript语言中的一些特定操作符来描述的。1个PDF文档包含了1个或多个页面，而每一页都可以包含文档、图形和图像。
　　一个典型的PDF文件包含4个部分，分别是：文件头、文件主体、交叉引用表和文件尾，如下所示：
　　<PDF file>::=<header>
<body>
<cross-reference table>
<trailer>
　　其中PDF文件的第1行就是文件头(Header)。它表明了当前文件所使用PDF规范的版本，我们在设计PDF软件包过程中使用的是1.2版的规范，因此生成的PDF文件头部应当是“%PDF-12”。PDF文件的主体(Body)中应当包括构成文件间接对象的1个序列，这些对象代表了文档中的各个组件，例如字体、页树和图像等等，文件主体的结构如图1所示。而在交叉引用表(Cross-Reference Table)中需要给出所有当前文件使用对象的入口地址，即字节偏移量，这样系统就可以随机访问不同的对象了。文件尾(Trailer)中包含了交叉引用表的起始地址和其中的对象总数、文档中Catalog(目录)对象的对象号等信息，这样一个读取PDF文件的应用程序就可以通过PDF文件的文件尾来快速地找到当前文件的交叉引用表和特定对象了。

图1  PDF文件主体的结构
2　用Java实现PDF软件包的设计框架
　　由于PDF文件中通过特定的标识符和语法来描述不同的对象，并通过诸多对象来组成文件，而对象之间又存在调用关系，因此对于一般用户来说掌握PDF语法比较困难，同时编写各个对象也是非常烦琐的事情。因此，我们利用Java语言的面向对象特性和向量、图像处理、压缩处理等功能，实现了PDF软件包。这样，程序员只需要调用PDF软件包中的类和方法，就可以直接生成PDF对象并完成相应的属性设置，同时系统还可以自动将所生成的对象按照用户指定的设置组合成1个PDF文件。
　　下面，具体阐述在PDF软件包中实现的几种主要功能。
2.1　具有多种字体的文字处理
　　首先，需要解决的一个重要的问题就是如何来处理文字。文字是PDF文件中最主要的内容。PDF规范要求在文件中不但要说明文字的内容，还要描述出文字的字体信息。我们在PDF软件包中生成了1个Text类，主要用于处理有关文字及其字体方面的内容。通过调用其中的setText(String text)、setXY(int x,int y)、setColor(Color color)和setRendering(intmode)等方法可以直接设置文字的内容、坐标、颜色以及显示模式。在PDF语法中并没有提供用于为文字添加下划线和边框的标识符，而我们在这个软件包中提供了相应的方法setUnderLine()和setcirRectangle()，通过绘制直线的方式来形成下划线和边框。在方法的实现过程中，利用了Java语言的多态特性，系统将根据用户调用这些方法时使用参数的不同，来决定所进行的操作(包括设置下划线或边框的颜色、坐标、长度或者使系统根据当前文字的宽度对相应参数进行自动设置)。
　　文字处理的难点在字体的实现上。根据PDF规范规定，读取PDF文件的应用软件(例如Acrobat Reader)只能是14种Typel类型的基本英文字体，而如果要在PDF文件中使用其他字体，则用户必须通过使用字体描述符对象来对当前字体下每个字符的宽度矩阵进行描述并定义字符代码与Unicode编码的映射关系，系统将根据这些数据来勾画出具体字符的形状。然而普通的用户并不需要了解这些内容。因此，我们在PDF软件包中生成了Fonts类，用户只需要调用方法Text.setfont(String fontname)，其中作为参数的fontname可以取值为14种基本的英文字体的名称，也可以取值为5种日文字体和4种中文字体的名称(日文字体包括gothic、ms mintyo等，中文字体包括黑体、宋体、楷体和仿宋等)，同时还可以将Font.ITALIC和Font.BOLD作为方法的参数使用，来设置黑体和斜体字。如果用户使用的是非基本字体，那么PDF软件包将根据参数fontname的取值来构造FontDescriptor和DescendantFonts对象，并调用其中的方法来自动构造新字体的矩阵关系。同时，我们还在PDF软件包中代表PDF文件主体的Body类和代表每个页面的Page类中运用了Java语言独创的Vector(向量)类型的变量font，并将其属性设置为public。Java语言独创的类Vector实现了动态可扩充数组，在使用时类似普通数组，它不但能够将普通类型的变量作为元素进行存储，而且可以将1个对象作为元素，因此利用Vector变量存储当前PDF文件和当前页面中存在的字体对象，这样当每次调用方法setfont()设置字体时，程序首先在Body和Page中的font变量中查找，如果在font中存在相同字体名称的对象，表明这种字体在当前的文件中已经被使用过，这样可以直接获得已经生成的字体对象和字体编号“Fn”(其中n为可变整数，随着当前PDF文件中字体种类的增加，n随之增大)；如果在font中没有找到具有相同名称的对象，则表明此字体在当前的文档中还没有被使用过，这样程序就会构造1个新的Fonts对象，并完成字体属性的设置。
2.2　图形功能的实现
　　在PDF软件包中增加图形功能相对比较容易。我们构造了1个类Line，程序员通过调用此类中的各个方法可以实现在PDF文件中添加直线(包括带箭头的直线和虚线)、矩形、圆形和Bezier曲线(见图2)的功能。由于PDF规范中并没有提供为绘制圆形专用的标识符，但是它提供了对Bezier曲线的支持，因此根据图形学的原理，利用多条Bezier曲线组合成为1个圆形，而这个组合过程对于用户来说却是透明的，用户只需要调用Line类中的方法drawCircle(int x0,int y0,int radius)即可绘制出1个圆形(参数为圆心坐标和半径大小)。


图2　Bezier曲线
　　实现图形的目的主要是为了勾画出特定的线条，同时由于PDF规范中没有提供针对表格功能的操作符，因此需要通过直线的组合来形成表格。
2.3　图像功能的实现
　　为了使PDF文件的内容更加充实，同时也为了避免用户在阅读文件时感到枯燥，必须要在PDF文件中增添一些相应的图像。这里通过Images类以及其中的方法来提供给用户在PDF文件中添加图像的功能。用户只需构造1个Images对象，并将所选择图像的相应存储路径及其名称作为参数传递给构造方法，系统就可以直接利用Java类库中的java.io和java.awt.image包获取图像文件的内容。对于GIF或JPEG格式的图像文件来说，每个象素点都由RGB三元色组成，每种元色又是由2位16进制数表示的，而PDF文件中的图像需要将象素点三元色的取值转换成由1、2、4或8位二进制数表示。因此程序还实现了根据用户设置的参数将每个象素点的颜色转换成不同位数二进制数的功能。
2.4　数据压缩处理方法的实现
　　在网络传输过程中，文件大小直接影响到传输的速度。为了使生成的PDF文件在容纳所有必需信息的同时，能尽量缩小文件占用空间，PDF文件支持对数据进行压缩处理。
　　在PDF软件包中，实现了Encoding类，它是一个基础类，用来对PDF的数据进行编码和压缩。目前Encoding类中实现了3种压缩方法：LZW、Flate和Run Length(行程)。这些压缩方法都可以对图像(二进制数据)和文本(ASCII数据)进行压缩，它们在各种信号处理中都是很常用的，但由于它们在PDF中的应用有其一定的特殊性，还要对其进行适合PDF的具体处理。在Java中，java.util.zip包提供了专门对Flate方法进行处理的Deflater类，所以Encoding类利用Deflater类来完成最底层的压缩算法。而其它几种压缩方法则由Encoding类来亲自完成。另外，Encoding类还实现了2种将二进制数据转换成ASCII码数据的编码方法：ASCII85和ASCIIHex。由于1个字节可表示8位二进制数据，而只能表示7位ASCII码数据，所以使用这2种编码方法会增大数据量，但是由于ASCII是移植性最好的形式，PDF手册建议最终PDF文件以文本文件形式表示。所以，PDF文件中可以进行压缩处理的图像内容和页面内文本、图形描述信息，通常先由Encoding类中压缩方法LZW、Flate和Run Length进行压缩，再由编码方法ASCII85和ASCIIHex转换成文本形式。
2.5　其他功能
　　除了上述主要的类和方法以外，我们还设置了Outlines和SubOutlines类。用户可以直接调用类中的方法来为每个页设置1个名字，这个名字将作为前页面在PDF规范中/Outlines属性的取值来对待。当生成1个PDF文件后，用户只需要用鼠标点击在Acrobat Reader窗口左部显示的Outline图标，即可以直接跳转到相应的页面上，实现了浏览过程的交互性。在将所有页面的/Outlines属性写入PDF文件的过程中，使用了递归调用的方法，从根页树到子页树逐层设置对象号和具体属性的调用关系。
　　利用Java语言面向对象的特性，将数据封装起来，使开发人员可以把设计的主要注意力集中到对对象和方法的调用上。所有有关PDF文件内部对象构造和文件组织的技术细节对于此软件包的使用者来说都是透明的。这样，用户在不必了解PDF程序设计语法的基础上就可以直接编写出PDF文件了。
3　应用前景
　　PDF是一种实用的电子出版文件。各种不同的企业可以根据自己的需要，设计特定的Java Applet用户接口和服务器程序。客户端程序由用户使用appletviewer、HotJava、IE4.0或Netscape 4.04等浏览器运行。用户可以通过访问这个主页来填写特定的定单。服务程序根据用户设置的字体名称(宋体、楷体等)、风格(斜体、黑体等)、大小以及颜色，考虑页面大小的限制，以最好的效果显示文字，并从数据库中获取记录，生成相应的PDF文件。客户最终利用辅助应用程序Acrobat Reader观看服务器端生成的PDF结果文件。服务器端程序由管理员使用JDK运行，监听客户端请求，根据用户提供的数据要求，通过调用PDF软件包，把数据格式转换成PDF文件格式。同时由于此软件包支持英文、中文和日文字体，因此全球使用不同语言的用户都可以利用它来直接生成电子票据。Java语言和PDF文件都具有可移植性，两者的结合可以说是相得益影。
　　EDI正迅速应用于WWW，使得众多的中小企业可以利用EDI从事商务活动，这必将促进商业界和工业界的发展。通过开发新一代的标准，EDI的应用将扩大到服务性行业。总之，电子商务是未来信息商业社会运作的核心，电子商业的平台是Internet，工具就是Java。 
作者单位：清华大学计算机系(100084)
参考文献
1　Bienz T,Cohn R,Meehan J R.Portable Document Format Reference Manual Version 1.2.Adobe Systems Incorporated,1996
2　Gosling J.Java Programming Guide.JavaSoft Corp.,Sun Microsystems,1996
3　　Bienz T,Cohn R,Meehan J R.CID-Keyed Font Technology Overview,Technical Note #5092.Adobe Systems Incorporated,1994
4　Bienz T,Cohn R.Font Naming Issues,Technical Note #5088.Adobe Systems Incorporated,1993
5　王克宏.Java语言编程技术.北京：清华大学出版社，1997
6　吴乐南.数据压缩的原理与应用.北京：电子工业出版社，1996
(收稿日期：1998-08-28)
