PDFlib使用(一)

【注】PDF标准大致上有近千页,因而采用程序生成pdf并不是件容易的事情,好在有现成的第三方库可以使用,大大简化了生成pdf的过程。本文使用的是PDFlib ver10+版,采用c++接口,本文涉及PDFlib的一些使用基础,并重点说明了table制作的要点。

一. 简介

PDFlib 是一个用于生成和操作PDF文档的开发库,提供了C/C++、Java、Python等语言绑定,支持文本、矢量图形、图像、多媒体元素(如视频/音频)的嵌入,‌PDI功能支持导入现有PDF页面并保留交互元素(如注释、表单字段),适用于文档合并、页眉/页脚添加等场景,PDF符合ISO标准(如PDF/A、PDF/X、PDF/UA),确保跨平台输出一致性。

二.一些基础

1.选项设置的格式

PDFlib中,全局的配置项,文本的输出样式等都是通过一个称之为”optlist”的文本字符串来表达。optlist中,可以包含多个设置项,各设置项用空格分割,如下所示:

设置名称1=内容1 设置名称2=内容2

上面的“内容“中,可以是布尔值(true/false),数值或字符串(不加引号),如果其中包含空格,逗号等字符,可用{}将其“包裹”起来,标识其为一项内容,同样,如果这个设置中本身可以包含多项内容,也用{}将它们“包裹“起来,看起来如下所示:

设置称名={项1 项2},}或  设置称名={{项1} {项2} }

视具体设置,上面的“项”可以是一个子设置。

2.全局设置

要使PDFlib能正常工作,首先要配置一些全局的设置,其中最主要“searchpath“,例如字体的文件,就可以放置在searchpath下,注意searchpath可以包含多个目录,一个典型的searchpath示意如下:

"searchpath={C:\\Windows\Fonts XXX\\bind\\data}"   \\XXX为PDFlib的安装目录

另一个全局设置是errorpolicy,一般设置为return,即

“errorpolicy=return”

return的意义是PDFlib的api发生错误时,返回一个错误值,与“抛出exception”相对应。

3.错误信息

PDFlib的api发生错误时,以下两个函数可以帮助我们判断为什么会发生错误,我们在写代码时,可以作为错误信息返回。

PDF_get_errmsg( )
PDF_get_apiname( )

4.元素的创建与销毁

PDFlib中元素的生命周期,类似于Qt,父元素销毁时,会将子元素也同时销毁,因而从理论上,我们只管创建元素,而无需考虑销毁它。PDFlib手册中的建议是,尽管可以不用考虑销毁,但手工销毁,会提高运行速度,例如table真正输出后,最好调用delete_table;独立的textflow输出后(加入table的textflow会在table销毁时会被销毁),最好调用delete_texflow等。

5.使用中文字符

在pdf中显示中文,应考虑2方面的问题:PDFlib函数字符串参数的编码和中文字库的载入。

传入(或传出)PDFlib函数字符串参数的编码

PDFlib函数可以接受unicode的多种编码,通过定义宏

PDFLIB_CPP_STRING
PDFLIB_CPP_U8STRING
PDFLIB_CPP_U16STRING
PDFLIB_CPP_U32STRING

来改变PDFlib函数可接受的字符串编码方式,通常定义PDFLIB_CPP_STRING或不定义,此时,PDFlib函数的字符串参数分别是std::string,std::wstring,它们又分别对应char(utf8)或wchar(utf16等)。

传入PDFlib函数的参数的来源有多种,例如来自源文件(即字符串常量),本地文件,网络流等,这里额外说明一下字符串常量(包含中文)的表达,它与使用的IDE有关,有时在IED中看起来没有问题,但不会得到最终的结果。

在Windows系统中,代码页(CodePage)是用于标识字符集编码的数字编号,其功能是建立字符与二进制编码的映射关系‌。例如代码页1200对应UTF-16 LE(Little Endian)编码,这是Windows内部处理Unicode文本的默认方式,代码页65001对应UTF-8,代码页936对应GB2312等。

这里,还要顺带说一下BOM。BOM(Byte Order Mark)是‌字节顺序标记‌,用于标识文本文件的编码格式(如UTF-8、UTF-16)和字节序(大端/小端)。它通常出现在文件开头,是一个文件“额外”的部分。Visual Studio可以识别BOM(即不会将它视为文件的内容),但其他编译器未必,因而如果想要跨平台,为减少麻烦,最好不要采用带BOM标示的文件。

此时,在VS中,问题就来了:如果没有BOM标记,VS会不能正确识别源文件的编码而采用默认的编码方式,而如果该文件是utf8,那么就会出错。

因而在windwos平台,如果源文件中包含中文,那么有两种方式:

  • 采用代码页936(GB2312),编译选项无需做任何修改
  • 采用代码页65001(TF-8,带BOM),编译选项无需做任何修改
  • 采用代码页65001(TF-8,无BOM),在项目的C/C++命令行下添加/utf-8

最后一种方式是针对全项目文件的,如果是跨平台应用,虽然麻烦一些,却是应该采用的方式,即所有源文件都采用无BOM utf-8编码。

源字符集取得后,就可以采用对应版本的PDFlib函数,当然,也可以进行转换,例如源字符为utf-16,转换成utf-8后,传递给utf-8版本的PDFlib函数。

描述了这么多,推荐方式为:所有中文统一采用utf-8编码(包含源文件中或外部源,如果不是,在入口处就进行转换),VS添加/utf-8编译选项,采用std::string形式的PDFlib函数。

中文字符的载入

中文中最基本的字库是宋体,文件名为SimSun.ttf,需要特别注意的是,目前windows上的中文字库大多变成了.ttc格式,而PDFlib目前并不支持ttc文件格式,因而不能载入ttc格式的字库文件。关于ttf与ttc格式的区别,请参阅有关文档,网上有工具可以将ttc文件转换成ttf文件。

载入宋体字库的写法如下:

 int font = pdf->load_font("SimSun", "unicode", "");

SimSun.ttf文件必须在pdflb的搜索目录下,注意文件名大小写,返回值不为-1表示成功,之后就能用此font编号或名称SimSun来指定字体。

6.中文编码转换

使用中文时,编码的转换一般不可避免,好在这不构成什么困难。

PDFlib中提供了一个字符编码转换的函数,声明如下:

string convert_to_unicode(string inputformat, string input, string optlist)

windows的ATL提供了A2W等一系列宏,可方便完成转换。当然根据应用场景,自己也可以写一个特定的转换函数(网上有许多示例)。

7.坐标系

将各种元素添加到页面时,一般要指定其位置。虽然PDFlib可以设置自定义的坐标,但还是采用其缺省的坐标为好:坐标的原点位于页面左下角,单位是磅(1/72英寸,约0.353mm),因此A4的页面,横向(X)最大为595,纵向(Y)最大为841。

8.样式设置

文本,图片等在pdf中的呈现样式,由样式字符串确定(pdf中参数名为optlist),其设计明显受了CSS的影响,二者有一定的相似性,因而在PDFlib中,设置元素样式字符串就是设置了诸如位置,字体,大小,颜色等内容。

【注】各种设置繁杂而多样,采用字符串方式进行索引和设置,会极大简化了接口设计。

9.版本兼容性

关于旧版本被抛弃的方法以及如何在版本10中采用替代方法,get_parameter( ),get_value( ),get_pdi_value( )等,可参阅《PDFlib-9.3.1-migration-guide.pdf》(官网)。

三.生成PDF的一般流程

使用PDFlib生成一个pdf一般的流程如下:

这个流程中,复杂的部分就是在页面添加各类元素以及设置它们显示的样式,依应用场景,分页判断有时需要自己完成。

图中标示了“页范围”和“文档范围”,范围的开始一般用begin_XXX()标识,范围的结束一般用end_XXX()标识,pdf函数有其应用范围,例如setfont,要在begin_page_ext()与end_page_ext()之间使用,而load_font可以在文档范围内使用。PDFlib中还有其他“范围”,例如path范围,template范围等。

制作PDF,如同在一张张指定大小的画布上绘制各类元素,元素在画布中的位置和大小(一般称为box,即在box中渲染元素),以及在状况下换新“画布”,都需要指定。PDFlib中提供了各种方法,用于判断元素被渲染后的各种信息,可以帮助解决元素排版和换页问题。

四.多行文本输出

多行文本的输出显然比单行文本复杂得多,因而PDFlib中,它们采用了两组不同的函数。涉及多行文本的函数有:

函数

意义

add_textflow( )/ create_textflow( )

创建

fit_textflow( )

放置

info_textflow( )

获取信息

delete_textflow( )

删除

大部分页面元素的函数都采用类似的设计与命名风格,在使用时应注意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值