OSDN Git Service

Merge branch 'kmaeda-manual' into kitagawa_test
authorHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Mon, 9 Apr 2012 12:40:12 +0000 (21:40 +0900)
committerHironori Kitagawa <h_kitagawa2001@yahoo.co.jp>
Mon, 9 Apr 2012 12:40:12 +0000 (21:40 +0900)
doc/manual-zh.pdf [new file with mode: 0644]
doc/manual-zh.tex [new file with mode: 0644]
src/luatexja-core.lua
src/luatexja-core.sty
src/luatexja/jfmglue.lua
src/luatexja/setwidth.lua
test/test04-jfm.pdf
test/test04-jfm.tex

diff --git a/doc/manual-zh.pdf b/doc/manual-zh.pdf
new file mode 100644 (file)
index 0000000..bab6252
Binary files /dev/null and b/doc/manual-zh.pdf differ
diff --git a/doc/manual-zh.tex b/doc/manual-zh.tex
new file mode 100644 (file)
index 0000000..50ac607
--- /dev/null
@@ -0,0 +1,423 @@
+\documentclass{ltjarticle}
+\usepackage[twoside,left=23mm,width=170mm,right=17mm,top=25mm,height=231mm,bottom=32mm]{geometry}
+\usepackage{multicol}
+\usepackage{showexpl}
+
+\lstset{
+  basicstyle=\ttfamily\small, pos=o, breaklines=true,
+  numbers=none, rframe={}, basewidth=0.5em
+}
+\DeclareYokoKanjiEncoding{ZH}{}{}
+\DeclareKanjiEncodingDefaults{}{}
+\DeclareErrorKanjiFont{ZH}{song}{m}{n}{10}
+\DeclareKanjiSubstitution{ZH}{song}{m}{n}
+\newcommand\songdefault{song}
+\newcommand\heidefault{hei}
+\renewcommand\kanjiencodingdefault{ZH}
+\renewcommand\kanjifamilydefault{\songdefault}
+\renewcommand\kanjiseriesdefault{\mddefault}
+\renewcommand\kanjishapedefault{\updefault}
+\DeclareKanjiFamily{ZH}{song}{}
+\DeclareFontShape{ZH}{song}{m}{n}{<->name:AdobeSongStd-Light:jfm=jis}{}
+\DeclareFontShape{ZH}{song}{bx}{n}{<->ssub*hei/m/n}{}
+\DeclareKanjiFamily{ZH}{hei}{}
+\DeclareFontShape{ZH}{hei}{m}{n}{<->name:AdobeHeitiStd-Regular:jfm=jis}{}
+\fontencoding{ZH}\selectfont
+\DeclareTextFontCommand{\textsong}{\songfamily}
+\DeclareTextFontCommand{\texthei}{\heifamily}
+\DeclareOldFontCommand{\song}{\normalfont\songfamily}{}
+\DeclareOldFontCommand{\hei}{\normalfont\heifamily}{}
+\DeclareSymbolFont{songti}{ZH}{song}{m}{n}
+\jfam\symsongti
+\SetSymbolFont{songti}{bold}{ZH}{hei}{m}{n}
+\DeclareSymbolFontAlphabet{\mathsong}{songti}
+\DeclareMathAlphabet{\mathhei}{ZH}{hei}{m}{n}
+\makeatletter
+\DeclareRobustCommand\songfamily{\not@math@alphabet\songfamily\mathsong\kanjifamily\songdefault\selectfont}
+\DeclareRobustCommand\heifamily{\not@math@alphabet\heifamily\mathhei\kanjifamily\heidefault\selectfont}
+\DeclareRobustCommand\rmfamily{\not@math@alphabet\rmfamily\mathrm\romanfamily\rmdefault\kanjifamily\songdefault\selectfont}
+\DeclareRobustCommand\sffamily{\not@math@alphabet\sffamily\mathsf\romanfamily\sfdefault\kanjifamily\heidefault\selectfont}
+\makeatother
+\def\LuaTeX{Lua\TeX}
+\def\pTeX{p\TeX}
+\def\pLaTeX{p\LaTeX}
+\begin{document}
+\section{\LuaTeX-ja的开发背景}
+\LuaTeX-ja是日本开发者北川弘典首倡的一个\LuaTeX的日文支持项目,该项目将\pTeX移植到了\LuaTeX,并做了一定的扩展,删除了一些不正常的特性。
+
+\LuaTeX-ja的项目开发者如下:北川弘典,前田一贵,八登崇之,黑木裕介,阿部纪行,山本宗宏,本田知亮,斋藤修三郎和马起园等。
+
+\LuaTeX-ja现在只能用于plain \TeX格式和\LaTeXe格式,尚不支持\TeX info和Con\TeX t格式。
+
+\LuaTeX-ja现在的代码实现依赖于\verb!luatexbase!以及\verb!luaotfload!等宏包,并且现在仅仅实现了横排,直排组版尚未实现。
+\section{一些约定}
+在本文档中,有下面一些约定:
+\begin{itemize}
+\item 所有的CJK字符为\textbf{JAchar},所有的其他字符为\textbf{ALchar}
+\item primitive,该词在本文档中不仅表示\LuaTeX的基本控制命令,也包括\LuaTeX-ja的相关的基本控制命令
+\item 所有的自然数从0开始
+\end{itemize}
+\section{安装使用}
+\subsection{\LuaTeX版本需求}
+\LuaTeX-ja需要使用版本号为大于0.65的\LuaTeX。如果用户使用的是\TeX Live2011或者Mac\TeX 2011以及最新版本的W32\TeX,都可以正常使用\LuaTeX-ja。
+\subsection{\LuaTeX-ja宏包安装}
+\begin{enumerate}
+\item \LuaTeX-ja宏包的获取:
+       \begin{itemize}
+       \item 如果用户使用git,那么可以使用如下命令获取:\\
+               \verb!$ git clone git://git.sourceforge.jp/gitroot/luatex-ja/luatexja.git!
+       \item 另外用户还可以直接下载master版本:\\
+               \verb!$ wget http://git.sourceforge.jp/view?p=luatex-ja/luatexja.git;a=snapshot;h=HEAD;sf=tgz!
+       \end{itemize}
+\item 用户需要将获取的\LuaTeX-ja宏包的\verb!src/!放置到你所用的发行版中的\verb!TEXMFLOACL!树下\verb!tex/!文件夹(如果不存在,请建立)下即可,查询该环境变量需要使用:\\
+       \verb!$ kpeswhich -expand-var "$TEXMFLOCAL"!
+\item 刷新数据库:\\
+       \verb!$ texhash!\\
+       \verb!$ mkluatexfontdb!
+\end{enumerate}
+\section{\LuaTeX-ja在plain \TeX格式下的使用}
+对于日本用户,日文的排版可以直接使用:
+\begin{verbatim}
+\input luatexja.sty
+\end{verbatim}
+
+这一行会默认调用\verb!luatexja.sty!文件,该文件作用相当于\pTeX中的\verb!ptex.tex!。该文件中设定了两款非嵌入字体:Ryumin-Light(明朝体)和GothicBBB-Medium(哥特体)。
+这些字体分别有三种大小:\verb!\tenmin!和\verb!\tengt!(10pt);\verb!\sevenmin!和\verb!\sevengt!(7pt);\verb!\fivemin!和\verb!\fivegt!(5pt)。
+
+有几点请用户注意:
+\begin{itemize}
+\item 上述的两款字体需要你的pdf阅读器带有良好的非嵌入字体的支持,这里建议使用Adobe Reader,该阅读器使用了Kozuka Mincho字体。
+\item 在定义字体的时候,可以使用“级”(Q)单位,$1 \mathrm{Q} = 0.25\mathrm{mm}$,在\LuaTeX-ja中可以使用\verb!\jQ!命令调用该长度单位
+\item 一般情况下,相同大小日文字体比西文字体要大一下(中文字体也是如此),所以定义日文字体的时候需要一个缩放率:0.962216
+\item 在\textbf{JAchar}和\textbf{ALchar}之间插入的胶大小为:$(0.25\times0.962216\times\mathrm{10pt})^{\mathrm{+1pt}}_{\mathrm{-1pt}} = 2.40554\mathrm{pt}^{\mathrm{+1pt}}_{\mathrm{-1pt}}$
+\end{itemize}
+\section{\LuaTeX-ja在\LaTeXe格式的使用}
+\subsection{日文排版设置}
+在\LaTeXe下使用\LuaTeX-ja比较便利:
+\begin{verbatim}
+\usepackage{luatexja}
+\end{verbatim}
+
+该宏包的作用相当于\pLaTeX中的\verb!plfonts.dtx!和\verb!pldefs.ltx!。
+\begin{itemize}
+\item 在该宏包中设定了\verb!JY3!编码,这个编码用来调用日文字体
+\item 该宏包定义了两个字体族:\verb!mc!和\verb!gt!。\\
+\begin{center}
+       \begin{tabular}{ccccc}
+       \hline
+       字体&字体族&\verb!\mdseries!&\verb!\bfseries!&缩放率\\
+       \hline
+       \textit{mincho}&\verb!mc!&Ryumin-Light&GothicBBB-Medium&0.962216\\
+       \textit{gothic}&\verb!gt!&GothicBBB-Medium&GothicBBB-Medium&0.962216\\
+       \hline
+       \end{tabular}
+\end{center}
+\item 在数学模式下,所有的字符使用\verb!mc!字体族来排印
+%中文的C\TeX和xeCJK都没有进行此项设定,导致不能在数学模式下输入中文
+\end{itemize}
+
+上述使用的宏包,只满足了最小的日文环境设定需求,并为满足所有的日文排版需求。
+\LuaTeX-ja宏包提供了两个文档类:\verb!jclasses!(\pLaTeX标准文档类)和\verb!jsclasses!(奥村晴彦)。用户可自行选择两种文档类。
+
+\subsection{中文排版设定}
+请先下载\verb!zh-classes!:
+\begin{verbatim}
+$ wget http://fandol-doc.googlecode.com/files/zh-classes.tar.xz
+\end{verbatim}
+
+该文档类是基于\verb!jclasses!文档的中文设定版。
+这个文档类需要你安装Adobe Reader并使用两款字体。
+值得注意的是,本文档类提供的两款字体并不嵌入,这首先是为了减轻文档大小,其次为了加快编译速度。
+这两款字体在你安装的中文版Adobe Reader的文件夹下。这两款字体设定如下:
+\begin{center}
+       \begin{tabular}{cccc}
+       \hline
+       字体&字体族&\verb!\mdseries!&\verb!\bfseries!\\
+       \hline
+       \textit{song}&\verb!song!&AdobeSongStd-Light&AdobeHeitiStd-Regular\\
+       \textit{hei}&\verb!hei!&AdobeHeitiStd-Regular&AdobeHeitiStd-Regular\\
+       \hline
+       \end{tabular}
+\end{center}
+
+例如:
+\begin{verbatim}
+\documentclass{zh-article}
+\title{Lua\TeX测试}
+\author{某人甲}
+\begin{document}
+\maketitle
+Lua\TeX-ja中文测试。{\hei 测试}
+\end{document}
+\end{verbatim}
+
+我们在这里建议用户更改\textsf{zh-classes.dtx}文件中的相关代码来定制符合自己的文档类。
+但请注意,请将你更改后的文档类更名为你自己的自定义名称。
+这里给出一些常见的中文字体组合:
+\begin{center}
+       \begin{tabular}{ccc}
+       \hline
+        组合&宋体&黑体\\
+       \hline
+        Windows$^{(1)}$&SimSun&SimHei\\
+        Windows$^{(2)}$&方正书宋&方正粗宋简体\\
+        Mac OS X&STSong&STHeiti\\
+       \hline
+       \end{tabular}
+\end{center}
+%名称        SIL-Kai-Reg-Jian        全名  Kai Regular 
+%名称        SimSun-ExtB             全名  SimSun-ExtB 
+%名称        FangSong                全名  仿宋
+%名称        SimHei                  全名  黑体
+%名称        STHeitiSC-Medium        全名  黑体-简 中等
+%名称        STFangsong              全名  华文仿宋
+%名称        STHeiti                 全名  华文黑体
+%名称        STHupo                  全名  华文琥珀
+%名称        STKaiti                 全名  华文楷体
+%名称        STLiti                  全名  华文隶书
+%名称        STSong                  全名  华文宋体
+%名称        STXinwei                全名  华文新魏
+%名称        STXingkai               全名  华文行楷
+%名称        STZhongsong             全名  华文中宋
+\subsection{fontspec}
+在\LuaTeX-ja中,和\texttt{fontspec}共存的一个包为\texttt{luatexja-fontspec}。
+这个包自动加载\texttt{fontspec}和\texttt{luatexja}宏包。
+
+在\texttt{luatexja-fontspec},定义了如下七条命令,这些命令和\texttt{fontspec}的相关命令对比如下:
+\begin{center}
+       \begin{tabular}{ccccc}
+       \hline
+       日文字体&\verb+\jfontspec+&\verb+\setmainjfont+&\verb+\setsansjfont+&\verb+\newjfontfamily+\\
+       西文字体&\verb+\fontspec+&\verb+\setmainfont+&\verb+\setsansfont+&\verb+\newfontfamily+\\
+       \hline
+       日文字体&\verb+\newjfontface+&\verb+\defaultjfontfeatures+&\verb+\addjfontfeatures+&\\
+       西文字体&\verb+\newfontface+&\verb+\defaultfontfeatures+&\verb+\addfontfeatures+&\\
+       \hline
+       \end{tabular}
+\end{center}
+\section{\LuaTeX-ja参数设定}
+\LuaTeX-ja包含大量的参数,以控制排版细节。
+设定这些参数需要使用命令:\verb!\ltjsetparameter!和\verb!\ltjgetparameter!命令。
+\subsection{JAchar范围的设定}
+在设定\textbf{JAchar}之前,需要分配一个小于217的自然数。如:
+\begin{verbatim}
+\ltjdefcharrange{100}{"10000-"1FFFF,`漢}
+\end{verbatim}
+
+请注意这个设定是全局性的,不建议在文档正文中进行设定。
+
+在范围设定好了之后,需要进行\verb!jacharrange!的设定:
+\begin{verbatim}
+\ltjsetparameter{jacharrange={-1, +2, +3, -4, -5, +6, +7, +8}}
+\end{verbatim}
+
+这里定义了8个范围,在每个范围之前使用“+”或“-”进行设定,其中如果为$-$,则代表该范围为\textbf{ALchar},如果为$+$,则该范围视作\textbf{JAchar}。
+
+\LuaTeX-ja默认设定了8个范围,这些范围来源于下列数据:
+\begin{itemize}
+\item Unicode 6.0
+\item Adobe-Japan1-6与Unicode之间的映射\verb!Adobe-Japan1-UCS2!
+\item 八登崇之的up\TeX宏包:\verb!PXbase!
+\end{itemize}
+
+\begin{description}
+\item[范围 $\mathbf{8^J}$] ISO 8859-1(Latin-1补充)的上半部和JIS X 0208(日文基本字符集)的重叠部分,包含下列字符:
+\begin{multicols}{2}
+       \begin{itemize}
+       \def\ch#1#2{\item \char"#1\ (\texttt{U+00#1}, #2)}
+       \ch{A7}{Section Sign}
+       \ch{A8}{Diaeresis}
+       \ch{B0}{Degree sign}
+       \ch{B1}{Plus-minus sign}
+       \ch{B4}{Spacing acute}
+       \ch{B6}{Paragraph sign}
+       \ch{D7}{Multiplication sign}
+       \ch{F7}{Division Sign}
+       \end{itemize}
+\end{multicols}
+
+\item[范围 $\mathbf{1^A}$] 包含于Adobe-Japan1-6中的拉丁字符,此范围包含下列Unicode区域,但不包括上述提到过的范围8:
+\begin{multicols}{2}
+       \begin{itemize}
+       \item \texttt{U+0080}--\texttt{U+00FF}: 拉丁字母补充-1
+       \item \texttt{U+0100}--\texttt{U+017F}: 拉丁字母扩充-A
+       \item \texttt{U+0180}--\texttt{U+024F}: 拉丁字母扩充-B
+       \item \texttt{U+0250}--\texttt{U+02AF}: 国际音标扩充
+       \item \texttt{U+02B0}--\texttt{U+02FF}: 进格修饰符元
+       \item \texttt{U+0300}--\texttt{U+036F}: 组合音标附加符号
+       \item \texttt{U+1E00}--\texttt{U+1EFF}: 拉丁字母扩充附加
+       \end{itemize}
+\end{multicols}
+
+\item[范围 $\mathbf{2^J}$] 希腊文和西里尔字母,使用JIS X 0208的大部分日文字体包含这些字符:
+\begin{multicols}{2}
+       \begin{itemize}
+       \item \texttt{U+0370}--\texttt{U+03FF}: 希腊字母
+       \item \texttt{U+0400}--\texttt{U+04FF}: 西里尔字母 
+       \item \texttt{U+1F00}--\texttt{U+1FFF}: 希腊文扩充
+       \end{itemize}
+\end{multicols}
+
+\item[范围 $\mathbf{3^J}$] 标点以及杂项符号:
+\begin{multicols}{2}
+       \begin{itemize}
+       \item \texttt{U+2000}--\texttt{U+206F}: 一般标点符号
+       \item \texttt{U+2070}--\texttt{U+209F}: 上标及下标
+       \item \texttt{U+20A0}--\texttt{U+20CF}: 货币符号
+       \item \texttt{U+20D0}--\texttt{U+20FF}: 符号用组合附加符号
+       \item \texttt{U+2100}--\texttt{U+214F}: 类字母符号
+       \item \texttt{U+2150}--\texttt{U+218F}: 数字形式
+       \item \texttt{U+2190}--\texttt{U+21FF}: 箭头符号
+       \item \texttt{U+2200}--\texttt{U+22FF}: 数学运算符号
+       \item \texttt{U+2300}--\texttt{U+23FF}: 杂项技术符号
+       \item \texttt{U+2400}--\texttt{U+243F}: 控制图像
+       \item \texttt{U+2500}--\texttt{U+257F}: 制表符
+       \item \texttt{U+2580}--\texttt{U+259F}: 区块元素
+       \item \texttt{U+25A0}--\texttt{U+25FF}: 几何形状
+       \item \texttt{U+2600}--\texttt{U+26FF}: 杂项符号
+       \item \texttt{U+2700}--\texttt{U+27BF}: 什锦符号
+       \item \texttt{U+2900}--\texttt{U+297F}: 补充性箭头-B
+       \item \texttt{U+2980}--\texttt{U+29FF}: 混合数学符号-B
+       \item \texttt{U+2B00}--\texttt{U+2BFF}: 杂项符号和箭头符号
+       \item \texttt{U+E000}--\texttt{U+F8FF}: 私用区域
+       \end{itemize}
+\end{multicols}
+
+\item[范围 $\mathbf{4^A}$] 通常情况下不包含于日文字体的部分。本范围包含有其他范围尚未涵盖部分。故,我们直接给出定义:
+\begin{verbatim}
+\ltjdefcharrange{4}{%
+   "500-"10FF, "1200-"1DFF, "2440-"245F, "27C0-"28FF, "2A00-"2AFF, 
+  "2C00-"2E7F, "4DC0-"4DFF, "A4D0-"A82F, "A840-"ABFF, "FB50-"FE0F, 
+  "FE20-"FE2F, "FE70-"FEFF, "FB00-"FB4F, "10000-"1FFFF} % non-Japanese
+\end{verbatim}
+
+\item[范围 $\mathbf{5^A}$] 代替以及补充私有使用区域。
+\item[范围 $\mathbf{6^J}$] 日文字符。
+\begin{multicols}{2}
+       \begin{itemize}
+       \item \texttt{U+2460}--\texttt{U+24FF}: 圈状字母数字
+       \item \texttt{U+2E80}--\texttt{U+2EFF}: CJK部首补充
+       \item \texttt{U+3000}--\texttt{U+303F}: CJK标点符号
+       \item \texttt{U+3040}--\texttt{U+309F}: 平假名
+       \item \texttt{U+30A0}--\texttt{U+30FF}: 片假名
+       \item \texttt{U+3190}--\texttt{U+319F}: 汉文标注号
+       \item \texttt{U+31F0}--\texttt{U+31FF}: 片假名音标补充
+       \item \texttt{U+3200}--\texttt{U+32FF}: 圈状CJK字母及月份
+       \item \texttt{U+3300}--\texttt{U+33FF}: CJK兼容
+       \item \texttt{U+3400}--\texttt{U+4DBF}: CJK统一表意文字扩充A            \item \texttt{U+4E00}--\texttt{U+9FFF}: CJK统一表意文字
+       \item \texttt{U+F900}--\texttt{U+FAFF}: CJK兼容表意文字
+       \item \texttt{U+FE10}--\texttt{U+FE1F}: 直行标点
+       \item \texttt{U+FE30}--\texttt{U+FE4F}: CJK兼容形式
+       \item \texttt{U+FE50}--\texttt{U+FE6F}: 小写变体
+       \item \texttt{U+20000}--\texttt{U+2FFFF}: (补充字符)
+       \end{itemize}
+\end{multicols}
+
+\item[范围 $\mathbf{7^J}$] 不包含于Adobe-Japan1-6的CJK字符。
+\begin{multicols}{2}
+       \begin{itemize}
+       \item \texttt{U+1100}--\texttt{U+11FF}: 谚文字母
+       \item \texttt{U+2F00}--\texttt{U+2FDF}: 康熙部首
+       \item \texttt{U+2FF0}--\texttt{U+2FFF}: 汉字结构描述字符
+       \item \texttt{U+3100}--\texttt{U+312F}: 注音字母
+       \item \texttt{U+3130}--\texttt{U+318F}: 谚文兼容字母
+       \item \texttt{U+31A0}--\texttt{U+31BF}: 注音字母扩充
+       \item \texttt{U+31C0}--\texttt{U+31EF}: CJK笔划
+       \item \texttt{U+A000}--\texttt{U+A48F}: 彝文音节
+       \item \texttt{U+A490}--\texttt{U+A4CF}: 彝文字母
+       \item \texttt{U+A830}--\texttt{U+A83F}: 一般印度数字
+       \item \texttt{U+AC00}--\texttt{U+D7AF}: 谚文音节
+       \item \texttt{U+D7B0}--\texttt{U+D7FF}: 谚文字母扩充-B
+       \end{itemize}
+\end{multicols}
+\end{description}
+\subsection{\textsf{kanjiskip}和\textsf{xkanjiskip}}
+\textbf{JAglue}分为下列三类范畴:
+\begin{itemize}
+\item JFM设定的胶或出格值。如果在一个日文字符附近使用\verb!\inhibitglue!,则胶便不会插入。
+\item 两个\textbf{JAchar}之间默认插入的胶(\textsf{kanjiskip})
+\item \textbf{JAchar}和\textbf{ALchar}之间默认插入的胶(\textsf{xkanjiskip})
+\end{itemize}
+
+\textsf{kanjiskip}和\textsf{xkanjiskip}的设定如下所示:
+\begin{verbatim}
+\ltjsetparameter{kanjiskip={0pt plus 0.4pt minus 0.4pt},
+                 xkanjiskip={0.25\zw plus 1pt minus 1pt}}
+\end{verbatim}
+
+当JFM包含“\textsf{kanjiskip}理想宽度”和/或“\textsf{xkanjiskip}理想宽度”数据时,上述设定产生作用。如果想用JFM中的数据,请设定\textsf{kanjiskip}或\textsf{xkanjiskip}为\verb!\maxdimen!。
+\subsection{\textsc{xkanjiskip}插入设定}
+并不是在所有的\textbf{JAchar}和\textbf{ALchar}周围插入\textsf{xkanjiskip}都是合适的。
+比如,在开标点之后插入\textsf{xkanjiskip}并不合适[如,比较“(あ”和“(\hskip\ltjgetparameter{xkanjiskip}あ”]。
+\LuaTeX-ja可以通过设定\textbf{JAchar}的\textsf{jaxspmode}以及\textbf{ALchar}的\textsf{alxspmode}来控制\textsf{xkanjiskip}在字符前后的插入。
+
+\begin{LTXexample}[pos=r]
+\ltjsetparameter{jaxspmode={`あ,preonly}, alxspmode={`\!,postonly}}
+pあq い!う
+\end{LTXexample}
+
+第二个参数\textsf{preonly}表示的含义为“允许在该字符前插入\textsf{xkanjiskip},但不允许在该字符之后插入”。
+其他参数还有\textsf{postonly},\textsf{allow}和\textsf{inhibit}。[TODO]
+
+用户如果想开启/关闭\textsf{kanjiskip}和\textsf{xkanjiskip}的插入,设定\textsf{autospacing}和\textsf{autoxspacing}参数为\textsf{true}/\textsf{false}即可。
+\subsection{基线浮动}
+为了确保日文字体和西文字体能够对其,有时需要浮动其中一者的基线。
+在\pTeX中,此项设定由设定\verb!\yabaselineshift!为非零长度(西文字体基线应向下浮动)。
+不过,如果文档的中主要语言不是日文,那么最好上浮日文字体的基线,西文字体不变。
+如上所述,\LuaTeX-ja可以独立设定西文字体的基线(\textsf{yabaselineshift}参数)和日文字体的基线(\textsf{yjabaselineshift}参数)。
+
+\begin{LTXexample}[pos=r]
+\vrule width 150pt height 0.4pt depth 0pt\hskip-120pt
+\ltjsetparameter{yjabaselineshift=0pt, yalbaselineshift=0pt}abcあいう
+\ltjsetparameter{yjabaselineshift=5pt, yalbaselineshift=2pt}abcあいう
+\end{LTXexample}
+
+上述水平线为此行基线。
+
+这里还有一个有趣的副作用:不同大小的字符可以通过适当调整这两个参数而在一行中垂直居中。下面是一个例子(注意,参数值并没有精心调整):
+
+\begin{LTXexample}[pos=r]
+xyz漢字
+{\scriptsize
+  \ltjsetparameter{yjabaselineshift=-1pt,
+    yalbaselineshift=-1pt}
+  XYZひらがな
+}abcかな
+\end{LTXexample}
+\subsection{裁剪框标记}
+裁剪框标记是在一页的四角和水平/垂直中央放置的标记。在日文中,裁剪框被称为“トンボ”。
+\pLaTeX和\LuaTeX-ja均在底层支持裁剪框标记。需要下列步骤来实现:
+\begin{enumerate}
+\item 首先,首先定义页面左上角将会出现的注记。这由向\verb!@bannertoken!分配一个token列完成。\\
+例如,下列所示将会设定注记为“\textsf{filename (YYYY-MM-DD hh:mm)}”:
+
+\begin{verbatim}
+\makeatletter
+
+\hour\time \divide\hour by 60 \@tempcnta\hour \multiply\@tempcnta 60\relax
+\minute\time \advance\minute-\@tempcnta
+\@bannertoken{%
+   \jobname\space(\number\year-\two@digits\month-\two@digits\day
+   \space\two@digits\hour:\two@digits\minute)}%
+\end{verbatim}
+
+\item {[TODO]}
+\end{enumerate}
+\section{Lua\TeX-ja与Lua\TeX相关阅读材料}
+\begin{itemize}
+\item Lua\TeX官方主页:\verb!http://www.luatex.org!
+\item Lua\TeX\ SVN:\verb!http://foundry.supelec.fr/gf/project/luatex/!
+\item Lua\TeX:\verb!http://ja.wikipedia.org/wiki/LuaTeX!
+\item Lua\TeX-ja官方主页:\verb!http://en.sourceforge.jp/projects/luatex-ja/!
+\item p\TeX官方主页:\verb!http://ascii.asciimw.jp/pb/ptex/!
+\item Publishing \TeX:\verb!http://ja.wikipedia.org/wiki/PTeX!
+\item Vertical typesetting in \TeX:\verb!http://tug.org//TUGboat/Articles/tb11-3/tb29hamano.pdf!
+\item up\TeX官方主页:\verb!http://homepage3.nifty.com/ttk/comp/tex/uptex.html!
+\item “LuaTeX で日本語”:\verb!http://oku.edu.mie-u.ac.jp/tex/mod/forum/discuss.php?d=627!
+\item luajalayout宏包:\verb!http://www-is.amp.i.kyoto-u.ac.jp/lab/kmaeda/lualatex/luajalayout/!
+\item luafontcomp宏包:\verb!http://www-is.amp.i.kyoto-u.ac.jp/lab/kmaeda/lualatex/luafontcomp/!
+\item 思わずLuaでLaTeXしてみた:\verb!http://zrbabbler.sp.land.to/lualatexlua.html!
+\item luaums.sty:\verb!http://oku.edu.mie-u.ac.jp/tex/mod/forum/discuss.php?d=378!
+\item koTeXは日本語LuaTeXへの先導役になるか?:\\\verb!http://oku.edu.mie-u.ac.jp/tex/mod/forum/discuss.php?d=485!
+\end{itemize}
+\end{document}
index 3ebe54b..3752e26 100644 (file)
@@ -35,6 +35,7 @@ local attr_jchar_class = luatexbase.attributes['ltj@charclass']
 local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
 local attr_yablshift = luatexbase.attributes['ltj@yablshift']
 local attr_icflag = luatexbase.attributes['ltj@icflag']
+local attr_uniqid = luatexbase.attributes['ltj@uniqid']
 local cat_lp = luatexbase.catcodetables['latex-package']
 
 local ITALIC = 1
@@ -215,16 +216,17 @@ function debug_show_node_X(p,print_fn)
    local k = debug_depth
    local s
    local pt=node_type(p.id)
-   local base = debug_depth .. string.format('%X', has_attr(p,attr_icflag) or 0) 
-   .. ' ' .. pt .. ' ' ..  tostring(p.subtype )
+   local base = debug_depth .. string.format('%X', has_attr(p,attr_icflag) or 0)
+   .. ' ' .. string.format('%X', has_attr(p, attr_uniqid) or 0)
+   .. ' ' .. node.type(p.id) .. ' ' ..  tostring(p.subtype )
    if pt == 'glyph' then
       s = base .. ' ' .. utf.char(p.char) .. ' ' .. tostring(p.font)
          .. ' (' .. print_scaled(p.height) .. '+' 
          .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width)
       print_fn(s)
-   elseif pt=='hlist' then
+   elseif pt=='hlist' or pt=='vlist' then
       s = base .. '(' .. print_scaled(p.height) .. '+' 
-         .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width)
+         .. print_scaled(p.depth) .. ')x' .. print_scaled(p.width) .. p.dir
       if p.shift~=0 then
         s = s .. ', shifted ' .. print_scaled(p.shift)
       end
@@ -282,7 +284,11 @@ function debug_show_node_X(p,print_fn)
    elseif pt == 'whatsit' then
       s = base .. ' subtype: ' ..  tostring(p.subtype)
       if p.subtype==sid_user then
-        s = s .. ' user_id: ' .. p.user_id .. ' ' .. p.value
+         if p.type ~= 110 then 
+            s = s .. ' user_id: ' .. p.user_id .. ' ' .. p.value
+         else
+            s = s .. ' user_id: ' .. p.user_id .. ' (node list)'
+         end
       else
         s = s .. node.subtype(p.subtype)
       end
index dcc3fb4..1a66f0c 100644 (file)
 %%%%%%%% Attributes for Japanese typesetting.
 \newluatexattribute\ltj@curjfnt   % index for ``current Japanese font''
 \newluatexattribute\jfam          % index for current jfam
+\newluatexattribute\ltj@uniqid    % unique id of box/paragraph
 \newluatexattribute\ltj@charclass % 
 \newluatexattribute\ltj@yablshift % attribute for \yabaselineshift
 \newluatexattribute\ltj@ykblshift % attribute for \ykbaselineshift
 \newluatexattribute\ltj@autospc   % attribute for autospacing
 \newluatexattribute\ltj@autoxspc  % attribute for autoxspacing
 \newluatexattribute\ltj@icflag    % attribute for italic correction
-\newlanguage\ltj@japanese
 
 %%%%%%%% Loading lua files
 \directlua{%
index 720cfa9..a73fcdd 100644 (file)
@@ -3,8 +3,8 @@
 --
 luatexbase.provides_module({
   name = 'luatexja.jfmglue',
-  date = '2011/06/27',
-  version = '0.2',
+  date = '2012/04/02',
+  version = '0.3',
   description = 'Insertion process of JFM glues and kanjiskip',
 })
 module('luatexja.jfmglue', package.seeall)
@@ -29,6 +29,7 @@ local node_insert_before = node.insert_before
 local node_insert_after = node.insert_after
 local round = tex.round
 local table_insert = table.insert
+local uniq_id = 0 -- unique id 
 
 local id_glyph = node.id('glyph')
 local id_hlist = node.id('hlist')
@@ -45,9 +46,10 @@ local id_kern = node.id('kern')
 local id_penalty = node.id('penalty')
 
 local id_glue_spec = node.id('glue_spec')
-local id_jglyph = node.id('glyph') + 256
-local id_box_like = node.id('hlist') + 256
-local id_pbox = node.id('hlist') + 512
+local id_jglyph = node.id('glyph') + 256      -- Japanese character
+local id_box_like = node.id('hlist') + 256    -- vbox, shifted hbox
+local id_pbox = node.id('hlist') + 512        -- already processed nodes (by \unhbox)
+local id_pbox_w = node.id('hlist') + 513      -- cluster which consists of a whatsit
 local sid_user = node.subtype('user_defined')
 
 local ITALIC = 1
@@ -69,6 +71,7 @@ local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
 local attr_icflag = luatexbase.attributes['ltj@icflag']
 local attr_autospc = luatexbase.attributes['ltj@autospc']
 local attr_autoxspc = luatexbase.attributes['ltj@autoxspc']
+local attr_uniqid = luatexbase.attributes['ltj@uniqid']
 local max_dimen = 1073741823
 
 local ltjs_get_penalty_table = ltjs.get_penalty_table
@@ -90,7 +93,7 @@ local spec_zero_glue = node_new(id_glue_spec)
    spec_zero_glue.width = 0; spec_zero_glue.stretch_order = 0; spec_zero_glue.stretch = 0
    spec_zero_glue.shrink_order = 0; spec_zero_glue.shrink = 0
 
-local function get_zero_glue()
+local function get_zero_spec()
    return node_copy(spec_zero_glue)
 end
 
@@ -224,24 +227,57 @@ local function check_box(box_ptr, box_end)
    return found_visible_node
 end 
 
+function check_box_high(Nx, box_ptr, box_end)
+   first_char = nil;  last_char = nil;  find_first_char = true
+   if check_box(box_ptr, box_end) then
+      if first_char then
+         if first_char.font == has_attr(first_char, attr_curjfnt) then 
+            set_np_xspc_jachar(Nx, first_char)
+         else
+            set_np_xspc_alchar(Nx, first_char.char,first_char, ligature_head)
+         end
+      end
+   end
+   return last_char
+end
+
 -------------------- Np の計算と情報取得
+
+luatexbase.create_callback("luatexja.jfmglue.whatsit_getinfo", "data", 
+                           function (Np, lp, Nq, box_stack_level) 
+                              if Np.nuc then return Np 
+                              else 
+                                 return Np  -- your code
+                              end
+                           end)
+luatexbase.create_callback("luatexja.jfmglue.whatsit_after", "data", 
+                           function (stat, Nq, Np, box_stack_level) return false end)
+
 -- calc next Np
 local function set_attr_icflag_processed(p)
    local a = has_attr(p, attr_icflag) or 0
-   if a<=1 then set_attr(p, attr_icflag, PROCESSED) end
+   if a<= ITALIC then 
+      set_attr(p, attr_uniqid, uniq_id) 
+      set_attr(p, attr_icflag, PROCESSED) 
+   end
 end
 
 local function check_next_ickern()
    if lp.id == id_kern and has_attr(lp, attr_icflag)==ITALIC then
-      set_attr(lp, attr_icflag, IC_PROCESSED); Np.last = lp; lp = node_next(lp)
+      set_attr(lp, attr_icflag, IC_PROCESSED) 
+      set_attr(lp, attr_uniqid, uniq_id) 
+      Np.last = lp; lp = node_next(lp)
    else Np.last = Np.nuc end
 end
 
 local function calc_np_pbox()
+   local uid = has_attr(lp, attr_uniqid)
    Np.first = lp; Np.id = id_pbox
-   lpa = KINSOKU -- dummy
-   while lp~=last and lpa>=PACKED and lpa~=BOXBDD do
-      Np.nuc = lp; lp = node_next(lp); lpa = has_attr(lp, attr_icflag) or 0
+   lpa = KINSOKU -- dummy=
+   while lp~=last and lpa>=PACKED and lpa~=BOXBDD
+      and has_attr(lp, attr_uniqid) == uid do
+      Np.nuc = lp; set_attr(lp, attr_uniqid, uniq_id) 
+      lp = node_next(lp); lpa = has_attr(lp, attr_icflag) or 0
    end
    check_next_ickern()
 end
@@ -294,13 +330,23 @@ local calc_np_auxtable = {
                  Np.last = lp; Np.id = id_disc; lp = node_next(lp); return true
               end,
    [id_whatsit] = function() 
-                    if lp.subtype==sid_user and lp.user_id==30111 then
-                       local lq = node_next(lp)
-                       head = node_remove(head, lp); node_free(lp); lp = lq; ihb_flag = true
-                    else
-                       set_attr_icflag_processed(lp); lp = node_next(lp)
-                    end
-                    return false
+                 if lp.subtype==sid_user then
+             if lp.user_id==30111 then
+                local lq = node_next(lp)
+                head = node_remove(head, lp); node_free(lp); lp = lq; ihb_flag = true
+             else
+                set_attr_icflag_processed(lp)
+                luatexbase.call_callback("luatexja.jfmglue.whatsit_getinfo"
+                                        , Np, lp, Nq, box_stack_level)
+                lp = node_next(lp)
+                if Np.nuc then 
+                   Np.id = id_pbox_w; Np.first = Np.nuc; Np.last = Np.nuc; return true
+                end
+             end
+          else
+            set_attr_icflag_processed(lp)
+                 end
+                 return false
                  end,
    [id_math] = function()
                  Np.first = lp; Np.nuc = lp; 
@@ -356,10 +402,11 @@ local function calc_np()
    while lp ~= last do
       lpa = has_attr(lp, attr_icflag) or 0
       if lpa>=PACKED then
-        if lpa == BOXBDD then
-           local lq = node_next(lp)
-           head = node_remove(head, lp); node_free(lp); lp = lq
-        else calc_np_pbox(); return end -- id_pbox
+         if lpa == BOXBDD then
+            local lq = node_next(lp)
+            head = node_remove(head, lp); node_free(lp); lp = lq
+         else calc_np_pbox(); return 
+         end -- id_pbox
       elseif calc_np_auxtable[lp.id]() then return end
    end
    Np = nil; return
@@ -371,37 +418,37 @@ end
 --            "Np is not a character" otherwise.
 
 -- 和文文字のデータを取得
-local function set_np_xspc_jachar(x)
+function set_np_xspc_jachar(Nx, x)
    local z = ltjf_font_metric_table[x.font]
    local c = x.char
    local cls = ltjf_find_char_class(c, z)
    local m = ltjf_metrics[z.jfm]
    set_attr(x, attr_jchar_class, cls)
-   Np.class = cls
-   Np.char = c
-   Np.size= z.size
-   Np.met = m
-   Np.var = z.var
-   Np.pre = ltjs_get_penalty_table('pre', c, 0, box_stack_level)
-   Np.post = ltjs_get_penalty_table('post', c, 0, box_stack_level)
+   Nx.class = cls
+   Nx.char = c
+   Nx.size= z.size
+   Nx.met = m
+   Nx.var = z.var
+   Nx.pre = ltjs_get_penalty_table('pre', c, 0, box_stack_level)
+   Nx.post = ltjs_get_penalty_table('post', c, 0, box_stack_level)
    z = fast_find_char_class('lineend', m)
-   local y = m.size_cache[Np.size].char_type[Np.class]
+   local y = m.size_cache[Nx.size].char_type[Nx.class]
    if y.kern and y.kern[z] then 
-      Np.lend = y.kern[z]
+      Nx.lend = y.kern[z]
    else 
-      Np.lend = 0 
+      Nx.lend = 0 
    end
    y = ltjs_get_penalty_table('xsp', c, 3, box_stack_level)
-   Np.xspc_before = (y%2==1)
-   Np.xspc_after  = (y>=2)
-   Np.auto_kspc = (has_attr(x, attr_autospc)==1)
-   Np.auto_xspc = (has_attr(x, attr_autoxspc)==1)
+   Nx.xspc_before = (y%2==1)
+   Nx.xspc_after  = (y>=2)
+   Nx.auto_kspc = (has_attr(x, attr_autospc)==1)
+   Nx.auto_xspc = (has_attr(x, attr_autoxspc)==1)
 end
 
 -- 欧文文字のデータを取得
 local ligature_head = 1
 local ligature_tail = 2
-local function set_np_xspc_alchar(c,x, lig)
+function set_np_xspc_alchar(Nx, c,x, lig)
    if c~=-1 then
       if lig == ligature_head then
         while x.components and x.subtype and math.floor(x.subtype/2)%2==1 do
@@ -412,79 +459,47 @@ local function set_np_xspc_alchar(c,x, lig)
            x = node_tail(x.components); c = x.char
         end
       end
-      Np.pre = ltjs_get_penalty_table('pre', c, 0, box_stack_level)
-      Np.post = ltjs_get_penalty_table('post', c, 0, box_stack_level)
+      Nx.pre = ltjs_get_penalty_table('pre', c, 0, box_stack_level)
+      Nx.post = ltjs_get_penalty_table('post', c, 0, box_stack_level)
    else
-      Np.pre = 0; Np.post = 0
+      Nx.pre = 0; Nx.post = 0
    end
-   Np.met = nil
+   Nx.met = nil
    local y = ltjs_get_penalty_table('xsp', c, 3, box_stack_level)
-   Np.xspc_before = (y%2==1)
-   Np.xspc_after  = (y>=2)
-   Np.auto_xspc = (has_attr(x, attr_autoxspc)==1)
+   Nx.xspc_before = (y%2==1)
+   Nx.xspc_after  = (y>=2)
+   Nx.auto_xspc = (has_attr(x, attr_autoxspc)==1)
 end
 
 -- Np の情報取得メインルーチン
 local function extract_np()
-   local x = Np.nuc
-   if Np.id ==  id_jglyph then
-      set_np_xspc_jachar(x)
-   elseif Np.id == id_glyph then
-      set_np_xspc_alchar(x.char, x, ligature_head)
-   elseif Np.id == id_hlist then
-      find_first_char = true; first_char = nil; last_char = nil
-      if check_box(x.head, nil) then
-        if first_char then
-           if first_char.font == has_attr(first_char, attr_curjfnt) then 
-              set_np_xspc_jachar(first_char)
-           else
-              set_np_xspc_alchar(first_char.char,first_char, ligature_head)
-           end
-        end
-      end
-   elseif Np.id == id_pbox then --  mikann 
-      find_first_char = true; first_char = nil; last_char = nil
-      if check_box(Np.first, node_next(Np.last)) then
-        if first_char then
-           if first_char.font == has_attr(first_char, attr_curjfnt) then 
-              set_np_xspc_jachar(first_char)
-           else
-              set_np_xspc_alchar(first_char.char,first_char, ligature_head)
-           end
-        end
-      end
-   elseif Np.id == id_disc then 
-      find_first_char = true; first_char = nil; last_char = nil
-      if check_box(x.replace, nil) then
-        if first_char then
-           if first_char.font == has_attr(first_char, attr_curjfnt) then 
-              set_np_xspc_jachar(first_char)
-           else
-              set_np_xspc_alchar(first_char.char,first_char, ligature_head)
-           end
-        end
-      end
-   elseif Np.id == id_math then
-      set_np_xspc_alchar(-1, x)
+   local x = Np.nuc;
+   if Np.id ==  id_jglyph then set_np_xspc_jachar(Np, x)
+   elseif Np.id == id_glyph then set_np_xspc_alchar(Np, x.char, x, ligature_head)
+   elseif Np.id == id_hlist then Np.last_char = check_box_high(Np, x.head, nil)
+   elseif Np.id == id_pbox then Np.last_char = check_box_high(Np, Np.first, node.next(Np.last))
+   elseif Np.id == id_disc then Np.last_char = check_box_high(Np, x.replace, nil)
+   elseif Np.id == id_math then set_np_xspc_alchar(Np, -1, x)
    end
 end
 
 -- change the information for the next loop
--- (will be done if Np is an alphabetic character or a hlist)
-local function after_hlist()
-   if last_char then
-      if last_char.font == has_attr(last_char, attr_curjfnt) then 
-        set_np_xspc_jachar(last_char, ligature_tail)
+-- (will be done if Nx is an alphabetic character or a hlist)
+function after_hlist(Nx)
+   if Nx.last_char then
+      if Nx.last_char.font == has_attr(Nx.last_char, attr_curjfnt) then 
+         set_np_xspc_jachar(Nx, Nx.last_char);
       else
-        set_np_xspc_alchar(last_char.char,last_char, ligature_tail)
+         set_np_xspc_alchar(Nx, Nx.last_char.char,Nx.last_char, ligature_tail)
       end
    else
-      Np.pre = nil; Np.met = nil
+      Nx.pre = nil; Nx.met = nil
    end
 end
-local function after_alchar()
-   local x = Np.nuc
-   set_np_xspc_alchar(x.char,x, ligature_tail)
+
+local function after_alchar(Nx)
+   local x = Nx.nuc
+   set_np_xspc_alchar(Nx, x.char,x, ligature_tail)
 end
 
 
@@ -495,8 +510,9 @@ local function lineend_fix(g)
       Nq.lend = 0
    elseif Nq.lend~=0 then
       if not g then
-        g = node_new(id_kern); g.subtype = 1
-        g.kern = -Nq.lend; set_attr(g, attr_icflag, LINEEND)
+        g = node_new(id_kern); g.subtype = 1; g.kern = -Nq.lend;
+     set_attr(g, attr_icflag, LINEEND)
+     set_attr(g, attr_uniqid, uniq_id) 
       elseif g.id==id_kern then
         g.kern = g.kern - Nq.lend
       else
@@ -515,7 +531,9 @@ local function handle_penalty_normal(post, pre, g)
         if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
         p.penalty = a
         head = node_insert_before(head, Np.first, p)
-        table_insert(Bp, p); set_attr(p, attr_icflag, KINSOKU)
+     table_insert(Bp, p); 
+     set_attr(p, attr_icflag, KINSOKU)
+     set_attr(p, attr_uniqid, uniq_id) 
       end
    else for i, v in pairs(Bp) do add_penalty(v,a) end
    end
@@ -529,7 +547,9 @@ local function handle_penalty_always(post, pre, g)
         if a<-10000 then a = -10000 elseif a>10000 then a = 10000 end
         p.penalty = a
         head = node_insert_before(head, Np.first, p)
-        table_insert(Bp, p); set_attr(p, attr_icflag, KINSOKU)
+        table_insert(Bp, p)
+     set_attr(p, attr_icflag, KINSOKU)
+     set_attr(p, attr_uniqid, uniq_id) 
       end
    else for i, v in pairs(Bp) do add_penalty(v,a) end
    end
@@ -541,7 +561,9 @@ local function handle_penalty_suppress(post, pre, g)
       if g and g.id==id_glue then
         local p = node_new(id_penalty)
         p.penalty = 10000; head = node_insert_before(head, Np.first, p)
-        table_insert(Bp, p); set_attr(p, attr_icflag, KINSOKU)
+        table_insert(Bp, p); 
+     set_attr(p, attr_icflag, KINSOKU)
+     set_attr(p, attr_uniqid, uniq_id) 
       end
    else for i, v in pairs(Bp) do add_penalty(v,a) end
    end
@@ -564,7 +586,9 @@ local function new_jfm_glue(Nn, bc, ac)
       g = node_new(id_kern)
       g.subtype = 1; g.kern = z.kern[ac]
    end
-   if g then set_attr(g, attr_icflag, FROM_JFM) end
+   if g then 
+      set_attr(g, attr_icflag, FROM_JFM); set_attr(g, attr_uniqid, uniq_id) 
+   end
    return g
 end
 
@@ -573,6 +597,7 @@ local function real_insert(w, g)
    if w~=0 then
       local h = node_new(id_kern)
       set_attr(h, attr_icflag, LINE_END)
+      set_attr(h, attr_uniqid, uniq_id) 
       h.kern = w; h.subtype = 1
       head = node_insert_after(head, Nq.last, h)
    end
@@ -615,14 +640,15 @@ local function get_kanjiskip()
            end
         elseif ak then
            gx.width = ak[1]; gx.stretch = ak[2]; gx.shrink = ak[3]
-        else node_free(gx); gx = get_zero_glue() -- fallback
+        else node_free(gx); gx = get_zero_spec() -- fallback
         end
         g.spec = gx
       else g.spec=node_copy(kanji_skip); node_free(gx) end
    else
-      g.spec =  get_zero_glue(); node_free(gx)
+      g.spec =  get_zero_spec(); node_free(gx)
    end
    set_attr(g, attr_icflag, KANJI_SKIP)
+   set_attr(g, attr_uniqid, uniq_id) 
    return g
 end
 
@@ -694,14 +720,15 @@ local function get_xkanjiskip(Nn)
         local bk = get_xkanji_skip_from_jfm(Nn)
         if bk then
            gx.width = bk[1]; gx.stretch = bk[2]; gx.shrink = bk[3]
-        else node_free(gx); gx = get_zero_glue() -- fallback
+        else node_free(gx); gx = get_zero_spec() -- fallback
         end
         g.spec = gx
       else g.spec=node_copy(xkanji_skip) end
    else
-      g.spec = get_zero_glue()
+      g.spec = get_zero_spec()
    end
    set_attr(g, attr_icflag, XKANJI_SKIP)
+   set_attr(g, attr_uniqid, uniq_id) 
    return g
 end
 
@@ -728,7 +755,7 @@ end
 -- (anything) .. jachar
 local function handle_np_jachar()
    local g
-   if Nq.id==id_jglyph or (Nq.id==id_pbox and Nq.met) then 
+   if Nq.id==id_jglyph or ((Nq.id==id_pbox or Nq.id==id_pbox_w) and Nq.met) then 
       g = calc_ja_ja_glue() or get_kanjiskip() -- M->K
       g = lineend_fix(g)
       handle_penalty_normal(Nq.post, Np.pre, g); real_insert(Nq.lend, g)
@@ -773,7 +800,7 @@ end
 -- (anything) .. (和文文字で終わる hlist)
 local function handle_np_ja_hlist()
    local g
-   if Nq.id==id_jglyph or (Nq.id==id_pbox and Nq.met) then 
+   if Nq.id==id_jglyph or ((Nq.id==id_pbox or Nq.id == id_pbox_w) and Nq.met) then 
       g = get_OB_skip() or get_kanjiskip() -- O_B->K
       g = lineend_fix(g)
       handle_penalty_normal(Nq.post, 0, g); real_insert(Nq.lend, g)
@@ -853,6 +880,8 @@ end
 
 -- initialize
 local function init_var()
+   uniq_id = uniq_id +1
+   if uniq_id == 0x7FFFFFF then uniq_id = 0 end
    lp = head; Bp = {}; widow_Bp = {}; widow_Np = {first = nil}
    par_indented = false 
    box_stack_level = ltjp.box_stack_level
@@ -875,7 +904,7 @@ local function init_var()
                 or ((lp.id==id_hlist) and (lp.subtype==3))) do
         if (lp.id==id_hlist) and (lp.subtype==3) then par_indented = true end
         lp=node_next(lp) end
-      last=node.tail(head)
+     last=node.tail(head)
    else 
       -- the current list is the contents of a hbox:
       -- insert a sentinelEG
@@ -884,6 +913,15 @@ local function init_var()
    end
 end
 
+-- Nq が前側のクラスタとなることによる修正
+local function adjust_nq()
+   if Nq.id==id_glyph then after_alchar(Nq)
+   elseif Nq.id==id_hlist or Nq.id==id_pbox or Nq.id==id_disc then after_hlist(Nq)
+   elseif Nq.id == id_pbox_w then 
+      luatexbase.call_callback("luatexja.jfmglue.whatsit_after",
+                              false, Nq, Np, box_stack_level)
+   end
+end
 -------------------- 外部から呼ばれる関数
 
 -- main interface
@@ -892,29 +930,22 @@ function main(ahead, amode)
    head = ahead; mode = amode; init_var(); calc_np()
    if Np then 
       extract_np(); handle_list_head()
-      if Np.id==id_glyph then after_alchar()
-      elseif Np.id==id_hlist or Np.id==id_pbox or Np.id==id_disc then after_hlist()
-      end
    else
       if not mode then head = node_remove(head, last); node_free(last) end
       return head
    end
    calc_np()
    while Np do
-      extract_np()
-      -- 挿入部
+      extract_np(); adjust_nq()
+     -- 挿入部
       if Np.id == id_jglyph then 
-        handle_np_jachar()
+         handle_np_jachar()
       elseif Np.met then 
-        if Np.id==id_hlist then handle_np_ja_hlist()
-        else handle_np_jachar() end
+         if Np.id==id_hlist then handle_np_ja_hlist()
+         else handle_np_jachar() end
       elseif Nq.met then 
-        if Nq.id==id_hlist then handle_nq_ja_hlist()
-        else handle_nq_jachar() end
-      end
-      -- Np の後処理
-      if Np.id==id_glyph then after_alchar()
-      elseif Np.id==id_hlist or Np.id==id_pbox or Np.id==id_disc then after_hlist()
+         if Nq.id==id_hlist then handle_nq_ja_hlist()
+         else handle_nq_jachar() end
       end
       calc_np()
    end
index a668f0f..cfd5306 100644 (file)
@@ -34,6 +34,7 @@ local attr_jchar_class = luatexbase.attributes['ltj@charclass']
 local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
 local attr_yablshift = luatexbase.attributes['ltj@yablshift']
 local attr_icflag = luatexbase.attributes['ltj@icflag']
+local attr_uniqid = luatexbase.attributes['ltj@uniqid']
 
 local ltjf_font_metric_table = ltjf.font_metric_table
 
@@ -89,6 +90,7 @@ function capsule_glyph(p, dir, mode, met, class)
       box.glue_set = 0; box.glue_order = 0; box.head = h
       box.shift = y_shift; box.dir = dir or 'TLT'
       set_attr(box, attr_icflag, PACKED)
+      set_attr(box, attr_uniqid, has_attr(p, attr_uniqid) or 0)
       if q then
         head = node_insert_before(head, q, box)
       else
index 654ce27..5b679df 100644 (file)
Binary files a/test/test04-jfm.pdf and b/test/test04-jfm.pdf differ
index 16b68f6..1aa90e0 100644 (file)
 
 \setbox0=\hbox{\rmlh あ$a$さ$a$か}
 \dumplist0
+
+\head{その他: unhbox の連続}
+\setbox0=\hbox{\tenmin\setbox1=\hbox{)}\setbox2=\hbox{a}\unhbox1\unhbox2}
+\dumplist0
+
+\setbox3=\hbox{\tenmin\setbox1=\hbox{)}\setbox2=\hbox{a}\unhbox1\unhbox2}
+\setbox0=\hbox{\unhbox3}
+\dumplist0
+
 \end