2012年3月23日金曜日

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

前回まででCSS 2.1テストスイートの達成率は約89%まで来ていました。今回は当面の目標としていた達成率90%を突破するところまで報告していきます。

匿名テーブルボックスの処理

・ table-anonymous-objects-155

このテストでは、空でないテキスト ノードが現れた時点で一度匿名のテーブルを閉じないといけません。

r2551
r2552でその点を修正し、また再描画がかかるようにいつも通り暫定的に DOMCharacterDataModified イベントを実装しています。

r2552
 ・ table-anonymous-objects-161

このテストでは、row-groupの処理中に匿名のテーブル行を生成した場合のテーブル行の改行処理ができていない場合がありました。

r2552
r2553で修正しています。

r2553
結合ボーダー モデルのテスト

・ collapsing-border-model-003

このテストでは、テーブルのセルや行のheightプロパティーの設定をセルの高さとしてまだ処理してしまっていた箇所が見つかりました。

 r2553
r2554で修正しています。

r2554
・ collapsing-border-model-004

このテストは仕様書17.6.2の、
Also, in this model, a table does not have padding (but does have margins).
という、結合ボーダーモデルではテーブルはパディングをもたない、という点をテストしています。

r2554
r2555で修正しています。

r2555
・ collapsing-border-model-005

このテストは仕様書17.6.2の、
UAs must compute an initial left and right border width for the table by examining the first and last cells in the first row of the table. The left border width of the table is half of the first cell's collapsed left border, and the right border width of the table is half of the last cell's collapsed right border. If subsequent rows have larger collapsed left and right borders, then any excess spills into the margin area of the table
という箇所の太字で示した部分のテストです。 『はみ出した左右のボーダーの幅は、テーブルのマージン領域にあふれる』というのを前回は、
r2542で、テーブル ボックスからはみ出たボーダーの幅は、テーブル ラッパー ボックスのマージンとつぶし合うようにしています。
と解釈して実装しました。一方、このテストではHTMLファイル中に、
Borders that spill into a table margin can overflow that table's container.
と、ボーダーはテーブル ラッパー ボックスの外側にあふれるかもしれない、と記載しています。そして、このテストでは、実際にテーブル ラッパー ボックスの外側に左右のボーダーがあふれることが成功条件になっています。

r2555
r2556で修正しています。r2542はちょっと凝りすぎだったわけです。

r2556
より複雑なテーブルのテスト

・ table-anonymous-block-005

テーブルのpositionに'relative'を設定しているテストです。r2556ではスタイルを共有しているテーブル ラッパー ボックスとテーブル ボックスの両方でpositionが有効な状態になっていて崩れていました。positionが有効なのはテーブル ラッパー ボックスの方です。

r2556
r2557で修正しています。

r2557
・ table-anonymous-block-018

このテストでは、青とオレンジのボックス間の距離については合っています。ただ、青とオレンジのボックスのベースラインが揃っていません。

r2557
r2557では仕様書17.5.3の、
If a row has no cell box aligned to its baseline, the baseline of that row is the bottom content edge of the lowest cell in the row.
という仕様が未実装でした。r2561でこの仕様を実装したほか、それまでにvertical-align関連のバグを合わせて修正しています。

r2561
・ table-layer-transparency-003

前回、セルの階層的な背景の描画にひとまず対応しましたが、このテストではさらにセルがスパンしている場合をテストしています。

r2561
前回の実装のバグの修正も含めて、r2562で対応しています。

r2562
・ background-root-003

このテストではルート要素がテーブルになっています。この場合、テーブルのbackgroundに指定している色でキャンバス全体を塗りつぶす必要があります。

r2569
 r2570で対応しました。

r2570
より複雑な'outline'の処理

・ outline-color-applies-to-008

このテストではインライン要素のアウトラインの描画をテストしています。

r2563
r2564ではインライン要素から生成されるボックスが1行に収まっているような場合に関して対応しました。

r2564
・ outline-color-applies-to-012

このテストではインライン ブロック要素のアウトラインの描画をテストしています。

r2564
r2565で対応しました。

r2565
・ outline-color-175

このテストは本来はoutlineの設定を'inherit'にして動作するかを調べているのですが、r2565では違う理由で失敗していました。

r2565
このテストでoutlineを設定している上側のボックスのpositionには'relative'が設定されているので、このボックスは別のスタッキング コンテキストを構築します。r2465での問題は、このようなスタッキング コンテキストのトップレベルにあるボックスのアウトラインを描画できない、というものでした。

r2566
r2566で修正しています。

・ outline-applies-to-001

このテストはtable-row-groupのアウトラインの描画をテストしています。

r2566
r2567でテーブルの行および行グループのアウトラインに対応しました。なおoutlineプロパティはテーブルの列および列グループに対しては無効です。

r2567
・ outline-applies-to-007

このテストはテーブル セルのアウトラインの描画をテストしています。

r2567
r2568で テーブル セルのアウトラインに対応しました。

r2568
・ outline-layout-004

このテストでは、ひとつのインライン要素からインライン ボックスが複数行にまたがって生成された場合のoutlineの描画をテストしています。

この処理は難しい面があって、モジラのBug 266122を見ると、もう8年近く議論が続いていることがわかります。'outline'自体があまり使われていない、ということかもしれないですね。このテストに関してはWebKitのようなレンダリングが正しくて、現状のFirefoxのレンダリングは正しくありません。

r2568
r2568のように何も変化がないよりはよいので、r2569では、実装の容易な現状のFirefoxのようなスタイルでアウトラインを描画しています。

r2569
正しいレンダリングでは、途中の行間の緑色の線は引いてはいけません。この点も直せないことはないと思いますが、今回は優先度的にここまでにしておいて、今後の課題としておきます。

リグレッション

・ background-bg-pos-205

これは#17で宿題にしておいたテストで、マイナスの下マージンが使われていると、最下部までスクロールできない、という問題が残っていました。

r2570
r2571で再びマイナスの下マージンを考慮してスクロールできるようにしました。

r2571
またr2571でスクロールはできるようになったのですが、本来黄色のボックスの右上すぐに表示されるはずのオレンジ色のルート要素の背景画像がまだ表示されていません。r2572でルート要素の背景の表示処理のバグを修正しています。

r2572
Acid2

前回のr2518がAcid2テストでリグレッションを起こしていました。空のリスト アイテムについて、空のインライン要素のように処理して生成されるボックスに高さを持たせる、という修正でした。この処理自体は仕様書に書かれているわけではなくて、他のブラウザの動きから想像したものですがどこか間違っている、ということになります。

ちなみにr2518の修正がAcid2に影響するのは、Acid2の最後の14行目で空のリスト項目が使われているためです。このリスト項目から作られるボックス中に空のインライン ボックスが追加されることで、そのボックスを含むテーブルのセルのベースラインが変わります。その結果、テーブルのvertical-alignの処理でリストの位置がずれてr2575のようなレイアウトの崩れにつながっています。

r2575
空のリスト項目のボックスの高さは結局どこから出てくるのかと言うことになるのですが、Acid2に関して言えば、空のリスト項目の要素にheightプロパティーが設定されています。r2578では、空のリスト項目に'auto'以外のheightが設定されていれば特別な処理をしないように修正しています。期待される正確な処理については改めて調べておくことにします。

r2578
まとめ

今回でCSS 2.1テストスイートの達成率は90.1%となりました(より詳細はこちらに)。Internet Explore 9やFirefoxには追い付いていませんが、rtl, bidiが未サポートという点を考慮すると、かなり標準に沿った実装になってきていると思います。昨年の9月末から21回にわたってES ウェブ ブラウザでのCSS 2.1の実装について報告してきたわけですが、ひとまず今回でCSS 2.1の集中実装期間は終わりになります。

次回からは、ESウェブ ブラウザの最初のリリースに向けてCSS以外の機能の実装に重点を移して行きます。まずはWeb IDLの最新の仕様へのキャッチアップとWeb IDLのC++11バインディングの改良を予定しています。また、CSSの実装についても、何か改善があればその都度このブログで報告していこうと思います。

2012年3月19日月曜日

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

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

ブロック要素の'outline'

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

・ outline-layout-001

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

r2513
・ outline-color-001

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

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

r2514

・ 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パーサーは無視しないといけません。

r2514
r2515で対応しています。

r2515
・ z-index-020

このテストは9.9.1のテストですが、アウトラインのz方向の位置のテストも行っているので、ここでテストしておきます。

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

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

r2517
現状では、メジャー ブラウザでは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, ……と続いていくように定義されています。

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

r2517
・ list-alignment-001

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

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

r2518
・ counter-increment-not-generated-001

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

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

r2520
・ counter-increment-applies-to-001

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

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

r2522
・ table-header-counter-001 (ESの追加テスト)

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

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

r2523
'content' プロパティー

12.2の'content'プロパティー関連のバグの修正や未対応のattr()などの実装を進めていきます。

・ content-001

単純なテストなのですが、スタイルの中で、
content: "FAIL FAIL";
content: none;
と2回contentプロパティーを設定しています。

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

r2524
・ content-037

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

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

r2525
・ quotes-001

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

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

r2526
'cursor'プロパティー

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

・ cursor-003

このテストでは、crosshairを使っています。

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

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

テーブル関連の詳細実装

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

・ empty-cells-002

17.6.1.1の'empty-cells'のテストです。

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

r2530
・ table-footer-group-005

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

r2530
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だけを特別に処理するようにしました。

r2531
現実的にはHTMLでも、ヘッダーやフッターは1つのテーブル内には1つだけにしておいた方が良さそうですね。

・ after-content-display-008

このテストでは、匿名のテーブル ボックスを擬似要素の中から生成しています。

r2531
r2532で対応しました。

r2532
・ table-backgrounds-bc-row-001table-backgrounds-bs-row-001

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

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

r2533 (bc)
r2533 (bs)
・ table-backgrounds-bc-rowgroup-001table-backgrounds-bs-rowgroup-001

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

r2535 (bc)
r2535 (bs)

・ table-backgrounds-bc-column-001table-backgrounds-bs-column-001table-backgrounds-bc-colgroup-001table-backgrounds-bs-colgroup-001

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

r2536 (bc-column)
r2536 (bs-column)
r2536 (bc-colgroup)
r2536 (bs-colgroup)
 ・ table-layer-transparency-example-001

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

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

r2537
・ table-backgrounds-bs-table-001

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

r2537
r2538で修正しています。

r2538
・ table-backgrounds-bc-table-001

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

r2538
結合ボーダー モデルを#9で実装したときに、
各セルのボーダーに相当する幅はCellBoxクラス中ではマージンとして確保しておいて、実際の結合したボーダーの描画は TableWrapperBoxクラスで行うようにしてみました(各セルからすると、ボーダーはテーブボックスに描かれたものが透けて見えている感じにな ります)。
と書きました。この考え方で基本的にうまく描画できているのですが、#9ではテーブル ボックスまでボーダーに相当する幅をマージンに確保してしまっていました。そのため、r2538では本来背景が描画されるべきボーダーの部分の背景が描画されていませんでした(余白がリファレンスよりも広くなってしまっています)

r2539で、テーブル ボックスについてはボーダーに相当する幅はボーダー領域に確保するように修正しています。またr2542で、テーブル ボックスからはみ出たボーダーの幅は、テーブル ラッパー ボックスのマージンとつぶし合うようにしています。

r2539
・ column-width-001

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

r2542
r2543で対応しました。

r2543
・ column-width-002

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

r2543
r2544で対応しました。

r2544
・ border-style-inset-002

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

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

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

r2547
・ table-margin-002

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

r2547
このテストでは、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で対応しています。

r2548
マーカーの位置

いくつかのテストで、リストのマーカーの位置がずれていた問題を修正しておきます。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-010padding-left-applies-to-010

border-left-width-applies-to-010では、リストのマーカーの位置はリストのボックスのボーダー エッジよりも左側になるということを期待してます(左マージンの中にはマーカーがあってもよい)。

padding-left-applies-to-010では、マーカーの絶対配置ボックスをレイアウトするために作られるラインボックスの親ボックスが匿名ボックスになります。配置場所の基準はさらに匿名ボックスの親のボックスでないといけませんでした。

r2548 (border-left-width-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 (padding-left-applies-to-010)
r2550, r2551ではこれまでのリグレッションの修正をしています。

まとめ

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