Shiki’s Weblog

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

2011/10/04 #ESウェブブラウザ通信

前回はW3CのCSS 2.1テストスイートからボックス モデルのテストを8.3.1の手前まで進めました。今回はその続きです。
8.3.1のマージンのつぶしの処理は9章, 10章のフォーマッティング モデルの実装が正しくないと、つぶし合うボックスの配置自体がそもそも違う、ということになってしまいそうなので、いったん飛ばして、8.4のパディングのテストから進めていきます。
padding-bottom-003
このテストは前回r1986で実装した高さ0のボックスのマージンの潰しにバグがあったので以下のように崩れていました。

r1986r1986

r1987で、ボックス間にボーダーやパディングがある場合にマージンを潰さないように修正しています。このテストでは直接影響はありませんが、r1994では、さらにボックス間にクリアランスがあった場合にもマージンを潰さないように修正しています。8.3.1のマージンの潰しをテストするときには、まだいろいろと修正が入りそうです。

r1987r1987

padding-bottom-045
このテストはパディングに負の値を指定した場合のテストです。8.4の'Unlike margin properties, values for padding values cannot be negative.'という部分のテストですね。

r1987r1987

r1988で負のパディングの値は無視するように修正しました。

r1988r1988

c5521-ibrdr-l-000
これはインラインボックスのボーダーのテストです。

r1988r1988

ダミーのテキストの段落の5行目に1箇所、 two blue lines to the left という表示がないのに'double'のボーダーが引かれてしまっています。このテストは8.5節のテストですが、このバグは9.4.2の'When an inline box is split, margins, borders, and padding have no visual effect where the split occurs (or at any split, when there are several).'の方ですね。
テストのソースをみると、<span class="one">で作られている要素の中にさらに<span>要素があって、内側のspan要素が終わったところで、不要なボーダーを引いてしまっていることがわかります。単純な複数行のまたがりについてはボーダーを正しく処理できているけれども、複数の要素が絡んできた場合のバグが残っているわけです。

r1989r1989

r1989で、このような場合に分割された最初のテキストノードの左端と最後のテクストノードの右端にだけボーダーを表示するように修正しています。ただより複雑なケースだとこの修正ではうまくいかない場合が考えられるので、合わせてTODOを追加しています(9.4.2のテストでそういった場合がある筈かなと)。
c5517-brdr-s-000
このテストではボーダー スタイルを一通り使ってみています。

r1989r1989

点線が角の部分で綺麗に連続していないという問題もあるのですが、groove, ridgeなどを指定した場合の明るい部分と暗い部分の色の変化を付け過ぎてしまっていたのをr1990でとりあえず直しました。

r1990r1990

実際の色の計算について、8.5.3では'UAs may choose their own algorithm to calculate the actual colors used.'ということになっているので適当な実装で済ませてしまっています。本当は、HSVに変換して明度を操作して、というのがいいのかもしれないですね。
border-bottom-width-036
このテストは本来はcm単位でボーダーの幅を指定できているかどうかを調べているのだと思うのですが、r1990の段階ではz-indexの処理のバグために赤い部分が見えてしまっています(基本的にCSSテストスイートでは何か赤いものが表示されればエラーです)。

r1990

z-indexは9章の機能なのでここではパスしてもよかったのですが、r1991で修正しています。

r1991r1991

border-bottom-width-083
このテストは、ボーダーの幅の指定に単位'ex'を使っています。r1991の段階では'ex'を単純にフォントサイズの半分としていたので、下のように崩れたようなっています。

r1991r1991

CSS 2.1のテストスイートでは、Ahemフォントというフォントを使っているのですが、このフォントでは'ex'で使用するx-heightの値がTrueTypeフォントのOS/2テーブルに格納されています。r1992では、このTrueTypeフォントの情報からx-heightの情報を取り出せるように、r1993では、そのx-heightを'ex'の計算に使用するように、それぞれ修正しています。

r1993r1993

現状のESウェブブラウザでは(configureの際に)/usr/share/fonts/ahemにAHEM____.TTFがあれば利用するようになっています。本当は別のディレクトリを指定できた方が良さそうなので、どこかで修正するかもしれません。
なお、Ahemフォントを利用しているCSS 2.1のテストには、一覧のFlagsというところにAhemと記載されています。ESウェブブラウザの場合、freetype2の設定方法の問題のためか小数点以下でascending、descendingの値がTrueTypeフォント中での指定と異なっているようで、フォントが描画される位置が下のように微妙にずれてしまっています。この点に付いては既知のFontManagerの実装の問題ということでしばらく無視して進めていきます。

c412-hz-box-000 でのAhemフォントの表示c412-hz-box-000 でのAhemフォントの表示

border-bottom-color-049
このテストは単純に色の指定にrgb(1%, 1%, 1%)とパーセンテージを使っているだけなのですが、バグのために全然違うRGBの値を算出していました。

r1994r1994

r1995でこの問題は修正しています。

r1995r1995

border-bottom-width-012
このテストにはInvalidフラグが付いているのですが、border-bottom-widthにあえて無効な負の値を設定してみる、というテストです。

r1996r1996

r1996ではわざわざボーダーを逆y方向に向かって展開して引いてしまっています。

r1997r1997

r1997で、ボーダーの幅が負の時は初期値の'medium'の太さとして扱うように修正しました。不正なCSSの設定はないものとして扱うのが普通なのでこういう動きになる、という解釈だと思います。
border-bottom-016
このテストは'border-bottom: inherit;'という設定が働くかどうかテストしています。

r2003r2003

r2004で、'border-top', 'border-right', 'border-bottom', 'border-left'についてショートハンドの処理を正しくできていなかったバグを修正しています。

r2004r2004

ちなみにこのテストに関するr1996の修正は誤りだったので、r2003でリバートしています。ESウェブブラウザでは各プロパティごとに継承するかどうかのフラグを持っているのですが、ショートハンドについてはフラグはショートハンドで指定できる個々のプロパティに立てるようになっています。
これで8章については、8.3.1のマージンのつぶしを除いて、マイクロソフト社から提供された基本的なスイートについてはパスするようになりました。ひとまず8章は終わりにして、9章へ進みます。
first-line-selector-014
このテストがビューポートのテストに入っている理由は、ウィンドウのサイズを変えたときもちゃんと表示されるかどうかみなさい、ということのようです。CSSのテストスイートでは同じテストが複数の章に出てくる場合があって、このテストは5章のセレクタのテストや16章のテキストのテストにも含まれています。

r1997r1997

r1997では、text-transformプロパティに未対応だったためにテストに適応していません。ただそれ以外のセレクタの処理などは実装が既に含まれているので、ついでに修正してしまいます。
r1998ではtext-transformプロパティをパースしてCSSStyleDeclarationImpクラスに格納するように、r1999では実際にtext-transformを適用しながら文字列の描画に必要な幅を計算するfitTextWithTransformation()を追加して、r2000ではこれらを組み合わせて実際にtext-transformプロパティの効果が画面上に表示されるようにしました。

r2000r2000

なお、r1999のfitTextWithTransformation()の実装は文字単位の単純な変換処理の実装になっています。英文ならこれでも大丈夫ですが、多言語に対応するためにはICUのFull Case Mapping等を使った実装に修正する必要があります。今のところESウェブブラウザは、日本語と英語以外にきちんと対応できていないので、今はこのまま先に進めます。
containing-block-029

これは:beforeセレクタでposition: absolute;を指定しているテストです。:before, :afterでできることには特に制約がないので実装も気をつけないといけないところです。

r2004r2004

r2004では、:beforeで生成したボックスがウィンドウの右下に配置されてしまっています。包含ブロックを正しく見つけられていないわけです。

r2005r2005

r2005では、この問題を修正しました。

anonymous-boxes-001

このテストは本来テストしたい内容がいまひとつ明確でない気もしますが、r2005では以下のように崩れていました。

r2005r2005

このテストでは、float: left;で緑色のボックスを、position: absoluteで大きさと位置が同じ赤いボックスを表示しています。DOMツリー中では緑色のボックスが赤いボックスの後に来るので本来は緑色で表示されるのが正解になります。

ESブラウザの実装では、floatもabsoluteもラインボックス中に保持されるようになっていって、単純に左から描画しています。そのため、DOMツリーでの順番が無視されて緑色float: leftのボックスが先に描画されて、あとで赤いボックスに上書きされてしまっていました。

r2006r2006

r2006ではとりあえずOpenGLに指定するz座標の値の小数点以下を利用して、DOMツリー中の順序を考慮するようにしています。ただこの実装はまだ問題がいくつかあるので、宿題になっているMultisample Transparencyを使わないz-indexの実装をするときに改めて修正します。

inline-box-002
このテストは、9.2.2.1の' When an inline box contains an in-flow block-level box, ...'で始まる段落のテストになっています。この段落はCSS 2の勧告にはなく、CSS 2.1で明確化された部分のひとつのようです。r2006では、以下のように崩れていました。

r2006r2006

r2007でこの問題を修正しています。

r2007r2007

このテストはWebKit系のブラウザでも10/2時点ではESウェブブラウザと同じように表示が崩れているようなので多少細かく問題点をまとめておきます。このテストのレンダー ツリーをテキストで表示すると、以下のようになります。

* block-level box [html]
  * block-level box [body]
    * block-level box [p]
      * line box
        * inline-level box "Test passes if the orange box is between the two blue boxes and all three boxes are below the yellow box."
    * block-level box [div]
      * block-level box [anonymous] (id="div2")
        * line box
          * inline-level box "Filler Text"
      * block-level box [div] (id="div3")
        * line box
          * inline-level box "Filler Text"
      * block-level box [anonymous] (id="div2")
        * line box
          * inline-level box "Filler Text"

id="div2"が指定されているdisplay: inlineのdiv要素は、仕様書にも記載されているとおり、レンダー ツリー中ではid="div3"のdiv要素をはさんで2つのanonymousブロック レベル ボックスに展開されています。CSS 2.1の仕様では、div2に指定されている'position: relative; width: 2in;'という相対位置指定を、レンダー ツリー中では兄弟関係であっても、DOMツリー中で子要素にあたるdiv3のdiv要素にも適用させなさい、と規定しているわけですね。
大抵はDOMツリー中で親子関係にある要素は、レンダーツリー中でも親子関係になっているので、相対位置指定は親の要素に反映すれば自動的に子要素にも反映されるわけですが、このテストのような場合に限ってはレンダーツリー中では兄弟関係になってしまうので見落としがちなのかなと思います。
今回はここまでです。次回も9章のテストスイートの続きから進めていきます。