Shiki’s Weblog

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

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

前回は、CSS 2.1テストスイートの5章、6章の確認とカスケーディング処理の高速化を行いました。今回からは、これまでまとまったテストは行っていなかった16章「テキスト」のテストを進めていきます。今回は、16.1の'text-indent'と16.6の'white-space'のテストを行っていきます。

改行可能位置の処理

c26-psudo-nest-000 テストスイートのテストに入る前に既知の改行可能位置の問題を修正しておきます。

r2364r2364

前回テストしたこのテストをIPAフォントで表示してよく見てみると、3番目の段落の2行目が.(ピリオド)ではじまってしまっています。HTMLファイル中ではこの部分は、

be <strong>teal≤/strong>.

のようになっていて、DOMツリーの中では'teal'と'.'は別のノードに入っています。r2364では、ノードの境界は常に改良可能として処理してしまっていたのでした。

r2366r2366

r2366で修正しています。基本的には改行しないといけない水平位置までインラインブロックの処理が進んだときに、直前のインラインブロックとの間で改行可能かどうか確認して、改行不可能であれば手前のインラインブロックを改行可能な位置から分割して次の行にまわして処理するようにしています。r2366は、もとの仮定が間違っていたので、大きな変更になってしまっています。リグレッションについては、CSS 2.1のテストスイートを使って、r2371(white-space-pre-001), r2372(white-space-processing-049), r2374(white-space-mixed-004)で修正をしています。

テキスト インデント

16.1の'text-indent'プロパティの実装とテストを進めていきます。

c547-indent-000 異なる単位を使って'text-indent'プロパティの処理をテストしています。

r2366r2366

r2367では、ラインボックスの左端にインデントに対応する余白をとるように実装しましたが、次のtext-indent-013でこの実装は良くないことがわかります。

r2367r2367

text-indent-013 このテストでは'text-indent'を指定している行にフローティング ボックスとインライン要素が両方入ります。そして、フローティング ボックスの配置は'text-indent'の設定には影響されないことをテストしています。テストに成功していれば、PASSという単語が表示されます。

r2367r2367

r2367のようにラインボックスの左端にインデント分の余白をとってしまうと、フローティング ボックスとインライン要素が重なってPASSという文字が見えなくなってしまいます。r2368では、最初に'text-indent'の指定が有効になるインラインブロックの左マージンにインデント分の余白を追加するように修正しています。

r2368r2368

text-indent-intrinsic-004 このテストではユニコードのzero width white-space (ZWSP)が使われています。

r2368r2368

r2368では、ZWSPに対応するグリフがないということで、×印がそのまま表示されてしまっています。r2369ではZWSPについてはフォントを描画しないように修正しています。

r2369r2369

なお、r2369では、HTML 5のwbr要素も適当にZWSPに対応付けるようにしてしまっていますが、このあたりはまだ落ち着いていない様子です。改行処理に関するヒントとしてのZWSPについては、今後改めて調べて実装していきます。この段階でtext-indentのテストに関しては、数テストを残して成功するようになりました。残りはtext-indentの処理自体ではなくて、その他の実装の不具合による失敗のようなので、今後実装の進捗に合わせて改めてテストしていくことにします。

ホワイトスペース

white-space-007 CSS 2.1の仕様書16.6.1の、

When wrapping, line breaking opportunities are determined based on the text prior to the white space collapsing steps above.

という部分のテストです。空白のつぶしによってレンダーツリーに残らなかったインライン要素でも改行位置としては影響する、という2007年から2009年の変更でCSS 2.1の仕様書で明確化された箇所のようです。文章にするとたった一文なのですが、その実装はわりと複雑です。

r2369r2369

このテストのオレンジ色の部分は、'<span>X </span> '(span要素の後にスペース1文字のテキスト ノード)が繰り返されています。span要素のwhite-spaceにはnowrapが、後ろのスペースにはnormalが設定されています。そのため、後ろのスペースは直前のspan要素の終わりのスペースでつぶされてなくなります。r2369では、つぶされたスペースの位置で改行可能だったという点を考慮していなかったのでテストに失敗しています。

r2370r2370

正しく処理できるとr2370のようにレンダリングされるのですが、r2370の修正自体は正しい実装ではありませんでした。この点は、あとでwhite-space-mixed-001で改めて修正を進めています。・white-space-nowrap-attribute-001 こちらはtd, th要素のnowrap属性のテストです。現在では仕様上はobsoleteですので、今はHTMLの属性ではなくてCSSを使いましょう、というのはこれまでと同じです。

r2372r2372

r2373で対応させています。

r2373r2373

white-space-mixed-001 このテストはHixieのテストで、いろいろな空白の処理を組み合わせた複合的なテストになっています。

r2374r2374

r2375でまだ残っていた空白のつぶしのバグを修正し、r2376でr2370での誤った実装も含めて改行位置の処理を修正しています。

r2376r2376

なお、r2376の修正では結果オーライでこのテストにはパスしてしまっていますが、HTMLファイル中、

'(空白)xx<span class="normal">x<span class="nowrap">x(改行)'

のようになっている箇所があって、改行可能位置の判定はr2366の修正のように直前のインライン要素とだけチェックするのではダメで、2つ以上前のインライン要素やテキスト ノードまで遡ってチェックしないといけない、ということがわかります。この点は、CSS 2.1のテストスイートでテストケースが用意されていないようなので次のws-001を用意してテストすることにしました。補足: このテストはFirefoxで失敗するようでバグがファイルされています。まだ"Assigned To: Nobody; OK to take it and work on it"のようです。・ws-001(ESで追加したテスト。要Ahemフォント) 1単語が複数のインライン要素(このテストでは5要素)にまたがっている場合に、正しく改行位置の処理ができているかどうかテストしています。本来は2行同じパターンで描画されなければいけません(WebKit系のブラウザも表示が崩れるようです)。

r2376r2376

テキストのレイアウトを行う BlockLevelBox::layOutText はr2365で一度整理していたのですが、ここまでの修正でまたごちゃごちゃになってしまっていたので、r2378,r2379でまず先にソースコードの整理をしました。 r2380では、素直に単語の先頭までインライン ブロックを戻っていって、そのインライン要素に対応するwhite-spaceプロパティをチェックして改行処理を行うように 修正しています。

r2380r2380

この段階で、16.6, 16.6.1のテストの成功率は約89%になりました。失敗している部分は、未サポートのbidiのテストの他、タブ文字の処理などになります。

まとめ

今回は少し短めですがここまでです。CSS 2.1テストスイート全体の成功率は71%になっています。次回も16章のテキスト処理の残ったテストを進めていきます。