PDF作成ツール「reportlab」で「つちよし」を出力してみた

仕事で人名漢字を使いたい!ということで
色々調査しておりました

・Mysqlで保存、取り出し
・Excel出力
・PDF出力
などなど

今回はPDF出力で調査した内容をメモっておきたいと思います

前提として、
・windows(64bit)
・python2.7
・試すのは「つちよし」吉の士が土になっているやつ
・PDF出力にはreportlab
・フォントはipa明朝(ipamjm.ttf)
です

まずは
https://pypi.python.org/pypi/reportlab
から
reportlab-3.3.0-cp27-none-win_amd64.whlを落とします

解凍して、所定の場所に格納(お使いの環境でpythonのパッケージが入っているとこ)

フォントの入手方法は割愛します

[code lang=”py”]
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont #ipaのフォント使う時に必要
from reportlab.lib.units import cm #単位

pdfFile = canvas.Canvas("任意の場所/hoge.pdf")
pdfFile.saveState()

作成者

pdfFile.setAuthor("ちろぶろ")

タイトル

pdfFile.setTitle("つちよし")

サブタイトル

pdfFile.setSubject("出力するよー!")

pdfのサイズ A4

pdfFile.setPageSize((21.0cm,29.7cm))

フォント IPA明朝

fontname = "IPAmjMincho"

フォントファイルの場所

pdfmetrics.registerFont(TTFont(fontname, ‘任意の場所/ipamjm.ttf’))

pdfFile.setFont(fontname, 30)

文字書き込み

pdfFile.drawString(5cm,25cm,"?")

pdfFile.restoreState()

PDF出力

pdfFile.save()

[/code]
以上でPDFの出力は出来ます!
さぁやってみましょー!

・・・いかがでしたでしょうか
文字化けしますよね!

これだけでは、「つちよし」が出力出来ません

「つちよし」はサロゲートペア対象文字なので
python上で扱う際には
\uD842\uDFb7
てな感じで2文字の扱いを受けます
サロゲートペアについての説明は割愛します

それをそのままPDFに書き込んでいるので
\uD842に対応する文字
\uDFB7に対応する文字
の2文字を出力してしまっています

これは困った・・・
ということで
解凍したreportlabフォルダの中の
reportlab/pdfbase/ttfonts.py
の中を少しいじります

splitStringという関数を探してください
[code lang=”py”]
def splitString(self, text, doc, encoding=’utf-8′):
asciiReadable = self._asciiReadable
try: state = self.state[doc]
except KeyError: state = self.state[doc] = TTFont.State(asciiReadable)
curSet = -1
cur = []
results = []
temp_code = 0
if not isUnicode(text):
text = text.decode(‘utf-8’) # encoding defaults to utf-8
a = {}
a["test"] = text
print len(text)
assignments = state.assignments
subsets = state.subsets
for code in map(ord,text):
if code in assignments:
n = assignments[code]
else:
if state.frozen:



[/code]
この部分に少し付け加えます
変更前
[code lang=”py”]
subsets = state.subsets
for code in map(ord,text):
if code in assignments:
n = assignments[code]
[/code]
変更後
[code lang=”py”]
temp_code = 0
for code in map(ord,text):
if 0xD800 < code < 0xDBFF:
temp_code = code
continue
elif 0xDC00 < code < 0xDFFF:
code = 0x10000 + (temp_code – 0xD800) * 0x400 + (code – 0xDC00)
[/code]

何をしているかというと、
上位サロゲート(U+D800 ~ U+DBFF)が来た場合には、コードを保持し、その後の処理は行わない
下位サロゲート(U+DC00 ~ U+DFFF)が来た場合には、保持した上位サロゲートを使って
元の文字コードを生成しています

temp_codeにD842
codeにDFB7を入れて計算してもらうと
20BB7という値になるはずです(「つちよし」の文字コード)

この20BB7を処理で使用することで、「つちよし」を出力出来るようにします

PDFを出力してみてください!
上手くいったでしょうか?

Comments are closed.

Post Navigation