分类 Web 下的文章

OpenType是TrueType的扩展。本文全流程介绍TrueType从字体设计到字体显示的每个步骤,这些步骤同样也适用于OpenType。

TrueType字体可能诞生于纸上,也可能从其他格式转换而来。但最终,字体文件中一定包含每个字形的描述信息。下图展示了从设计稿原件到数字化字形,再到字体文件中数字化轮廓的过程。

图1 设计稿原件、数字化字形、字体文件中以FUnit坐标表示的数字化轮廓

那么TrueType字体是如何在显示设备(屏幕、打印机)上应用的呢?

首先,要将字体文件中存储的轮廓缩放到要求的尺寸,即将字体文件中以FUnit(Font Uint,字体单位)表示的原始轮廓转换为特定于设备的像素坐标。

然后,解释器运行与字形关联的指令,运行指令的结果是完成字形的网格适配(grid-fit)。完成网格适配,再由扫描转换程序生成最张在目标设备上呈现的位图图像。

图2 字体渲染流程

  1. 在TrueType字体文件中以FUnit坐标形式描述字形的轮廓
  2. 缩放程序将FUnit转换为像素坐标,并缩放至应用程序要求的大小
  3. 轮廓缩放至新网格
  4. 缩放后以像素坐标表示的轮廓
  5. 解释程序执行与字形B关联的指令,进行网格适配
  6. 网格适配后的轮廓
  7. 网格适配后的轮廓
  8. 扫描转换器决定打开哪些像素
  9. 在目标设备上渲染位置

- 阅读剩余部分 -

CSS Font Module Level 3(本文以下简称“ML3”)新增了字体特性(Font Feature)属性,用于扩展font-variant,以支持丰富OpenType字体特性,如连字。

我们知道,字体文件中包含着从Unicode码点到字形的映射。在给简单的拉丁文本应用字体时,就是根据字体文件中的映射表逐个把对应的字形找到并显示出来。而OpenType和AAT(Apple Advanced Typography)等字体标准支持更复杂的处理模式。比如,给定字符的字形不仅可以根据码点来选择和定位,也可以根据相邻字符或者语言、文字以及文本本身启用的特性来选择和定位。

风格性的字体特性分两类:影响与周围字符关系的和影响字形选择的。前者比如字距调整(kerning)和连字(ligature)相关的特性,后者比如小型大写字母(small-caps)、上/下标(superscript/subscript)及替代(alternate)特性。

为了支持这些字体特性,ML3扩展了font-variant,基于它增加了很多子属性用于控制相应的字体特性,比如font-variant-ligaturesfont-variant-postionfont-variant-capsfont-variant-numericfont-variant-east-asian。而font-variant则变成了一个涵盖所有这些属性的简写属性,类似font那样。不过,以上这些子属性只会影响字形选择与定位,不影响字体选择。

因为这些字体特性都与风格有关,所以字体特性的英文也叫stylistic font features。这个意义上,unstyled text就不是"未应用样式文本",而是"未启用风格化字体特性的文本"。

font-kerning

用于根据字体文件中的数据来调整字形间距。auto表示由UA决定,normal表示应用字体文件中的数据,none表示不应用。

对于不包含相关数据的字体,这个属性没有影响。OpenType标准建议默认启用间距调整,即应用OpenType的kern特性(对于垂直文本则是vkrn)。如果同时定义了letter-spacing属性,则字体内置的间距作为默认值,在此基础上再进行调整。

- 阅读剩余部分 -

本文是阅读CSS标准文档的笔记,也是对CSS字体相关知识的一个梳理。

Cascading Style Sheets, level 1

CSS 1定义的字体属性包括:font-familyfont-stylefont-variantfont-weightfont-sizefont。其算法要求UA(User Agent,用户代理)对给定元素中的字符逐个查找匹配的CSS属性,首先尝试匹配font-style,比如italicoblique。然后匹配font-variantnormal匹配非small-caps(小型大写)字体,而small-caps则匹配(1)标识为small-caps的字体(2)合成小型大写字母的字体(3)将小写字母替换为大写字母的字体(小型大写字母可以通过将normal字体的大写字母缩小来实现)。接着匹配font-weightfont-size,这两个属性都是必须匹配成功的。

font-family是一个按照优先级排列的字体或通用字体名字的列表,每个名字以逗号分隔,表示多选一。

body { font-family: gill, helvetica, sans-serif; }

有两种值:字体名和通用字体名。在上面的例子中,gillhelvetica就是明确指定的字体名,而sans-serif则是通用字体名。CSS 1定义了5种通用字体:

  • serif:衬线
  • sans-serif:非衬线
  • cursive:手写
  • fantasy:装饰
  • monospace:等宽

通常,除了指定特定的字体名,最后都应该指定一个通用字体名。另外,如果字体名包含空格,必须用引号括起来。

- 阅读剩余部分 -

本文通过分析一个小案例帮大家从一个侧面理解JavaScript的异步执行机制,从而可以在实践中避免类似的尴尬。

小背景

我们都知道,alert这种内置弹框会阻塞后续代码执行:

之所以如此,就是因为JavaScript代码在浏览器中是单线程执行的。换句话说,浏览器中只有一个主线程负责运行所有JavaScript代码(不考虑Web Worker)。

提到浏览器中的JavaScript,基本上只有三个来源:

  • BOM API的代码,让我们可以操作并利用浏览器提供的能力
  • DOM API的代码,让我们可以操作网页内容
  • 我们自己写的ECMAScript代码

这没什么。我们也知道,setTimeout用于“定时”执行代码,比如这样可以定时在3秒钟之后执行一段代码(函数):

setTimeout(delayCode, 3000)

- 阅读剩余部分 -

各位,如果你的职业是开挖掘机,你说要不要深入理解挖掘机?通常来说,深入理解你操纵的机器才能最终达到人机一体的境界。

当然,你可以说:不用,因为如果挖掘机不好使,我可以换一台。嗯,也有道理。不过,假如你同时又是一名前端开发者,那你要不要深入理解浏览器呢?注意,身为前端,你不太可能有机会因为浏览器不好使就强迫用户换一个你认为好使的。这时候,你好像别无选择了。

不过也不用害怕,今天我们的现代浏览器深度游会非常轻松、快乐。这首先必须感谢一位名叫Mariko Kosaka(小坂真子,https://kosamari.com/)的同行。她在Scripto工作,2018年9月在Google开发者网站上发表了“Inside look at modern web browser”系列文章。本文就是她那4篇文章的“集合版”。为什么搞这个“集合版”?因为她的4篇文章写得实在太好,更难得的是人家亲手绘制了一大堆生动的配图和动画,这让深入理解现代浏览器变得更加轻松愉快。

好了,言归正传。本文分4个部分,对应上述4篇文章(原文链接附后)。

  • 架构:以Chrome为例,介绍现代浏览器的实现架构。
  • 导航:从输入URL到获到HTML响应称为导航。
  • 渲染:浏览器解析HTML、下载外部资源、计算样式并把网页绘制到屏幕上。
  • 交互:用户输入事件的处理与优化。

先来个小小的序言。很多人在开发网站时,只关注怎么写自己的代码,关注怎么提升自己的开发效率。这些当然重要,但是写到一定的阶段,就应该停下来想想:浏览器到底会怎么运行你写的代码。如果你能多了解一些浏览器,然后对它好一点,那么就会更容易达成你提升用户体验的目标。

- 阅读剩余部分 -