LGJ Notes

蒙古大夫 2.0。 這裡紀錄的都不是我的專業,我的專業就是不專業。別傻了,什麼是專業?

« LaTeX CJK 已完整支援 Unicode | Main | 「身長」? »

LaTeX 中文 PDF outline
2006/02/21,18:27 :: 點閱次數 (16464)
所謂 PDF outline 或一般較為熟悉的名詞,稱為 bookmarks。就是 PDF 檔案中的一種結構,在 PDF 瀏覽器瀏覽時,左邊會有一個較小視窗,來顯示文件的目錄結構,滑鼠去點他也會有超連結的功能,這時右邊的內文頁面會直接跳到所點選的章節處。


這個 bookmarks 在 PDF 規格中是屬於 text string 這個型態。這個型態,依 PDF 規格,必需使用以下兩種的編碼:

  1. PDFDocEncoding:ISO Latin 1 的 superset。
  2. Unicode character encoding:必須是 UTF-16BE(big-endian) 的編碼。

其中,在 Document Information Dictionary(就是作者姓名、文件標題、文件製作日期……等這些資訊)中的文字部份也是 text string 的型態,必須使用以上兩種編碼。

這在英文的情況容易解決,使用 PDFDocEncoding 就可以了, 通常就是原英文字本身(有少數例外)。但在中文的情況,會變得相當複雜,必須把他轉碼成 UTF-16BE。這在 LaTeX 處理起來會更複雜,由於 TeX 是 single byte 的語言,程式本身也不具備轉碼的功能,因此,這也是以往中文 LaTeX PDF 文件很頭疼的地方。

以目前的話,我們可以利用 hyperref package 中的 \texorpdfstring 來插入轉碼過後的八進位值。例如:

\chapter{將進酒}
要轉成
\chapter{\texorpdfstring{將進酒}{\13407\22062\221\122}}

如果你的系統有 recode 這個工具,那麼可以使用以下的方法來轉換(以下是在 gnome-terminal UTF-8 環境下執行):

echo -n '將進酒'|recode u8..utf16b/o
0134, 0007, 0220, 0062, 0221, 0122
或進一步由 sed 來完整轉換
echo -n '將進酒'|recode u8..utf16b/o|sed -e 's/^0/\\/' -e 's/, 0/\\/g'
\13407\22062\221\122

當然,如果一篇好幾百頁的文稿都要這樣子轉,對中文使用者而言,這是很辛苦,很不人道的。我們也可以使用外部的工具程式去處理,是會方便些,但這樣就多了一道手續,也還是不很方便。

那麼,我們可以從 tex(the program) 本身,或者由 hyperref package,或者我 們常使用於中文的 LaTeX CJK package,這三個方向來著手想辦法。TeX 是 single byte 的語言,要處理多字元編碼會相對困難。所以,從 package(TeX macro) 來著手,可能是目前比較容易達成的方法。

這裡要很感謝 LaTeX CJK 的作者 Werner LEMBERG 大力幫忙,重新定義了他所寫的 CJKutf8 macro,使得可以在 CJK 環境下, 順利的把他處理掉。當然,這尚未納入新的 LaTeX CJK package 當中,你想測試的話,需要新的 CJKutf8.sty,這暫時可以由 cjk mailing list 取得。下一個正式版本(目前最新版本是 4.6.0),希望可以順利的把這個功能納入。也希望大家多多來測試回報,讓下一個版本的 LaTeX CJK 更完善。

我們就來看一個簡單的測試例子:

% in UTF-8 encoding
% utf8bks3: test CJK pdf outline.
% Edward G.J. Lee 2006.02.21.
\documentclass[12pt,a4paper]{article}
\usepackage{CJKutf8}
\usepackage[T1]{fontenc}
\usepackage[unicode,dvipdfm]{hyperref}
\begin{document}
\begin{CJK}{UTF8}{bsmi}
  \tableofcontents
  \hypersetup{pdfauthor={李果正 Edward G.J. Lee},
              pdftitle={中文 PDF outline 測試}}

  \section{將進酒}
  君不見,黃河之水天上來,奔流到海不復回。

  \section{桃花源記}
  晉太元中,武陵人,捕魚為業,緣溪行,忘路之遠近。

\newpage
\end{CJK}
\end{document}

這裡我們使用 TUG TeXLive 預設的 bsmi 字型來測試,測試環境是 TeXLive-20051102。 其中,這個新的 CJKutf8.sty 要置放於你的工作目錄下,這樣才會蓋過舊版的。如果希望直接使用 pdflatex 的話,那麼把文稿中的 dvipdfm 去掉就可以了。但這樣一來,當然對中文的拷貝、複製功能就沒有了,這要 dvipdfmx 才有這樣的功能。

以下是使用 kpdf 來閱覽的情形:

pdfoutline 圖示

編譯好的 PDF 檔,可在此下載:

http://edt1023.sayya.org/tex/tmp/utf8bks3.pdf

當然,以上只適用於 UTF-8 編碼的文件,在 Big-5 文件則目前 LaTeX CJK 並沒有內建的更好方式,只能使用手動修改。但在 Chen Chi-Hung 幫忙下,針對這個問題提出了他的解決方式:

http://home.pchome.com.tw/world/rawde/tmp/t-cjk4.zip
http://edt1023.sayya.org/tex/tmp/t-cjk4.zip

他是直接去修改所產生的 dvi 檔,來讓他把 text string 的部份轉成 UTF-16BE 的八進位值。要注意的是,如果你的系統是 Unix-like 的系統,這個檔案下載後,有一個 Perl 的可執行檔(a04.pl),他是 DOS 格式,請先把他轉成 Unix 格式。

使用方法很簡單,把 hyperref.cfga04.pl 置於你的工作目錄下,依一般編譯 Big-5 編碼的文件方式即可,但在執行兩次 bg5latex 後,先使用 a04.pl 處理一下所生成的 *.dvi 檔,再來使用 dvipdfmx 來處理修改過的 *.dvi 檔即可,以 zip 檔案裡頭所附的測試檔 t.tex 為例:

bg5latex t.tex
bg5latex t.tex
./a04.pl t.dvi
dvipdfmx t.utf16be.dvi

這樣就會產生 t.utf16be.pdf,這才是最後所要的結果。雖然好像多了一道手續,但比起手動去修改就方便多了,在此感謝 Chen Chi-Hung 的幫忙。


Tue Oct 31 22:13:30 CST 2006 修訂
CJK 4.7.0 已釋出,請參考:
LaTeX CJK 4.7.0 已釋出!一文。

迴響

Comment Icon UTF8.bdg

對了,這個例子,你必需使用 cvs 的版本:
http://cjk.ffii.org/cjk/devel/cjk-current.tar.gz

Posted by: LGJ at 2006/02/21, 21:09
Comment Icon 似乎不行

在使用这个功能之前,CJK 的 UTF8 配置是可以工作的。下面是我运行的 log:

--

LaTeX2e
Babel and hyphenation patterns for english, dumylang, nohyphenation, ge
rman, ngerman, french, loaded.
(C:\CTeX\texmf\tex\latex\base\article.cls
Document Class: article 2004/02/16 v1.4f Standard LaTeX document class
(C:\CTeX\texmf\tex\latex\base\size12.clo))
(C:\CTeX\localtexmf\tex\latex\CJK\CJKutf8.sty
(C:\CTeX\texmf\tex\latex\base\inputenc.sty
(C:\CTeX\texmf\tex\latex\base\utf8.def (C:\CTeX\texmf\tex\latex\base\t1enc.dfu)
(C:\CTeX\texmf\tex\latex\base\ot1enc.dfu)
(C:\CTeX\texmf\tex\latex\base\omsenc.dfu)))
(C:\CTeX\localtexmf\tex\latex\CJK\CJK.sty
(C:\CTeX\localtexmf\tex\latex\CJK\mule\MULEenc.sty)
(C:\CTeX\localtexmf\tex\latex\CJK\CJK.enc))
(C:\CTeX\texmf\tex\latex\base\fontenc.sty))
(C:\CTeX\texmf\tex\latex\base\fontenc.sty
(C:\CTeX\texmf\tex\latex\base\t1enc.def))
(C:\CTeX\texmf\tex\latex\hyperref\hyperref.sty
(C:\CTeX\texmf\tex\latex\graphics\keyval.sty)
(C:\CTeX\texmf\tex\latex\hyperref\pd1enc.def)
(C:\CTeX\texmf\tex\latex0miktex\hyperref.cfg)
(C:\CTeX\texmf\tex\latex\hyperref\puenc.def)
Implicit mode ON; LaTeX internals redefined
(C:\CTeX\texmf\tex\latex\ltxmisc\url.sty))
*hyperref using driver hdvipdfm*
(C:\CTeX\texmf\tex\latex\hyperref\hdvipdfm.def) (cjku8.aux)
(C:\CTeX\texmf\tex\latex\hyperref\nameref.sty) (cjku8.out) (cjku8.out)
(C:\CTeX\localtexmf\tex\latex\CJK\UTF8\UTF8.bdg)
(C:\CTeX\localtexmf\tex\latex\CJK\UTF8\UTF8.enc)
(C:\CTeX\localtexmf\tex\latex\CJK\UTF8\UTF8.chr) (cjku8.toc)
! Extra \else.
\CJK@XXX ...\number `#1\endcsname {`#2}{`#3}\else
\csname u8:\string #1\stri...
l.12 ...rsetup{pdfauthor={涓枃 Edward G.J. Lee}}

?

Posted by: jjgod at 2006/02/22, 03:57
Comment Icon UTF-8 BOM?

另外,LaTeX 可以处理带 BOM 的 UTF-8 文件么?

Posted by: jjgod at 2006/02/22, 03:58
Comment Icon Re: 似乎不行

請先檢查:
C:\CTeX\localtexmf\tex\latex\CJK\CJKutf8.sty
是不是由 cjk mailing list 取得的?

另外,是使用 cjk-current 的版本嗎?

Posted by: LGJ at 2006/02/22, 16:54
Comment Icon Re: UTF-8 BOM?

另外,LaTeX 可以处理带 BOM 的 UTF-8 文件么?

目前不行。UTF-8 編碼的 byte order 是內部預先製定的,他是固定的,所以不會有 byte oder 的問題。Unicode book 也不建議採用 UTF-8 BOM。

Posted by: LGJ at 2006/02/22, 17:10
Comment Icon CJKutf8.sty

是的,是看完您的文章之后去重新抓的一份 cjk-current.tar.gz。

Posted by: jjgod at 2006/02/23, 04:14
Comment Icon IM

另外,您使用什么 IM 么?我还有一些琐碎的问题希望请教。

MSN: gzjjgod@hotmail.com
gtalk: gzjjgod@gmail.com

Posted by: jjgod at 2006/02/23, 14:02
Comment Icon Re: IM

我是使用 gcin 的嘸蝦米輸入法,輸入法表格是自行編進去的。如果是在 GNU/Linux 系統的話,你的輸入法不支援 CJKUIEB,可以暫時使用 gucharmap 來輸入(copy&paste)。

Sorry,我沒有,也不會使用 MSN/gtalk。:-)

my email: edt1023_AT_info.sayya.org

Posted by: LGJ at 2006/02/23, 16:44
Comment Icon 我也似乎不行

我用了TeXLive 2007,里面的CJKutf8.sty是2006年10月21日的版本,也遇到了类似jjgod的问题。

Posted by: cevitamic at 2007/05/03, 17:04
Comment Icon 问题找到了

似乎找到问题了,如果在最后不加上\newpage,就会出错,不知道是不是这个原因。

Posted by: cevitamic at 2007/05/03, 17:12
Comment Icon Re: 问题找到了

是的,這是因為 CJK 處理未完成,需要一個 \newpage 去 flush 它。

Posted by: LGJ at 2007/05/03, 19:05
Comment Icon texlive 2007 中,直接使用 pdflatex

我在 texlive 2007 中,試了下文章中的例子,直接使用 pdflatex 就己經得到正確的結果‧

另外,把文稿最後的 \newpage 也可以得到同樣的結果‧

Posted by: 大呆 at 2007/11/05, 11:43
 
Accessible and Valid XHTML 1.0 Strict and CSS Powered by BS2 Blog