QT分析之WebKit(八)

來源:互聯網
上載者:User
QT分析之WebKit(八)

程式人生 2010-03-08 10:20:23 閱讀937 評論0   字型大小:大小 訂閱

分析到HTML解析,看到一個博士的blog,對WebKit結構的解析相當犀利,轉貼如下:
鄧侃的部落格

http://blog.sina.com.cn/s/blog_46d0a3930100d5pt.html
【20】WebKit的結構與解構

從指定一個HTML文字檔,到繪製出一幅布局複雜,字型多樣,內含圖片音頻視頻等等多媒體內容的網頁,這是一個複雜的過程。在這個過程中Webkit所做的一切,都是圍繞DOM Tree和Rendering Tree這兩個核心。上一章我們談到這兩棵樹各自的功用,這一章,我們借一個簡單的HTML檔案,展示一下DOM Tree和Rendering Tree的具體構成,同時解剖一下Webkit是如何構造這兩棵樹的。Figure 1. From HTML to webpage, and the underlying DOM

tree and rendering tree.
Courtesy http://farm4.static.flickr.com/3351/3556972420_23a30366c2_o.jpg

1. DOM Tree 與 Rendering Tree 的結構

Figure 1中左上是一個簡單的HTML文字檔,右上是Webkit rendering engine繪製出來的頁面。頁面的內容包括一個標題,“AI”,一行本文,“Ape's Intelligence”,以及一幅照片。整個頁面分成前後兩個層面,標題和本文繪製在前一個層面,照片處於後一個層面。L君和我亦步亦趨地跟蹤了,從解析這個HTML文字檔,到產生DOM Tree和Rendering Tree的整個流程,目的是為了瞭解DOM Tree和Rendering Tree的具體成份,以及構造的各個步驟。

先說Figure 1中左下角的DOM Tree。基本上HTML文字檔中每個tag,在webkit/webcore/html中都有一個class與之對應。譬如<HTML> tag 對應HTMLHtmlElement,<HEAD> tag 對應HTMLHeadElement,<STYLE> tag 對應HTMLStyleElement 等等。比較特別的是DOM Tree的根節點,HTMLDocument,在HTML文字檔中沒有哪個tag與之對應。關於HTMLDocument的作用,我們稍後介紹。整個 DOM Tree的結構,與HTML文字檔中各個tags的嵌套關係也一一對應。一言以蔽之,DOM Tree就是把HTML文字檔翻譯成object樹狀結構。

需要強調的是,DOM Tree是一個通用資料結構,任何XML文字檔都可以翻譯成DOM Tree,而不僅僅限於HTML文字檔。webkit/webcore/html 中林林總總html classes,基本上都是webkit/webcore/dom 中的某個class的子類,也就是說,/html 是 /dom的一個特例。這樣的設計,為將來把Webkit拓展到HTML格式以外的頁面的布局和渲染,埋下了伏筆。所以嚴格地講,Figure 1中左下的DOM Tree,實際上是一個HTML DOM Tree。

再看Rendering Tree,顯著的特點在於,

a. 整個Rendering Tree樹狀結構,與HTML DOM Tree樹狀結構一一對應。也就是說,幾乎每個HTML DOM Tree中的節點,在Rendering Tree中都有對應的節點。節點與節點之間的父子或兄弟關係也一一對應。

例外的是,在HTML DOM Tree有HTMLStyleElement葉子節點,而在Rendering Tree中,沒有相應的葉子節點。原因是,Rendering Tree各個節點,都涉及頁面中某塊地區的布局和渲染。而HTMLStyleElement,並不直接涉及某塊地區的布局和渲染,HTML DOM Tree中HTMLStyleElement葉子節點包含的內容,已經融入Rendering Tree中RenderImage葉子節點的屬性中去了。另外,因為Rendering Tree中不存在與HTMLStyleElement相應的葉子節點,所以,與HTMLHeadElement對應的節點也沒有必要存在。

b. webkit/webcore/rendering中各個class與HTML tags並沒有一一對應的關係。

Rendering Tree是一個通用的規劃頁面配置和渲染的機制,這個通用機制可以服務於HTML頁面,但是並不僅僅限於為HTML頁面服務,我們可以用 Rendering Tree來規劃其它格式的頁面的布局和渲染。以DOM Tree和Rendering Tree為核心的Webkit渲染機,是一個功能強大,擴充性良好的通用渲染機。它不僅可以用來繪製HTML頁面,也可以用來渲染其它格式的頁面,譬如可以用它來製作email閱讀和管理器,製作資料庫管理工具,甚至製作遊戲介面。

稍微讓人有點吃驚的是,對於 HTMLHtmlElement,HTMLBodyElement,HTMLHeadingElement和HTMLParagraphElement,在Rendering Tree中通通以RenderBlock呼應。如果說HTMLHeadingElement和HTMLParagraphElement的區別不大,僅僅是字型和對齊有些微小的差別,所以Rendering Tree可以用RenderBlock來統一應對。那麼問題是,HTMLHtmlElement和HTMLBodyElement是兩種容器,總是出現在 DOM Tree的中部,而從來不會作為葉子節點出現,對應於這樣的容器節點,為什麼Rendering Tree不另設一種class,與RenderBlock有所區別呢?不過話又說回來,這不是個大問題,最多是個美感的問題。

Figure 2. The construction sequence of the root of the DOM tree.
Courtesy http://farm4.static.flickr.com/3010/3554310018_e34d271344_o.jpg

2. DOM Tree 與 Rendering Tree 的根節點

前一節中我們提到HTMLDocument是一個比較特殊的class,它是整個HTML DOM Tree的根節點,但是不對應任何HTML tag。JavaScript中經常出現的document,指的就是這個根。例如,
 

   “document.getElementById(x).style.background="yellow";”

HTML文字檔,通常是以<HTML>開頭,以</HTML>結尾。但是<HTML> tag並不對應DOM Tree的根節點,而是根以下的第一個子節點,即HTMLHtmlElement節點。

初看Figure 2 覺得有點意外,當使用者在瀏覽器裡開啟一個空白頁面的時候,立刻產生了DOM Tree的根節點HTMLDocument,與Rendering Tree的根節點RenderView。而這個時候,使用者並沒有給定URL,也就是說,對於瀏覽器來講,這時候具體的HTML文字檔並不存在。根節點與具體HTML內容相脫節,或許暗示了Webkit的兩個設計思路,

a. DOM Tree的根節點HTMLDocument,與Rendering Tree的根節點RenderView,可以重複利用。

當使用者在同一個瀏覽器頁面中,先後開啟兩個不同的URLs,也就是兩個不同的HTML文本文時,HTMLDocument和RenderView兩個根節點並沒有發生改變,改變的是HTMLHtmlElement以下的子樹,以及對應的Rendering Tree的子樹。

為什麼這樣設計?原因是HTMLDocument和RenderView服從於瀏覽器頁面的設定,譬如頁面的大小和在整個螢幕中的位置等等。這些設定與頁面中要顯示什麼的內容無關。同時HTMLDocument綁定HTMLTokenizer和HTMLParser,這兩個構件也與某一個具體的HTML內容無關。

b. 同一個DOM Tree的根節點可以懸掛多個HTML子樹,同一個Rendering Tree的根節點可以懸掛多個RenderBlock子樹。

在我們目前所見到的瀏覽器中,每一個頁面通常只顯示一個HTML檔案。雖然一個HTML檔案可以分割成多個frames,每個frame承載一個獨立的 HTML檔案,但是從DOM Tree結構來講,HTMLDocument根節點以下,只有一個子節點,這個子節點是HTMLHtmlElement,它領銜某個HTML文字檔對應的子樹。Rendering Tree也一樣,目前我們見到的網頁中,一個RenderView根節點以下,也只有一個RenderBlock子節點。

但是Webkit的設計,卻允許同一個根以下,懸掛多個HTML子樹。雖然我們目前沒有看到一個頁面中,並存多個HTML檔案,並存多個布局和渲染風格的情景,但是Webkit為將來的拓展留下了空間。前文中所設想的個人化,多皮膚,多視角的瀏覽器頁面繪製,用Webkit實現起來難度不大。

Figure 3. The construction sequence of the DOM Tree and the Rendering Tree.
Courtesy http://farm4.static.flickr.com/3627/3554182242_b0bec88534_b.jpg

 

3. DOM Tree 與 Rendering Tree 的構築

HTMLDocument 根節點包含的最重要的構件是HTMLTokenizer,而HTMLTokenizer又包含HTMLParser這個構件。HTMLTokenizer 從前到後讀取HTML文字檔中每一個字元,並從中提取出各個HTML tags以及它們的內容。而HTMLParser不僅負責HTML DOM Tree的構築,而且也同時負責Rendering Tree的構築。

在Figure 3中,從第8步到第11步,HTMLParser根據一個HTML Tag產生一個HTML DOM Tree節點。從第12步到第17步,產生相應的Rendering Tree的節點,並把它和HTML DOM Tree的節點勾連在一起。這張圖的細節過多,讀解不容易。Figure 4把第8步到第17步示範了一下。

Figure 4. An illustration of the construction of a DOM tree node and its corresponding Rendering tree node.
Courtesy http://farm4.static.flickr.com/3306/3554259140_3deb9736ea_o.jpg

值得注意的是,每當HTMLParser產生一個DOM Tree的節點的時候,相應地,也同時產生一個Rendering Tree節點。然後把它們兩個新節點勾連在一起。換而言之,Rendering Tree與DOM Tree同步生長。

Webkit 值得讚賞的地方非常多,但是HTMLParser讓DOM Tree和Rendering Tree同步生長的做法,卻值得商榷。如果同步生長,那麼Rendering Tree必然平鋪直敘地刻板地忠實於DOM Tree。假設先產生DOM Tree,再產生Rendering Tree,把兩者割裂開,就有機會讓Webkit發揮更加奇妙的布局和渲染。平鋪直敘固然符合大多數Rendering Tree同步生長,這樣的布局和渲染是難以想像的。人在大多數時間裡的閱讀習慣,但是離經叛道的設計,也會有市場。一個例子就是上一章末尾處那張多視點的地圖。如果讓DOM Tree  與Rendering Tree同步生長,這樣的布局和渲染是難以想像的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.