PDFで文字化けについて

2,157 views
Skip to first unread message

Syysk

unread,
Apr 23, 2008, 3:03:28 AM4/23/08
to Redmine Users (japanese)
PDFで文字化けについて

CentOS 5.0
ruby 1.8.5
rails 2.0.2
rake 0.8.1
Acrobat Reader 8.1
Redmine 0.7.0 RC1(r1330)

にてRedmineを運用しています。

r1300
http://www.redmine.org/repositories/revision/redmine?rev=1300
のTranslation updatesにて
general_pdf_encoding: SJIS
から
general_pdf_encoding: UTF-8
に変更になった事によりPDF文字化けが発生しています。

ついでだったので機種依存文字を解決するために
encording関連をすべてCP932へ変更した所、
機種依存文字などの文字化けはほぼ解消しています。

general_csv_encoding: CP932
general_pdf_encoding: CP932

WindowsServer環境ではテストできないですが
文字化けがまだ発生している方は上記の設定にすると
NEC拡張文字などによる文字化けなどは解決するかもしれません。

ただ、優先度の "普通" が "通" に 名前 と 苗字 が全角2文字の場合に 鈴木 さん → 鈴木さ
のようになります。

データ上改行が入っておらず、PDF出力時に改行する場合の切られ方の問題と
文字数とバイト数の違いによる問題な気がしていますが
プログラムを追いきれてません。

解決策など知っている方おられますでしょうか?

# Google Group は使用した事がほとんど無いのですが、
# 過去Topicの"PDFで文字化け"に返信ができませんでした。
# http://groups.google.com/group/redmine-users-ja/browse_thread/thread/2470591a4d42384c#
# 古すぎるTopicには返信できないのでしょうか?

以上です。

Kazuhiro NISHIYAMA

unread,
Apr 23, 2008, 3:20:15 AM4/23/08
to redmine-...@googlegroups.com
2008/4/23 Syysk <syys...@gmail.com>:
> 解決策など知っている方おられますでしょうか?

http://rubyforge.org/tracker/index.php?func=detail&aid=6554&group_id=1869&atid=7320
のパッチでどうでしょうか?

# 他にも同じようなgsubがあるのでそちらも直した方がいいのかもしれませんが。

Syysk

unread,
Apr 23, 2008, 5:43:49 AM4/23/08
to Redmine Users (japanese)
Syyskです。

返信ありがとうございます。

> http://rubyforge.org/tracker/index.php?func=detail&aid=6554&group_id=...
> のパッチでどうでしょうか?

vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb
のtxt.gsub!('\\', '\\\\')をすべてtxt.gsub!('\\', '\\\\\\')
に変更してみても
文字が切れる現象と、改行発生時に文字化けする場合がある現象が直りませんでした。

fpdf.rbにて出力している部分になにか問題がありそうなので
もうちょっとfpdf.rbを眺めてみます。

fmkt

unread,
Apr 23, 2008, 6:41:25 AM4/23/08
to Redmine Users (japanese)
こんばんは。

おぉ!っと思ってやってみたら、やはり直らなかったです・・・。

私はソースを追いかけて
"vendor/plugins/rfpdf/lib/rfpdf/japanese.rb"
この辺りのせいではないかなと思いましたが、
結局トレースがしづらかったので放置していました...

SJISMultiCell メソッドの 167行目あたりにある
if o==10 ですが、本来 LF で切り分けるための処理が
マルチバイト文字の0x10に引っかかっていけない処理を
してるのではないかなと予想していました。

結局確かめていないので信憑性はなく、
なんの解決にもなっていないですが...

では。

poro

unread,
May 1, 2008, 2:40:14 AM5/1/08
to Redmine Users (japanese)
はじめまして。

仕事で丁度redmineの設定をしていて、
PDFの文字化けにぶつかっちゃいました。

で、色々と調べたんですが、
やっぱりjapanese.rbでおかしくなっているみたいですね。

japanese.rbのMultiCell()に文字列が入ってくる時点でUTF-8なのに
SJISとして処理しようとしてるために、文字コードでの切り分けが
うまく動作していないみたいです。

MultiCell()に渡す文字列がUTF-8なのが根本的な問題だと思うんですが、
手前でSJISに変換するのがややこしそうだったので、
文字コードでの切り分け処理をUTF-8用に変更すればうまくいきました。
(合ってるかどうかわからないですが・・・)

Index: japanese.rb
===================================================================
--- japanese.rb (revision 1382)
+++ japanese.rb (working copy)
@@ -184,16 +184,31 @@
if(o==32)
sep=i
end
- elsif(o>=161 and o<=223)
+ # elsif(o>=161 and o<=223)
+ elsif(o==239 and ((o==189 and (o>=161 and o<=191)) or (o==190
and(o>=128 and o<=159))))
#Half-width katakana
l+=500
- n=1
+ # n=1
+ n=3
sep=i
else
#Full-width character
l+=1000
- n=2
+ # n=2
sep=i
+
+ if(o>=192 and o<=223)
+ n=2
+ elsif(o>=224 and o<=239)
+ n=3
+ elsif(o>=240 and o<=247)
+ n=4
+ elsif(o>=248 and o<=251)
+ n=5
+ # elsif(o>=252 and o<=253)
+ else
+ n=6
+ end
end
if(l>wmax)
#Automatic line break
@@ -275,16 +290,31 @@
if(o==32)
sep=i
end
- elsif(o>=161 and o<=223)
+ # elsif(o>=161 and o<=223)
+ elsif(o==239 and ((o==189 and (o>=161 and o<=191)) or (o==190
and(o>=128 and o<=159))))
#Half-width katakana
l+=500
- n=1
+ # n=1
+ n=3
sep=i
else
#Full-width character
l+=1000
- n=2
+ # n=2
sep=i
+
+ if(o>=192 and o<=223)
+ n=2
+ elsif(o>=224 and o<=239)
+ n=3
+ elsif(o>=240 and o<=247)
+ n=4
+ elsif(o>=248 and o<=251)
+ n=5
+ # elsif(o>=252 and o<=253)
+ else
+ n=6
+ end
end
if(l>wmax)
#Automatic line break

bbbb

unread,
May 3, 2008, 11:27:00 AM5/3/08
to Redmine Users (japanese)
On 4月23日, 午後4:03, Syysk <syysk2...@gmail.com> wrote:
> PDFで文字化けについて

> general_csv_encoding: CP932
> general_pdf_encoding: CP932

確かに、こちらの方が良さそうではありますね。とりあえずは SJIS にしました。


> 解決策など知っている方おられますでしょうか?

とりあえずは、手元では以下のような修正で直っているように見えます。
(手元はsyysk氏と同じような環境です。)

ちなみに、vendor/plugins/rfpdf/ 以下をいくら修正しても、
上流側(元々の Ruby FPDF 側)で反映されない限り、
取り込んでもらえないように思うので、app/helper/ifpdf_helper.rb 側を編集してます。
ただし、特異メソッドの MultiCell() をオーバーライドできずに、
MultiCell2() としている所がダサく、やむを得ず app/views/issues/ 以下も
合わせていじっていますし、日本語の事しか考えてないので、
いろいろ副作用があるかもしれません。
もっとうまい方法がある気がするので、だれか教えて下さい。

ついでに、プロパティのタイトルの文字化けも修正してあります。
(SetTitle() と textstring() をオーバーライド)。

--
Hajime BABA

=======================================================================

Index: app/helpers/ifpdf_helper.rb
===================================================================
--- app/helpers/ifpdf_helper.rb (revision 1401)
+++ app/helpers/ifpdf_helper.rb (working copy)
@@ -56,6 +56,17 @@
end

def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
+ txt = convUTF8toSJISandEscape0x5c(txt)
+ super w,h,txt,border,ln,align,fill,link
+ end
+
+ def MultiCell2(w,h,txt,border=0,align='L',fill=0)
+ txt = convUTF8toSJISandEscape0x5c(txt)
+ MultiCell(w,h,txt,border,align,fill)
+ end
+
+ def convUTF8toSJISandEscape0x5c(txt)
+ txt << " "
@ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
# these quotation marks are not correctly rendered in the pdf
txt = txt.gsub(/[“”]/, '"') if txt
@@ -67,9 +78,8 @@
rescue
txt
end || ''
- super w,h,txt,border,ln,align,fill,link
end
-
+
def Footer
SetFont(@font_for_footer, 'I', 8)
SetY(-15)
@@ -79,7 +89,31 @@
SetX(-30)
Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
end
-
+
+ def SetTitle(txt)
+ case current_language.to_s
+ when 'ja', 'zh', 'zh-tw'
+ txt = begin
+ utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
+ hextxt = "<FEFF" # FEFF is BOM
+ hextxt << utf16txt.unpack("C*").map {|x|
sprintf("%02X",x) }.join
+ hextxt << ">"
+ rescue
+ txt
+ end || ''
+ end
+ super(txt)
+ end
+
+ def textstring(s)
+ # Format a text string
+ if s =~ /^</ # This means the string is hex-dumped.
+ return s
+ else
+ return '('+escape(s)+')'
+ end
+ end
+
end

end
Index: app/views/issues/index.rfpdf
===================================================================
--- app/views/issues/index.rfpdf (revision 1401)
+++ app/views/issues/index.rfpdf (working copy)
@@ -42,9 +42,9 @@
pdf.Cell(30, row_height, issue.priority.name, 0, 0,
'L', 1)
pdf.Cell(40, row_height, issue.assigned_to ?
issue.assigned_to.n
ame : '', 0, 0, 'L', 1)
pdf.Cell(25, row_height,
format_date(issue.updated_on), 0, 0, 'L
', 1)
- pdf.MultiCell(0, row_height, (@project ==
issue.project ? issue.
subject : "#{issue.project.name} - #{issue.subject}"))
+ pdf.MultiCell2(0, row_height, (@project ==
issue.project ? issue
.subject : "#{issue.project.name} - #{issue.subject}"))
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
pdf.SetY(pdf.GetY() + 1)
end
%>
-<%= pdf.Output %>
\ No newline at end of file
+<%= pdf.Output %>
Index: app/views/issues/_pdf.rfpdf
===================================================================
--- app/views/issues/_pdf.rfpdf (revision 1401)
+++ app/views/issues/_pdf.rfpdf (working copy)
@@ -48,7 +48,7 @@
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, custom_value.custom_field.name + ":","L")
pdf.SetFontStyle('',9)
- pdf.MultiCell(155,5, (show_value custom_value),"R")
+ pdf.MultiCell2(155,5, (show_value custom_value),"R")
end

pdf.SetFontStyle('B',9)
@@ -60,7 +60,7 @@
pdf.SetFontStyle('B',9)
pdf.Cell(35,5, l(:field_description) + ":")
pdf.SetFontStyle('',9)
- pdf.MultiCell(155,5, issue.description,"BR")
+ pdf.MultiCell2(155,5, issue.description,"BR")

pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY)
@@ -77,7 +77,7 @@
pdf.Ln
unless changeset.comments.blank?
pdf.SetFontStyle('',8)
- pdf.MultiCell(190,5,
changeset.comments)
+ pdf.MultiCell2(190,5,
changeset.comments)
end
pdf.Ln
end
@@ -97,7 +97,7 @@
end
if journal.notes?
pdf.SetFontStyle('',8)
- pdf.MultiCell(190,5, journal.notes)
+ pdf.MultiCell2(190,5, journal.notes)
end
pdf.Ln
end
Index: lang/ja.yml
===================================================================
--- lang/ja.yml (revision 1401)
+++ lang/ja.yml (working copy)
@@ -50,7 +50,7 @@
general_lang_name: 'Japanese (日本語)'
general_csv_separator: ','
general_csv_encoding: SJIS
-general_pdf_encoding: UTF-8
+general_pdf_encoding: SJIS
general_day_names: 月曜日,火曜日,水曜日,木曜日,金曜日,土曜日,日曜日
general_first_day_of_week: '7'


==================================================================================



Syysk

unread,
May 6, 2008, 8:59:25 PM5/6/08
to Redmine Users (japanese)
Syyskです。

poroさん、bbbbさん、返信ありがとうございます。

On 5月1日, 午後3:40, poro <iet.p...@gmail.com> wrote:
> で、色々と調べたんですが、
> やっぱりjapanese.rbでおかしくなっているみたいですね。
> japanese.rbのMultiCell()に文字列が入ってくる時点でUTF-8なのに
> SJISとして処理しようとしてるために、文字コードでの切り分けが
> うまく動作していないみたいです。
> MultiCell()に渡す文字列がUTF-8なのが根本的な問題だと思うんですが、
> 手前でSJISに変換するのがややこしそうだったので、
> 文字コードでの切り分け処理をUTF-8用に変更すればうまくいきました。
> (合ってるかどうかわからないですが・・・)

この修正で正常に動作する事は確認できました。

MultiCellにUTF8で渡してるって事は環境依存問題っぽいですね。
Linuxのみで発生する問題でしょうか。

On 5月4日, 午前12:27, bbbb <baba.haj...@gmail.com> wrote:
> ちなみに、vendor/plugins/rfpdf/ 以下をいくら修正しても、
> 上流側(元々の Ruby FPDF 側)で反映されない限り、
> 取り込んでもらえないように思うので、app/helper/ifpdf_helper.rb 側を編集してます。
> ただし、特異メソッドの MultiCell() をオーバーライドできずに、
> MultiCell2() としている所がダサく、やむを得ず app/views/issues/ 以下も
> 合わせていじっていますし、日本語の事しか考えてないので、
> いろいろ副作用があるかもしれません。
> もっとうまい方法がある気がするので、だれか教えて下さい。
>
> ついでに、プロパティのタイトルの文字化けも修正してあります。
> (SetTitle() と textstring() をオーバーライド)。

こちらの修正でも問題なく動作する事を確認できました。

現在、どちらの修正でも問題なく稼動する事は確認できています。
Windows環境での確認はできてません。

rfpdfですが、もともとPHPで書かれてるものをRubyで書き直しているもののようですね
そのFPDF自体の更新も何年か止まってるみたいでした。

どっちの修正を適用するかはもうちょっと考えたいと思います。
ありがとうございました。

fmkt

unread,
May 6, 2008, 9:19:30 PM5/6/08
to Redmine Users (japanese)
こんにちは。

以下、参考までに。

> > ちなみに、vendor/plugins/rfpdf/ 以下をいくら修正しても、
> > 上流側(元々の Ruby FPDF 側)で反映されない限り、
> > 取り込んでもらえないように思うので、app/helper/ifpdf_helper.rb 側を編集してます。

> どっちの修正を適用するかはもうちょっと考えたいと思います。

今回のpdfではないですが、
public/javascripts/calendar/ 以下のファイルも本家が更新されていることに対し
redmineでは独自のfixがされています。

そういう背景から vendor/plugins/rfpdf 以下の修正でもいいのかもしれません。

では。

fmkt

unread,
May 6, 2008, 9:30:56 PM5/6/08
to Redmine Users (japanese)
こんにちは。

修正をあてた報告ですが、うまく文字化けはなくなっているようです。

ですが、ところどころ変なところに "¥" が入ってますね。
これは私の環境だけの問題でしょうか・・・?

同じパッチをあてた方はどうなっていますか?

では。

Syysk

unread,
May 7, 2008, 12:37:06 AM5/7/08
to Redmine Users (japanese)
Syyskです。

On 5月7日, 午前10:30, fmkt <fmkt.ne...@gmail.com> wrote:
> ですが、ところどころ変なところに "¥" が入ってますね。
> これは私の環境だけの問題でしょうか・・・?

大量に問題を出力してみた所、確かに "¥"が入っています。
それとよくよく見ると文章がすべて出力されていない場合があるようです。

1."¥"が入る現象は
正) 機能追加
誤) 機能¥追‰

2.文字が切れる現象は

正) A4帳票に変更する
誤) A4帳票に変更す

のようになります。
"¥"がつく文字は表、()など固定の文字にかならずつきます。

以上です。

Syysk

unread,
May 7, 2008, 5:56:33 AM5/7/08
to Redmine Users (japanese)
Syyskです。

poroさんの対応を一旦取りやめてbbbbさんの対応のみ再度適用し直した所、
"¥" 出力の問題は正常になりました。

文字が切れる現象もほぼ出なくなていますが、何故か切れる所が存在し
担当者の出力部分で AA さん という人がいた場合に "ん" が出力されなくなります。

姓名の順序を変えれなかった時に運用で名前に姓を、姓に "さん" を登録する運用
としている為、さんの "さ"だけ出力されます。
ただ、文字化けは完全に無くなりましたし、切れるのも最後の1文字だけ、また
殆ど発生しないためとりあえずbbbbさんのpatchを当てた形で運用していくつもりです。

また何かわかりましたら報告致します。

以上です。

poro

unread,
May 7, 2008, 6:29:06 AM5/7/08
to Redmine Users (japanese)
こんにちわ、poroです。

> poroさんの対応を一旦取りやめてbbbbさんの対応のみ再度適用し直した所、
> "¥" 出力の問題は正常になりました。

んー、なんでだろう・・・
私の環境では'¥'が表示されずにうまく出力されてるのですが。
なんか環境設定に違いがあるのかも。

ただ、bbbbさんの修正と同時使用した場合は問題がでると思います。
bbbbさんの修正ではMultiCell()に文字が渡されたあとに
SJIS変換してから改行チェックが走るのですが、
私の修正ではMultiCell()内の改行チェックをSJISではなくUTF-8で
チェックしてるのでおかしくなっちゃいます。

Syysk

unread,
May 8, 2008, 3:38:32 AM5/8/08
to Redmine Users (japanese)
Syyskです。

On 5月7日, 午後7:29, poro <iet.p...@gmail.com> wrote:
> > poroさんの対応を一旦取りやめてbbbbさんの対応のみ再度適用し直した所、
> > "¥" 出力の問題は正常になりました。
>
> んー、なんでだろう・・・
> 私の環境では'¥'が表示されずにうまく出力されてるのですが。
> なんか環境設定に違いがあるのかも。

すいません。こちらは自分の勘違いでした。

数件前のメッセージでの
> http://rubyforge.org/tracker/index.php?func=detail&aid=6554&group_id=...
> のパッチでどうでしょうか?
vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb
のtxt.gsub!('\\', '\\\\')をすべてtxt.gsub!('\\', '\\\\\\')

をした事によりifpdf_helper.rb の0x5c対応と、rfpdfでの0x5c対応が2重に入り
出力に "¥" が含まれてしまったようです。
bbbbさんのパッチを当てる前に一度最新にしたため正常になりました。

> ただ、bbbbさんの修正と同時使用した場合は問題がでると思います。
> bbbbさんの修正ではMultiCell()に文字が渡されたあとに
> SJIS変換してから改行チェックが走るのですが、
> 私の修正ではMultiCell()内の改行チェックをSJISではなくUTF-8で
> チェックしてるのでおかしくなっちゃいます。

了解しました。どちらの修正でも問題はなさそうです。

最後の1文字が出力されない問題ですが、
どこで消えてるのかDebugした所、rfpdfでsprintfしている部分でマルチバイトを出力すると
1文字消える事がある事がわかりました。

具体的には
vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb
636 s=s+sprintf('BT %.2f %.2f Td (%s) Tj ET',
637 (@x+dx)*@k,(@h-(@y+0.5*h+0.3*@FontSize))*@k,txt)

の部分で(%s)にて"AA さん " などを出力すると
最後の1文字がおかしくなるみたいです。

$KCODE=UTF8 な環境でsprintfにてSJISを出力しているのが原因みたいです。
Rubyの問題な感じなので安定版の最新版にしてみると正常になりました。

テスト時のRubyのバージョンは
ruby 1.8.5 (2007-09-24 patchlevel 114) [i386-linux]
だったため
ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-linux]
に変更すると現象は解決しました。

以上で文字化けについては解決しました。
ありがとうございました。

fmkt

unread,
May 8, 2008, 4:29:52 AM5/8/08
to Redmine Users (japanese)

こんにちは。

> vendor/plugins/rfpdf/lib/rfpdf/fpdf.rb
> のtxt.gsub!('\\', '\\\\')をすべてtxt.gsub!('\\', '\\\\\\')
>
> をした事によりifpdf_helper.rb の0x5c対応と、rfpdfでの0x5c対応が2重に入り
> 出力に "¥" が含まれてしまったようです。

全く同じことをしていてお恥ずかしい限りですorz

では。

suzukyu

unread,
May 8, 2008, 3:39:55 PM5/8/08
to Redmine Users (japanese)

On 5月7日, 午前9:59, Syysk <syysk2...@gmail.com> wrote:
> rfpdfですが、もともとPHPで書かれてるものをRubyで書き直しているもののようですね
> そのFPDF自体の更新も何年か止まってるみたいでした。

完全に余談ですが、FPDFは後継としてTCPDFとして開発されているようです。
TCPDF - PHP Class for PDF
http://www.tecnick.com/public/code/cp_dpage.php?aiocp_dp=tcpdf
Reply all
Reply to author
Forward
0 new messages