广东专业商城网站建设,软文投稿平台有哪些,他达拉非能延时多久,wordpress内链插件《WebKit 技术内幕》之七#xff08;1#xff09;#xff1a; 渲染基础 WebKit的布局计算使用 RenderObject 树并保存计算结果到 RenderObject 树。 RenderObject 树同其他树#xff08;如 RenderLayer 树等#xff09;#xff0c;构成了 WebKit 渲染的为要基础设施。
1…《WebKit 技术内幕》之七1 渲染基础 WebKit的布局计算使用 RenderObject 树并保存计算结果到 RenderObject 树。 RenderObject 树同其他树如 RenderLayer 树等构成了 WebKit 渲染的为要基础设施。
1 RenderObject树
1.1 RenderObject基础类 为了解释说明渲染原理首先使用一个网页示例代码来说明。示例代码7-1是一个网页的源代码它的结构很简单主要由一些HTML基本元素组成例如html、head、div、a、img、table等然后它还包含了一个特别的HTML5元素——canvas而且还有一小段JavaScript代码。考虑到一些没有很强HTML5背景的读者简单解释一下这段JavaScript代码的含义。这段代码是为“canvas”元素创建一个WebGL3D绘图技术的上下文对象Context有了这个对象Web开发者就可以在canvas元素上绘制任何3D的内容。这个类似于OpenGL或者OpenGLES的上下文概念关于canvas元素、canvas2D和WebGL会在GPU加速内容中做介绍。
示例代码 一个简单的网页示例源代码
!DOCTYPE html html langen
head/head
body divabc/div canvas idwebg1 width80 height80/canvas a hrefmailto:joeexample.com?subjectfeedbackemail me/a img src alt input typebutton name / select name multiple option valueoption/option /select table tr tddata/td /tr /table script var canvas document.getElementById(webg1) var g1 canvas.getContext(experimental-webg1) if (g1) { alert(Theres no WebGl context available. ) return } /script /body
/html 上面的代码经过WebKit解释之后生成的DOM树读者应该能够很容易想象得出。在DOM树构建完成之后WebKit所要做的事情就是为DOM树节点构建RenderObject树。那么什么是RenderObject呢它的作用是什么呢下面笔者就逐步来揭开它的面纱。 在DOM树中某些节点是用户不可见的也就是说这些只是起一些其他方面而不是显示内容的作用。例如表示HTML文件头的“meta”节点在最终的显示结果中用户是看不到它的存在的笔地称之为“非可视化节点”。该类型其实还包含很多元素例如示例代码7-1中的“head”、“script”等。而另外的节点就是用来展示网页内容的例如示例代码7-1中的“body”、“div”、“span”、“canvas”、“img”等这些节点可以显示一块区域如文字、图片、2D图形等被称为“可视节点”。 对于这些“可视节点”因为WebKit需要将它们的内容绘制到最终的网页结果中所以WebKit会为它们建立相应的RenderObject对象。一个RenderObject对象保存了为绘制DOM节点所需要的各种信息例如样式布局信息经过WebKit的处理之后RenderObject对象知道如何绘制自己。这些RenderObject对象同DOM的节点对象类似它们也构成一棵树在这里我们称之为RenderObject树。RenderObject树是基于DOM树建立起来的一棵新树是为了布局计算和渲染等机制而构建的一种新的内部表示。RenderObject树节点和DOM树节点不是一一对应关系那么哪些情况下为一个DOM节点建立新的RenderObject对象呢以下是三条规则从这些规则出发会为DOM树节点创建一个RenderObject对象。
DOM树的document节点。DOM树中的可视节点例如html、body、div等。而WebKit不会为非可视化节点创建RenderObject节点例如上面提到的一些例子。某些情况下WebKit需要建立匿名的RenderObject节点该节点不对应于DOM树中的任何节点而是WebKit处理上的需要典型的例子就是匿名的RenderBlock节点。 前面介绍了影子DOM那么WebKit该如何处理影子DOM树中的节点呢WebKit处理影子DOM没有什么特别的不同虽然JavaScript代码没法访问影子DOM但是WebKit需要创建并渲染RenderObject。 WebKit在创建DOM树被创建的同时也创建RenderObject对象。当然如果DOM树被动态加入了新节点WebKit也可能创建相应的RenderObject对象。下图示例的是RenderObject对象被创建时所涉及的主要类。 图·从DOM节点到创建RenderObject节点 每个Element对象都会递归调用“attach”函数该函数检查Element对象是否需要创建RenderObject。如果需要该函数会使用NodeRenderingContext类来根据DOM节点的类型来创建对应的RenderObject节点。 DOM树中元素节点包含很多类型。同DOM树一样RenderObject树中的节点也有很多类型。下图描述了RenderObject类和它的主要子类。图中间的是RenderObject类它包含了RenderObject的主要虚函数大概可以分成以下几类。
为了遍历和修改RenderObject树而涉及的众多函数遍历操作函数如parent()、firstChild()、nextSibling()、previousSibling()等修改操作函数如addChild()、removeChild()等。用来计算布局和获取布局相关信息的函数例如layout()、style()、enclosingBox()。用来判断该RenderObject对象属于哪种类型的子类这里面有各式各样的类似“IsASubClass”的函数这些函数可以知道它们的类型以作相应的转换。跟RenderObject对象所在的RenderLayer对象相关的操作这些操作将在下一节中再描述。坐标和绘图相关的操作WebKit使用这些操作让RenderObject对象将内容绘制在传入的绘制结果对象中例如paint()、repaint()等。
其实WebKit还定义了其他各式各样的类这里只描述一些主要部分和后面使用到的函数。 图RenderObject基类和它的主要子类 RenderBoxModelObject类是描述所有跟CSS中的框模型相关联类的基类所以读者能够看到子类例如RenderInline类div:inline-box和RenderBox类。RenderBox类则是使用箱子模型的类它包括了外边距、边框、内边距和内容等信息。 RenderBlock类用来表示块元素。为了处理上的方便WebKit某些情况下需要建立匿名的RenderBlock对象因为RenderBlock的子女必须都是内嵌的元素或者都是非内嵌的元素。所以当RenderBlock对象包含两种元素的时候WebKit会为相邻的内嵌元素创建一个块节点也就是RenderBlock对象然后设置该对象为原先内嵌元素父亲的子女最后设置这些内嵌元素为RenderBlock对象的子女。由于匿名RenderObject对象它没有对应的DOM树中的节点所以WebKit统一使用Document节点来对应匿名对象。 还有很多RenderObject类的子类并没有在图中表示出来典型的如RenderVideo类它继承自RenderImage类。
1.2 RenderObject树 RenderObject对象构成了一棵树。RenderObject树的创建过程主要是由NodeRenderingContext类来负责下图描述了WebKit如何创建RenderObject对象并构建RenderObject树的。 图 RenderObject对象和RenderObject树的创建过程 基本思路是首先WebKit检查该DOM节点是否需要创建RenderObject对象。如果需要WebKit建立或者获取一个创建RenderObject对象的NodeRenderingContext对象NodeRenderingContext对象会分析需要创建的RenderObject对象的父亲节点、兄弟节点等设置这些信息后完成插入树的动作。 那么建立后的RenderObject树和DOM树之间的对应关系是怎么样的呢根据示例代码中网页的源代码WebKit中的DOM树表示如下图左边所示的结构省略了一些次要节点下图右边描述的就是WebKit中对应的RenderObject树。 图DOM树节点和RenderObject树的对应关系 上图使用虚线箭头表示两种树的节点对应关系其中HTMLDocument节点对应RenderView节点RenderView节点是RenderObject树的根节点。另外从图中可以看出WebKit没有为HTMLHeadElement节点非可视化元素没有被创建RenderObject子类的对象。