tableを本文領域いっぱいに広げる table/@pgwide="1"

久しぶりに自分でオーサリングして、自分でスタイルシートインプリメントしてという仕事をやっていたのですが、自分が作ったプラグインにもかかわらず、table/@pgwide="1"としても幅の小さなものは本文領域幅いっぱいに広まってくれません.何故かスタイルシートを見ていたのですが、やっていることはfo:tableの@strart-ondent="0mm"としているだけでした.これは実はDITAの仕様には沿っているのですが、テーブルの幅を広げられる保証はありません.

3.2.3.1 <table>

"For print-oriented display, the value "1" places the element on the left page margin; "0" aligns the element with the left margin of the current text line and takes indention into account."

実はDITAのtableはOASISのCALSテーブルとほぼ同じです.というよりそれを使っています.

3.2.3 Table elements

The <table> element uses the OASIS Exchange Table Model (formerly known as the CALS table model). 
 
では元のCALSテーブルの仕様はどうなっているかというと、本文領域(ページ幅から左右マージンを取ったもの)に広がることが明記されています.
 
XML Exchange Table Model Document Type Definition
3.1.2.4. pgwide — make table span full page width

  
If non-zero, the table spans the width of the entire page (possibly causing any previous multicolumn text on the page to be balanced and any extra processing associated with column balancing and page spanning to be performed).

という訳で元々のCALSテーブルの仕様をインプリメントするようにスタイルシートの仕様を変えてみました.やってみたのは、fo:tableに@start-indent="0mm"、end-indent="0mm"を指定して、width="100%"を指定することです.

<fo:table start-indent="0mm" end-indent="0mm" width="100%">
  ...
</fo:table>


ところがいろいろ試しているとこの方法でもダメなことがわかりました.問題はwidth="100%"なのです.この100%は何を参照するのでしょうか?本文領域(fo:region-body)の幅なのでしょうか?実は違うのです.XSL仕様を見ると次のように書かれています.

1. まずwidthはinline-progression-dimension(インラインの進行方向の幅)に自動的にマップされます.
2. inline-progression-dimensionの%指定は、実はその指定されているFOの「直近のブロックレベルオブジェクトで生成された幅」に対するものになります.

7.15.7 "inline-progression-dimension"

"The percentage is calculated with respect to the corresponding dimension of the closest area ancestor that was generated by a block-level formatting object."

ですから、あまりないと思いますが、tableの親がfo:blockで

<fo:block start-indent="10mm" end-indent="10mm">
  <fo:table start-indent="0mm" end-indent="0mm" width="100%">
    ...
  </fo:table>
</fo:block>

のような構造になっていると、start-indent="10mm" end-indent="10mm"のところまでしか広まってくれません.つまり本文領域いっぱいにはなってくれないのです.

このため必ず本文領域の幅全体に広げるためには上位でどのようなインデントが設定されているかわかりませんので

<fo:block-container start-indent="0mm" end-indent="0mm">
  <fo:tablewidth="100%">
    ...
  </fo:table>
</fo:block-container>

とfo:block-containerで囲んで@start-indentと@end-imdemtをリセットしてやる必要があります.これでtable/@width="100%"を指定すれば確実に本文領域幅全体に広まります.結構厄介ですね.これにDITA 1.3で加わったテーブルの回転(landscape)が加わるとなおスタイルシートは複雑になります.

ちなみにDITA-OTの最新版(DITA-OT 2.3.2)のPDF2ではどうなっているかというと、

org.dita.pdf2/xsl/fo/tables.xsl line 310

<xsl:if test="(parent::*/@pgwide) = '1'">
    <xsl:attribute name="start-indent">0</xsl:attribute> 
    <xsl:attribute name="end-indent">0</xsl:attribute> 
    <xsl:attribute name="width">auto</xsl:attribute> 
</xsl:if>

こんなコーディングが唯一@pgwide属性を参照している箇所です.width="auto"では全然ダメですよね.autoは

No constraint is imposed by this property. The inline-progression-dimension is determined by the formatter taking all other constraints into account.

と制約条件をつけないのです."other constraints"はテーブル本体の内容くらいでしょう.こんなコーディングになっているのは、テーブルの自動フォーマッティングをサポートしていないFOPなんかでやっているからではないか?と思います.

ともかく@pgwideのインプリメントは昔からなんの疑問も持っていませんでしたが、よくよく調べてみたら結構大変でした.