Office Word 是如何根据字体的 OS/2 表等信息计算「单倍行距」的

以 Office 2013 附带的 华文中宋 为例计算默认行高 [1]:
  • 按苹果最初为 TrueType 设计的 hhea 规则
    ( hhea.ascent + hhea.descent + hhea.lineGap ) / head.unitsPerEm 
    
    计算得 1.325(华文中宋在 Pages 中的效果符合此数值);
  • 按 OpenType 规范的 sTypo 规则
    ( OS/2.sTypoAscender + OS/2.sTypoDescender + OS/2.sTypoLineGap )
      / head.unitsPerEm 
    
    计算得 1.144;
  • 按 Windows 里最主流但不符合规范的 usWin 规则
    ( OS/2.usWinAscent + OS/2.usWinDescent ) / head.unitsPerEm
    
    计算得 1.137。
以上三个结果都与  Word 2013  里的「单倍行距」效果(似乎是一个介于 1.47 与 1.48 之间的数值,且「如果定义了文档网格,则对齐到网格」已关闭)不一致。

那么,Word 是如何计算并实现「单倍行距」的呢?

另外, Word for Mac 2011  里的「单倍行距」似乎和 Windows 版 Word 里的数值并不一致,和 Pages 也不一样。它仿佛是这样计算的,完全忽略 hhea.lineGap 数值,又自己给乘上 1.3,不符合任何规范或事实标准:
( hhea.ascent + hhea.descent ) / head.unitsPerEm * 1.3
这是造成同一文件在 Windows 与 Mac 版 Word 及 Pages 中开启时版式不一致的原因之一吗?

[1] 下附用 ttx dump 出的华文中宋相关数据供参考(若代码未高亮请尝试展开补充说明):
<head>
  <!-- Most of this table will be recalculated by the compiler -->
  <tableVersion value="1.0"/>
  <fontRevision value="1.0"/>
  <checkSumAdjustment value="0xb611830c"/>
  <magicNumber value="0x5f0f3cf5"/>
  <flags value="00000000 00000011"/>
  <unitsPerEm value="1000"/>
  <created value="Fri Jul 17 10:51:22 1998"/>
  <modified value="Wed Oct 30 08:28:00 2002"/>
  <xMin value="-186"/>
  <yMin value="-318"/>
  <xMax value="1317"/>
  <yMax value="1007"/>
  <macStyle value="00000000 00000000"/>
  <lowestRecPPEM value="14"/>
  <fontDirectionHint value="1"/>
  <indexToLocFormat value="1"/>
  <glyphDataFormat value="0"/>
</head>

<hhea>
  <tableVersion value="1.0"/>
  <ascent value="1007"/>
  <descent value="-318"/>
  <lineGap value="0"/>
  <advanceWidthMax value="1365"/>
  <minLeftSideBearing value="-186"/>
  <minRightSideBearing value="-186"/>
  <xMaxExtent value="1317"/>
  <caretSlopeRise value="1"/>
  <caretSlopeRun value="0"/>
  <caretOffset value="0"/>
  <reserved0 value="0"/>
  <reserved1 value="0"/>
  <reserved2 value="0"/>
  <reserved3 value="0"/>
  <metricDataFormat value="0"/>
  <numberOfHMetrics value="25185"/>
</hhea>

<OS_2>
  <version value="1"/>
  <xAvgCharWidth value="492"/>
  <usWeightClass value="400"/>
  <usWidthClass value="5"/>
  <fsType value="00000000 00001000"/>
  <ySubscriptXSize value="100"/>
  <ySubscriptYSize value="100"/>
  <ySubscriptXOffset value="0"/>
  <ySubscriptYOffset value="150"/>
  <ySuperscriptXSize value="100"/>
  <ySuperscriptYSize value="100"/>
  <ySuperscriptXOffset value="0"/>
  <ySuperscriptYOffset value="650"/>
  <yStrikeoutSize value="100"/>
  <yStrikeoutPosition value="250"/>
  <sFamilyClass value="0"/>
  <panose>
    <bFamilyType value="2"/>
    <bSerifStyle value="1"/>
    <bWeight value="6"/>
    <bProportion value="0"/>
    <bContrast value="4"/>
    <bStrokeVariation value="1"/>
    <bArmStyle value="1"/>
    <bLetterForm value="1"/>
    <bMidline value="1"/>
    <bXHeight value="1"/>
  </panose>
  <ulUnicodeRange1 value="00000000 00000000 00000010 10000111"/>
  <ulUnicodeRange2 value="00001000 00001111 00000000 00000000"/>
  <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
  <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
  <achVendID value="SINO"/>
  <fsSelection value="00000000 01000000"/>
  <fsFirstCharIndex value="32"/>
  <fsLastCharIndex value="65509"/>
  <sTypoAscender value="800"/>
  <sTypoDescender value="-200"/>
  <sTypoLineGap value="144"/>
  <usWinAscent value="912"/>
  <usWinDescent value="225"/>
  <ulCodePageRange1 value="00000000 00000100 00000000 10011111"/>
  <ulCodePageRange2 value="11011111 11010111 00000000 00000000"/>
</OS_2>


  
  
作者:VinnyXiong 链接:http://www.zhihu.com/question/23349103/answer/24328488 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
下图为“华文中宋”字体“国”字,用的是FontCreater7.5,相应的字体参数已经标明。 通过在Word中手工测量(字体设置为200磅,放大到500%,测量像素然后转为twips,再计算),以及使用FontCreater修改字体参数,发现了一些规律:
  1. Word中的字体高度仅取决于 WinAscent WinDescent 两个值。
  2. 测量发现的高度总是大于 ( WinAscent + WinDescent ),说明Word在此基础上有扩展的高度 Extend
  3. 多次测试不同字体以及不同字号之后发现,实际高度 LineHeight (WinAscent + WinDescent) 之间存在一个可能是固定的比例关系,大约在 1.29 ~ 1.31 之间,即 LineHeight = ( WinAscent + WinDescent ) * 1.3
  4. 通过FontCreater修改 WinAscent 或 WinDescent 之后发现,扩展的Extend是平均分配到上面和下面的,Extend1 与 Extend2 相等,如上图所示。
    LineHeight = ( WinAscent + WinDescent ) * 1.3
               = ( WinAscent + WinDescent ) + ( WinAscent + WinDescent ) * 0.3
               = ( WinAscent + WinDescent ) + Extend1 + Extend2
               = ( WinAscent + WinDescent ) + Extend * 2
    
    Extend = ( WinAscent + WinDescent ) * 0.15
    
  5. 对于以上计算出的系数 0.15 目前没有确切的值,可能有偏差,还可能跟不同的字体有关。通过程序验证之后得到可能比较精确的值如下:
    第一种:0.14845,适用于 仿宋、宋体、幼圆、新宋体、方正姚体、方正舒体、楷体、隶书、黑体。
    第二种:0.15002,适用于 华文中宋、华文仿宋、华文宋体、华文新魏、华文楷体、华文琥珀、华文细黑、华文行楷、华文隶书、华文彩云、宋体-方正超大字符集、微软雅黑。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值