本文主要包含浏览器,渲染文本等相关知识,佚名 希望在学习及工作中可以帮助到您
浏览器是我们最常用的软件之一,文本又是网页中最主要的元素,在浏览器显示文本的过程中有许多有趣的细节,值得展开来讲讲,或许能减少一些误解。这是一个比较粗略的,概括性的介绍,尽可能不涉及过多的技术细节和具体实现,而立足于给 Web 开发者和设计师提供一些正确的概念。
下面的介绍主要根据我对 WebKit 和 Gecko (Firefox) 的印象来谈,其他的浏览器也大致相同,如有阙漏之处欢迎指出。
当浏览器收到来自 Web 服务器的网页数据之后,第一步是要把它解码成可以阅读的文本,因为历史原因,不同区域和语言的网页可能会使用不同的编码方式,而浏览器判断编码主要是依据以下方法:
1.Web 服务器返回的 HTTP 头中的 Content-Type: text/html; charset= 信息,这一般有最高的优先级;
2.网页本身 meta header 中的 Content-Type 信息的 charset 部分,对于 HTTP 头未指定编码或者本地文件,一般是这么判断;
3.假如前两条都没有找到,浏览器菜单里一般允许用户强制指定编码;
4.部分浏览器 (比如 Firefox) 可以选择编码自动检测功能,使用基于统计的方法判断未定编码。
编码确定后,网页就被解码成了 Unicode 字符流,可以进行进一步的处理,比如 HTML 解析了,不过我们这里跳过 HTML/XML 解析的细节,单讲得到了解析后的文本元素之后该怎么处理。
因为我们得到的文本可能是很多种语言混杂的,里面可能有中文、有英文,它们可能要用不同的字体显示;也可能有阿拉伯文、希伯来文这种从右到左书写的文字;也有可能涉及印度系文字这样涉及复杂布局规则的文字;另外,还可能有网页内自己指定的文本语言,比如 <span lang="jp">日本语</span> 这样的标记,使得日文汉字可以使用日文字体显示 (因为 Han Unification 导致这些汉字和中文里的汉字使用同样的代码点,尽管很多写法不同),"lang" 属性也可以在 HTTP 头、<meta> 或者 <html> 出现,用于标记整个文档的全局语言,通常这是一种好的习惯,方便浏览器进行字体匹配。
为了统一处理所有这些复杂的情况,我们要将文本分为由不同语言组成的小段,在有的文本布局引擎里,这个步骤称为“itemize”,分解后的文本段常被称作“text run”,但是具体划分的规则可能根据不同的引擎有所区别,比如 HarfBuzz 和 ICU 一般是根据要使用的不同排版类来划分 (常称作“shaper”),比如英语和法语可能使用同一个 shaper 排版,那么相邻的英语和法语文本就会划分到同一个 run 里,而希伯来文需要另一个 shaper,就划分到它自己的 run 里,以 HarfBuzz 为例,它有这样一些 shaper:
通用的 (适用于中文、英文等等大多数布局规则简单的语言)
阿拉伯文
希伯来文
印度系文字
高棉文
缅文
谚文
不少浏览器还会在这个划分下面,在确定具体使用的字体之后,根据使用字体的不同划分更细的 run,这种 run 可能称作“SimpleTextRun”,每个都会使用和相邻不同的字体,最后把它们逐一交给 shaper 进行排版得到要绘制的字形,这样一来,shaper 的工作就被简化为在确定的语言、确定的字体下排版确定的文本,生成对应的字形和它们应该放置的位置、占用的空间。下面先详细说说确定字体的步骤。
说到字体,首先必须提到的就是 CSS 里的 font 和 font-family 等规则。比如这样的规则:
4
下面的介绍主要根据我对 WebKit 和 Gecko (Firefox) 的印象来谈,其他的浏览器也大致相同,如有阙漏之处欢迎指出。
当浏览器收到来自 Web 服务器的网页数据之后,第一步是要把它解码成可以阅读的文本,因为历史原因,不同区域和语言的网页可能会使用不同的编码方式,而浏览器判断编码主要是依据以下方法:
1.Web 服务器返回的 HTTP 头中的 Content-Type: text/html; charset= 信息,这一般有最高的优先级;
2.网页本身 meta header 中的 Content-Type 信息的 charset 部分,对于 HTTP 头未指定编码或者本地文件,一般是这么判断;
3.假如前两条都没有找到,浏览器菜单里一般允许用户强制指定编码;
4.部分浏览器 (比如 Firefox) 可以选择编码自动检测功能,使用基于统计的方法判断未定编码。
编码确定后,网页就被解码成了 Unicode 字符流,可以进行进一步的处理,比如 HTML 解析了,不过我们这里跳过 HTML/XML 解析的细节,单讲得到了解析后的文本元素之后该怎么处理。
因为我们得到的文本可能是很多种语言混杂的,里面可能有中文、有英文,它们可能要用不同的字体显示;也可能有阿拉伯文、希伯来文这种从右到左书写的文字;也有可能涉及印度系文字这样涉及复杂布局规则的文字;另外,还可能有网页内自己指定的文本语言,比如 <span lang="jp">日本语</span> 这样的标记,使得日文汉字可以使用日文字体显示 (因为 Han Unification 导致这些汉字和中文里的汉字使用同样的代码点,尽管很多写法不同),"lang" 属性也可以在 HTTP 头、<meta> 或者 <html> 出现,用于标记整个文档的全局语言,通常这是一种好的习惯,方便浏览器进行字体匹配。
为了统一处理所有这些复杂的情况,我们要将文本分为由不同语言组成的小段,在有的文本布局引擎里,这个步骤称为“itemize”,分解后的文本段常被称作“text run”,但是具体划分的规则可能根据不同的引擎有所区别,比如 HarfBuzz 和 ICU 一般是根据要使用的不同排版类来划分 (常称作“shaper”),比如英语和法语可能使用同一个 shaper 排版,那么相邻的英语和法语文本就会划分到同一个 run 里,而希伯来文需要另一个 shaper,就划分到它自己的 run 里,以 HarfBuzz 为例,它有这样一些 shaper:
通用的 (适用于中文、英文等等大多数布局规则简单的语言)
阿拉伯文
希伯来文
印度系文字
高棉文
缅文
谚文
不少浏览器还会在这个划分下面,在确定具体使用的字体之后,根据使用字体的不同划分更细的 run,这种 run 可能称作“SimpleTextRun”,每个都会使用和相邻不同的字体,最后把它们逐一交给 shaper 进行排版得到要绘制的字形,这样一来,shaper 的工作就被简化为在确定的语言、确定的字体下排版确定的文本,生成对应的字形和它们应该放置的位置、占用的空间。下面先详细说说确定字体的步骤。
说到字体,首先必须提到的就是 CSS 里的 font 和 font-family 等规则。比如这样的规则:
4