Shiki’s Weblog

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

2012/03/05 #ESウェブブラウザ通信

前回はAcid2テストのテストを進めましたが、今回はまたCSS 2.1のテストスイートに戻って、インライン要素の背景やボーダーの描画処理でこれまで対応していなかった部分を実装していきます。

インライン要素から複数のインライン ボックスが生成された場合のボックス間の背景、ボーダー

vertical-align-baseline-005
このテストは元々はvertical-alignのテストで、#8で位置関係の崩れは修正しました。今回はそこではなくて、青いボックスがふたつに分断して表示されてしまっている問題を修正します。本当は下図で左右の青いボックスは青い背景でつながって1つになっていないといけません。

r2458r2458

このテストの、

<span id =" span1 "> X < span id =" span2 "> XXXXX XXXXX XXXXX XXXXX XXXXX < /span> X < /span>

という部分は、 span1が青い背景のインライン要素、span2はオレンジ色のインラインブロック要素になっています。ESウェブブラウザは、この部分から、

  * inline-level box (8, 137.518) w:20 h:20 "X" #0000ff
  * inline-level box (28, 53.5183)w:100 h:100 #ffa500
  * inline-level box (128, 137.518)w:20 h:20 "X" #0000ff

のように3つのインライン レベル ボックスを生成します。これらのインライン レベル ボックスには親子関係がありません(そうしておいた方が平面上の位置決めの処理が簡単なのです)。これまでの描画処理はボックスの内側だけを描画するものでした。ところが、span1のように1つのインライン要素から複数のインライン レベル ボックスが生成された場合には、そのボックス間の背景を何らかの方法で描画しないといけない、というわけです。

r2460r2460

r2460でインライン要素が複数のボックスに分割されて配置された場合は、行ごとに1つの矩形にまとめて背景を描画するように修正しています。

背景と同様に、1つのインライン要素が分断されて生成された複数のインライン レベル ボックス間のボーダーも描画されます。この辺のテストは1ヶ所にまとまっていなくて探すのが大変だったりしますが、9章のposition-relative-033がその例になっています。以前は分断された隙間に青いボーダーが引かれていませんでした。

r2411 (position-relative-033)

r2462 (position-relative-033)r2462 (position-relative-033)

背景色とボーダーの処理を改善していくと、インライン要素の背景画像は?という疑問が沸いてくるのですが、CSS 2.1では、

The tiling and positioning of the background-image on inline elements is undefined in this specification. (14.2.1)

となっていて未定義になっています(CSS 3 Backgroundで詳細が決められていくようです)。そういうわけで、CSS 2.1のテストではインライン要素に背景画像を設定しているものはないのだと思います。

空のインライン要素、空のインライン ボックス

インライン要素の中にテキストノードなど一切の子ノードがないものは、空の(empty)インライン要素となります。このような空のインライン要素に関して、仕様書10.8では、

Empty inline elements generate empty inline boxes, but these boxes still have margins, padding, borders and a line height, and thus influence these calculations just like elements with content.

と規定しています。この規程が意味することについては、9.2.1.1のテストのうち、block-in-inline-*シリーズがそのテストにもなっているので、これを使って実装とテストを進めていきます。
このシリーズはMozillaのBoris Zbarskyさんが用意されたもののようですが、WebKitやInternet Explorerでもバージョン8まではちょこちょこ取りこぼしていて実装のややこしい部分のようです。正しい描画結果についてはテストページの=マークの部分をクリックすると確認することができます。

block-in-inline-empty-001,block-in-inline-empty-003
この2つのテストのインライン要素には空白のテキスト ノードしかなく、最終的にテキストはすべて削除されます。しかし、それでも空のインライン ボックスは生成しないといけません。インライン要素には、001はpadding-rightに10pxが、003はpadding-leftに10pxが指定されています。また青色のボーダーが上下に指定されているので、正しくインライン ボックスを生成できていれば、001は右端のパディングなので'x'のあとに、003は左端のパディングなので'x'の前に、それぞれ青いボーダーつきのパディング部分が表示されるということになります。このテストではインライン要素の中にさらにブロック要素があるので複雑なことになっています。

r2463 (001)r2463 (001)

r2463 (003)r2463 (003)

r2463の段階では上図のとおり、インライン ボックスが生成されていないために青色のボーダーが見えていません。r2464でこういった空のインライン ボックスの生成に対応しています。

r2464 (001)r2464 (001)

r2464 (003)r2464 (003)

block-in-inline-whitespace-001a
このテストではひとつのインライン要素から文字を含まない2つのインライン ボックスが異なる匿名ブロック ボックスの中に生成されます。r2468では、分断して生成されたインライン ボックスについて、先頭のブロック ボックス内でしか背景やボーダーの処理をしていない、という問題が残っていました。

r2468r2468

r2469で修正しています。

r2469r2469

block-in-inline-insert-006
block-in-inline-whitespace-001aと一見似ているのですが、block-in-inline-whitespace-001aはインライン要素の中にテキストノードが含まれているのに対して、このblock-in-inline-insert-006はインライン要素の中にテキストノードが含まれていない、という違いがあります。

r2470r2470

r2470では生成された2つ空のインライン ボックスが左端にあるのか右端にあるのかの判別ができずに、表示が崩れていました。ESウェブブラウザ内部では、テキストノードが左端や右端にあるかどうかの判定と、空のインライン要素が左端や右端にあるかどうかの判定処理が別々になっているためです。r2471で修正しています。

r2471r2471

block-in-inline-insert-012
このテストではThreeの下側に縦のボーダーが引かれないといけません。

r2471r2471

r2472で、空のインライン要素を擬似要素の内側に配置してしまっていたバグを修正しました。

r2472r2472

block-in-inline-insert-013
:before擬似要素がある場合、ボーダーのための空のインラインボックスはさらにその手前に生成しないといけない、という点をテストしています。

r2472r2472

r2473で対応しています。

r2473r2473

このテストでは、インライン要素が空ではなかったので、インライン要素が空の場合もテストしておかないといけません。ちょうどよいテストがなかったので、テストを2つr2474で追加しています。

r2474 ( ib-005.html )r2474 ( ib-005.html )

r2474では空のインライン ボックスが左端なのか右端なのかの判別に失敗してしいた箇所をr2475で修正しています。

r2475 (ib-005.html)r2475 (ib-005.html)

block-in-inline-insert-016b

このテストはどこが崩れているのかちょっと見ただけでは気付かないのですが、 "One"の上下のボーダーが右側に2px分だけ長く伸びてしまっています。

r2475r2475

r2476で、擬似要素がある場合にインラインボックスが要素の末尾にあるかどうかの判定をし損ねている箇所が残っていたので修正しています。

r2476r2476

まとめ

今回はここまでです。大きな修正もいくつかあったのですが、CSS 2.1テスト スイート全体の成功率はほとんど変わらず約82%となっています。次回は、directionが'ltr'のテキストまわりの処理でもうひとつ宿題にしているvertical-alignの詳細実装とテストを進めていく予定です。