WebKit 布局Layout

来源:互联网 发布:台达人机界面编程软件 编辑:程序博客网 时间:2024/06/05 09:55

转:http://blog.csdn.net/milado_nju/article/details/7854312

# WebKit布局(layout)基础

## 概述

一个网页从文本信息到最后的渲染结果,要经过很多复杂的过程,前面介绍过DOM树、Render树的创建,也阐述了页面如果被渲染的,其实,这两者中间还有一个非常重要的步骤――布局计算,这是因为在渲染每个元素之前,渲染引擎必须知道它的位置大小等布局信息,我们把计算这些信息的过程称之为布局。

布局根据其计算的范围大致可以分为两类,第一类是对整个Render树进行的计算,第二类是对Render树中某个子树的计算,常见于文本元素或者是overflow:auto块的计算,这种情况一般是其子树布局的改变不会影响其周围元素的布局,因而不需要重新计算更大范围内的布局。

按照惯例,为了便于表述,首先我们来看一个能够帮助理解问题的例子。这个例子不复杂,其重点是包含两个div元素,其中id为adiv的元素是类型为aclass元素的父亲。CSS样式设置了类型aclass的样式属性值。


## 箱子(box)模型

先介绍箱子模型。CSS布局计算是基于箱子模型来进行的,其基本构成是一个矩形区域,包含了外边距(margin),内边距(padding),边框(border)和内容(content),也就是说每个元素的布局都是按照箱子模型来排布的,通过设置这些属性,达到特定的布局效果。如下图所示,最外层的虚线以内就是一个box模型的实例,这个实例表示的就是一个元素布局表示。


这个图相信大家都看过,这里简单介绍一下。箱子最边缘部分分别是四个方向上的外边距(TM, RM, BM, LM),可以设置不同的大小,其次往内是四个方向上的边框(TB, RB, BB, LB),再次是四个方向上的内边距(TP, RP, BP, LB),最后是中间的内容。下面结合实例来解释,给人以直观印象,便于深入了解。下图就是本章开始时候介绍的示例在浏览器中的显示结果,最外边的矩形框就是ID为‘adiv’的div元素的显示区域,其内部就是对于属于’.aclass’的类型的div元素的box模型实例。旁边的标注表明了box模型的各个属性值,读者可以跟上面的箱子模型进行对照理解。


例子中,文字被设置为‘A B C… T’,其表示的是内容区域,之所以设置成这样,是为了让布局随时可以换行,便于读者更清晰地看到内边距和内容区域。同样地,建议读者修改本章例子的各个参数,亲身体验这些设置带来的布局变化。

介绍了箱子模型后,箱子内部的位置和大小可以被确定了,那么箱子本身的位置和大小是如何确定的?这就需要“包含块”的帮助了。

##Containing block(包含块)

当需要计算元素的箱子的位置和大小的时候,需要计算它和另外一个矩形区域的相对位置,这个矩形区域称为该元素的包含块,箱子模型就是在包含块内计算和确定其一系列的属性值的,包含块的具体定义如下:

1)      根元素的包含块称为初始包含块,通常它的大小就是可视区域(viewport)的大小。

2)      对于其他位置属性设置为’static’或者’relative’元素,它的包含块就是的最近的祖先的箱子模型中的内容区域(content)。

3)      如果元素的位置属性为’fixed’,其脱离文档,固定在可视区域的某个特定位置。

4)      如果元素的位置属性为’absolute’,其包含块由最近的包含属性’absolute’, ‘relative’或者’fixed’的祖先决定,具体规则如下:

a)        如果其是一个inline元素,那么元素的包含块是包含该祖先的第一个和最后一个inline盒子的内边距的区域。

b)        否则,则是由该祖先的内边距所包围的区域。

这个复杂的定义读起来比较让人头痛,webkit中简单理解起来就是:

Render节点的包含块是该节点的负责决定该节点的祖先节点对应的块区域。根节点RenderView表示的就是”初始包含块”,其初始大小始终是可视区域的大小。

结合实例来讲,类型为’aclass’的div元素的包含块就是父亲的内容区域,其箱子模型就是在该内容区域上进行计算生成得来的。

## 布局计算

布局计算的相关信息都保存在RenderStyle对象中,如之前介绍,该对象属于Render节点。 RenderStyle没有什么特别之处,就是包含各个样式的属性值。同时,Render节点也包含一个位数组,该数组会保存一些用来表示是否需要重新计算布局等信息。

下面看看如果计算布局的。其主要由RenderObject中的layout方法来完成:

首先,layout函数会判断Render节点是否需要重新计算,通常这通过检查位数组中的相应标记位,子女是否需要计算布局等来确定。一般来说,初始显示,可视区域变化,样式值变化(例如动画,JavaScript操作样式值)等都会需要重新计算布局。

其次,它会遍历其每一个子女节点,依次计算它们的布局。

再次,对于每一个元素来说,它会实现自己的layout方法,根据特定的算法来计算该类型元素的布局。如果页面元素定义了其自己的宽高,那么webkit按照其定义的宽高来确定其大小,而对于象文本节点这样的Inline元素则需要结合其字体大小及文字的多少等来确定其对应的宽高。如果页面元素所确定的宽高超过了布局容器包含块所能提供的宽高,同时其overflow 属性为visible 或auto,则会提供滚动条来保证可以显示其所有内容。除非定义了页面元素的宽高,一般说来页面元素的宽高是在布局的时候通过相关计算得出来的。

## 布局测试(layouttests)

渲染引擎要处理各式各样、越来越复杂的网页,这需要Layout测试来保证它的质量。

Layout测试可以说是WebKit中最重要并且最著名的测试了。其基本测试工作方式是,预先准备很多很多的简单网页和期望的渲染结果,然后根据WebKit编译出来的DumpRenderTree(DRT)来测试网页,把得到的结果和期望的结果进行对比,以检查WebKit引擎的对网页排版布局等的正确性。每个WebKit的移植都会提供一个DumpRenderTree,通查由于移植的差异性,它们的期望结果也不一样,所以通常每个移植都有自己特殊的期望结果。

每个测试都会有一个或者多个期望结果,一般地,期望结果是一些文本结果,但是,对一些复杂的测试,单纯的文本不能够满足需求,因为测试渲染结果可能需要比较布局,字体,图片等等,所以这时候期望结果其实是一幅图片(还有其他类型),这个图片其实就是网页应该渲染的结果。不幸的是,由于字体,平台的样式等差异性(例如Qt,GTK等就不一样),相同的网页渲染出的结果可能不一样,所以,你可以看到布局测试对不同的移植会有不同的期望结果。

一般来讲,当开发者提交新的补丁时候,需要先进行布局测试,只有当该测试通过,才有可能被WebKit所接受。如果你提交的是解决了一个新问题,那么,建议你提交一个新的测试用例来保证代码的正确性。 

## 源文件目录

third_party/WebKit/Source/WebCore/rendering/style

  渲染所需要的样式的支持类,其依赖于CSS解析器及其结果 

## 参考文献

1.      http://www.webkit.org/projects/layout/index.html

2.      http://www.w3.org/TR/CSS21/box.html#box-dimensions

3.      http://www.webkit.org/blog/1452/layout-tests-theory/

4.      http://www.webkit.org/blog/1456/layout-tests-practice/

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩眼睛近视怎么办才能恢复正常 3岁宝宝近视怎么办啊 6个月婴儿近视怎么办 近视眼的人老了怎么办 一千多度的近视怎么办 近视镜片磨花了怎么办 眼镜镜片磨花了怎么办 戴眼镜鼻梁有印怎么办 狗狗发烧怎么办最有效 狗狗感冒怎么办最有效 狗狗发烧去医院怎么办 眼睛里长了虫子怎么办 吃了没熟的猪肉怎么办 没熟的鸡肉吃了怎么办 狗狗大便有绦虫怎么办 吃了有虫的猪肉怎么办 米猪肉吃了会怎么办 吃了鱼的寄生虫怎么办 鱼身体里有线虫怎么办 幼猫半夜一直叫怎么办 猫半夜4点叫不停怎么办 眼睛里长了黄斑怎么办 眼睛周围长小疙瘩怎么办 眼睛被手机砸了怎么办 眼睛被东西砸了怎么办 眼睛被打了一下怎么办 眼睛被树枝伤了怎么办 眼球被打了一下怎么办 眼睛黄有血丝是怎么办 上眼皮有异物感怎么办 20岁眼周围皱纹怎么办 才22岁眼睛皱纹怎么办 眼周围发干皱纹怎么办 眼周围淤血肿了怎么办 每到秋季就咳嗽怎么办 左肾泥沙样结石怎么办 双肾泥沙样结石怎么办 温州市民卡丢了怎么办 上眼皮过敏肿了怎么办 上眼皮又痒又肿怎么办 上眼皮红肿痛是怎么办