Shiki’s Weblog

ESウェブブラウザ通信 - CSS 2.1 Test Suite #9

2011/12/02 #ESウェブブラウザ通信

前回はline-heightのテストを進めました。今回はテーブルの実装をもう少し進めて、CSS 2.1の17章のテストを少し進めていきます。

その前に

ESウェブブラウザで、もうすこし色々なサイトを表示できるようにしておきたい、ということでいくつか修正を入れています。
r2155では、EUC-JPとJISコードを使っているページを表示できるようにしています。ICUのucnv_open()の使い方が悪いのかもしれないのですが、エンコード名のエイリアスが一部期待通りに動いてくれていないのでした。
r2156以前はHTTPリクエストのホストヘッダーに、

Host: shiki.esrille.com:80

のようにデフォルトのポート番号80まで表記して送信していました。r2156では、

Host: shiki.esrille.com

のようにデフォルトのポート番号は省略するようにしました。意外なことにかなりのウェブサイトがこの違いをチェックして、:80がついていると、管理画面らしきものを表示するサイト、英語ページを表示するサイト、等々予想外の動きします。
r2157では大きさが0のフローティング ボックスの処理で問題があったので修正しています(なお、この修正自体もr2179で再修正しています)。

r2157r2157

この段階でまだ崩れている部分が結構ありますが、このブログもESウェブブラウザでひとまず何かは表示されるようになりました。

テーブル

テーブルに関しては、もともとGoogleのトップページを表示できるように、という目的だけで実装したものなのでかなり適当な実装になっていました。そのため一連のCSS 2.1のテストでも、テーブルの処理の所為で表示が一部崩れているテストが結構ありました。今回はもう少し標準に合わせた実装を進めていきます。
CSSのテーブルの処理で面倒な部分は列の幅や行の高さを解決していく部分だと思います。特に結合ボーダーモデル(collapsing border model. こういった用語の日本語訳はどこのものが好まれているのでしょう?)ではボーダーの幅を先に解決しないと列や行の大きさも解決できない、ということがあるので、順序はひっくり返りますがまず17.6.2.1のBorder conflict resolutionから実装を進めていきます。

r2158r2158

r2158まではまったく実装が入っていなかったので、r2159でひとまずの実装とバグの修正を入れています。仕様書に出てくるはそれなりに表示できるようになりました。

r2159r2159

これを見ているとcolspanやrowspanが使われたときの動作が気になってきます。先ほどの例を少し改造したこの例では、r2159ではまだスパンに対応していないので、競合を解決する前の状態が見えます。

r2159 (スパンが使われている場合)r2159 (スパンが使われている場合)

この場合、テーブルのセル2の右辺とセル6の左辺はどう処理したらいいのか、仕様書では明確には記載されていない気がします。単純にどちらのエッジが優先されるかというだけの判定でよいとすれば、2の右辺は6の左辺に勝つので、6の左辺がすべて、つまり8の右辺まで青くなりそうです。もっと丁寧にエッジをグリッドごとに処理するのだとすれば、6の左辺の上半分はブルーに、下半分は緑の破線で描画することもできそうです。
実際のブラウザはどんな感じになってるか見てみました。

Chrome 15

Firefox 8

Chromeは前者、Firefoxは後者の考え方で実装されているようです。こうメジャーなブラウザで実装が割れると、ESウェブブラウザでどちらの実装にするかちょっと悩むところです。Webデザイナの期待に近いのどちらでしょうか?そもそもこういうテーブルは使わない、という説が一番有力な気もしますが、とりあえずより直感的なFirefoxのスタイルに倣ってみます。

r2163r2163

r2163で実装を追加して、それらしくなってきました。すこし大きめの変更ですが、考え方としては、各セルのボーダーに相当する幅はCellBoxクラス中ではマージンとして確保しておいて、実際の結合したボーダーの描画はTableWrapperBoxクラスで行うようにしてみました(各セルからすると、ボーダーはテーブボックスに描かれたものが透けて見えている感じになります)。
改めて17.6.2.1の例に戻って見比べてみると、ボーダーとボーダーの交差する部分の処理がr2163ではあまり綺麗ではありません。r2163では左上から順にボーダーを描画しているので、セル6の右下隅が黄色になっている、とか色々と細かい部分で違います。

r2163r2163

このへんはFirefoxでもそこまで作り込まれてはいないようですが、仕様の解釈としてはボーダーの交点についても、もっとも目立つボーダーがそこを占有する、と考えるべき、ということなんだと思います。いまはこの点はTODOということにしておいて、先に進みます。
補足: この例はCSS テストスイートのborder-conflict-example-001としても含まれています。
table-intro-example-004(その1)
結合ボーダーモデルの実装はすこし進められたので、分離ボーダーモデルもサポートしておきます。

r2163r2163

r2164で実装を追加しました。内部的には、CellBoxのマージンにborder-spacingに相当する値を入れるようにしています。結合ボーダーモデルのときも、ボーダーがある部分はCellBoxではマージンになっていて背後のテーブルボックスが見えるようにしていたので、コードとしては共通になっている部分がわりとあります。

r2164r2164

r2165でキャプションもとにかく表示するようにしました。

r2165r2165

まだテーブルの幅の計算ができていないので、キャプションの位置はだいぶズレています。(あとで修正しています。)
fixed-table-layout-006
必要な部品はひととおり揃ってきたので、テーブルのレイアウトの処理のもう少し詳細な実装を進めていきます。まずは簡単な固定テーブルレイアウトをr2166で一気に実装しています。

r2165r2165

固定テーブルレイアウトは、アルゴリズム自体は単純なのですが、分離ボーダーモデルでは、ボーダー幅が未指定のカラムに幅を設定しく際に、幅が指定されているカラムのボーダーの幅なども差し引いて計算しないといけません。 列の幅を確定する前に一部のセルやカラムのスタイルの解決値が必要になる点がやや面倒なところです。

r2166r2166

fixed-table-layout-006はその処理ができていないと表示が崩れます(WebKit系が現状失敗しているようです)。
fixed-table-layout-010

r2166r2166

このテストに関してはテーブルのレイアウトではなくて、white-spaceの'pre'に対応していなかったために途中で改行してしまっていました。r2167で対応しました。

r2167r2167

この段階でfixed-table-layout-xxxシリーズはひとまずすべてパスするようになりました。
border-conflict-element-001
自動表組みアルゴリズムに入る前に、17.6.2.1のボーダーの競合のテストを進めておきます。

r2167r2167

ひとまずr2168でテーブルに指定されたwidth, heightが効いていなかったバグを修正しました。

r2168r2168

これで17.6.2.1のボーダーの競合のテストを進められます。
border-conflict-style-005
これは、ボーダーが'hidden'のときは他の要素の設定に関わらず'hidden'扱いになっているかどうかのテストです。

r2168r2168

r2169でhiddenの処理を修正しています。

r2169r2169

border-conflict-resolution-002
tr要素で設定したボーダーが表示されるかどうかテストしています。

r2169r2169

r2170で下端・右端のボーダーを処理できていなかったバグを修正しています。

r2170r2170

border-conflict-resolution-003
前の002と似てますが、tbody要素で(display設定が'table-row'ではなくて'table-row-group')ボーダーを指定したときのテストです。

r2170r2170

r2171で対応しています。

r2171r2171

border-conflict-element-004
ボーダーの色だけが違う場合のテストです。

r2171r2171

r2172で要素の処理順にバグがあったので修正しています。

r2172r2172

ここまでで、未対応のrtlに関する3つのテストを除いて、17.6.2.1のボーダーの競合のテストにすべてパスするようになりました。続いて、テーブルのレイアウトのごく基本的なバグをつぶしていきます。
border-spacing-001
Microsoft社からのお約束の無効な負の値がborder-spacingに指定された場合のテストです。

r2172r2172

CSSの仕様上の初期値は0なのですが、HTMLのデフォルトのスタイルシートでの初期値は2なので、負の値が設定された場合には2を返すようにr2174で修正しています。これまでもこういった感じで対処してきましたが、そろそろCSSパーサーの段階で無効な値を無視する仕組みを導入しないといけない感じがしてきました。

r2174r2174

separated-border-model-004
このテストでは黒いテーブルと青いボックスの幅が同じになれば成功です。テーブル内では、'table-cell'がdisplayに設定されている要素のwidthに'50px'が設定されているのですが、テーブルのwidthが'200px'、border-spacingが'50px 0' (水平方向が50px)なので、セルの幅は最終的に200px - 2 x 50px = 100px まで広げないといけないのです。

r2174r2174

r2175で幅が'auto'でないセルの幅を広げることができなっていたのを修正しています(関連してTableWrapperBox::layOutFixedで'border-spacing'の幅もwidths[]に含めるように修正しています)。

r2175r2175

table-intro-example-004(その2)
その1のときは放置していましたが、キャプションの幅も合わせておくようにします。

r2175r2175

r2177では、自動テーブルレイアウトは仕様の方も割と緩い( they can use any other algorithm even if it results in different behavior. )ということもあって、あまり凝ったことはしていないので、とりあえずテーブルボックスの幅でキャプションのボックスをレイアウトしています。キャプションのボックスにもっと広い幅が指定されていたりすると、デザイナの期待としては各列の幅も広がるのだと思いますが、いまはそこまではしていません。

r2177r2177

なお、ふだん表示に使用しているIPAフォントですと、まだフォントマネージャーの側で太字での表示に対応できていないので、LiberationSansフォントを使った場合の様子も載せておきます。この場合は1列目は本来の意図通り太字で表示されます。

r2177 (LiberationSansでの表示)r2177 (LiberationSansでの表示)

c411-vt-mrgn-000
テーブルのレイアウトの基本的な部分は出来てきたので、一度harnessをつかってリグレッション テストをします。

r2129r2129

これまではテーブルを使っているテストで最後の列やボーダーの色違いは無視してください、という断りをいれていたものが結構あったのですが、今回の修正でそういった点はほとんど解決していそうです。このテストでも最後に色違いの行が見えていたのが消えました。

r2177r2177

r2178からr2180では、これまで成功していたテストを崩してしまっていた修正を再修正しています。
block-in-inline-001
このテストもテーブルの処理の問題で赤い行が最後に残っているかと思っていたのですが、r2180でも赤い部分が残ったままでしたので、詳しく見てみました。

r2180r2180

調べてみると、ブラウザ内部では左の列のLine 3というテキストの後に空白が1文字一度追加されていて、行末ということで改めてその空白が削除されています。問題は、最後の1文字の空白がラインボックスの高さを大きくしていて、その効果がそのまま残っていて一番下のセルの高さを想定よりも高くしてしまっていたのでした。ラインボックスから行末の空白を削除した場合には、幅だけでなくて高さも再計算しないといけない場合があったのでした。r2181で修正しています(実際に再計算しているわけではなくて、取り除いた行末の空白を追加する前の値に戻すようにしています)。

r2181r2181

table-visual-layout-010
リグレッション テストは大丈夫そうなので、またもう少し細かいテーブルのテストに戻ります。このテストでは青いボックスが右側のオレンジのボックスの上端から下端まで伸びていれば成功です。

r2181r2181

クリックして拡大して見てみないと分かりにくいのですが、青いセルの高さが1pxだけ大きくなってしまっています。r2182でスパンが2以上のセルの端がテーブルの右端と下端まで来たときのborder-spacingの処理が入っていなかったのを修正しています。

r2182r2182

table-visual-layout-013
このテストでは、黒いセルが1列右に行き過ぎていました。

r2182r2182

r2183で自分自身のスパンの分まで右に位置をずらしていたバグを修正しています。

r2183r2183

collapsing-border-model-001
このテストではオレンジとブルーのボックスの幅が同じであれば成功なのですが、r2183ではブルーのボックスの表示位置が間違っていました。

r2183r2183

つぶしボーダーモデルでは、テーブルボックスにもボーダーが付きます。r2184でその分の計算が入っていなかったのを修正しています。また、テーブルの2行目以降で収まりきらなかったボーダーの分はテーブルラッパーボックスのマージンに含まれる、という処理も入れています(collapsing-border-model-002がそのテストしています)。

r2184r2184

今回はここまでです。17章のテストスイートに関しては50%強のテストに成功するようになりました。テストスイート全体では40%強のテストに成功するようになりました。
テーブルに関しては、まだ背景やアラインの部分が未実装だったり、17.2のCSSのテーブルモデルには基本的には未対応(ESウェブブラウザが現在実装しているのはHTMLのテーブルモデルの方です)だったり、さらに、CSS 2.1の仕様自体でも細かい部分で議論が続いているようなので、残りのテーブルのテストについては対応するのはしばらく先になりそうです。
次回はまた細かな改善から進めて行く予定です。