字体子集化后如何保留字符原始尺寸?
我碰到过类似的问题,大概率是子集化过程中丢失了字体的全局垂直度量信息,或者单个字符的排版属性被修改了,导致Android系统计算按钮高度时出现偏差。咱们一步步来排查解决:
核心原因分析
问题出在字体的这些关键属性上:
- 全局度量值:字体的
Ascent(上升高度)、Descent(下降高度)、Line Gap(行间距)是系统计算控件高度的核心依据。子集化工具经常会自动调整这些值,只匹配保留的字符,但实际上必须和原字体完全一致才能保证控件尺寸正常。 - 字符自身度量:单个字符的边界框(Bounding Box)、垂直偏移量如果被修改,也会让系统误以为这个字符的高度更小,从而压缩按钮尺寸。
用FontForge修复的具体步骤
核对全局度量值
打开子集后的字体,依次点击Element > Font Info > General,查看Ascent、Descent、Line Gap这三个值。然后打开完整的M PLUS 1p Medium字体,把这三个值复制过来,确保子集字体和原字体完全一致。比如原字体的Ascent可能是1040,Descent是-240,Line Gap是0,具体数值以原字体为准。
检查OS/2和Hhea表的度量
这两个表是Android系统依赖的关键排版表:- 点击
Element > Font Info > OS/2,把Win Ascent、Win Descent、Typo Ascent、Typo Descent改成和原字体一致。 - 点击
Element > Font Info > Hhea,同步Ascender、Descender、Line Gap的值到原字体的数值。
- 点击
确保字符度量未被修改
选中左箭头(U+2190)和被迫加入的上箭头(U+2191),点击Metrics > Glyph Info,查看Top、Bottom、Width这些属性,确保和原字体里对应字符的数值完全相同。如果不一样,手动调整或者直接从原字体复制粘贴这些值。子集化时关闭自动优化
下次子集化时,点击File > Generate Fonts,在生成窗口的Options区域,取消勾选任何带有“Optimize metrics”(优化度量)、“Adjust vertical metrics”(调整垂直度量)的选项,避免工具自动修改关键属性。
在线工具的注意事项
如果你用在线子集化工具,一定要在设置里找到保留原始度量的选项:
- FontSquirrel:在“Expert Options”里找到“Vertical Metrics”,选择“Keep original”而不是“Auto-Adjust”。
- 其他工具:查找类似“Preserve font metrics”、“Don't modify vertical bounds”的选项,确保全局度量不被改动。
Android端的辅助排查
虽然你说设置android:layout_height="match_parent"没用,但可以试试给按钮加上android:includeFontPadding="false",这个属性可以去掉系统默认的字体内边距,不过核心还是要先把字体本身的度量修好。另外你同时设置android:fontFamily和app:fontFamily的做法是对的,兼容了不同Android版本。
总结一下:只要保证子集字体的全局垂直度量值和单个字符的排版属性完全匹配原字体,Android系统计算按钮高度时就会和用完整字体时一致,不会出现“矮一截”的问题。
备注:内容来源于stack exchange,提问作者Viktor Brešan

