%% gyoudori-ja.tex: gyoudoriパッケージのマニュアル（日本語版）
%% 組版：platex gyoudori-ja && platex gyoudori-ja && dvipdfmx gyoudori-ja
\documentclass[paper=a4,dvipdfmx]{jlreq}
\usepackage{amsmath}
\usepackage{url}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\usepackage[displaymath]{gyoudori}
\input{gyoudori-fig}

\newcommand\pkg[1]{\textsf{#1}}
\newcommand\opt[1]{\texttt{#1}}
\newcommand\env[1]{\texttt{#1}}
\newcommand\cs[1]{\texttt{\char`\\#1}}
\newcommand\meta[1]{$\langle$\textit{#1}$\rangle$}
% 命令名の記号と和文の間にも和欧文間のアキを入れる（pTeXの既定では入らない）
\ifdefined\xspcode
  \xspcode`\\=3 \xspcode`\{=1 \xspcode`\}=2 \xspcode`\*=3
  \xspcode`\$=3 \xspcode`\[=3
\fi
% 実例の枠
\newenvironment{demo}
  {\par\medskip\noindent
   \begin{minipage}{\linewidth}\hrule\smallskip}
  {\par\smallskip\hrule\end{minipage}\par\medskip}

\title{\pkg{gyoudori}パッケージ\\[.5ex]\large 行取り（行ドリ）の実現}
\author{木枝祐介}
\date{2026年10月26日\quad v20261026.0}

\begin{document}
\maketitle

\begin{abstract}
\pkg{gyoudori}は見出し・ディスプレイ数式・フロートを行取り（行ドリ）で配置し，
その前後の本文の行を基本版面の行位置からずらさないための\LaTeX{}パッケージである．
pLaTeX，upLaTeX，LuaLaTeX（LuaTeX-ja）で動く．このパッケージは横組用である．
英語版のマニュアル（\texttt{gyoudori-en.pdf}）もある．
\end{abstract}

\section{行取りとは何か}

\emph{行取り}（行ドリ）とは恣意的なレイアウトのひとつで，見出しのように本文と大きさの違う要素が行送り方向に占める領域を基本版面の何行分かとして決め，その後ろの本文の行を基本版面で決めた行の位置（行のグリッド）からずらさないようにする方法である．

行取りは日本語の書籍などの組版で，各ページの本文の行を行のグリッドにそろえて配置するよう指定されたときに用いられる．
このパッケージはそうした指定のもとで組版しなければならない場合のための道具である．

このパッケージは横組用である．縦組は考慮していない（縦組で試した結果は\ref{sec:limit}\nobreak 節に記す）．

\subsection{行取りの領域}

$n$行取りの領域の行送り方向の大きさはJLREQ（W3C『日本語組版処理の要件』）\S4.1.6の定義のとおり
\[
  \text{字の枠の高さ}\times n + \text{行間}\times(n-1)
  = \text{行送り}\times(n-1) + \text{字の枠の高さ}
\]
である．
つまり，$n$行分の行の位置のうち，1行目の字の枠の上端から$n$行目の字の枠の下端までの範囲である（図\nobreak\ref{fig:area}）．
見た目にはページ（段）の途中ではこの領域の前後に行間が加わり，ページ（段）の先頭では後ろにだけ行間が加わる．
図の行送りはベースライン（破線）どうしの間隔で示している．
このマニュアルでは行送りを測る基準点を仮にベースラインとしている（\ref{sec:pitch}\nobreak 節）．

\begin{figure}[htbp]
  \centering
  \GyFigArea{本文}{字の枠}{行間}{行送り}{3行取りの領域}{見出し}%
    {$3\times\text{字の枠}+2\times\text{行間}$}
  \caption{3行取りの領域と，その中央に置いた見出し（3行取り中央）}
  \label{fig:area}
\end{figure}

このパッケージは既定では内容を領域の中央に置く．位置の指定（\opt{t}，\opt{c}，\opt{b}）で，上寄せと下寄せに変えられる（図\nobreak\ref{fig:pos}）．
領域の中のどこに置くかは組版の指定によって異なり，JLREQも中央のほかの配置方法をあげている（\ref{sec:pos}\nobreak 節）．

\begin{figure}[htbp]
  \centering
  \GyFigPos{本文}{\opt{t}：上寄せ}{\opt{c}：中央（既定）}{\opt{b}：下寄せ}
  \caption{領域の中での位置}
  \label{fig:pos}
\end{figure}

\subsection{このパッケージでの寸法}
\label{sec:dims}

行送りには\cs{normalsize}の\cs{normalbaselineskip}を，字の枠の高さには\cs{normalsize}の「あ」の高さ$+$深さ（JFMの寸法）を使う．
文中で\cs{small}などに切り替えていても基準は本文の行のグリッドである（ディスプレイ数式と，\env{gyoudori}環境・\cs{gyoudoriarea}に\opt{local}をつけた場合を除く．
\ref{sec:env}\nobreak 節，\ref{sec:displaymath}\nobreak 節）．

字の枠の高さはJFMによって異なる．upLaTeX，LuaTeX-ja（\pkg{jlreq}を含む）の標準のJFMでは全角幅と同じ（正方形の字の枠）で，JLREQの定義と一致する．pLaTeXの標準のJFM（\texttt{jis}）では全角幅の0.952倍である．
このパッケージはJFMの字の枠に従うので，pLaTeXでは領域がJLREQの定義より全角幅の0.048倍だけ短くなる．

\subsection{行送りの基準点と\cs{baselineskip}}
\label{sec:pitch}

JLREQ（\S2.4.2の注）は行送りを「隣接する行同士の基準点から基準点までの距離」としているが，基準点そのものは定めていない．
基準点は処理系により異なるとしたうえで，横組では字の枠の天地中央とする例が多いと述べているが，その根拠は示されていない．
また，\LaTeX{}（\TeX{}）は行をベースラインで並べるので，天地中央を基準点とする考え方とは大きく異なる．

そこでこのマニュアルでは行送りの基準点を仮にベースラインとする．\LaTeX{}の既定の動作もこのパッケージの実装も，ベースラインを基準にしているからである．
つまり，行送りはベースラインどうしの間隔である．

\LaTeX{}の\cs{baselineskip}は隣接する行のベースラインの間隔である．
\TeX{}は前の行の深さと次の行の高さから，ベースラインの間隔が\cs{baselineskip}になるように行の間にグルーを入れる．
ただし，行の間が\cs{lineskiplimit}より狭くなるときは代わりに\cs{lineskip}を入れるので，間隔は\cs{baselineskip}より広がる．

このパッケージは本文の行送り$b$として\cs{normalsize}の\cs{normalbaselineskip}を使い（\cs{linespread}で変えた場合も反映される），ベースラインが$b$の間隔で並ぶ位置を本文の行の位置（行のグリッド）とみなす．
各行の字の枠はベースラインから上に「あ」の高さ$h$，下に深さ$d$の範囲である．
したがって$n$行取りの領域は1行目のベースラインの$h$上から$n$行目のベースラインの$d$下までで，大きさは$(n-1)b+h+d$である．
領域は1行目のベースラインが直前の行のベースラインから$b$の位置に来るように置き，
領域の後の行のベースラインが$n$行目のベースラインから$b$の位置に来るようにする（\ref{sec:place}\nobreak 節）．
ディスプレイ数式も式の1行目と最後の行のベースラインの中点を，領域の1行目と最後の行のベースラインの中点に合わせて置く（\ref{sec:math}\nobreak 節）．

同じ大きさの文字だけが並ぶ行どうしでは基準点をどこにとっても行送りの値は変わらない．
JLREQの関係（行送り$=$文字サイズ$+$行間）も領域の大きさの式も，基準点によらない．基準点の違いが効くのは大きな見出しのように文字の大きさが違う行を含むときで，ベースラインの間隔と天地中央の間隔は一致しなくなる．
このパッケージはそうした見出しなどを行取りの領域に収め，前後の本文の行をベースラインで行のグリッドにそろえる．

また，このパッケージの行間（行送り$-$字の枠の高さ）は字の枠が正方形のJFMではJLREQの行間（行送り$-$文字サイズ）と一致する．
pLaTeXの標準のJFMでは字の枠の高さが全角幅の0.952倍なので，JLREQの行間より全角幅の0.048倍だけ大きくなる．

\section{動作環境とインストール}

\begin{itemize}
\item pLaTeX，upLaTeX，またはLuaLaTeX$+$LuaTeX-ja（\pkg{ltjsarticle}，\pkg{jlreq}など）．
 横組のみを対象とする．
\item \LaTeX{} 2022-06-01以降（パッケージオプションにカーネルのkey-value機能\cs{DeclareKeys}，\cs{ProcessKeyOptions}を，環境の前後の処理に環境フック\cs{AddToHook}を使う）．
 ほかのパッケージは必要ない．
\end{itemize}

\texttt{gyoudori.sty}をTEXMFツリー（例えば\texttt{tex/latex/gyoudori/}）に置く．

\section{使い方}

\subsection{\env{gyoudori}環境}
\label{sec:env}

\begin{verbatim}
\begin{gyoudori}[<オプション>]{<行数>}
<内容>
\end{gyoudori}
\end{verbatim}
\meta{内容}を\meta{行数}行取りする．\meta{行数}は1以上の整数で，そうでなければエラーになる．\meta{オプション}には次のものをカンマで区切って指定する．
\begin{description}
\item[位置] \opt{t}（上寄せ），\opt{c}（中央．既定），\opt{b}（下寄せ）のいずれか．
\item[\opt{local}] 基準をその場の文字サイズにする（下記）．
\item[\opt{indent}，\opt{noindent}] \meta{内容}の段落を字下げするかしないか．
 既定はパッケージオプション\opt{indent}による（\ref{sec:indent}\nobreak 節．既定は字下げしない）．
\end{description}
\meta{内容}は垂直モードで組まれるので，複数行や文字サイズの変更を含められる．
\meta{内容}は字の枠で位置を決める．1行目のベースラインの上に\meta{内容}の最後の文字サイズの「あ」の高さ，最後の行のベースラインの下に「あ」の深さをとった範囲を，領域の中で位置の指定に従って置く．
このため，欧文だけの見出しも和文の見出しと同じ位置に置かれる．
\meta{内容}の字面が領域の外側の行間に半分を超えてはみ出すときは警告を出す（パッケージオプション\opt{overflow}でエラーにできる．\ref{sec:overflow}\nobreak 節）．

\opt{local}をつけると，\cs{normalsize}の行送りではなく，その場の文字サイズの「あ」の高さ・深さと\cs{baselineskip}を基準に行取りする．
\cs{small}などに切り替えた部分のなかで，まわりの行にそろえるときに使う（例：\verb|\begin{gyoudori}[b,local]{2}|）．
\opt{local}をつけないときは文字サイズによらず\cs{normalsize}の行送りが基準である．

\begin{demo}
本文の行である．前の段落の最後の行である．
\begin{gyoudori}{3}
\large 3行取り中央の見出し
\end{gyoudori}

本文の行である．
見出しの後の段落も行の位置からずれない．
\begin{gyoudori}[b]{2}
2行取り下寄せの見出し
\end{gyoudori}
空行を置かずに続けた本文は字下げされない．
\end{demo}

次は\cs{small}で組んだ部分のなかで\opt{local}をつけた例である．グレーの帯で\cs{small}の行のグリッドを示す．

\begin{demo}
\small\GyBands[local]{5}\cs{small}で組んだ本文の行である．
\begin{gyoudori}[local]{3}
\normalsize\bfseries 3行取り中央の見出し
\end{gyoudori}
続く本文の行も\cs{small}のグリッドにのる．
\end{demo}

\begin{itemize}
\item \verb|\end{gyoudori}|の直後に空行がなければ，後続の文は字下げせず\cs{parskip}も入れない（ディスプレイ数式の後と同じ扱い）．
 空行があれば，新しい段落として字下げし\cs{parskip}も入れる．
\item 領域は分割されない．ページ（段）の末尾に領域が入りきらなければ，見出し全体が次のページ（段）の先頭に送られる（JLREQ \S4.1.7のa，c）．
\item 見出しの直後では改ページ・改段しない．見出しの後ろに本文の行が1行も入らないときは見出し全体が次のページ（段）の先頭に送られる（JLREQ \S4.1.7のb）．
  いずれの場合も前のページ（段）の末尾は空いたままになる．
\end{itemize}

\subsection{\cs{gyoudoriarea}命令}

\begin{verbatim}
\gyoudoriarea[<オプション>]{<行数>}{<内容>}
\end{verbatim}
\env{gyoudori}環境と同じく行取りする．
\meta{オプション}も同じである．
命令なので，直後の字下げの制御はない．

\subsection{JLREQの配置方法との対応}
\label{sec:pos}

JLREQ \S4.1.6は行取りによる別行見出しの配置方法としてaからdをあげている．
このパッケージでは次のように書ける．
\begin{description}
\item[a　複数行の領域の中央] \verb|\begin{gyoudori}{3}|（3行取り中央）．
\item[b　中央に置き，前後に行単位の空きをとる] 行送りの整数倍の空きを組みあわせる．
  例えば前を1行アキにするなら，\verb|\vspace{\baselineskip}|の後に\env{gyoudori}環境を置く．
\item[c　領域の中の指定位置] 上寄せ（\opt{t}）と下寄せ（\opt{b}）を用意している．
  それ以外の位置は\meta{内容}の中に空きを入れて調整する．
\item[d　1行の見出しを行の位置に置き，前を1行アキ] 本文と同じ大きさの見出しを2行取り下寄せ（位置\opt{b}，行数2）にすると同じ配置になる．
\end{description}

\paragraph{見出しとしての行取りがページの先頭に来たとき}

見出しの行取りの領域もページ（段）の先頭では版面の天につき，領域の中の位置は位置の指定に従う（\ref{sec:edge}\nobreak 節）．
例えばdの「前を1行アキにした小見出し」（2行取り下寄せ）がページの先頭に来ると，1行目が空き見出しは2行目に来る．
これはJLREQ \S4.1.8の「常に1行アキにする」方針に対応する．

\subsection{ページの先頭・末尾での行取りの領域}
\label{sec:edge}

見出しに限らず，\env{gyoudori}環境，\cs{gyoudoriarea}，ディスプレイ数式の行取りの領域はページ送りの都合で偶然ページ（段）の先頭や末尾に来ることがある．
そのときの挙動は次のとおりである．
フロートの置き場所は\LaTeX{}が決めるのでここでは扱わない（\ref{sec:float}\nobreak 節）．

\paragraph{行取りの領域がページの先頭に来たとき}

領域そのものが版面の天につき（天ツキ），領域の前には行間が入らない．
領域の中の位置はページの途中と同じく位置の指定（\opt{t}，\opt{c}，\opt{b}）に従う（図\nobreak\ref{fig:top}）．
$n$行取りの次の行は$n+1$行目から始まる．
ディスプレイ数式も同じで，数式は領域の中でページの途中と同じ位置に置かれる．

\begin{figure}[htbp]
  \centering
  \GyFigTop{見出し}{ページの途中\\（\opt{c}）}{ページの先頭\\（\opt{t}）}%
    {ページの先頭\\（\opt{c}）}{ページの先頭\\（\opt{b}）}{版面の天}
  \caption{3行取りの領域がページの途中と先頭に来たとき（左の数字は行番号）}
  \label{fig:top}
\end{figure}

\paragraph{行取りの領域がページの末尾に来たとき}
領域は分割しない．
領域が版面の最終行までに収まればそのページに置き，収まらなければ領域全体を次のページ（段）の先頭に送る．
このとき前のページ（段）の末尾は入らなかった行数だけ空いたままになる．
\begin{itemize}
\item \env{gyoudori}環境と\cs{gyoudoriarea}は見出しとして使うことを想定して直後では
 改ページしない．
 領域が最終行で終わり，後ろに本文の行が1行も入らないときも領域全体を次のページ（段）に送る（\ref{sec:env}\nobreak 節）．
\item ディスプレイ数式の後では改ページしてよい．
 領域が最終行で終わればそのページに収まり，続く本文は次のページ（段）の1行目から始まる．
 複数行の数式も1つの領域なので，\cs{allowdisplaybreaks}を指定しても途中で改ページしない．
\end{itemize}

\section{パッケージオプション}

オプションはkey-value形式で指定する．真偽値のオプションはキーだけを書くと\opt{true}になる．
\begin{verbatim}
\usepackage[displaymath,float,textfloatsep=2\baselineskip]{gyoudori}
\end{verbatim}

\subsection{\opt{overflow=warning|error}}
\label{sec:overflow}

\env{gyoudori}環境・\cs{gyoudoriarea}の\meta{内容}が領域に収まらないとき（字面が領域の外側の行間に半分を超えてはみ出すとき）に，警告を出すか（\opt{warning}．既定），エラーにするか（\opt{error}）を指定する．行数は自動では増やさない．

\subsection{\opt{indent=true|false}}
\label{sec:indent}

\env{gyoudori}環境・\cs{gyoudoriarea}の\meta{内容}の段落を字下げするかを指定する．
既定は\opt{false}（字下げしない）である．
環境ごとに\opt{indent}，\opt{noindent}で変えられる（\ref{sec:env}\nobreak 節）．

\subsection{\opt{displaymath=true|false}}
\label{sec:displaymath}

ディスプレイ数式を自動的に行取りする．既定は\opt{false}である．

\paragraph{対象}

\env{equation}，\env{eqnarray}，\cs{[}と\cs{]}で囲む数式（\env{displaymath}環境）と，\pkg{amsmath}の\env{equation*}，\env{align}，\env{gather}，\env{multline}，\env{flalign}，\env{alignat}，およびそれぞれの\env{*}つきである．
\verb|$$|で囲む数式は対象外である．
式番号，\cs{label}，\cs{eqref}は，このオプションを使わないときと同じように使える．

\paragraph{行数}

数式が要する行数に1行を足した行数で行取りする．2行に満たなければ2行とする．
足す行数は\opt{displaymathextra}で変えられる（\ref{sec:displaymathextra}\nobreak 節）．
数式が要する行数とは，その行数の領域の外側の行間に半分まではみ出して数式が収まる最少の行数である．本文の行の字面が字の枠からはみ出すのと同じ扱いである．
例えば，1行で足りる式は2行取り，2行を要する式は3行取りになる．
式の上下には，合わせて1行分のアキが加わる．
数式の前後の\cs{abovedisplayskip}などは使わない．

\paragraph{位置}

数式はその1行目と最後の行のベースラインの中点を，領域の1行目と最後の行のベースラインの中点に合わせて置く．
1行の式は奇数行取りなら式のベースラインが中央の行のベースラインにのり，偶数行取りなら2つの行のベースラインの中間に来る．
式番号が下の行に付いた式など，上下が非対称でこの位置では収まらない式は収まる範囲に寄せて置く．

\paragraph{測り方}

\pkg{amsmath}が各行に入れる支柱（\cs{strut}）は「あ」の字の枠の大きさにして測るので，見えない支柱の深さで行数は増えない．
式の直前にhyperrefのリンクの着地点などが入ってもそれを1行と数えることはない．

\paragraph{行取りの基準}

その場の文字サイズの「あ」の高さ・深さと\cs{baselineskip}である．
\cs{normalsize}の本文では\cs{normalsize}の行送りと同じになり，脚注や\cs{small}で
組んだ解答などのなかではまわりの行送りにそろう．

\begin{demo}
\GyBands{8}本文の行である．次の式は行取りされる．
\begin{align}
  a &= b + c \\
  d &= e
\end{align}
式の後の本文もグリッドにのる．
\begin{gather*}
  x = y
\end{gather*}
本文の行である．
\end{demo}

グレーの帯で行のグリッド（各行の字の枠）を示す．この例では2行の\env{align}は3行取り，1行の\env{gather*}は2行取りの領域の中央に置かれ，その前後の本文はどれもグリッドにのっている．

分数や積分，総和を含む大きな数式も要する行数に1行を足した行数で行取りされる．

\begin{demo}
\GyBands{13}本文の行である．積分と総和の式である．
\begin{gather}
  \int_0^1 f(x)\,dx = \sum_{k=1}^{n} \frac{a_k}{k!}
\end{gather}
式の後の本文である．次は2行の式である．
\begin{align}
  S_n &= \sum_{k=1}^{n} k = \frac{n(n+1)}{2} \\
  I &= \int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}
\end{align}
続く本文である．場合分けの式である．
\begin{gather}
  f(x) =
  \begin{cases}
    \frac{x^2}{2} & (x \ge 0) \\
    -x & (x < 0)
  \end{cases}
\end{gather}
最後の本文の行である．
\end{demo}

この例では上から3行取り，5行取り，3行取りになっている．どの場合も次の本文はグリッドにのる．

次は\cs{small}で組んだ部分のなかの例である．グレーの帯で\cs{small}の行のグリッドを示す．

\begin{demo}
\small\GyBands[local]{6}\cs{small}で組んだ解答の行である．
\begin{gather*}
  \int_0^1 x^2\,dx = \frac{1}{3}
\end{gather*}
続く行も\cs{small}のグリッドにのる．
\begin{gather*}
  x = y
\end{gather*}
最後の行である．
\end{demo}

\subsection{\opt{displaymathextra=\meta{整数}}}
\label{sec:displaymathextra}

\opt{displaymath}で，ディスプレイ数式が要する行数に足す行数を指定する（0以上の整数）．
既定は1である．行取りの行数は「要する行数$+$この値」で，2行に満たなければ2行とする．
0にすると，数式が収まる最少の行数（2行以上）になり，式と前後の行の字の枠との間は行間の半分まで詰まることがある．2以上にすると，その分だけ式の上下のアキが広がる．
\begin{verbatim}
\usepackage[displaymath,displaymathextra=0]{gyoudori}
\end{verbatim}

\subsection{\opt{float=true|false}}
\label{sec:float}

フロートを行取りで配置する．既定は\opt{false}である．以下ではページ（段）の上に置かれたフロートを「上のフロート」，下に置かれたものを「下のフロート」，本文の途中（配置の指定\opt{h}の位置）に置かれたものを「本文中のフロート」と呼ぶ．
\begin{itemize}
\item フロートはそれが収まる最少の行数（1行以上）の行取りの領域の大きさにする．
\item 置き場所が決まったら，領域の中での位置を次のようにする．上のフロートは上寄せで，領域の上端を本文1行目の字の枠の上端にそろえる．
 下のフロートは下寄せで，領域の下端を本文の行の字の枠の下端にそろえる．
 本文中のフロートは中央で，前後の本文の行にそろえる．
\item フロートまわりの5つのアキ（\cs{floatsep}など．次節）は「行間$+$行送りの整数倍」のうち指定値以上で最小の値に丸め，伸縮をなくす．
 \cs{intextsep}はフロートの上下に入るので，行間を半分ずつ割り振った値になる．
\item フロートだけのページ（段）ではフロートを上寄せにし，最初のフロートの領域の上端を本文1行目の字の枠の上端にそろえる．
 フロートの間のアキ（\cs{@fpsep}）も同じように丸める．
\item 版面より高いフロートは\LaTeX{}と同じく警告を出して縮めて置く．
 その上端を行の位置にそろえるため，\LaTeX{}より少し（\ref{sec:float-impl}\nobreak 節の\cs{@fptop}の分）多く縮める．
\end{itemize}
これにより，フロートの前後で本文の行は行の位置からずれない．
\LaTeX{}は\opt{[h]}だけの指定を\opt{[ht]}に変える．
その場に置けずに上に回ったフロートは上寄せで組み直される．
本文中のフロートの直前では改段しない．

\subsection{\opt{floatsep}，\opt{textfloatsep}，\opt{intextsep}，
  \opt{dblfloatsep}，\opt{dbltextfloatsep}}

同名の長さを設定する．指定しなければ，クラスファイルの値を使う．
\opt{float=true}のときはこの値をもとに上記の丸めを行う．

\section{ほかのパッケージとの併用}

以下は\opt{float=true}のときの動作である．
\begin{description}
\item[\pkg{nidanfloat}] 段抜きのフロート（\env{figure*}）は上なら版面の上端に，
 下なら版面に入る最終行の字の枠の下端にそろえる．2段組の段ごとの下のフロートは段に入る最終行の字の枠の下端にそろえる．
 読み込み順は問わない．
\item[\pkg{stfloats}] 段抜きのフロートの上と下を同じようにそろえる．
\item[\pkg{flushend}] 最終ページでそろえた段の中のグルーを伸縮させず，行を行の位置に保つ．
 \opt{spread}，\opt{shrink}系のオプションは効かない．
 左右の段のつなぎ目の間隔は行送りの整数倍に切り上げる．
\item[\pkg{evenend}] （LuaLaTeX）最終ページでそろえた段のフロートを，上なら上寄せ，下なら下寄せにそろえる．
 段数の切り換えや最終ページで持ち越されて段の上に置かれる段内フロートも上寄せにそろえる．
\end{description}

\section{JLREQとの関係}

JLREQの行取りに関する記述と，このパッケージの動作を照合した．

\begin{description}
\item[行送りの基準点（\S2.4.2の注）] JLREQは基準点を定めていない．このパッケージは
  ベースラインを基準点とする（\ref{sec:pitch}\nobreak 節）．
\item[領域の大きさ（\S2.5.2，\S4.1.6）] 一致する．字の枠にはJFMの寸法を使うので，
  pLaTeXの標準のJFMでは正方形の字の枠を前提にした定義より全角幅の0.048倍だけ
  短くなる（\ref{sec:dims}\nobreak 節）．
\item[領域の中の配置（\S4.1.6のaからd）] aは既定の中央で，cは上寄せ・下寄せで
  対応する．bとdは組みあわせで実現する（\ref{sec:pos}\nobreak 節）．
\item[ページ末・段末の見出し（\S4.1.7）] 一致する．領域が入りきらないときと，
  見出しの後ろに本文の行が1行も入らないときは見出し全体を次のページ（段）の先頭に
  送る．縦組の偶数ページの例外は横組のみが対象なので扱わない．
\item[ページ先頭の見出し（\S4.1.6，\S4.1.8）] 一致する．領域は版面の天につき，
  その後ろにだけ行間が加わる（\S4.1.6）．前を1行アキにした小見出しでは
  \S4.1.8の3つの方針のうち「常に1行アキにする」に対応する（\ref{sec:pos}\nobreak 節）．
\item[段の末尾の空き（\S4.1.7のc）] JLREQは段末を空けないための何らかの処理を
  望ましいとしつつ，やむを得ない場合は空けてよいとしている．このパッケージは
  空けたままにする．
\item[別行の数式（\S4.1.6のNote）] JLREQは文字サイズより大きい別行の数式について，
  行取りで指定する方法と，前後に最低の行間をとって半端を版面の中で調整する方法を
  あげている．\opt{displaymath}は前者である．数式が要する行数に1行を足すこと
  （\opt{displaymathextra}で変えられる）と，最少2行とすることはこのパッケージの
  設計である．
\item[図版（\S2.5.2，\S4.3）] JLREQは図版などの行送り方向の占める領域も基本版面の
  行の位置にそろえるべきだとしている．\opt{float}はこれに従う．図版の前後に
  本文が1行だけ来る配置を避けること（\S4.3）は\LaTeX{}のフロート配置に任せて
  おり，扱わない．
\end{description}

\section{仕組み}

\subsection{記号}

$b$：行送り（\cs{normalsize}の\cs{normalbaselineskip}），
$h$，$d$：\cs{normalsize}の「あ」の高さと深さ（字の枠），
$g=b-h-d$：行間，
$A(n)=(n-1)b+h+d$：$n$行取りの領域の高さ，
$t_1$：版面（段）の上端から本文1行目のベースラインまで（\cs{topskip}と$h$の大きいほう．
\TeX{}は1行目の高さが\cs{topskip}より大きいと，ベースラインを行の高さの位置に置く）．

特定のクラスの設定は前提にしていない．クラスについて前提にしているのは次のことだけである．
\begin{itemize}
\item 本文の行送りが，\cs{normalsize}を実行したときの\cs{normalbaselineskip}になる
  こと（文字サイズを\cs{fontsize}や\cs{@setfontsize}で定める通常の定義ならそうなる）．
\item 本文の行の高さ・深さが「あ」の高さ・深さ（JFMの字の枠）であること．
\item 本文の段落の間の\cs{parskip}が0であること（0でなければ，このパッケージによらず
  段落ごとに行の位置がずれる）．
\end{itemize}
版面の高さ（\cs{textheight}）が行送りの整数倍にそろっている必要はない．\cs{topskip}，
\cs{maxdepth}，フロートまわりのアキはクラスの値をそのまま使う（アキは丸める）．

\subsection{行取りの領域の置き方}
\label{sec:place}

内容を高さ$A(n)$の\cs{vbox}に組み，その高さを$h$に，深さを0につけ替える（中身は
下にはみ出して描かれる）．段落を閉じてから，この箱，行送りの$n-1$倍のカーン，
高さ0・深さ$d$の空の箱を続けて置く．\TeX{}は直前の行のベースラインから$b$の位置に
箱のベースライン（領域の1行目のベースライン）が来るように\cs{baselineskip}の
グルーを入れる．空の箱が領域の最後の行にあたるので，次の行はそのベースラインから
$b$の位置，つまり$n+1$行目に来る．ページ（段）の先頭では\cs{topskip}によって
領域の上端が1行目の字の枠の上端につく．3つの要素の間では改ページできず，
ページ分割の上では$n$行の本文の行と同じに扱われる．この置き方は阿部紀行氏のアルゴリズム
（\url{https://abenori.blogspot.com/2017/12/gyodori.html}）を参考にし，改良を加えたもので
ある．阿部氏のアルゴリズムは領域を深さの大きい1つの箱で表すが，深さが\cs{maxdepth}を
超える箱はページ分割で最終行の下にはみ出すことがあるので，3つの要素に分けた．

\env{gyoudori}環境と\cs{gyoudoriarea}では\meta{内容}の箱の先頭に\cs{penalty}$-10000$を
置き，ディスプレイ数式と同じ方法（\ref{sec:math}\nobreak 節）で1行目と最後の行の
ベースラインの距離$\Delta$を求める．\meta{内容}の最後の文字サイズの「あ」の高さ・深さを
$h_c$，$d_c$とし，字の枠の範囲（高さ$\Delta+h_c+d_c$）を位置に応じて領域の上端・中央・
下端にそろえる．
\opt{local}をつけたときは$h$，$d$，$b$にその場の「あ」の高さ・深さと\cs{baselineskip}を
使う．

\env{gyoudori}環境と\cs{gyoudoriarea}は置いた直後に\cs{nobreak}を入れて，見出しの
直後での改ページを禁じる．\env{gyoudori}環境と数式の環境の後では\LaTeX{}の
\cs{@doendpe}と同じ仕組みで，空行がなければ次の段落を字下げせず，\cs{parskip}も0に
する．

\subsection{ディスプレイ数式}
\label{sec:math}

$h$，$d$，$b$にはその場の「あ」の高さ・深さと\cs{baselineskip}を使う．
\begin{enumerate}
\item 環境フック（\texttt{env/<環境名>/before}と\texttt{after}）で，環境の外側に
  \cs{vbox}を開き，その中で\cs{abovedisplayskip}などを0にして数式を組む．
  箱の中では\cs{strutbox}を「あ」の字の枠の大きさにし（\pkg{amsmath}の各行の支柱），
  \cs{predisplaypenalty}を$-10000$にする．
\item \TeX{}は式の直前に\cs{predisplaypenalty}を入れるので，そこで\cs{vsplit}して，
  式の前の部分（式の前に段落ができたときの行など）と式の部分に分ける．以下では
  式の部分だけを測る．式の前の部分は最後に高さ0の箱にして式の先頭に重ねて残す．
\item 式の部分の先頭に\cs{penalty}$-10000$を置いた複製を，\cs{splittopskip}を十分大きな
  値$S$にして\cs{vsplit}すると，残りの先頭に「$S-{}$1行目の高さ」のグルーが入る．
  そこで「残りの高さ$-S$」が，数式の1行目と最後の行のベースラインの距離$\Delta$になる．
\item 数式の箱の高さを$H$，深さを$D$とすると，最後の行のベースラインは箱の上端から
  $H$，1行目は$H-\Delta$の位置にある．領域の上端から箱の上端までの距離を
  \[ y = h + \frac{(n-1)b}{2} - H + \frac{\Delta}{2} \]
  とすると，数式のベースラインの中点が領域のベースラインの中点にそろう．
\item $k=1$から順に増やし，$H+D\le A(k)+g$となる最小の$k$（数式が要する行数．箱は
  領域の外側の行間に半分まではみ出してよい）を求め，$n=k+e$とする．$e$は
  \opt{displaymathextra}の値（既定は1）で，$n<2$なら$n=2$とする．$y$が$-g/2$より小さければ$-g/2$に，
  $A(n)+g/2-H-D$より大きければその値にして，箱を収まる範囲に寄せる．
\item 箱を領域の中で$y$だけ下げて，\ref{sec:place}\nobreak 節と同じ方法で置く．
\end{enumerate}

\subsection{フロート}
\label{sec:float-impl}

\begin{description}
\item[大きさ] \cs{@endfloatbox}の後で，フロートの箱を，高さ$+$深さ$\le A(n)$となる
  最小の$n$（1以上）の高さ$A(n)$の\cs{vbox}に組み直す（中身は上寄せ）．
\item[組み直し] 置き場所が決まったら，箱の外形（高さと深さ）を保ったまま，中身を
  位置$p$（\opt{t}，\opt{c}，\opt{b}）に置き直し，さらに$\delta$だけ下げる．
  外形を変えないので\LaTeX{}のフロート配置の計算は変わらず，段抜きフロートの印
  （深さ1\,sp）も保たれる．\cs{@endfloatbox}を通らずに積まれた箱（\cs{twocolumn}の
  段抜きの表題など）は中身を取り出せないので組み直さない．
\item[上のフロート（\cs{@cflt}）] $p=\opt{t}$，$\delta=t_1-h$．領域の上端が
  本文1行目の字の枠の上端に来る．
\item[下のフロート（\cs{@cflb}）] $p=\opt{b}$，$\delta=d-d_{\mathrm{last}}$．
  $d_{\mathrm{last}}$は段の最後の箱の深さである（段の箱の深さは\cs{maxdepth}で
  打ち切られていることがあるので，最後の箱を取り出して測る）．フロートの並びの末尾には高さ0・深さ$d$の空の行と，
  「$r-d$」のグルーを置く．$r$は「段の高さ$-t_1$」を$b$で割った余りである．
  こうすると，\cs{clearpage}の\cs{vfil}で押し下げられたときも並びの下端が段に入る
  最終行の字の枠の下端にそろい，字の枠の下端が版面からはみ出すクラスでも
  Overfullにならない．押し下げられた場合（段の末尾がグルー）は$\delta=0$とし，
  \cs{@textbottom}の伸びを打ち消す．
\item[本文中のフロート（\cs{@addtocurcol}）] $p=\opt{c}$，
  $\delta=g/2+d-d_{\mathrm{prev}}$．$d_{\mathrm{prev}}$は直前の行の深さ（\cs{@pagedp}）
  である．フロートの直前には\cs{nobreak}を入れさせ，段の先頭に来ないようにする．
\item[アキの丸め] 各アキを，$g+kb$（$k$は0以上の整数）のうち指定値以上で最小の値に
  し，伸縮をなくす．\cs{intextsep}はフロートの上下に入るので$g/2+kb$とする．
  こうすると「フロートの領域$+$アキ」が行送りの整数倍になり，本文の行がずれない．
\item[フロートだけのページ] \cs{@fptop}を$t_1-h$（伸縮なし）にし，
  \cs{@fpsep}をほかのアキと同じく丸め，\cs{@fpbot}に伸びを残す．フロートを積む
  \cs{@wtryfc}で中身を上寄せに組み直す（本文中のフロートとして試したときの組み方が
  残っているため）．収まるかの判定（\cs{@xtryfc}）は\cs{@fptop}を数えないので，判定の
  間だけ段の高さから差し引く．\LaTeX{}は版面より高いフロートを版面の高さに縮める
  （\cs{@largefloatcheck}）が，この判定と合わせて\cs{@fptop}の分も縮め，警告を出す．
  段抜きのフロートだけのページも同じである．
\item[脚注の積み順] pLaTeXの\cs{@makecol}はフロートの後に脚注を積むので，$r$を
  求めるときに脚注の高さを段の高さから引く．\LaTeX{} 2025-06-01以降の
  \cs{@makecol}（LuaLaTeXなど）は脚注の後にフロートを積むので，下のフロートがある
  段では脚注の前に\cs{vfil}を入れ，脚注と下のフロートを版面の下端に置く．
\end{description}

\subsection{ほかのパッケージとの接続}

\begin{description}
\item[段抜きのフロート（\cs{@comdblflelt}）] \cs{@dbltoplist}にあれば上の並びで，
  $p=\opt{t}$，$\delta=t_1-h$である．なければ下の並び（\pkg{nidanfloat}，
  \pkg{stfloats}）で，$p=\opt{b}$，$\delta=d-r$（$r$は「$\cs{textheight}-t_1$」
  を$b$で割った余り）とし，並びの先頭に\cs{vfil}を置く．
\item[\pkg{nidanfloat}] 段ごとの上のフロートは\cs{@cflt}と同じである．下のフロートは
  \cs{L@cflb}，\cs{R@cflb}を置き換え，並びを段に入る最終行の字の枠の下端にそろえ，
  伸びは本文とフロートの間に置く．
\item[\pkg{flushend}] 最終ページの段を組み上げた後，段の中のグルーを伸縮させずに
  組み直す（末尾にfill次のグルー）．左右の段のつなぎ目（\cs{atColsBreak}）では
  左段の最後の要素のベースラインから右段の最初の要素のベースラインまでを，$b$の
  整数倍に切り上げる．フロートの箱では中身のずらし量$\delta$も考慮する．
\item[\pkg{evenend}] 最終ページの段内フロートの複製をとる前に，上のフロートを
  \opt{t}に，下のフロートを\opt{b}に組み直す．持ち越された段内フロートはevenendが
  段に入れる前に呼ぶフック\texttt{evenend/deferredfloat}で，上のフロートと同じく
  組み直す．
\end{description}

\section{制限事項}
\label{sec:limit}

\begin{itemize}
\item フロートの行取りは\cs{normalsize}の行送りが基準である．
 \env{gyoudori}環境と\cs{gyoudoriarea}も\opt{local}をつけなければ同じである（\ref{sec:env}\nobreak 節）．
\item 箇条書きの\cs{topsep}，\cs{itemsep}，\cs{parsep}は行送りの整数倍ではないので，
 箇条書きの中や前後では行の位置がずれる．
\item 縦組は考慮していない．ただし試した範囲（pLaTeXの\pkg{tarticle}と\pkg{jlreq}の\opt{tate}，LuaLaTeXの\pkg{ltjtarticle}）では\env{gyoudori}環境，ディスプレイ数式，
 フロートの行取りは横組と同じように働き，前後の本文の行は行のグリッドにのる．
 縦組では行が右から左へ進むので，位置の\opt{t}は右寄せ，\opt{b}は左寄せになり，
 ページの先頭に来た領域は版面の右端につく．JLREQ \S4.1.7の縦組の偶数ページの例外は扱わない．縦組での2段組や，ほかのパッケージとの併用は試していない．
\item \cs{flushbottom}の文書，\pkg{float}パッケージの\opt{[H]}との組みあわせは試していない．
\item \pkg{flushend}と脚注と，最終ページの下のフロートまたは本文中のフロートが重なると，本文が1\,pt前後ずれることがある．
\item \pkg{stfloats}の\cs{fnbelowfloat}はpLaTeXでは効かない（pLaTeXは独自の\cs{@makecol}を使うため）．
\item \verb|$$|で囲んだディスプレイ数式は行取りしない．
\item 既知の未対応事項：\pkg{nidanfloat}は左の段からあふれた本文を右の段につなぐとき，
 左の段の最後の行の深さを考えずに行間を入れるので，右の段の行が「あ」の深さだけずれることがある．ページの組み方によって起きたり起きなかったりする．
\item 既知の未対応事項：pLaTeXで\opt{float}，\pkg{nidanfloat}，脚注を一緒に使うと，段組のページの出力でOverfullが出ることがある．
\end{itemize}

\section{参考文献}

\begin{itemize}
\item W3C, \textit{Requirements for Japanese Text Layout}（日本語組版処理の要件），\url{https://www.w3.org/TR/jlreq/}
\item 阿部紀行「行取り」，\url{https://abenori.blogspot.com/2017/12/gyodori.html}
\end{itemize}

\section{ライセンス}

MITライセンスである．

\end{document}
