DOM树(The DOM Tree)
网页的HTML源代码会被解析成一棵名叫文档对象模型(Document Object Mode,DOM)的,由各个节点组成的树。树节点的基类为Node。
Node.h
节点被分成多种类型。与渲染代码相关的节点类型有:
- Document文档– DOM树的根节点为文档类型。文档类型相关的类有3个,Document,HTMLDocument和SVGDocument。Document类,用于除了SVG文档以外的全部XML文档。HTMLDocument类(继承于Document类),用于HTML文档。而SVGDocument类(继承于Document类),则用于SVG文档。
Document.h
HTMLDocument.h
- Element元素– HTML或XML源代码的所有标签(Tag)将被解析为元素(Element)。从渲染角度来看,元素就是一个具有标签名的节点(DOM树节点),该节点将转换成一个特定类型的子类,以在渲染时候,得到相关数据。
Element.h
- Text文本– 出现在元素之间的纯文本将被解析成文本节点。文本节点存储着纯文本内容,渲染树(render tree)可以通过查询文本节点得到文本的字符数据。
Text.h
渲染树(The Render Tree)
渲染的核心就是渲染树(render tree)。渲染树与DOM树非常相似。渲染树中的每一个树节点与DOM树中的节点(文档,元素,文本)一一对应,除非之外,渲染树中的树节点也可以是独立存在的,即该节点在DOM树中没有对应的节点。
渲染树节点的基类是RenderObject。
RenderObject.h
DOM树节点可以通过Node类的renderer方法获得对应的RenderObject对象。
RenderObject* renderer() const
下面几个方法是遍历渲染树最常用的方法:
RenderObject* firstChild() const;
RenderObject* lastChild() const;
RenderObject* previosSibling() const;
RenderObject* nextSibling() const;
这里是一个遍历渲染树某一个节点的直接子节点的例子。该例子所用的方法,在渲染树代码中是最常用的遍历方法。
for (RenderObject* child = firstChild(); child; child =child->nextSibling()) {
…
}
渲染树的创建(Creating the RenderTree)
渲染树是通过在DOM树上执行一个名叫“连接(attachment)”的过程创建的。当文档被解析和DOM树被创建后,DOM树节点的attach方法将被调用,以创建对应的渲染树节点。
void attach()
attach方法会计算DOM树节点的样式信息。如果节点的display样式值为none,或者其父节点的display样式值为none,那么,渲染树节点将不会被创建。DOM树节点的节点类型和CSS样式的display属性值将会被一起考虑,从而决定为该DOM树节点创建怎样的渲染树节点。
连接(attachment)过程是一个至顶向下的递归操作。父节点对应的渲染树节点总是比其子节点的渲染树节点先被创建。
渲染树的销毁(Destroying the RenderTree)
当渲染树对应的DOM树节点从文档中移除时,或者文档被销毁(例如,关闭浏览器的标签/窗口)时,渲染树节点将会被销毁。一个名为detach的DOM树节点方法将会被调用,以取消DOM树节点和渲染树节点的关联和销毁渲染树节点。
void detach()
取消连接(detachment)过程是一个至底向上的递归操作。子节点对应的渲染树节点总是比其父节点的渲染树节点先被销毁。
样式信息的访问(Accessing StyleInformation)
在连接过程,DOM会查询CSS,以获取元素的样式信息。查询到的样式信息会被保存在一个RenderStyle类对象中。
RenderStyle.h
每一个WebKit支持的CSS属性都可以通过查询该对象得到。RenderStyle对象会被引用计数。如果一个DOM树节点创建了对应的渲染树节点,这时,DOM树节点会调用对应渲染树节点的一个名为setStyle方法,以将样式信息与该渲染树节点关联起来。
void setStyle(RenderStyle*)
渲染树节点将会对它所关联的RenderStyle对象的引用计算加1。另一方面,当渲染树节点需要关联一个新的RenderStyle对象,或者渲染树节点被销毁时,渲染树节点会对当时所关联的RenderStyle对象的引用计数减1 。
通过渲染树节点(RenderObject对象)上的style方法,可以得到关联的RenderStyle对象。
RednerStyle* style() const
CSS盒模式(The CSS BoxModel)
RenderObject一个主要的子类是RenderBox类。RenderBox类代表了符合CSS盒模型标准的对象。这将包括具有边框(border),内间距(padding),外间距(margin),宽(width)和高(height)的对象。当前,一些不满足CSS盒模式标准的对象(例如,SVG对象)也继承于RenderBox类。这个“不恰当”的继承关系将在今后重构渲染树的过程中修正。
该图来自于CSS2.1标准中描述CSS盒部分的内容。使用下面几个方法可以得到边框/外间距/内间距的大小。一情况下,RenderStyle对象不会被直接使用,除非,为了查询原始的样式信息。因为,对RederObject的样式进行分析计算已经完成(该分析计算逻辑因元素而异。特别地,对于表格元素,表格元素可以覆盖单元格的内间距以及在单元格间的边框),并且可以直接通过相应方法获取。
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)是元素的CSS盒模型中的除去边框和滚动条的区域,但包括内间距。
int clientLeft() const { return borderLeft(); }
int clientTop() const { return borderTop(); }
int clientWidth() const;
int clientHeight() const;
内容区域盒(content box)是元素的CSS盒模型中的除去边框和内间距的区域。
IntRect contentBox() const;
int contentWidth const { return clientWidth() – paddingLeft()– paddingRight(); }
int contentHeight const { return clientHeight() –paddingTop() – paddingBottom(); }
当盒具有横滚动条或竖滚动条时,滚动条将会被置于盒边框和内间距之间。滚动条的大小包括在客户区域盒的宽和高之中(非译文:这里什么意思,与上面关于client box的描述有冲突???)。滚动条不属于内容盒的一部分。可滚动区域和当前滚动位置可以通过RenderObject对象获得。我将于今后专门开一个章节来更深入的描述与滚动相关的信息。
int scrollLeft() const;
int scrollTop() const;
int scrollWidth() const;
int scrollHeight() const;
盒还具有x轴和y轴的位置属性。一般情况下,x轴和y轴属性是相对于父元素(父元素决定子元素的盒的位置)。另一方面,存在很多例外情况,x轴和y轴属性不一定相对于父元素。盒的定位是渲染树中最使人迷惑的部分之一。
int xPos() const;
int yPos() const;
原文地址:http://www.webkit.org/blog/114/webcore-rendering-i-the-basics/