Windows環境でSphinxを使って日本語PDFを作成するメモ
参考URL
- http://sphinx-users.jp/gettingstarted/install_windows.html
- http://sphinx-users.jp/cookbook/pdf/rst2pdf.html
前提条件
easy_installで依存ライブラリもインストールされるはず。今回試したのは以下のバージョン。
- python 2.6.6
- docutils 0.7
- jinja 2.5.2
- PIL 1.1.7
- pygments 1.3.1
- reportlab 2.5
- rst2pdf 0.16
- sphinx 1.0.4
ディレクトリ構成はこんな感じ
WORK_DIR +-build ・・・ 成果物格納ディレクトリ +-fonts ・・・ フォント格納ディレクトリ +-souce ・・・ ソース格納ディレクトリ +- index.rst ・・・ ソース +- conf.py +- ja.json +- make.bat +- Makefile
日本語フォント
VLゴシックフォントとIPAフォントをダウンロードしてきて、WORK_DIR\Fontsにコピーする。C:\WINDOWS\Fontsディレクトリにインストールしてもいいが、Sphinxの設定はPythonコードなので、フォントパスを指定してあげればどこに配置しても構わないはず。
conf.py修正
参考URLのように修正すればいいが、次の2点は以下のように修正する。
- pdf_stylesheetsは、sphinxとjaのみ指定する。そうしないと余計なフォントを探しに行って、PDF作成にとても時間がかかる。
- pdf_font_pathには、先程ダウンロードしてきたフォントのコピー先を指定する。
pdf_stylesheets = ['sphinx','ja'] import os font_dir = os.path.abspath(os.path.join(os.path.split(__file__)[0], os.pardir, 'fonts')) pdf_font_path = [font_dir, 'C:\WINDOWS\Fonts'] pdf_language = "ja"
ja.json
これはほぼ参考URLのとおり。ただし、IPAフォントは*.otfではなくて*.ttfなので、そこだけ修正する。
{ "embeddedFonts" : [ [ "VL-Gothic-Regular.ttf", "VL-PGothic-Regular.ttf", "ipam.ttf", "verdanaz.ttf" ] ], "fontsAlias" : { "stdFont": "VL-PGothic-Regular", "stdBold": "VL-PGothic-Regular", "stdItalic": "VL-PGothic-Regular", "stdBoldItalic": "VL-PGothic-Regular", "stdMono": "VL-PGothic-Regular", "stdMonoBold": "VL-PGothic-Regular", "stdSanBold": "VL-PGothic-Regular", "stdSansBold": "VL-PGothic-Regular" }, "styles" : [ ["base" , { "wordWrap": "CJK", "kerning" : true }], ["literal" , { "wordWrap": "None" }] ] }
バッチファイル修正
make.batを修正して、"make pdf"でPDFを作成できるようにする。
if "%1" == "pdf" ( %SPHINXBUILD% -b pdf %ALLSPHINXOPTS% %BUILDDIR%/pdf echo. echo.Build finished. The PDF files are in %BUILDDIR%/pdf goto end )
これで一応日本語PDFが作成できるんだけども、外部リンクを貼るときターゲット定義とリンクを分割するとエラーが発生する。原因はよくわからない。
目次 詳細は `Sphinx Document`_ を参照してください。 .. _Sphinx Document: http://sphinx-users.jp/doc10/index.html
Running Sphinx v1.0.4 loading translations [ja]... done loading pickled environment... done building [pdf]: targets for 1 source files that are out of date updating environment: 0 added, 0 changed, 0 removed looking for now-outdated files... none found processing pythontest... index resolving references... done writing pythontest... [ERROR] pdfbuilder.py:129 FragLine instance has no attribute 'lineBreak' FAILED build succeeded. Traceback (most recent call last): File "D:\Work\pytest\python\lib\site-packages\rst2pdf-0.16-py2.6.egg\rst2pdf\pdfbuilder.py", line 126, in write docwriter.write(doctree, destination) File "D:\Work\pytest\python\lib\site-packages\docutils-0.7-py2.6.egg\docutils\writers\__init__.py", line 76, in write self.translate() File "D:\Work\pytest\python\lib\site-packages\rst2pdf-0.16-py2.6.egg\rst2pdf\pdfbuilder.py", line 624, in translate compressed=self.compressed) File "D:\Work\pytest\python\lib\site-packages\rst2pdf-0.16-py2.6.egg\rst2pdf\createpdf.py", line 666, in createPdf pdfdoc.multiBuild(elements) File "D:\Work\pytest\python\lib\site-packages\reportlab-2.5-py2.6-win32.egg\reportlab\platypus\doctemplate.py", line 960, in multiBuild self.build(tempStory, **buildKwds) File "D:\Work\pytest\python\lib\site-packages\reportlab-2.5-py2.6-win32.egg\reportlab\platypus\doctemplate.py", line 880, in build self.handle_flowable(flowables) File "D:\Work\pytest\python\lib\site-packages\rst2pdf-0.16-py2.6.egg\rst2pdf\createpdf.py", line 774, in handle_flowable if frame.add(f, canv, trySplit=self.allowSplitting): File "D:\Work\pytest\python\lib\site-packages\rst2pdf-0.16-py2.6.egg\rst2pdf\flowables.py", line 555, in add return Frame.add(self, flowable, canv, trySplit) File "D:\Work\pytest\python\lib\site-packages\reportlab-2.5-py2.6-win32.egg\reportlab\platypus\frames.py", line 174, in _add flowable.drawOn(canv, self._x + self._leftExtraIndent, y, _sW=aW-w) File "D:\Work\pytest\python\lib\site-packages\reportlab-2.5-py2.6-win32.egg\reportlab\platypus\flowables.py", line 108, in drawOn self._drawOn(canvas) File "D:\Work\pytest\python\lib\site-packages\reportlab-2.5-py2.6-win32.egg\reportlab\platypus\flowables.py", line 89, in _drawOn self.draw()#this is the bit you overload File "D:\Work\pytest\python\lib\site-packages\reportlab-2.5-py2.6-win32.egg\reportlab\platypus\paragraph.py", line 992, in draw self.drawPara(self.debug) File "D:\Work\pytest\python\lib\site-packages\reportlab-2.5-py2.6-win32.egg\reportlab\platypus\paragraph.py", line 1458, in drawPara dpl( tx, offset, lines[0], noJustifyLast and nLines==1) File "D:\Work\pytest\python\lib\site-packages\reportlab-2.5-py2.6-win32.egg\reportlab\platypus\paragraph.py", line 335, in _justifyDrawParaLineX simple = last or abs(extraSpace)<=1e-8 or line.lineBreak AttributeError: FragLine instance has no attribute 'lineBreak' Build finished. The PDF files are in build/pdf
追記
reportlab.platypus.paragraphモジュールの335行目が原因なので、lineBreak属性がなくても例外が発生しないように無理やり修正したらなんとかPDFが作成できた。ただし、コードブロックの日本語が文字化けする・・・
def _justifyDrawParaLineX( tx, offset, line, last=0): setXPos(tx,offset) extraSpace = line.extraSpace #simple = last or abs(extraSpace)<=1e-8 or line.lineBreak simple = last or abs(extraSpace)<=1e-8 or getattr(line, 'lineBreak', False) if not simple: nSpaces = line.wordCount+sum([_nbspCount(w.text) for w in line.words if not hasattr(w,'cbDefn')])-1 simple = not nSpaces if not simple: tx.setWordSpace(extraSpace / float(nSpaces)) _putFragLine(offset, tx, line) tx.setWordSpace(0) else: _putFragLine(offset, tx, line) #no space modification setXPos(tx,-offset)