XSL-FOでの日本語組版用チューニング
前置き
『日本語組版処理の要件』[1]が現場で適用するレイアウトルールと誤解されがち、みたいな話があります[2]。本記事は、「日本語組版をするならこうしなければ」という話ではありません。飽く迄、「なんか言語化できないけれど、組版が好い感じにならないな」というときに、「こうしてみると好いんじゃない?」というフワっとした話です。
<fo:root>
)
基本テキスト設定(先ず、主に利用するテキスト設定については<fo:root>
で行うのが好いです。
テキスト周りのプロパティは指定が無いとき継承されるものが殆どです。そしてFOのルート要素である<fo:root>
に指定されていればちぐはぐな設定を減らせます。継承というのは、同名プロパティの直接的な話に限りません。例えば、@font-size
を基に決定される相対的な値としてemがあります。<fo:region-after>
の@extent
にem単位で指定をして、<fo:page-sequence>
で指定したfont-sizeでの適用を期待したりすると想定外の長さになってしまうかもしれません[3]。
好みやフォントにもよりますが、日本語メインのテキストでは欧文よりもline-heightを大きめに取ると好いでしょう(欧文1.3程度の箇所では日本語は1.4や1.5にするとか)。欧文の場合文字の高さは仮想ボディの最大まで来るとは限りませんが、CJKの文字は高さいっぱいまで来ることが殆どなので、行間の境界での文字の濃さが違います。
<fo:root>
で言語(@xml:lang
または個別プロパティ)を明示しましょう。多言語組版を行う場合でも、「メインとなる言語は何か」は存在します。大抵は。
<!-- ex -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xml:lang="ja"
font-family="SourceCodePro, Noto Sans CJK JP, sans-serif"
font-size="9pt"
line-height="1.5"
line-height.conditionality="discard">
...
</fo:root>
line-height.conditionality="discard"
については後述。
<fo:region-body>
) 2023-02-24修正
基本版面 (
版面を文字基準で設定すると、@text-align
が左揃えであっても改行のときに端がガタガタ(ragged)になり辛くなります。両端揃えでも、字間が調整されて大きくなる可能性を減らせます。
XSL-FOの場合、4隅のmarginによって版面が決定する関係上、調整は一手間です。XSL-FO処理系に計算式の状態でstringを渡せばよいので、色々な方法があるでしょう、
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
>
<!-- 文字数、行数を基にした版面の計算例 -->
<!--ページサイズ -->
<xsl:variable name="page-height" as="xs:string" select="'192mm'"/>
<xsl:variable name="page-width" as="xs:string" select="'167mm'"/>
<!-- 文字サイズ、line-height -->
<xsl:variable name="main-text-font-size.length" as="xs:string" select="'9pt'"/>
<xsl:variable name="main-text-line-height.length" as="xs:string" select="'1.4 * $main-text-font-size.length'" />
<!-- 行あたりの文字数、ページあたりの行数 -->
<xsl:variable name="main-text-cjkchar-num-per-line" as="xs:integer" select="30"/>
<xsl:variable name="main-text-line-nums-per-page" as="xs:integer" select="30"/>
...
<!-- 行幅計算は文字サイズ * 行あたりの文字数 -->
<xsl:variable name="main-text-width"
select="$main-text-font-size.length || ' * ' || string($main-text-cjkchar-num-per-line")" as="xs:string"/>
<xsl:variable name="main-text-height" as="xs:string"
select="(: 行数にline-heightの長さを掛ける :)
string($main-text-line-nums-per-page) || '*' || $main-text-line-height.length || (: line-heightとfont-sizeの差分を加える :) ' + (' || $main-text-line-height || ' - ' || $main-text-font-size.length || ')'"/>
...
<xsl:variable name="page-margin-start-end" as="xs:string"
select="$page-width || '- (' || $main-text-width ||')'"
/>
<xsl:variable name="page-margin-before-end" as="xs:string"
select="$page-height || '- (' || $main-text-height || ')'"/>
<xsl:template ...>
...
<!-- 求めた値をmargin-*に入れるが、実際のところ片側を決めないと反対側が決まらない-->
<fo:region-body ...
margin-top="..."
margin-end="..."
margin-left="..."
margin-right="..."/>
...
</xsl:template>
...
</xsl:stylesheet>
実はハーフレーディングとかの理解が怪しいので、計算式合っているかちょっと自信ないです。
ブロックレベル・インラインレベル (公開時点から編集有)
『XSL-FO の基礎 第2版』「10–3–3 ページや段の先頭行の前と最終行の後の空き量を無くす方法」がズバリの内容です。
-
@line-height.conditionality
にdiscard
を設定しましょう。
ざっくりいうと、ブロックで最初の行の上のアキ・最後の行の下のアキを除くための設定です。つまり、基本版面が本文だけで埋まる場合、版面のギリギリまで本文が表示されるようにします。
段落中の文が同じサイズのテキストで構成されることが保証される場合、@line-stacking-strategy
にfont-height
を指定するとページ上下のアキがほぼ無くせます。
処理系が言語を見てよしなにしてくれない場合、dominant-baseline
を設定しましょう。フォントの混在などを行う場合、フォント自体が小さい文字が基準から浮いて見えてしまったりします。日本語文書の場合は@dominant-baseline
はcentral
かideographic
が好い場合が多いでしょう。
!
?
後の全角スペース(U+3000)を改行時行頭に出したくない場合
方法としては2つ考えてみました。
-
!
?
で終わる文を<fo:inline>
に入れ、@space-end``space-end.conditionality
を設定する -
!
?
後の全角スペースをfo:character
として、-
@treat-as-word-space
をtrue
-
@whitespace-treatment
をignore-if-after-linefeed
-
全角空白自体を存在として保持するかどうか、あたりが判断基準でしょうか。
参考
- Extensible Stylesheet Language (XSL) Version 1.1
W3C Recommendation 05 December 2006 https://www.w3.org/TR/xsl11/ - XSL-FO の基礎 第2版 - XML を組版するためのレイアウト仕様 https://www.antenna.co.jp/AHF/ahf_publication/index.html#fo-basis
- XSL-FO による書籍の自動組版 https://www.antenna.co.jp/ml/back/OOXMLBK/OOXMLBK.html
Discussion