WebKit 在渲染页面之前,需要确定各个元素的位置、大小,而这个过程就是layout(布局)。下面,我们对layout的主要过程进行一番说明。
一、FrameView::layout方法
FrameView作为与View相关的类,其主要涉及与显示相关的内容,而其中对页面元素的布局至关重要,这也是浏览器的核心处理部分。
我们都知道浏览器从Web服务器获得数据后,经解析会构建DOM树、Render树,然后进行布局处理,进而为渲染页面作好准备,其中的布局处理往往由FrameView::layout方法发起,让我们来具体看看其实现,一窥其主要实现过程。
|
FrameView::layout往往会调用Render树根的layout方法即RenderView::layout。
二、RenderView::layout方法
|
三、RenderBlock::layoutBlock方法
layoutBlock 会分成两个分支:
layoutInlineChildren 和
layoutBlockChildren
// Make sure the rect is still non-empty after intersecting for overflow above |
四、RenderBlock::layoutBlockChildren方法
|
layoutBlockChild 方法就比较复杂了,具体可以自己看代码。
五、RenderBlock::layoutInlineChildren方法
这个方法相当复杂,其作用就是布局文字、图像等,对文字行高确定、断行等处理,同时还包括 文字从左到右或从右到左的布局处理。具体可以参考bidi.cpp中的源码实现。
六、调用FrameView::layout方法的时机
由于从Web服务器获取的网页数据不可能一次性完成,往往需要边获取数据,边布局,然后渲染,这样才可能获得良好的用户感受。
所以一旦获得主要数据如css数据及body等标签后,就可以开始布局,布局完后会根据当前条件决定是否将布局的数据渲染出来,或者继续布局处理后来获取的数据,这样也增加了布局处理过程的复杂度。
而调用layout方法的时机也至关重要,因为layout本身就可能需要花费大量的时间如layoutBlockChildren、layoutInlineChildren等处理,其往往与网页的内容有关,而网页的内容却由网页开发者来确定,对浏览器来讲是千变万化的,这就对layout方法的实现及调用时机提出更高的要求,同时确定了其复杂性。
调用layout的时机主要有获得一定DOM文档数据后调用Document::updateLayout()、需要重新使用CSS数据时调用Document::recalcStyle()、改变窗口大小后调用Frame::forceLayout()等来实现。。。
七、总结
其实WebKit涉及网页布局方面的layout方法蛮复杂的,如其他RenderObject子类也会根据自身情况重载实现layout,还有对float、fixed、absolute、inline元素等的处理,但其主要逻辑就象上面所提,这里只是汇总一下主要流程及概念,针对每一个具体标签或RenderObject的布局实现则需要更深一步的了解,希望大家能对了解WebKit的网页布局过程有一个清晰而准确的认识。。