Shiki’s Weblog

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

2011/11/20 #ESウェブブラウザ通信

前回8.3.1のマージンのつぶしのテストを行いました。今回は10章までのテストでもうひとつまるごとスキップした10.8のline-heightのテストを進めていきます。

単純なline-heightのテスト

line-height-001 line-heightに不正な負の値を指定した場合に、指定を無視しているかどうかテストしています。Microsoft社から提供されたテストにはこういった値域のテストが必ず入っていますね。

r2131r2131

r2132で修正しています。

r2132r2132

line-height-002 このテストでは、インラインレベルボックスのline-heightに0を設定して値がそのまま使用されるかどうか確認しています。line-heightはブロックコンテナに指定された場合はラインボックスの高さの最小値の指定になりますが、インラインレベルボックスについてはその値がそのまま計算値になります。

r2132r2132

r2132では、line-heightをすべて最小値扱いにしていたために、左側のAhemフォントの"X X"の部分で改行が入ったときにフォントの高さ分だけ2つめの'X'が下にずれてしまっていました。

r2133r2133

r2133で修正しています。このテストの場合、高さ0のラインボックスを含むブロックレベルボックスでもcollapse throughはできない、という状況になっているので、前回修正したmargin collapseまわりの隠れていたバグも合わせて修正しています。ESウェブブラウザでは、インラインボックスにほぼ対応するInlineLevelBoxクラスのheightにはコンテントエリアの高さ(基本的にはフォントの高さ、AD)を格納しています。line-heightはラインボックスの高さとしてだけ残ります。

line-height, AD, and Lline-height, AD, and L

すこし分かりにくいので図でまとめておくと、 ライム 色の線で示したラインボックスの高さはline-heightの設定が使われるのに対して、 アクア 色で示したコンテントエリアの高さは使用しているフォントのAD(Ascent-Decent)で与えられます。レディング(L)は、L='line-height'-ADで計算されるので、ADをコンテントエリアの高さとした場合、コンテントエリアの高さにLは一切含まれないことになります。また、インラインボックスのパディング、ボーダー、マージンは(line-heightとは無関係で)アクア色で示したコンテントエリアの外側からはじまります。特に、このテストでは、line-heightが0なので、Lは-ADとなり、インラインボックスはAD/2だけラインボックスの上側の位置からはじまることになります。

line-height = 0 のときline-height = 0 のとき

このあたりCSS 2.1の仕様はわりと未定義で、10.6.1で、

The height of the content area should be based on the font, but this specification does not specify how.

The vertical padding, border and margin of an inline, non-replaced box start at the top and bottom of the content area, and has nothing to do with the 'line-height'.

という記述があって、line-heightとcontent areaを区別しているものの、10.8.1でも、

CSS 2.1 does not define what the content area of an inline box is and thus different UAs may draw the backgrounds and borders in different places.

と改めてコンテントエリアの詳細は未定義としているのです。その分、実際のウェブブラウザの実装ではどう実装するかこのように決めておく必要がある、というわけです。(ADの定義はどうなっているの?という話もあるのですが、それは今回後の方でまた触れます。) ひとまず、このr2133の修正でMicrosoft社で開発されたline-height-xxxシリーズのテストはすべてパスするようになりました。

単純な vertical-alignのテスト

より複雑なline-heightのテストに進む前に、同様にMicrosoft社で開発されたシンプルなvertical-align-xxxのテストを進めておきます。

この一連のテストに関してはr2133の段階ではかなりのテストでブラウザ自体がassertで落ちていました。'vertical-align'の計算値を求める際に'line-height'が'normal'だとパーセンテージの計算が不可能、というのが理由でした。r2134, r2135では計算値と解決値の2段階に分けて解決するようにしましたが、こういう場合、'vertical-align'の設定をinvalidとして初期値の'baseline'扱いにしたいいのかもしれません(未テストです)。なお、vertical-alignの処理では、インライン要素の親にさらに別のインライン要素がある場合など少し複雑な処理が発生するのですが、今回はそういった複雑なパターンはスキップして、ラインボックスの中に単純にインラインボックスがある場合にだけ対応していきます。(入れ子のインライン要素の処理については、テキストまわり処理と一緒に修正していく予定です。)

vertical-align-baseline-004

r2136r2136

こちらはテスト本来の意図であるインラインボックスのアラインの処理ではなくて、ラインボックスの高さの計算にバグがありました。

r2137r2137

r2137で修正しています。薄い縦線はAhemフォントの描画によるものです。・vertical-align-baseline-005

このテストではインラインブロックのoverflowに'hidden'が指定されている場合のベースラインの計算をチェックしています。標準に従っていれば、ベースラインは下マージンのエッジと同じ位置なので、下マージンのあるオレンジのボックスは青いボックスよりも上側に配置されます。

r2137r2137

r2138で修正しています。

r2138r2138

本当は左右の青いボックスの間も青く塗られるべきなのですが、現状は入れ子になっているインラインボックスでは外側のインラインボックスのスタイルは画面に描画できない、というバグがあります。

vertical-align-baseline-006 このテストもインラインブロックのベースラインの計算に関するテストです。先ほどのvertical-align-baseline-005とは違って、インラインブロックがvisibleなのでベースラインはインラインブロック中の最後のラインボックス(もしあれば)のベースラインに合わせないといけません。

r2138r2138

r2139で修正しています。

r2139r2139

vertical-align-121 このテストは成功すれば十マークが表示されます。

r1240r1240

ラインボックスで保持するベースラインの計算にバグがあったのでr2141で修正しています。

r1241r1241

ここまでで、vertical-alignの基本的なテストにはパスするようになりました。入れ子のインライン要素の対応などが必要な sub, super, text-bottom, text-top 等はテキストまわりの処理を改善するときに合わせて対応する予定です。

line-heightのより複雑なテスト

line-box-height-001 このテストは結構ややこしいものがあります。こちらでも指摘されているように、HTMLファイル中に記載されているテストの説明は実際の動作とはほとんど無関係に思います。ただ、成功した場合は左右のボックスの高さが同じになります。

r2139r2139

左側の青いボックスは実際はAhemフォントの"X"が縦に2文字並んだものです。r2139では青いボックスが低くなってしまっていますが、これは2文字目の"X"の開始位置がレディングが計算式'line-height'-ADに従うと0-96pxで-96pxとなって、その半分の-48px分だけ上にずれているのです。今回2番目にテストしたline-height-002もやはりline-heightが0で文字の位置はフォントの高さの半分だけ上にずれていました。このテストの場合には上にズレない、という点をどう仕様から解釈するのかがちょっと謎なのです。line-height-002との違いはインライン要素の方はどちらも'line-height'が0なのですが、ブロックコンテナの方がline-height-002は0、今回のline-box-height-001は'normal'という点です。そこでレディングの計算式を、

L = max(インライン要素のline-height, ブロックコンテナのline-height)- AD

のように変更すると、他のテストも崩すことなく、うまく行くようです。(このあたりCSSの仕様書でもうすこしクリアになっているといいと思いますが、どうでしょう?)

r2140r2140

c548-ln-ht-000

r2142r2142

このテストに関しては上側の'line-height'を使っている方ではなくて、下側のpre要素の方で改行を含んだテキストの行の折り返しと描画処理(改行コードを描画してしまっている)にバグがありました。r2143で修正しています。

r2143r2143

line-height-bleed-003 このテストはインラインレベルボックスのline-heightは0だけれど、ボーダーはline-heightは関係なくてコンテントエリアの回りに引いているかどうかをテストしています。

r2144r2144

r2145で描画まわりを修正しています。なお、ラインボックスの高さはコンテナのline-heightが'normal'なので、BR要素でふつうに1文字の高さ分だけ改行されています。

r2145r2145

c44-ln-box-003 このテストは緑色の枠の中が真っ白になればOKです。

r2143r2143

r2144で1行にいろいろなボックスが入っている場合のレディングの計算まわりのバグを主に修正しています。r2143で赤色の横長の線になって見えている部分です。このテストではインラインのimg要素にマイナスの水平方向のマージンを使っているので、赤い縦長の線はマージンの処理のバグのように思えたのですが、実際にはwhite-spaceの処理にバグがあってimgの直前のテキストの最後の空白を余計に消去してしまっていたのでした。r2147,r2150でwhite-spaceのバグを修正しています。なお、この前後でボックスの水平マージンの処理も見直して、r2148でだいたい落ち着きました。通常のブロックでは右マージンがマイナスだとボックスの幅が広がるのに対して、インラインでは次のインラインブロックの開始位置がその分左にずれるだけなので、少し場合分けが必要な場面が残っていました。

r2148r2148

margin-inline-002 このあたりで10.8のline-heightのテストで今回対応しておきたかったものはパスするようになりました。ただ以前も一度修正したことがあるこの8章のテストがまた崩れてしまっていたので修正します。

r2151r2151

このテストで暗黙に仮定されていることは、line-heightが'normal'のときはコンテントエリアの高さとラインボックスの高さは一致しないといけない、というものです。r2151では仕様書の推奨にならってコンテントの高さに使用するADをTrueTypeフォントのsTypoAscender - sTypoDescenderとしていたわけですが、以前#4で、position-relative-035をパスするためには'normal'のラインの高さはラインギャップを含んだusWinAscent + usWinDescentとしなければいけない、ということがありました。で、ESウェブブラウザではコンテントエリアの高さをADとするように決めたわけですから、仕様書の推奨はここでは無視してADはusWinAscent + usWinDescentに合わせておくようにします。修正はr2152になります。

r2152r2152

ちなみにESウェブブラウザでよく使用しているIPAGothicフォントとAhemフォントのOS/2テーブルの内容は以下のような感じになっています。 IPAGothic units_per_EM 2048 sTypoAscender 1802 sTypoDescender -246 sTypoLineGap 0 usWinAscent 1802 usWinDescent 401 sxHeight 1040 Ahem units_per_EM 1000 sTypoAscender 800 sTypoDescender -200 sTypoLineGap 0 usWinAscent 800 usWinDescent 200 sxHeight 800 sTypoLineGapの値はまったく当てにならなくて、フォント デザイナの想定しているラインギャップはusWinAscent+usWinDescent-units_per_EMで計算しないといけない、Ahemフォントにはラインギャップがない、といったことがわかります。この辺はラインギャップありのフォントも別途用意してテストケースを作っていった方がいい感じがしますね。

まとめ

今回はここまでです。9月下旬から進めてきたCSS 2.1のテストスイートによるテストも、ようやく1/3強のテストにパスするようになりました。複雑なテストで個別にスキップしているものは残っているのですが、テキストが絡まなければボックスのレイアウトはだいたい標準通りになってきたように思います。大物のテーブルとテキストがまだ残っていますが、ESブラウザ全体としてみるとCSSモジュールの開発だけが一歩進んだ感じになってきているので、今後はCSS以外の部分の開発もペースを上げていきたいところです。