Sphinx reStructuredText中文PDF输出解决方案之rst2pdf

以前尝试用rst2pdf将Sphinx reStructuredText文档输出为PDF时总是报错,即便是用不含中文的文档也没成功过。rst2pdf其实是个不太完美的作品,其作者甚至说过他一度想要放弃这个项目了(见这里)。前几天偶然看到rst2pdf更新到0.91版本,据说是解决了Sphinx整合问题,我赶紧试了一下,于是便有了本文(基于Windows XP平台)。

截至本文发布时,如果你直接使用setuptool的命令esay_install rst2pdf来安装rst2pdf,那么你本地取到的版本依然是0.16。所以,若要使用最新的0.91版本,需要稍微改一下这个命令:easy_install “rst2pdf==0.91″。

接下来,按照rst2pdf用户手册的说明,在Sphinx的配置文件confy.py中添加了扩展名rst2pdf.pdfbuilder,并在该文件底部添加一系列代码(Options for PDF output)用于定制PDF输出的行为方式。

# — Options for PDF output ————————————————–
# Grouping the document tree into PDF files. List of tuples
# (source start file, target name, title, author, options).
#
# If there is more than one author, separate them with \\.
# For example: r’Guido van Rossum\\Fred L. Drake, Jr., editor’
#
# The options element is a dictionary that lets you override
# this config per-document.
# For example,
# (‘index’, u’MyProject’, u’My Project’, u’Author Name’,
#  dict(pdf_compressed = True))
# would mean that specific document would be compressed
# regardless of the global pdf_compressed setting.

pdf_documents = [
(‘index’, u’MyProject’, u’My Project’, u’Author Name’),
]
# A comma-separated list of custom stylesheets. Example:
pdf_stylesheets = [‘sphinx’,’kerning’,’a4′]

# A list of folders to search for stylesheets. Example:
pdf_style_path = [‘.’, ‘_styles’]

# Create a compressed PDF
# Use True/False or 1/0
# Example: compressed=True
#pdf_compressed = False

# A colon-separated list of folders to search for fonts. Example:
# pdf_font_path = [‘/usr/share/fonts’, ‘/usr/share/texmf-dist/fonts/’]

# Language to be used for hyphenation support
#pdf_language = “en_US”

# Mode for literal blocks wider than the frame. Can be# overflow, shrink or truncate
#pdf_fit_mode = “shrink”

# Section level that forces a break page.
# For example: 1 means top-level sections start in a new page
# 0 means disabled
#pdf_break_level = 0

# When a section starts in a new page, force it to be ‘even’, ‘odd’,
# or just use ‘any’
#pdf_breakside = ‘any’

# Insert footnotes where they are defined instead of
# at the end.
#pdf_inline_footnotes = True

# verbosity level. 0 1 or 2
#pdf_verbosity = 0

# If false, no index is generated.
#pdf_use_index = True

# If false, no modindex is generated.
#pdf_use_modindex = True

# If false, no coverpage is generated.
#pdf_use_coverpage = True

# Name of the cover page template to use
#pdf_cover_template = ‘sphinxcover.tmpl’

# Documents to append as an appendix to all manuals.
#pdf_appendices = []

# Enable experimental feature to split table cells. Use it
# if you get “DelayedTable too big” errors
#pdf_splittables = False

# Set the default DPI for images
#pdf_default_dpi = 72

# Enable rst2pdf extension modules (default is only vectorpdf)
# you need vectorpdf if you want to use sphinx’s graphviz support
#pdf_extensions = [‘vectorpdf’]

# Page template name for “regular” pages
#pdf_page_template = ‘cutePage’

# Show Table Of Contents at the beginning?
#pdf_use_toc = True

# How many levels deep should the table of contents be?
Sphinxpdf_toc_depth = 9999

# Add section number to section references
pdf_use_numbered_links = False

# Background images fitting mode
pdf_fit_background_mode = ‘scale’

在Windows环境下,还要把以下代码添加到make.bat文件中:

if “%1” == “pdf” (
%SPHINXBUILD% -b pdf %ALLSPHINXOPTS% %BUILDDIR%/pdf
echo.
echo.Build finished. The PDF files are in %BUILDDIR%/pdf
goto end
)

完成以上步骤后,无需做其他改动,即可将Sphinx默认项目的源文件index.rst转换成PDF格式,命令为make pdf。不过你会发现,即便能够生成PDF文档,命令行窗口依然会出现很多报错提示,主要意思是说找不到某些字体,但rst2pdf自动用一些默认字体将其替换掉了。

问题来了,当你的rst源文档中包含了中文时,执行完make pdf命令后,所有的中文字符都没法显示。这是因为,rst2pdf默认使用的字体不适用于中文。那解决问题的思路就出来了,换字体呗。根据rst2pdf的用户手册说明,可以使用自定义的style样式表来指定字体,并将这些字体嵌入PDF文档中。Google了一下,发现一个常用的中文模板:

{
“styles”:
{
“base”:
{
“wordWrap”: “CJK”
}

},
“embeddedFonts” : [[“wqy-zenhei.ttf”,”msyhbd.ttf”,”wqy-zenhei.ttf”,”wqy-zenhei.ttf”]],

“fontsAlias” : {

“stdFont”: “wqy-zenhei”,

“stdBold”: “msyhbd”,

“stdItalic”: “wqy-zenhei”

}
}

将以上代码另存为一个名为chinese.style的文档,并放进rst2pdf安装目录下的styles文件夹中(我机器上的实际路径是C:\Python27\Lib\site-packages\rst2pdf-0.91-py2.7.egg\rst2pdf\styles)。

关于以上样式的说明:

  • embeddedFonts用于嵌入字体,经试验,必须包含至少四个值才不会报错。不过这四个字体值可以是重复的。
  • fontsAlias用来指定各类字形用什么字体。如stdFont指正文字体,stdBold指粗体,stdItalic指斜体。其他的还有stdBoldItalic粗斜体,stdMono等宽体,等等。
  • 确保所用字体已经安装在你的操作系统上,且字体必须是TTF类型的(Windows环境下限制比较多~)。
  • wordWrap用于指定换行规则,CJK就是适用于中日韩文字的规则。这是从网上的模板抄来的,但经我的测试发现,如果用CJK规则的话,中英混排的文档里面英文部分就没法正常断行,这真是个遗憾。

实际上,fontsAlias的分类很多都只对英文字体有意义,如严格来讲中文是没有所谓斜体的(不过因为Word的普及,经常看到中文被设置为斜体的情形)。如果是纯中文文档,当然随便用哪些中文字体都行,如宋体。现实中,经常会有中英文混排的情形,所以如果全用中文字体的话,英文部分就没法显示斜体等字形了。

创建完自定义样式表后,需要把它用到make pdf命令中。导入样式表的方式是,修改conf.py中的pdf_stylesheets参数(在前面自定义添加过的PDF参数中):

默认是:
pdf_stylesheets = [‘sphinx’,’kerning’,’a4′]

改为:
pdf_stylesheets = [‘chinese’,’a4′]

关于pdf_stylesheets的说明:

  • 这个参数中默认使用的某些样式包含了一些字体,而这些字体并非在所有操作系统上都找得到。’sphinx’和’kerning’都是默认提供的样式,要么不用它们,要么直接修改其包含的字体。
  • ‘a4’指设置输出的PDF为A4纸大小。
  •  默认的样式文件可以在rst2pdf的安装路径下找到。

我试验了一下,用微软雅黑Bold来显示粗体,用文泉驿正黑(wqy-zenhei)显示正文字体,效果还行,如下图所示:
本文只是一个简单的尝试,如果有兴趣深入研究的,可以参考rst2pdf手册。个人觉得rst2pdf还是有很多小问题,仍待进一步完善。不过,Sphinx作为一个轻量级的技术文档写作工具,还是值得一试的。

其他补充:

  • rst2pdf自带的配置文件似乎只是在linux系统上才有,Windows上找不到……
  • 如果不用make pdf,而是用rst2pdf自带的命令(如rst2pdf index.rst -s chinese -o output.pdf)来生成PDF,则相当于绕开了Sphinx的配置文件中所做的定义。真要这么做的话,最好是使用标准的rst语法来写文档,因为Sphinx特有的一些指令如toctree在这个情形下会报错,说明rst2pdf自带的PDF输出命令对Sphinx rst文档不是百分百支持。

本文主要参考资料:
http://d.hatena.ne.jp/tk0miya/20111208
http://code.google.com/p/rst2pdf/

Update: 本文提到的方法对最新版Sphinx/rst2pdf已失效,可参考《使用rst2pdf生成中文PDF》

“Sphinx reStructuredText中文PDF输出解决方案之rst2pdf”的一个回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注