WebCore Rendering I – The Basics

WebCoreRendering I – The Basics

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

 

DOMtree

  网页会被parse成一棵包含很多nodes的tree,称为DocumentObject Model(DOM)。DOM tree中所有nodes的基本类为Node。

相关代码:

Webkit/Source/WebCore/dom/Node.h

  这些nodes可以分成很多种类,其中与rendering代码相关的是以下几类:

Ø  Document :树的根总是document实例。一共有三个document类,Document, HTMLDocument 和SVGDocument, 第一个可以用于所有除了SVGdocuments 以为的XML documents,第二个只能用于HTML documents,并且是从Document继承而来的,第三个适用于SVG document,也是从Document继承而来。

相关代码:

Webkit/Source/WebCore/dom/Document.h

Webkit/Source/WebCore/html/HTMLDocument.h

Ø  Elements:所有在HTML和XML文件中的出现tag构成elements。从rendering 的角度来看,一个element就是一个有tag名的节点,可以获得其对应的子类和渲染时所需要的数据。

相关代码:

Webkit/Source/WebCore/dom/Element.h

Ø  Text: elements tags之间出现的一些原始文本就是文本节点。文本节点保存这些原始文本,render tree可以通过查询获得其字符数据。

相关代码:

Webkit/Source/WebCore/dom/Text.h

 

TheRender Tree

Rendering 的核心就是Render Tree,它与DOM tree类似,是一棵由对象组成的树,这些对象可以找到与DOM Tree中相对应的节点,但是Render Tree也包含一些在DOM Tree中找不到对应节点的对象。Render Tree中的所有对象的基本类型是RenderObject。

相关代码:

Webkit/Source/WebCore/rendering/RenderObject.h

下面列出的是最常用来遍历rendertree的方法:

RenderObject* firstChild() const;

RenderObject* lastChild() const;

RenderObject* previousSibling() const;

RenderObject* nextSibling() const;

下面的一个遍历renderer孩子节点的例子,这时render tree代码中非常普遍的一种遍历子节点方法。

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

   ...

}

 

创建Render Tree

 Renderers是通过在DOM tree上执行“attachment”操作获得的。当一个document已被解析,DOM nodes已被添加到其中,attach方法被调用,作用于这个DOM tree变可以获得其对应的renders。

Void attach()

  Attach方法会计算DOM node的style信息,如果一个node的display为none,或者它在一个display为none的父辈容器中,那么就不需要为它创建render。一个节点的子类和css样式值共同决定需要为它创建什么样的render。Attach方式是自顶向下的递归操作,所以子孙节点的render创建总是要晚于祖先节点。

 

销毁render tree

当相应的DOM nodes从document中被删除,或者是document被关掉(如document对应的tab或者窗口被关闭)时,detach方法被作用于DOM nodes上,就可以拆除并销毁对应的renders。

Void detach()

Detach方法是自底向上的递归操作,所以子孙节点的render销毁总是要先于祖先节点。

 

访问样式信息

在attachment过程中DOM会查询节点的CSS样式信息,该信息会被保存在一个RenderStyle对象中。相关代码:

Webkit/Source/WebCore/rendering/style/RenderStyle.h

Webkit支持的每一个css属性都可以通过这个对象来查询。RenderStyle对象是对引用计数的。如果一个DOM node创建了render,那么通过setStyle方法来链接render和样式信息。

Void setStyle(RenderStyle *)

一旦链接,render会增加改RenderStyle的引用计数,这个引用计数一直有效除非node的样式更新或者render被销毁。

RenderStyle对象可以通过RenderObject,用style方法获得:

RenderStyle * style() const

 

TheCSS Box Model

RenderObject中一个非常重要的子类是RenderBox,这个子类代表css box模型。其中包括很多对象,如borders, padding, margins, width and height.有些不是css box模型中的对象也是RenderBox的子类(如,SVG 对象)这实质上是个差错,将来再重构render tree部分代码时会被改正。

图1:css boxmodel

下面这些方法可以用来获得border/margin/padding widths。除非想要看原始的样式信息,否则RenderStyle是不应该被用到的。因为RenderObject中真正计算出来的数据与原始值可能会有很大的差别,特别是表格,表格中的cell padding可以有重叠部分,cell之间的boders也可以被收缩。

 

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 { returnborderLeft(); }

int clientTop() const { returnborderTop(); }

int clientWidth() const;

int clientHeight() const;

 

content box则是表示不包括边框,也不包括padding被区域。

IntRect contentBox() const;

int contentWidth() const { returnclientWidth() - paddingLeft() - paddingRight(); }

int contentHeight() const { returnclientHeight() - paddingTop() - paddingBottom(); }

当一个css box有横向或者纵向的滚动条时,滚动条会被放在边框与padding之间。滚动条的大小被包含在client width 和 client height中,但是滚动条不是content box的部分。滚动条的大小以及现在的位置也是可以通过RenderObject获得的。

int scrollLeft() const;

int scrollTop() const;

int scrollWidth() const;

int scrollHeight() const;

 

css boxes还有x,y坐标信息,这是相对坐标位置,相对于那个决定box具体位置的祖先。然而,也有很多例外,这部分是render tree代码中最容易混淆的地方。

 

int xPos() const;

int yPos() const;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值