原始文本宽度通常在typographer's points中计算,但由于字体定义的目的定义为1/72英寸,因此可以轻松将其转换为任何其他单位。
为了得到一个字符(在EM单位表示)的设计宽度,你需要访问字体的低级别的数据。最简单的方法是pip install fonttools
,它有一切工作在尽可能低的字体定义水平。
在安装fontTools,您可以:
- 负载的字体数据 - 这需要路径到实际字体文件;
字符宽度存储为字形宽度,这意味着您必须检索'character-to-glyph'映射;这是cmap
表中的一种字体:
a。为您的字体加载cmap
。最有用的是Unicode映射 - 一种字体可能包含其他字体。 b。加载字形集为您的字体。这是该字体中字形名称的列表。
然后,对于每个Unicode字符,首先查找其名称,然后使用名称以设计单位检索其宽度。
- 不要忘记,'设计单位'是基于字体的整体'设计宽度'。这可以是
1000
(典型用于Type 1字体),2048
(TrueType字体的典型值)或任何其他值的标准值。
导致此功能:
from fontTools.ttLib import TTFont
from fontTools.ttLib.tables._c_m_a_p import CmapSubtable
font = TTFont('/Library/Fonts/Arial.ttf')
cmap = font['cmap']
t = cmap.getcmap(3,1).cmap
s = font.getGlyphSet()
units_per_em = font['head'].unitsPerEm
def getTextWidth(text,pointSize):
total = 0
for c in text:
if ord(c) in t and t[ord(c)] in s:
total += s[t[ord(c)]].width
else:
total += s['.notdef'].width
total = total*float(pointSize)/units_per_em;
return total
text = 'This is a test'
width = getTextWidth(text,12)
print ('Text: "%s"' % text)
print ('Width in points: %f' % width)
print ('Width in inches: %f' % (width/72))
print ('Width in cm: %f' % (width*2.54/72))
print ('Width in WP Units: %f' % (width*1200/72))
结果是:
Text: "This is a test"
Width in points: 67.353516
Width in inches: 0.935465
Width in cm: 2.376082
Width in WP Units: 1122.558594
,并比较一下Adobe InDesign中报告时是正确的。 (请注意,每个字符字距不适用于此!这将需要更多的代码。)
在字体中未定义的字符将被静默忽略,并且通常会这样做,将使用.notdef
字形的宽度。如果您希望将此报告为错误,请删除该函数中的if
测试。
在函数getTextWidth
中强制转换为float
,所以它可以在Python 2.7和3.5下使用,但是请注意,如果使用Python 2.7和更大值的Unicode字符(而不是纯ASCII),则需要正确地重写函数使用UTF8字符。
当我看到这个问题时非常兴奋,但是当没有答案的时候我很兴奋:/ – teewuane 2015-08-29 19:26:32
@teewuane我最终发现一个强制Word Perfect的计算本身(通过用软换行符替换所有空格) – twneale 2015-09-09 14:50:01