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