序文
WebkitでのCSSの実装は比較的独立したモジュールに属しますが、ここで述べていることは相対的なものであることに注意してください。
WebkitにおけるCSSの役割は自明です。Web の初期、ドキュメントの構造とスタイルが分離されていなかったとき、 HTML はドキュメントの構造とスタイルの二重のタスクを引き受けました。つまり、HTML はドキュメントの構造を担当し、ドキュメントのスタイルもHTMLのタグの属性によって指定されました。当時のHMTLページの開発や利用は現在よりも不便だったと考えられます。
しかし、よく考えてみると、これは当時の技術開発のレベルと大きく関係しているのかもしれません、第一に、インターネットは今ほど普及していませんでしたし、ウェブページも今ほど複雑ではありませんでしたし、今と違って世の中の情報発信の主流はウェブページであると言えますし、それを説明できるデータはありませんが、少なくともそういう傾向だったのではないかと思います。このようにインターネットは進歩を続け、Webの開発形態を大きく改善したCSSの登場以降、ドキュメントの構造とスタイルは 2 つに明確に分かれるようになりました。HTMLは主にドキュメントの構造を担当し、CSSはドキュメントのスタイルを指定します。
CSSについてはすでにインターネット上で多くの紹介がなされていますが、ここでは主にWebkit実装の観点から紹介します。
1.CSSとは何ですか?
CSSはCascading Style Sheetsの略で、公式の定義によれば、構造化文書 (HTML 文書) のスタイルを指定できるスタイル シート言語と見なされます。CSS を使用すると、ユーザーはドキュメントのコンテンツとスタイルを分離できるため、Web ページの開発と保守が簡素化されます。
スタイルシート言語と言われるだけあって、スタイルシートの記述方法を定めた文法規則があり、その機能や文書内容が書き手の望む体裁を実現することができます。CSSの文法規則は比較的単純で、トップダウンの観点から見ると、カスケード スタイル シート ( CSS ) は一連の規則 ( ruler ) で構成され、各規則はセレクター ( selector ) といくつかの宣言 ( Declaration )で構成されます。各宣言 ( Declaration ) はキーと値のペアであり、次の図に示すように、属性 ( property ) と値 ( value ) で構成されます。
ここからわかるように、構文は非常に単純で、実際に使用するのも非常に簡単です。なお、ここでは「使いやすい」というだけで、鉛筆と同じで誰でも使えますし、もちろん鉛筆もこれ以上簡単なわけではありませんが、とてもありふれた道具であり、プロと一般の人の手で作れるものは全く違います。つまり、何が言いたいかというと、CSSの使い方をすぐに覚えられるからといって、美しいWebページが作れるわけではなく、あくまでツールであり、どこまで使いこなせるかは人によるということです。
裏を返すと、その単純な構文からは対応するプログラミング モデルに変換するだけのように見えますが、実際には CSS の実装はまだ比較的複雑です。その複雑さは CSS 自体の複雑さにあります。スタイルを指定する要素、継承されるスタイルと継承されないスタイルの継承関係、および同じ要素に作用する複数のスタイルの重ね合わせを決定するための一連のルールが定義されており、指定できるすべてのスタイルに対応する属性の完全なセットを持っています。。したがって、実装の観点から見ると、完全な標準互換のCSS実装のために考慮する必要があることがまだ多くあります。
2. CSS実装モデル
Webkit CSS部分の実装コードは、ディレクトリwebcore/cssにあります。これは、webkitの比較的独立したモジュールです。次のクラス図は、CSS実装をよりよく理解するために私が作成したもので、CSSの内部実装の概要を示しています。
ユーザーが作成したCSSドキュメントは、最終的にwebkit内のモデル表現に変換されます。ここにはいくつかの重要なクラスがあります。
3.CSSデフォルトスタイルシート
Webkit CSSの実装から、スタイル シートを指定しなくても、実際には、CSSモジュールが動作するときに、いくつかのデフォルト スタイル シートがロードされることがわかります。CSSStyleSelectorのコンストラクターでは、関数loadDefaultStyle()が常に呼び出され、その機能がデフォルト スタイル シートをロードすることを知っておく必要があります。
これらのデフォルトのスタイル シートには、一部のHTML要素の最も基本的なスタイル情報が含まれています。CSSを使用するほとんどのユーザーは正しくないと思います
デフォルトのスタイル シートは次の 4 つです。
- html4UserAgentStyleSheet。
- quirksUserAgentStyleSheet。
- svgUserAgentStyleSheet。
- ソースUserAgentStyleSheet。
さて、1と2は名前からも大まかに分かると思いますが、これらはファイルとして保存されるのではなく、CSS上の文字配列の形で現れる、つまりデータとしてコードにコンパイルされるもので、I/Oによるパフォーマンスの低下を軽減するために毎回デフォルトのスタイルシートを使用する必要があると考えるべきです。
先ほど述べたことを説明するために、これらのデフォルトのスタイル シートには HTML 要素に関する最も基本的な情報の一部が記述されています。例を見てみましょう。
たとえば、html4UserAgentStyleSheet は、名前からわかるように、これは伝説的なブラウザのデフォルト スタイル シートです。それが何なのか見てみましょう。ここではほんの一部を紹介します。
html {
2 display: block
3 }
4
5 head {
6 display: none
7 }
8
9 meta {
10 display: none
11 }
12
13 title {
14 display: none
15 }
16
17 link {
18 display: none
19 }
20
21 style {
22 display: none
23 }
24
25 script {
26 display: none
27 }
28
29 body {
30 display: block;
31 margin: 8px
32 }
33
34 p {
35 display: block;
36 margin: 1.0__qem 0px
37 }
38
39 div {
40 display: block
41 }
42
43 layer {
44 display: block
45 }
上記からもわかるように、実際には最も基本的な属性の一部の指定ですが、これらのデフォルト値の指定がない場合、ユーザーが自分でこれらのルールを追加する必要があり、非常に面倒になります。
他のテーブルはここでは分析されません。
4.CSSの解析
CSSを使用する場合は、その文法仕様に従って一連のルールを記述し、それを **.cssファイルとして保存し、 htmlで参照するだけです。もちろん、外部スタイル シートを使用する方法はCSSの使用方法の 1 つにすぎません。ここでは CSS** の使用方法をいくつか説明するつもりはないので、外部スタイル シートを使用します。
では、文法規則に従って記述されたこのCSSスタイルシートは、どのようにしてWebkit内のCSSモデルに変換されるのでしょうか。当然、字句解析と文法解析が必要になります。ここでは、Webkit は自動コード生成ツールを使用して対応するコードを生成します。つまり、字句解析と構文解析のコードは自動的に生成されますが、それらは完全ではありません。その後、実際の CSS モジュールを動作させるために、一致するコードを記述する必要があります。率直に言うと、これらの自動生成されたコードを Call Back させるための関数をいくつか記述する必要があります。他のタイプのパーサーを使用したことがある友人は、これに精通しているはずです。コードのこの部分に興味がある人は、勉強してみてください。クロスプラットフォームのバグを見つけるためにコードのこの部分を調整しました。構造は非常に単純ですが、コードはもう少し見た目が良くなります。入口はyylexとyyparseですので、興味のある方はご自身で覗いてみてください。
では、これらのコールバックはWebkitのどこに実装されているのでしょうか? It's in CSSParser . 明らかに、生成されたコードとは別に、これは手動で実行する必要があるCSS解析コードの一部です。CSSの一部の解析関数の入り口もここにあり、 lex、parseなどを呼び出してコードを生成します。対照的に、生成されたコードで必要なコールバックもここで実装する必要があります。
例として、汎用ルールを作成する必要があるときに呼び出される、より大きな単位のコールバック関数createStyleRule()の実装を見てみましょう。
CSSRule* CSSParser::createStyleRule(CSSSelector* selector)
{
CSSStyleRule* rule = 0;
if (selector) {
rule = new CSSStyleRule(styleElement);
m_parsedStyleObjects.append(rule);
rule->setSelector(sinkFloatingSelector(selector));
rule->setDeclaration(new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties));
}
clearProperties();
return rule;
}
この関数の実装から、パーサーが特定の条件を満たし、 CSSStyleRuleを作成する必要がある場合、この関数が呼び出されることは明らかです。この関数の機能は、CSSStyleRule を作成し、解析されたスタイル オブジェクト リストm_parsedStyleObjectsに追加することです。ここでのオブジェクトはRuleを指します。このように、解析後、入力スタイル シート内のすべてのスタイル ルールがWebkitの内部モデル オブジェクトCSSStyleRuleオブジェクトに変換され、これは Vector であるm_parsedStyleObjectsに保存されます。
このような関数には、 createCharsetRule、createImportRule、createMediaRuleなどが含まれます。これらの関数は通常、 createStyleRuleに似ており、すべてRulesを作成するために準備されていますが、異なるタイプのRulesです。
上記を理解すると、CSS解析がどのように機能するかをほぼ理解できるようになります。しかし、分析したい結果は何でしょうか? CSSStyleSheetのparseString関数を呼び出すと、 CSS解析プロセスが開始され、解析後、すべてのルールが対応するCSSStyleSheetオブジェクトに格納されます。ただし、現時点ではルールはまだ扱いにくいため、CSSRuleSetに変換する必要があります。CSSRuleSetにはaddRulesFromSheetメソッドが用意されており、これによりCSSStyleSheetのルールをCSSRuleSetのルールに変換できるため、すべての純粋なスタイル ルールが対応するコレクションに格納されます。このコレクションの抽象化はCSSRuleSetです。将来的には、各ページの要素のスタイルは、後で紹介するこれらのCSSRuleSetに基づいて決定できるようになります。
5. CSS が Render Tree でどのように機能するか
Render Treeに対するいわゆるエフェクトとは、実際には、上記の解析結果に基づいて、対応するRender Objectに特定のスタイルを指定することを指し、このスタイルの抽象化はRenderStyleです。