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

2023-10-08 01:30

本文主要是介绍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 * 2Extend = ( WinAscent + WinDescent ) * 0.15
    
  5. 对于以上计算出的系数 0.15 目前没有确切的值,可能有偏差,还可能跟不同的字体有关。通过程序验证之后得到可能比较精确的值如下:
    第一种:0.14845,适用于 仿宋、宋体、幼圆、新宋体、方正姚体、方正舒体、楷体、隶书、黑体。
    第二种:0.15002,适用于 华文中宋、华文仿宋、华文宋体、华文新魏、华文楷体、华文琥珀、华文细黑、华文行楷、华文隶书、华文彩云、宋体-方正超大字符集、微软雅黑。

这篇关于Office Word 是如何根据字体的 OS/2 表等信息计算「单倍行距」的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/161793

相关文章

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

解决Office Word不能切换中文输入

我们在使用WORD的时可能会经常碰到WORD中无法输入中文的情况。因为,虽然我们安装了搜狗输入法,但是到我们在WORD中使用搜狗的输入法的切换中英文的按键的时候会发现根本没有效果,无法将输入法切换成中文的。下面我就介绍一下如何在WORD中把搜狗输入法切换到中文。