Shiki’s Weblog

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

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

前回はインライン要素やテーブル セルのvertical-alignの処理を改善しました。今回は、#18,#19とテスト数が少なくCSS 2.1のテスト スイートの達成率はあまり変わらないという状況が続きましたので、テストスイートの達成率が低い12章(生成コンテンツ)、18章(UI)、それから未実装の機能がまだ多い17章(テーブル)の機能の実装とテストを中心に達成率を底上げしていきます。

ブロック要素の'outline'

アウトラインは、CSS 2.1の仕様書18.4で規程されている機能です。インライン要素のアウトラインの処理は多少複雑な場合がありますが、ブロック要素のアウトラインはボーダーの処理とほとんど同じなので先に実装しておきます。
outline-layout-001

r2512r2512

r2513で、ブロック レベル ボックスのアウトラインの描画に対応しました。

r2513r2513

outline-color-001
このテストでは、collapse throughしているボックスにアウトラインを付けているのですが、そのときの描画位置が違っていました。

r2513r2513

アウトラインの起点もトップ ボーダー エッジを考慮しないといけません。r2514で修正しています。

r2514r2514

outline-style-hidden-001
仕様書18.4の、

The 'outline-style' property accepts the same values as 'border-style' , except that 'hidden' is not a legal outline style.

という部分のテストです。hiddenはoutline-styleの有効な値ではないのでCSSパーサーは無視しないといけません。

r2514r2514

r2515で対応しています。

r2515r2515

z-index-020
このテストは9.9.1のテストですが、アウトラインのz方向の位置のテストも行っているので、ここでテストしておきます。
アウトラインは、Appendix E.で、ラインボックスを描画した後(オプション)、もしくは、各スタッキング コンテキストの最後(推奨)に描画するように規程されています。正しく実装できていれば、このテストでは、 マゼンダ 色のアウトラインも含めて、一番上のボックスは下の2つのどちらかと同じように描画されます。

r2516r2516

r2516では、アウトラインを単純にブロック ボックス内で最後に描画していたので、下の2つのどちらとも一致していません。推奨されているレンダリングは真ん中のスタイルなのですが、r2517では実装が容易な一番下のスタイルで描画するように修正しています。

r2517r2517

現状では、メジャー ブラウザではOperaが推奨されているスタイルで描画するようです。GeckoとWebKitはr2517と同様の描画になります。IEはr2516と同じ崩れ方をしているようです。

カウンター

12.4のカウンターについては、#11でごく基本的な部分は実装しましたが、今回は未対応だった部分の実装をさらに進めていきます。
lists-alpha-wrap-001
このテストでは'upper-alpha'で表示するカウンタの値に27(アルファベットは26文字ですね)を指定した場合のテストをしています。CSS 2.1の仕様書では、

This specification does not define how alphabetic systems wrap at the end of the alphabet. For instance, after 26 list items, 'lower-latin' rendering is undefined.

とされていますので、このテストはCSS 2.1のテストとしては適切ではないとも言えますが、CSS 3リストでの規程にはしたがっています。CSS 3では、26でZまで進んだら、数字のように位が上がってAA, AB, ……と続いていくように定義されています。

r2516r2516

r2517で、CSS 3相当のアルゴリズムとHTMLのstart属性に対応しました。

r2517r2517

list-alignment-001
このテストではテスト本来の目的とは別に、<li></li>のような空のリスト項目から生成されたボックスの高さが0になっている問題が見つかりました。

r2517r2517

r2518で、空のリスト要素も空のインライン要素と同様にボックスが高さを持つように修正しました。

r2518r2518

counter-increment-not-generated-001
このテストでは、擬似要素のdisplayが'none'のときにカウンタを操作してしまっていないかどうかテストしています。

r2519r2519

r2520で、displayが'none'の擬似要素の処理をしないように修正しました。

r2520r2520

counter-increment-applies-to-001
このテストでは、table-row-group要素のスタイルでカウンタを操作できるかどうかテストしています。

r2521r2521

r2522で、テーブル関連の要素のスタイルでカウンターを操作できるようにしました。

r2522r2522

table-header-counter-001(ESの追加テスト)
table-header-group-005を改造したテストです。table-header-groupでカウンタを操作する場合、カウンタを操作するのはDOMツリー順になっているかどうかチェックしています。r2522ではtable-header-groupの列を一番最後にレイアウトして先頭に戻すような実装にしていたので、カウンタの値が6になってしまっていました。

r2522r2522

r2523で、table-header-groupもDOMツリー順に処理して、最後に列だけを入れ替えるような実装に修正しました。

r2523r2523

'content' プロパティー

12.2の'content'プロパティー関連のバグの修正や未対応のattr()などの実装を進めていきます。
content-001
単純なテストなのですが、スタイルの中で、

content: "FAIL FAIL";
content: none;

と2回contentプロパティーを設定しています。

r2523r2523

r2524で、contentプロパティーを2回以上設定するときに以前の設定が残ってしまっていたバグを修正しました。

r2524r2524

content-037
attr()を使った簡単なテストです。CSS 3 Values and Unitsではattrを使える場面が大きく拡大されていますが、今はCSS 2.1の範囲に限定して実装します。

r2524r2524

r2525で、attr()に対応しました。

r2525r2525

quotes-001
12.3の'quotes'プロパティーを使って、'content'プロパティーの中で利用しているテストです。

r2525r2525

r2526で、quotesプロパティーに対応して、'content'プロパティーの中で、open-quote, close-quote, no-open-quote, no-close-quoteを使えるようにしました。

r2526r2526

'cursor'プロパティー

仕様書18.1のcursorプロパティーから、今回はひとまず'crosshair'といったキーワードで指定するタイプのカーソルを一通りサポートします。
cursor-003
このテストでは、crosshairを使っています。

r2527r2527

r2528でキーワードカーソルのを一通りサポートしました。といっても、対応するGLUTのglutSetCursorを呼び出しているだけです。'move'には、対応するGLUTのIDがないので、ひとまず×印(GLUT_CURSOR_DESTROY)で表示しています。

r2528r2528

URIで指定した画像を使ったカーソルのサポートは次回以降に対応していきます。

テーブル関連の詳細実装

未対応だった'empty-cells'やrowやcolumnで指定された背景の描画などに対応していきます。
empty-cells-002
17.6.1.1の'empty-cells'のテストです。

r2529r2529

ひとまず単純に処理できる'empty-cells'についてr2530で対応しました。

r2530r2530

table-footer-group-005
これはtable-footer-groupのテストです。r2530では、HTMLテーブルモデルの名残りですべてのfooter要素を下に移動させてしまっていました。

r2530r2530

r2531でCSSテーブルモデル(17.2)の、

If a table contains multiple elements with 'display: table-footer-group', only the first is rendered as a footer; the others are treated as if they had 'display: table-row-group'.

という仕様にしたがって、最初のtable-footer-groupだけを特別に処理するようにしました。

r2531r2531

現実的にはHTMLでも、ヘッダーやフッターは1つのテーブル内には1つだけにしておいた方が良さそうですね。
after-content-display-008
このテストでは、匿名のテーブル ボックスを擬似要素の中から生成しています。

r2531r2531

r2532で対応しました。

r2532r2532

table-backgrounds-bc-row-001,table-backgrounds-bs-row-001
このテストでは、table-rowに設定された背景が描画できるかどうかテストしています。bcが結合ボーダー モデル、bsが分離ボーダー モデルのテストです。背景画像の原点が、(各セルではなくて)行の左上隅になる点など注意すべき部分がいくつかあります。r2532では未実装の機能なので空白になっています。

r2532 (bc)r2532 (bc)

r2532 (bs)r2532 (bs)

r2533,r2534で対応しました。原点を合わせるだけでなくて、行の幅と高さも正しく計算しないとリファレンス通りには描画できません(Firefox以外のメジャーブラウザでは今のところうまくいっていなさそうです)。r2533では、このテストに関してはリファレンス通りに描画できていますが、セルがスパンしていると正しく描画できない場合がまだ残っています(TODOコメントを残してあります)。

r2533 (bc)r2533 (bc)

r2533 (bs)r2533 (bs)

table-backgrounds-bc-rowgroup-001,table-backgrounds-bs-rowgroup-001
同様にtable-row-groupのテストです。r2535で対応しました。実装前はただの空白の画面なので省略します。

r2535 (bc)r2535 (bc)

r2535 (bs)r2535 (bs)

table-backgrounds-bc-column-001,table-backgrounds-bs-column-001,table-backgrounds-bc-colgroup-001,table-backgrounds-bs-colgroup-001
col, colgroupに関する同様の背景のテストです。実装前はやはり省略します。r2536で対応しました。

r2536 (bc-column)r2536 (bc-column)

r2536 (bs-column)r2536 (bs-column)

r2536 (bc-colgroup)r2536 (bc-colgroup)

r2536 (bs-colgroup)r2536 (bs-colgroup)

table-layer-transparency-example-001
これは17.5.1に載っている例とほぼ同じテストです。17.5.1では行の色をredにしていますが、テストスイートでは red はFAILを意味するので orange に変えたのでしょうね。

r2536r2536

r2536では、テーブルの背景を一番最初に描画できていなかったために、行をオレンジ色で塗ったあとで黄色で塗り直してしまっていました。r2537で修正しています。

r2537r2537

table-backgrounds-bs-table-001
分離ボーダー モデルでのテーブルの背景の描画テストです。r2537ではテーブルに関してbackground-positionプロパティーの解決を行っていなかったために、3つ目のボックスの表示がリファレンス通りになっていませんでした。

r2537r2537

r2538で修正しています。

r2538r2538

table-backgrounds-bc-table-001
結合ボーダー モデルでのテーブルの背景の描画テストです。

r2538r2538

結合ボーダー モデルを#9で実装したときに、

各セルのボーダーに相当する幅はCellBoxクラス中ではマージンとして確保しておいて、実際の結合したボーダーの描画は TableWrapperBoxクラスで行うようにしてみました(各セルからすると、ボーダーはテーブボックスに描かれたものが透けて見えている感じにな ります)。

と書きました。この考え方で基本的にうまく描画できているのですが、#9ではテーブル ボックスまでボーダーに相当する幅をマージンに確保してしまっていました。そのため、r2538では本来背景が描画されるべきボーダーの部分の背景が描画されていませんでした(余白がリファレンスよりも広くなってしまっています)
r2539で、テーブル ボックスについてはボーダーに相当する幅はボーダー領域に確保するように修正しています。またr2542で、テーブル ボックスからはみ出たボーダーの幅は、テーブル ラッパー ボックスのマージンとつぶし合うようにしています。

r2539r2539

column-width-001
自動テーブル レイアウトでカラム要素で指定されているwidthが、セルの幅に反映されているかどうかテストしています。

r2542r2542

r2543で対応しました。

r2543r2543

column-width-002
自動テーブル レイアウトでカラム グループ要素で指定されているwidthが、セルの幅に反映されているかどうかテストしています。

r2543

r2544で対応しました。

r2544r2544

border-style-inset-002
このテストでは、仕様書17.6.3の、結合ボーダー モデルでは、'inset', 'outset'はそれぞれ'ridge', 'groove'として描画する、という仕様をテストしています。(そうしておかないと、結合ボーダー モデルでは、どのセルから見て'inset'なのかとか別に規定しないといけなくなってしまいますね。)

r2545r2545

r2546で、ひとまず'inset', 'outset'をそれぞれ'ridge', 'groove'に変換して処理する、というテスト本来の部分の実装をいれました。ただ、r2546では四隅でのボーダー線がリファレンスのように綺麗に対角線に沿ってつながっていません。(明暗の加減が弱めで見分けにくい点は今後修正していきます。)

r2546r2546

r2547で、テーブルの四隅のボーダーを対角線にそってつなげるように修正しました。なお、2行2列以上のテーブルの四隅以外のボーダーの交点はどう処理するのかとなると、各ブラウザでバラバラなようです。r2547では、単純に四隅以外は交点の中心から中心までの長さのボーダーを描くようにしています。(すべての交点で'ridge'や'groove'らしい描画をするような実装は、今のところどのメジャー ブラウザでもしていないようです。)

r2547r2547

table-margin-002
なぜか8章のテスト スイートに含まれているのですが、テーブルのボーダーがテーブル ボックスの幅に与える影響をチェックしています。r2547では未考慮でテストに失敗しています。

r2547r2547

このテストでは、div要素が包含ブロックとして、まずテーブル ラッパー ボックスの幅に影響します。そして、その内側のテーブル ボックスの幅は、そこからさらにtable要素のborderプロパティーの影響を受けて小さくなります。仕様書では17.4の、

The computed values of properties 'position', 'float', 'margin-*', 'top', 'right', 'bottom', and 'left' on the table element are used on the table wrapper box and not the table box; all other values of non-inheritable properties are used on the table box and not the table wrapper box.

という部分です。1つのtable要素からは、テーブル ラッパー ボックスとテーブル ボックスと2つのボックスが生成されるので注意が必要な箇所でした。r2548で対応しています。

r2548r2548

マーカーの位置

いくつかのテストで、リストのマーカーの位置がずれていた問題を修正しておきます。CSS 2.1では、

CSS 2.1 does not specify the precise location of the marker box or its position in the painting order, but does require that for list items whose 'direction' property is 'ltr' the marker box be on the left side of the content -12.5.1

という規程があるだけですが、テストスイートではもう少し踏み込んでいるようです。
border-left-width-applies-to-010,padding-left-applies-to-010

border-left-width-applies-to-010では、リストのマーカーの位置はリストのボックスのボーダー エッジよりも左側になるということを期待してます(左マージンの中にはマーカーがあってもよい)。
padding-left-applies-to-010では、マーカーの絶対配置ボックスをレイアウトするために作られるラインボックスの親ボックスが匿名ボックスになります。配置場所の基準はさらに匿名ボックスの親のボックスでないといけませんでした。

r2548 (border-left-width-applies-to-010)r2548 (border-left-width-applies-to-010)

r2548 (padding-left-applies-to-010)r2548 (padding-left-applies-to-010)

r2549で対応しました。なお、親要素でカウンタがリセットされている場合は、さらにCSS 3 Listsで規程されている、

the horizontal static position of the marker is such that the marker's "end" edge is placed against the "start" edge of the list item's parent.

という動作に合わせておかないといけない点はこれまで通りです。

r2549 (border-left-width-applies-to-010)r2549 (border-left-width-applies-to-010)

r2549 (padding-left-applies-to-010)r2549 (padding-left-applies-to-010)

r2550,r2551ではこれまでのリグレッションの修正をしています。

まとめ

今回でCSS 2.1テスト スイート全体の達成率は前回から6%向上して約89%となりました。次回はさらに未対応の機能の実装を進めて当面の目標となっている達成率90%を目指していきます。