webkit 基礎

weixin_34391854發表於2012-07-24

引用:http://blog.csdn.net/milado_nju/article/details/7292131

# WebKit渲染基礎

## 概述

WebKit是一個引擎,而不是一個瀏覽器,它專注於網頁內容展示,其中渲染是其中核心的部分之一。本章著重於對渲染部分的基礎進行一定程度的瞭解和認識,主要理解基於DOM樹來介紹Render樹和RenderLayer樹的構建由來和方式。

那麼什麼是DOM?簡單來說,DOM是對HTML或者XML等文件的一種結構化表示方法,通過這種方式,使用者可以通過提供標準的介面來訪問HTML頁面中的任何元素的相關屬性,並可對DOM進行相應的新增、刪除和更新操作等。相關資訊可查閱W3C的文件,這裡不再贅述。

基於DOM樹的一些可視(visual)的節點,WebKit來根據需要來建立相應的RenderObject節點,這些節點也構成了一顆樹,稱之為Render樹。基於Render樹,WebKit也會根據需要來為它們中的某些節點建立新的RenderLayer節點,從而形成一棵RenderLayer樹。

Render樹和RenderLayer樹是WebKit支援渲染所提供的基礎但是卻非常重要的設施。這是因為WebKit的佈局計算依賴它們,瀏覽器的渲染和GPU硬體加速也都依賴於它們。幸運地是,得益於它們介面定義的靈活性,不同的瀏覽器可以很方便地來實現自己的渲染和加速機制。

為了直觀瞭解這三種樹,下圖給出了這三種樹及其它們之間的對應關係,後面會詳細介紹裡面的細節。

 

## Render樹

###Render樹的建立

Render樹是基於DOM樹建立起來的一顆新的樹, 是佈局和渲染等機制的基礎設施。 Render樹節點和DOM樹節點不是一一對應關係,那麼哪些情況下需要建立新的Render節點呢?

a)      DOM樹的document節點;

b)      DOM樹中的視覺化節點,例如HTML,BODY,DIV等,非視覺化節點不會建立Render樹節點,例如HEAD,META,SCRIPT等;

c)      某些情況下需要建立匿名的Render節點,該節點不對應於DOM樹中的任何節點;

RenderObject物件在DOM樹建立的同時也會被建立,當然,如果DOM中有動態加入元素時,也可能會相應地建立RenderObject物件。下圖示例的是RenderObject物件被建立的函式呼叫過程。

Render樹建立之後,佈局運算會計算出相關的屬性,這其中有位置,大小,是否浮動等。有了這些資訊之後,渲染引擎才只知道在何處以及如何畫這些元素。

###RenderObject類及其子類

RenderObject是Render樹的節點基礎類,提供了一組公共的介面。它有很多的子類,這些子類可能對應一些DOM樹中的節點,例如RenderText,有些則是容器類,例如RenderBlock。下圖給出了一些常用的類的繼承關係圖,這其中RenderBlock是一個非常重要的類。

                     

### 匿名RenderBlock物件

CSS中有塊級元素和內嵌(inline)元素之分。內嵌元素表現的是行佈局形式,就是說這些元素以行進行顯示。以’div’元素為例,如果設定屬性’style’為’display:inline’時,則那是內嵌元素,那麼它可能與前面的元素在同一行;如果該元素沒有設定這個屬性時,則是塊級元素,那麼在新的行裡顯示。

RenderBlock用來是用來表示塊級元素, 為了處理上的方便,某些情況下需要建立匿名的RenderBlock物件,因為RenderBlock的子女必須都是內嵌的元素或者都是非內嵌的元素。所以,當它包含兩種元素的時候,那麼它會為相鄰的內嵌元素建立一個塊級RenderBlock節點,然後設定該節點為自己的子女並且設定這些內嵌元素為它的子女。

 

##RenderLayer樹

RenderLayer樹是基於Render樹建立起來的一顆新的樹。同樣,RenderLayer節點和Render節點不是一一對應關係,而是一對多的關係。那麼哪些情況下的RenderObject節點需要建立新的RenderLayer節點呢?

a)      DOM樹的document節點對應的RenderView節點

b)      DOM樹中的document 的子女節點,也就是HTML節點對應的RenderBlock節點

c)      顯式的CSS位置

d)      有透明效果的物件

e)      節點有溢位(overflow),alpha或者反射等效果的

f)       Canvas 2D和3D (WebGL)

g)      Video節點對應的RenderObject物件

 

一個RenderLayer被建立之後,其所在的RenderObject物件的所有後代均包含在該RenderLayer,除非這些後代需要建立自己的RenderLayer。而後代的RenderLayer的父親就是自己最近的祖先所在的不同的RenderLayer,這樣,它們也構成了一顆RenderLayer樹。

每個RenderLayer對應的Render節點內容均會繪製在該RenderLayer所對應的層次上(或者內部儲存結構上)。不同的RenderLayer可以共享同一個內部儲存結構,也可以有各自的後端儲存,這取決於不同的移植。在軟體渲染下,通常各個RenderLayer的內容都繪製在同一塊後端儲存上。在GPU硬體加速的下,某些RenderLayer可能有自己獨立的後端儲存,而後通過合成器來把這些不同的後端合成在一起,最終形成網頁的視覺化內容。

RenderLayer在建立RenderObject物件的時候,如果需要,也會同時被建立,當然也有可能在執行JavaScript程式碼時,更新頁面的樣式從而需要新建立一個RenderLayer。

 ## 一個例子

以上說了那麼多,一堆堆的類,一個個的建立規則,聽起來太抽象,不太容易理解,那麼一個具體的Render樹和RenderLayer樹到底是怎麼樣的呢?為了視覺化理解Render樹和RenderLayer樹,下面給出一個具體的例子來加以解釋和說明。

首先,讓我們來看一個簡單的HTML網頁,原始碼如下所示。

 

上面的程式碼結構很簡單,就是一些HTML的基本元素組成的,例如HTML,HEAD,DIV,A,  IMG, TABLE等等, 然後包含一個特別的HTML5元素CANVAS,而且還有一小段JavaScript程式碼。照顧到一些沒有相關背景的讀者,簡單解釋一下這段程式碼的含義。這段程式碼是對CANVAS元素建立一個WebGL的Context,有了這個context,就可以在canvas元素上繪製3D的內容。這個類似於OpenGL或者OpenGLES的context,具體canvas和WebGL會有另外專門的章節來介紹。

這段HTML原始碼被WebKit解析後會生成一顆DOM樹。這段程式碼的DOM樹主要結構如本章第一幅圖中的‘DOM樹’部分所示。當DOM樹生成時,WebKit同時建立了一顆Render樹,如上所說,程式碼的Render樹被列印成如下圖所示的文字資訊。

首先,上圖中的“layer at (x, x)”表示不同的RenderLayer節點,下面的所有RenderObject均屬於該RenderLayer。以第一個layer為例,它對應於DOM中的Document節點。後面的(0, 0)表示該節點在座標系中的位置,最後的1028x683表示該節點的大小。它包含的RenderView節點後面的資訊也是同樣的意思。

其次,看其中最大的部分-第二個layer,包含了HTML中的絕大部分元素。這裡有三點需要解釋一下:第一,Head元素沒有相應的RenderObject,如上面所解釋的,因為它不是一個可視的元素。第二,Canvas元素不在其中,而是在第三個layer中(RenderHTMLCanvas)。但是它仍然是RenderBody節點的子女。第三,匿名的RenderBlock節點,它包含了RenderText, RenderInline等節點,原因如前所說。

再次,來看一下第三個layer。因為從Canvas建立了一個WebGL3D Context物件,這裡需要重新生成一個新的layer。

最後,來說明一下三個layer的建立時間。第一和第二個layer在建立DOM樹後,會觸發建立;第三個layer測試資源載入解析好之後,執行後面的JavaScript程式碼後所建立。

基於上面的描述,相信大家已經對Render樹和RenderLayer樹有了一定的瞭解。現在讓我們回憶一下本章的第一幅圖。該圖其實是給出了示例的HTML網頁在WebKit中三種樹的對應關係(僅選取其中重要的部分),相信現在你已經瞭解它們的含義了。 

## 原始碼目錄

WebKit/Source/WebCore/rendering

         WebKit為支援渲染所涉及的各個類

WebKit/Source/WebCore/dom/

         DOM樹的相關檔案,包括一些基礎類及其介面定義

WebKit/Source/WebCore/html/

         為HTML網頁的元素所定義的相關的基礎類,它們基於DOM的Node類 

## 參考文獻

1.      Google design documents:

http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome

 By zhuyongsheng2010@gmail.com

相關文章