《WebKit 技术内幕》学习之七(2): 渲染基础

66 篇文章 0 订阅
48 篇文章 1 订阅

2 网页层次和RenderLayer树

2.1 层次和RenderLayer对象

        前面章节介绍了网页的层次结构,也就是说网页是可以分层的,这有两点原因,一是为了方便网页开发者开发网页并设置网页的层次,二是为了WebKit处理上的便利,也就是说为了简化渲染的逻辑。

        WebKit会为网页的层次创建相应的RenderLayer对象。当某些类型RenderObject的节点或者具有某些CSS样式的RenderObject节点出现的时候,WebKit就会为这些节点创建RenderLayer对象。一般来说,某个RenderObject节点的后代都属于该节点,除非WebKit根据规则为某个后代RenderObject节点创建了一个新的RenderLayer对象。

        RenderLayer树是基于RenderObject树建立起来的一棵新树。根据上面所述笔者可以得出这样的结论:RenderLayer节点和RenderObject节点不是一一对应关系,而是一对多的关系。那么哪些情况下的RenderObject节点需要建立新的RenderLayer节点呢?以下是基本规则。

  • DOM树的Document节点对应的RenderView节点。
  • DOM树中的Document的子女节点,也就是HTML节点对应的RenderBlock节点。
  • 显式的指定CSS位置的RenderObject节点。
  • 有透明效果的RenderObject节点。
  • 节点有溢出(Overflow)、alpha或者反射等效果的RenderObject节点。
  • 使用Canvas 2D和3D (WebGL)技术的RenderObject节点。
  • Video节点对应的RenderObject节点。

        除了根节点也就是RenderLayer节点,一个RenderLayer节点的父亲就是该RenderLayer节点对应的RenderObject节点的祖先链中最近的祖先,并且祖先所在的RenderLayer节点同该节点的RenderLayer节点不同。基于这一原理,这些RenderLayer节点也构成了一棵RenderLayer树。

        每个RenderLayer节点包含的RenderObject节点其实是一棵RenderObject子树。理想情况下,每个RenderLayer对象都会有一个后端类,该后端类用来存储该RenderLayer对象绘制的结果。实际情况中则比较复杂,在不同的渲染模式下,不同WebKit的移植中,情况都不一样,这些在后面介绍。RenderLayer节点的使用可以有效地减小网页结构的复杂程度,并在很多情况下能够减少重新渲染的开销。

        在WebKit创建RenderObject树之后,WebKit也会创建RenderLayer树。当然某些RenderLayer节点也有可能在执行JavaScript代码时或者更新页面的样式被创建。同RenderObject类不同的是,RenderLayer类没有子类,它表示的是网页的一个层次,并没有“子层次”的说法。

2.2 构建RenderLayer树

        RenderLayer树的构建过程其实非常简单,甚至比构建RenderObject树还要简单。根据前面所述的条件来判断一个RenderObject节点是否需要建立一个新的RenderLayer对象,并设置RenderLayer对象的父亲和兄弟关系即可,这里不再介绍。

        为了直观地理解RenderLayer树,根据示例代码中的源代码,WebKit中的RenderObject树表示如图7-5左边所示的结构(省略了一些节点),图7-5的右边描述的就是WebKit所生成的对应RenderLayer树。根据RenderLayer对象创建的条件来看,该示例代码的RenderLayer树应该包含三个RenderLayer节点——根节点和它的子女,以及叶节点。

                                图 RenderObject树和RenderLayer树的关系

        在上一章,笔者介绍了布局计算,本章紧接着又介绍了RenderObject树和RenderLayer树,通过一些示意图,相信读者应该理解这些概念的含义。下面来看一下示例代码7-1在WebKit中的实际内部表示和布局信息,图7-6是WebKit内部表示的具体结构RenderObject树、RenderLayer树和布局信息中的大小和位置信息。下面根据RenderLayer树的节点来分析它们。

        首先,图=中的“layer at (x, x)”表示的是不同的RenderLayer节点,下面所有RenderObject子类的对象均属于该RenderLayer对象。以第一个RenderLayer节点为例,它对应于DOM树中的Document节点。后面的“(0, 0)”表示该节点在网页坐标系中的位置,最后的“1028×683”信息表示该节点的大小,第一层包含的RenderView节点后面的信息也是同样的意思。

        图 示例代码的布局信息、RenderObject树和RenderLayer树

        其次,读者仔细查看其中最大的部分,也就是第二个layer,其包含了HTML中的绝大部分元素。这里有三点需要解释一下:第一,“head”元素没有相应的RenderObject对象,如上面所解释的,因为“head”不是一个可视的元素;第二,“canvas”元素并在第二个layer中,而是在第三个layer(RenderHTMLCanvas)中,虽然该元素仍然是RenderBody节点的子女;第三,该layer层中包含一个匿名(Anonymous)的RenderBlock节点,该匿名节点包含了RenderText和RenderInline等子节点,原因之前已经介绍过。

        再次,来看一下第三个layer层,也就是最下面的层。因为JavaScript代码为“canvas”元素创建了一个WebGL的3D绘图上下文对象,WebKit需要重新生成一个新的RenderLayer对象。

        最后,来说明一下三个层次的创建时间。在创建DOM树之后,WebKit会接着创建第一个和第二个layer层。但是,第三个RenderLayer对象是在WebKit执行JavaScript代码时才被创建的,这是因为WebKit需要检查出JavaScript代码是否为“canvas”确实创建了3D绘图上下文,而不是在遇到“canvas”元素时创建新的RenderLayer对象。

        基于上面的描述,相信大家已经对布局计算结果、RenderObject树和RenderLayer树有了更进一步的了解。

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jyl_sh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值