Files
reader/docs
hectorqin fd743f3a3f fix(web): 修好图标与文字的对齐,并让字体度量不再说谎
界面图标显示正常但歪,实测每个字形都偏离所在盒子中心 0.496em(半个盒子),
也就是 9px 以上,且每一行歪的幅度还不一样。代价是三条互相独立的缺陷叠在
一起,而此前所有图标测试都只读 `cmap` 和字形名,一条都不覆盖这些位置。

一、`.icon` 把字体自己的行盒换成了一个方块(主因)

`line-height: 0; display: inline-block; width: 1em; height: 1em` 会得到
一个**锚在基线上、向下一整个 em** 的盒子,而字形是围绕基线画的。于是墨迹贴在
盒子上沿、盒子下方整片是空的。UI 里每个容器都在居中这个盒子,盒子确实居中了,
字形却差了半个 em——这就是「显示正常但不对齐」,也是每行幅度不同的来源:各行的
容器不同,锚法就不同。

改为用字体自己的行盒(`line-height: 1`,不再给高度),只保留 `width: 1em`
这个字体给不了的东西(可预测的前进宽度),并补 `vertical-align: middle` 给
正文里行内出现的图标。**刻意不用 `transform`**:它能在 flex/grid 里生效
(`vertical-align` 在那里是惰性的),但它改的是绘制期位置,会让「图标占的位置」
和「看起来占的位置」不再一致。

二、字体度量与字形不自洽(次因)

表格声明上升部 960 / 下降部 -64(基线靠近 em 底部),而字形是按
`(GRID/2 - y)` 围绕 em 中心画的。两者各自自洽、互相矛盾,而输的是盒子。
现在上升部与下降部各取半个 em:**对称**不是审美——UI 里每个容器都在居中盒子,
只有度量对称时「居中盒子」和「居中字形」才是一回事。

同时修掉三处字段错位(都会静默通过解析):

- `OS/2` 的 `sTypoAscender/Descender` 一直写在 panose 区域,真正的排印窗口是 0/0;
- `usWinAscent/Descent`(**无符号**)也写错了位置,读出来是 0 / 65506;
- `fsSelection` 原本声明 BOLD,`usWeightClass` 是 500——一个不粗的字体谎称自己粗,
  引擎就会合成加粗,而合成出来的图标是糊的。改为 `REGULAR | USE_TYPO_METRICS`。

`head` 的每个字形包围盒补一格下限:`more` 的三个点是用 0.06 单位描边写的,
四舍五入后两个轴各只剩一个点,包围盒为空——空包围盒是栅格化器有权跳过的图形,
于是「更多」按钮画出来是白的,而 `cmap` 依然映射它的码位,所以读表的断言全都
满意。`settings` 的路径解析出了一组跑到网格外的坐标(y 到 24.8、x 到 0.8),
重画成真正的齿轮;`chevron-right` 与 `chevron-left` 共用同一个框却差一个单位。

三、图标按钮有两条构建路径

`manager-more` 是手搭的 `<button class="icon-button">`,而 `.icon-button` 的
对齐靠的是「里面有 `.icon`」这个约定——手搭的那条路径绕过了它。现在一律走
`IconButton`,`label` 必填、字形是名字而不是任意子节点;图标加文字的新组合收进
`IconTextButton`,因为那正是最容易歪、且每次都歪得一样的组合。

验证:新增 10 条断言,覆盖字体度量、字形包围盒与 `.icon` 规则本身;把改动逐条
还原后它们会红(已验证)。真浏览器验收:37 个字形逐个测量,墨迹中心与盒子中心
最大偏差 0.88px(改前是 9px+);书架与阅读器两屏在真实产物上截图核对。客户端
`typecheck` / 317 个测试 / `build`、`check-shell.sh`、`verify-web-assets.sh` 全过。
产物 259.68KB → 259.68KB,字体 16.34KB,CSS 24.54KB。

Ref: #34
2026-09-18 11:30:36 +08:00
..