好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

WebCore

WebCore

 

WebCore渲染之一:基础

原文地址: http://www.webkit.org/blog/114/webcore-rendering-i-the-basics/

不少人都对WebCore的渲染系统感兴趣,于是我准备了一系列的文章进行讲解,本文是该系列文章的第一篇。

文档树

网页会被解析成一个包含若干结点的树形结构,即文档对象模型(DOM)。树中所有结点的基类为Node。

Node.h

结点被划分为若干类型。与渲染代码相关的结点类型包括:

Document(文档类):树的根节点总为文档。有三个文档相关的类:Document、HTMLDocument和SVGDocument。第一个用来表示除SVG文档以外的所有XML文档。第二个继承自Document,只表示HTML文档。第三个也继承自Document,用来表示SVG文档(涉及: Document.h 、 HTMLDocument.h )。 Elements(元素类):在HTML或XML代码中的标签最终会变为元素。从渲染角度看,元素是一个具有标记名的结点,可用来在渲染时转换为某个特定的子类,从而获取其数据。(涉及: Element.h ) Text(文本):元素之间的纯文本会被转化为一个文本结点。文本结点负责存储纯文本信息,渲染树可通过它来获取数据(涉及: Text.h )。

渲染树

渲染树是渲染过程的核心。渲染树和DOM树很像,都是树形结构,树中的每个元素可对应到文档、元素或者文本结点。渲染树还能包含一些DOM树中没有的结点。

渲染树结点的基类为RenderObject。

RenderObject.h

DOM结点所对应的RenderObject对象可通过Node的renderer()方法获得。

RenderObject* renderer()  const 

以下方法是遍历渲染树最常用的:

RenderObject* firstChild()  const  ;
RenderObject * lastChild()  const  ;
RenderObject * previousSibling()  const  ;
RenderObject * nextSibling()  const ;

下面的例子我们循环访问了一个渲染结点的子结点。这在渲染树的代码中很常见。

 for  (RenderObject* child = firstChild(); child; child = child-> nextSibling()) {
    ...
} 

创建渲染树

渲染结点通过一个叫做attachment的过程创建出来。随着文档被解析、DOM结点被添加,一个叫做attach的方法会被DOM结点调用来创建每个渲染结点。

 void  attach()

attach方法为DOM结点计算样式信息。如果元素CSS的display属性为none,或者元素是某个display为none的元素的子元素,那么渲染结点就不会被创建。结点相关的子类与CSS的display属性一起决定了该创建什么样的渲染结点。

Attach是一个自顶向下的递归过程。一个父结点的渲染结点的创建总会早于其子结点的渲染结点的创建。

销毁渲染树

在DOM结点被移除时或者整个文档被销毁时(比如关闭页面),渲染结点会随之销毁。此时DOM结点的detach方法就会被调用,用来销毁渲染结点。

 void  detach()

Detach是一个自底向上的递归操作。子结点的渲染结点会先于其父节点销毁。

获取样式信息

在attach过程中,DOM会通过CSS获取元素样式信息。结果会存储在RenderStyle对象中。

RenderStyle.h

每个WebKit支持的CSS属性都可通过该对象查询。RenderStyles对象是引用计数的对象,如果DOM结点创建了一个渲染结点,那么它将调用渲染结点的setStyle方法将样式信息与之关联。

 void  setStyle(RenderStyle*)

渲染结点增加了一个对样式对象的引用,该引用将一直被维护除非结点获得一个新样式或者被销毁。

RenderStyle可通过RenderObject的style()方法获得。

RenderStyle* style()  const 

CSS盒模型

RenderObject中的一个主要子类为RenderBox,该子类表示遵循CSS盒模型的对象,这些对象会有自己的border(边框)、padding(内边距)、margin(外边距)、width(宽)和height(高)。不过现在一些没有遵循CSS盒模型的对象也继承于RenderBox(例如:SVG对象)。这个问题以后会在重构渲染树的过程中修复。

CSS 2.1规范的 这幅图 描述了CSS盒模型的各个部分。下面的方法可用来获取边框和内外边距。RenderStyle只有在获取原始样式信息时用到,因为RenderObject的计算结果会有很大差别(特别是表格元素,它可以将单元格的padding属性覆盖,表格之间的边框也可以重叠在一起)。

 int  marginTop()  const  ;
  int  marginBottom()  const  ;
  int  marginLeft()  const  ;
  int  marginRight()  const  ;

  int  paddingTop()  const  ;
  int  paddingBottom()  const  ;
  int  paddingLeft()  const  ;
  int  paddingRight()  const  ;

  int  borderTop()  const  ;
  int  borderBottom()  const  ;
  int  borderLeft()  const  ;
  int  borderRight()  const ;

width()和height()方法给出宽度和高度(包含边框的)。

 int  width()  const  ;
  int  height()  const ;

client box包含了边框和滚动条,padding也包括:

 int  clientLeft()  const  {  return   borderLeft(); }
  int  clientTop()  const  {  return   borderTop(); }
  int  clientWidth()  const  ;
  int  clientHeight()  const ;

content box用来描述不包含border和padding的CSS盒子:

IntRect contentBox()  const  ;
  int  contentWidth()  const  {  return  clientWidth() - paddingLeft() -  paddingRight(); }
  int  contentHeight()  const  {  return  clientHeight() - paddingTop() - paddingBottom(); }

当盒子出现滚动条时,它被放在border和padding之间。滚动条的大小被包含在client width和client height中。滚动条不算在content box内。滚动条的大小以及当前滚动的位置可通过RenderObject获取。这个问题后续在单独章节中再详细说明。

 int  scrollLeft()  const  ;
  int  scrollTop()  const  ;
  int  scrollWidth()  const  ;
  int  scrollHeight()  const ;

盒子还有x和y的位置属性。这些位置相对于元素的父元素,父元素来决定盒子该放置在什么地方。这个规则存在许多例外情况,这也是渲染树中最令人困惑的地方。

 int  xPos()  const  ;
  int  yPos()  const ;

 

 

标签:  webkit ,  浏览器原理

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于WebCore的详细内容...

  阅读:31次