2010-11-16 52 views
2

我可以用PIL(见下面)以像素为单位获得字符的高度和宽度,但是(除非我误)像素大小取决于屏幕的DPI,而DPI可能会有所不同。相反,我想要做的是以绝对单位计算字符的宽度,如英寸或1200英寸(“wordperfect单位”)。如何使用Python获得1200英寸英寸的truetype字体字符的宽度?

>>> # Getting pixels width with PIL 
>>> font = ImageFont.truetype('/blah/Fonts/times.ttf' , 12) 
>>> font.getsize('a') 
(5, 14) 

我希望这样做的理由是创建一个用于编写二进制Word Perfect文档的文字包装功能。 Word Perfect需要在整个文本的有效位置插入软换行代码,否则该文件将被损坏且无法打开。问题在于将它们添加到可变宽度字体的位置。

我意识到我没有完全理解像素与屏幕分辨率和字体大小之间的关系。我是否全部错了?

+0

当我看到这个问题时非常兴奋,但是当没有答案的时候我很兴奋:/ – teewuane 2015-08-29 19:26:32

+0

@teewuane我最终发现一个强制Word Perfect的计算本身(通过用软换行符替换所有空格) – twneale 2015-09-09 14:50:01

回答

0

原始文本宽度通常在typographer's points中计算,但由于字体定义的目的定义为1/72英寸,因此可以轻松将其转换为任何其他单位。

为了得到一个字符(在EM单位表示)的设计宽度,你需要访问字体的低级别的数据。最简单的方法是pip install fonttools,它有一切工作在尽可能低的字体定义水平。

在安装fontTools,您可以:

  1. 负载的字体数据 - 这需要路径到实际字体文件;
  2. 字符宽度存储为字形宽度,这意味着您必须检索'character-to-glyph'映射;这是cmap表中的一种字体:

    a。为您的字体加载cmap。最有用的是Unicode映射 - 一种字体可能包含其他字体。 b。加载字形集为您的字体。这是该字体中字形名称的列表。

  3. 然后,对于每个Unicode字符,首先查找其名称,然后使用名称以设计单位检索其宽度。

  4. 不要忘记,'设计单位'是基于字体的整体'设计宽度'。这可以是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字符。

相关问题