使用Reportlab生成中文PDF文档
最近在研究如何将 reStructurctedText 转换为PDF格式, Reportlab 是其中一种方法。
Reportlab 并不是 docutils 项目推荐的最佳PDF生成方法, docutils 推荐还是走 Latex 的路径。
Reportlab 是一个轻量级的PDF生成工具,纯Python,依赖少,性能也不错,一直是我关注的一个项目。
但是Reportlab对中文支持存在一些问题。 limodou 兄 对reportlabs中文支持有所说明 。 总结一下,就是有2中支持方法:
- 使用CID标准字体
- 速度快,输出文件小(非内嵌),但是只有1种中文字体(需要到adobe上下载CID字库)
- 使用TTF字体
- 必须内嵌字体,生成速度有影响,输出文件也比较大,但是支持很多字体
使用下来发现存在问题:
- 中英文混合的时候,英文是全角宽度,需要单独为英文设置字体才行。
- 使用段落的时候,中文不能自动换行。Reportlabs愚蠢的使用空格判断换行。
具体到reStructuredText->PDF的转换上, dreamcatcher 上也 有一个实现 但是这个实现方法还不大成熟,不支持图片等很多特性,做出的PDF也不大美观。
总结下来,虽然Reportlab对中文有一定的支持,但是如果让文档轻松转换为PDF,则还很有一些工作要做。 reStructuredText->PDF,看来还是应该走LaTex之路了。
我的修改,支持中文字体和换行
## Hack for Chinese fonts ############################
import reportlab.rl_config
reportlab.rl_config.warnOnMissingFontGlyphs = 0
import reportlab.pdfbase.pdfmetrics
import reportlab.pdfbase.ttfonts
reportlab.pdfbase.pdfmetrics.registerFont(reportlab.pdfbase.ttfonts.TTFont(song, /usr/share/fonts/truetype/wqy/wqy-zenhei.ttf))
import reportlab.lib.fonts
reportlab.lib.fonts.ps2tt = lambda psfn: (song, 0, 0)
reportlab.lib.fonts.tt2ps = lambda fn,b,i: song
## for CJK Wrap
import reportlab.platypus
def wrap(self, availWidth, availHeight):
# work out widths array for breaking
self.width = availWidth
leftIndent = self.style.leftIndent
first_line_width = availWidth - (leftIndent+self.style.firstLineIndent) - self.style.rightIndent
later_widths = availWidth - leftIndent - self.style.rightIndent
try:
self.blPara = self.breakLinesCJK([first_line_width, later_widths])
except:
self.blPara = self.breakLines([first_line_width, later_widths])
self.height = len(self.blPara.lines) * self.style.leading
return (self.width, self.height)
reportlab.platypus.Paragraph.wrap = wrap
import sys
reload(sys)
sys.setdefaultencoding(utf8)
########################################################
reportlab 2.0似乎解决了上面的问题
大部分问题都解决了,见:http://www.reportlab.org/whatsnew_2_0.html