《WebKit 技术内幕》之六(3): CSS解释器和样式布局

3 WebKit布局

3.1 基础

        当WebKit创建RenderObject对象之后,每个对象是不知道自己的位置、大小等信息的,WebKit根据框模型来计算它们的位置、大小等信息的过程称为布局计算(或者称为排版)。

        图描述了这一过程中涉及的主要WebKit类。第5章描述过Frame类,用于表示网页的框结构,每个框都有一个FrameView类,用于表示框的视图结构。

                                        图布局计算中的主要WebKit类

        FrameView类主要负责视图方面的任务,例如网页视图大小、滚动、布局计算、绘图等,它是一个总入口类。图中标注了两个跟布局计算密切相关的函数——“layout”和“needsLayout”,它们用来布局计算和决定是否需要布局计算,实际的布局计算则是在RenderObject类中。

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

3.2 布局计算

        布局计算是一个递归的过程,这是因为一个节点的大小通常需要先计算它的子女节点的位置、大小等信息。

        下图描述了RenderObject节点计算布局的主要过程,中间省略了很多判断和步骤,主要逻辑都是由RenderObject类的“layout”函数来完成。

                                        图布局计算过程

        首先,该函数会判断RenderObject节点是否需要重新计算,通常这需要通过检查位数组中的相应标记位、子女是否需要计算布局等来确定。

        其次,该函数会确定网页的宽度和垂直方向上的外边距,这是因为网页通常是在垂直方向上滚动,而水平方向尽量不需要滚动。

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

        最后,节点根据它的子女们的大小计算得出自己的高度,整个过程结束。

        哪些情况下需要重新计算布局呢?总体来讲,只要样式发生变化,WebKit都需要重新计算,但是实际场景中,有以下一些情况。

        首先,当网页首次被打开的时候,浏览器设置网页的可视区域(viewport),并调用计算布局的方法。这其实也描述了一种常见的情景,就是当可视区域发生变化的时候,WebKit都需要重新计算布局,这是因为网页的包含块的大小发生了改变。

        其次,网页的动画会触发布局计算。当网页显示结束后,动画可能改变样式属性,那么WebKit就需要重新计算。

        然后,JavaScript代码通过CSSOM等直接修改样式信息,它们也会触发WebKit重新计算布局。

        最后,用户的交互也会触发布局计算,例如翻滚网页,这会触发新区域布局的计算。

        CSS的布局计算是以包含块和框模型为基础的,这表示这些元素的布局计算都依赖于块,例如“div”通常就是一个块,如前面所述它们通常是在垂直方向上展开。但是,CSS标准也规定了行布局形式,这就是内联元素。内联元素表现的是行布局形式,就是说这些元素以行进行显示。以“div”元素为例,如果设置属性“style”为“display:inline”时,则该元素是内联元素,那么它可能与前面的元素在同一行。如果该元素没有设置这个属性时,则是块元素,那么在新的行里显示。这显然会增加处理的复杂性,为此,WebKit的处理方式是——对于一个块元素对应的RenderObject对象,它的子女要么都是块元素的RenderObject对象,要么都是非内联元素对应的RenderObject对象,这可以通过建立匿名块(Anonymous Block)对象来实现,在下一章也会作介绍。 (2)

        布局计算相对也是比较耗时间的,更糟糕的是,一旦布局发生变化,WebKit就需要后面的重新绘制操作。另一方面,减少样式的变动而依赖现在HTML5的新功能可以有效地提高网页的渲染效率,这些在后面介绍绘图的时候一并分析。

3.3 布局测试

        在这里介绍布局测试(Layout Tests)貌似也有点文不对题,因为其实布局测试不仅测试布局,还包括渲染等综合渲染结果。本章主要介绍CSS的样式计算和布局计算,不过它们也或多或少存在联系。

        布局测试可以说是WebKit中最重要并且最著名的测试了,用于测试网页的整个渲染结果,包括网页加载和渲染整个过程。渲染引擎要处理各式各样越来越复杂的网页,这需要布局测试来保证引擎的渲染结果的正确性。基本测试工作方式是:预先准备大量用于单元测试的网页和期望的渲染结果,然后使用WebKit编译出来的DumpRenderTree(DRT)来测试网页,把得到的结果和期望的结果进行对比,以检查WebKit引擎对网页排版布局等的正确性。每个WebKit的移植都会提供一个DumpRenderTree, (3) 通常由于移植的差异性,它们的期望结果也不一样,所以通常每个移植都有特殊的期望结果。

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

        一般来讲,当开发者提交新的代码补丁包时,需要先进行布局测试,只有当该测试通过并且没有造成其他的测试出现新错误的时候,才有可能被WebKit项目所接受。如果读者提交代码的目的是解决一个新问题,那么,强烈建议读者提交一个新的测试用例来保证代码的正确性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/639186.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【解决方法】PPT不能编辑,按钮都是灰色,怎么办?

PPT文件打开之后,发现无法编辑,再仔细查看发现工具栏中的功能按钮都是灰色的,无法使用,这是什么原因?该如何解决? 原因:无法编辑PPT文件,并且功能按钮都是灰色,这是因为…

qnx 上screen + egl + opengles 最简实例

文章目录 前言一、qnx 上的窗口系统——screen二、screen + egl + opengles 最简实例1.使用 addvariant 命令创建工程目录2. 添加源码文件3. common.mk 文件4. 编译与执行总结参考资料前言 本文主要介绍如何在QNX 系统上使用egl和opengles 控制GPU渲染一个三角形并显示到屏幕上…

cuda中的定点数优化技术

这里学习一下定点数的优化操作,实际上就是以整数代替浮点数,乘除法的操作均通过左右移位来实现,适合在算力非常低的场景下使用,极致的压榨性能。 https://zhuanlan.zhihu.com/p/338588296 定点数介绍 以下给出函数的具体实现&…

纸黄金实战投资技巧:避免亏损的有效策略

在纸黄金交易的实战中,避免亏损是每位投资者都追求的目标。虽然任何投资都存在一定的风险,但采取一些有效的策略可以帮助投资者最大限度地减少亏损的可能性。以下是一些在纸黄金交易中避免亏损的实战技巧: 一、设定止损点是避免亏损的关键 止…

【Linux】

Linux零基础入门 列出文件/文件夹新建/切换路径查看当前路径重命名或者移动文件夹拷贝文件/文件夹删除文件夹设置环境变量编辑文本文件压缩和解压查看cpu的信息查看/杀死进程查看进程的CPU和内存占用重定向日志场景一场景二场景三场景四 列出文件/文件夹 命令:Ls(L…

All the stories begin at installation

Before installation, there are some key points about Conan: “Conan is a dependency and package manager for C and C languages.”“With full binary management, Conan can create and reuse any number of different binaries (for different configurations like a…

基于SpringBoot的智慧社区居家养老健康管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式 🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 &…

Kafka常见指令及监控程序介绍

kafka在流数据、IO削峰上非常有用,以下对于这款程序,做一些常见指令介绍。 下文使用–bootstrap-server 10.0.0.102:9092,10.0.0.103:9092,10.0.0.104:9092 需自行填写各自对应的集群IP和kafka的端口。 该写法 等同 –bootstrap-server localhost:9092 …

Unity 抽象工厂模式(实例详解)

文章目录 简介实例1实例2 简介 抽象工厂模式是一种创建型设计模式,它提供了一种方式来封装一组相关或相互依赖对象的创建过程,而无需指定具体类。这种模式常用于系统中有多组相关产品族,且客户端需要使用不同产品族中的对象时。 在Unity中&a…

Windows7关闭谷歌浏览器提示“若要接收后续 Google Chrome 更新,您需使用 Windows 10 或更高版本”的方法

背景 电脑比较老,系统一直没有更新,硬件和软件版本如下: 操作系统版本:Windows7 企业版 谷歌浏览器版本:109.0.5414.120(正式版本) (64 位) 该版本的谷歌浏览器是支持…

MySQL不同插入方式性能对比实验

最近负责的项目需要数据同步入库MySQL,为了测速那种入库方式效率比较高,为此进行了以下的对比实验,在此记录一下 实验表单数据格式 实验代码 共三种方法对比 mutiSqlInsert: 一条一条插入,最后一次提交 singleSqlInsert&…

LabVIEW滚动轴承故障在线监测

展示了如何将LabVIEW开发出一种有效的滚动轴承故障在线监测系统。介绍了该系统的开发过程、工作原理及其在实际应用中的效果。该系统成功地应用于对滚动轴承故障的早期诊断,提高了故障检测的准确性和效率。 滚动轴承在工作过程中会产生复杂的振动信号,包…

Proxmox VE 8 试装Oracle 23c

作者:田逸(formyz) Oracle 当前的最新版本是23c,虽然官方网站下载不了它的正式版本,但是却提供了一个性能受限的免费版本“Oracle Database 23.3 Free”(存储容量受限、内存使用受限)。这里就只…

[机缘参悟-129] :个人对人生之苦解决之道的思考

目录 前言: 第1层:环境层 1.1 环境的分类 1.2 理解环境的运作的基本原理 1.3 主动选择适合自己的愉快的环境 1.4 主动构建适合自己的愉快的环境 第2层:生理层 2.1 生理健康和情绪之间的关系 2.2 学习人的生物、生理、健康的基本知识…

MySQL与PostgreSQL对比

对比 许可证 License MySQL 社区版采用 GPL 许可证。Postgres 发布在 PostgreSQL 许可下,是一种类似于 BSD 或 MIT 的自由开源许可。 即便 MySQL 采用了 GPL,仍有人担心 MySQL 归 Oracle 所有,这也是为什么 MariaDB 从 MySQL 分叉出来。 …

数据出境——电商API接口使得电商数据跨境流动已成为趋势

在数字经济的当下,数据已经成为商业决策的关键因素。尤其是电商领域,电商API数据采集不仅关乎企业运营效率,还涉及到用户隐私与国家安全。近年来,随着电商市场的全球化发展,电商数据出境与跨境贸易已成为不可逆转的趋势…

vue3-模版引用ref

1. 介绍 概念&#xff1a;通过 ref标识 获取真实的 dom对象或者组件实例对象 2. 基本使用 实现步骤&#xff1a; 调用ref函数生成一个ref对象 通过ref标识绑定ref对象到标签 代码如下&#xff1a; 父组件&#xff1a; <script setup> import { onMounted, ref } …

Android Studio 之 菜单 Menu

选项菜单 OptionsMenu 用xml添加&#xff08;更建议使用&#xff09; 创建一个菜单布局 : 在 res文件下新建一个menu 目录&#xff0c;此时的菜单id为&#xff1a;R.menu.option <?xml version"1.0" encoding"utf-8"?> <menu xmlns:android&…

不同开发语言在进程、线程和协程的设计差异

不同开发语言在进程、线程和协程的设计差异 1. 进程、线程和协程上的差异1.1 进程、线程、协程的定义1.2 进程、线程、协程的差异1.3 进程、线程、协程的内存成本1.4 进程、线程、协程的切换成本 2. 线程、协程之间的通信和协作方式2.1 python如何实现线程通信&#xff1f;2.2 …

【Unity】AB包下载

【Unity】AB包下载 1.使用插件打AB包 a.AB包分类 一般地&#xff0c;将预制体作为AB包资源&#xff0c;不仅需要对预制体本身进行归类&#xff0c;还要对其涉及的动画&#xff08;AnimationClip&#xff09;、动画状态机&#xff08;AnimatorController&#xff09;、以及所…