大致近似于Python中文本字符串的宽度?


问题内容

使用Python如何估计给定文本字符串的字体宽度?

我正在寻找一个类似原型的函数:

def getApproximateFontWidth(the_string, font_name="Arial", font_size=12):
   return ... picas or pixels or something similar ...

我并不是在寻找任何非常严格的东西,大概是可以的。

这样做的动机是我在Webapp的后端中生成了一个截断的字符串,并将其发送到要显示的前端。多数情况下,琴弦是小写字母,但有时琴弦都用大写字母,因此很宽。如果字符串未正确删节,则看起来很难看。我想知道根据字符串的大致宽度将字符串截断多少。如果偏差减少10%,这没什么大不了的,这是一项装饰性功能。


问题答案:

以下是我的简单解决方案,可使您达到80%的精度,非常适合我的目的。它仅适用于Arial,并且假定使用12 pt字体,但也可能与其他字体成比例。

def getApproximateArialStringWidth(st):
    size = 0 # in milinches
    for s in st:
        if s in 'lij|\' ': size += 37
        elif s in '![]fI.,:;/\\t': size += 50
        elif s in '`-(){}r"': size += 60
        elif s in '*^zcsJkvxy': size += 85
        elif s in 'aebdhnopqug#$L+<>=?_~FZT' + string.digits: size += 95
        elif s in 'BSPEAKVXY&UwNRCHD': size += 112
        elif s in 'QGOMm%W@': size += 135
        else: size += 50
    return size * 6 / 1000.0 # Convert to picas

如果要截断字符串,则为:

def truncateToApproximateArialWidth(st, width):
    size = 0 # 1000 = 1 inch
    width = width * 1000 / 6 # Convert from picas to miliinches
    for i, s in enumerate(st):
        if s in 'lij|\' ': size += 37
        elif s in '![]fI.,:;/\\t': size += 50
        elif s in '`-(){}r"': size += 60
        elif s in '*^zcsJkvxy': size += 85
        elif s in 'aebdhnopqug#$L+<>=?_~FZT' + string.digits: size += 95
        elif s in 'BSPEAKVXY&UwNRCHD': size += 112
        elif s in 'QGOMm%W@': size += 135
        else: size += 50
        if size >= width:
            return st[:i+1]
    return st

然后是以下内容:

>> width = 15
>> print truncateToApproxArialWidth("the quick brown fox jumps over the lazy dog", width) 
the quick brown fox jumps over the
>> print truncateToApproxArialWidth("THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG", width) 
THE QUICK BROWN FOX JUMPS

呈现时,这些字符串的宽度大致相同:

快速的棕色狐狸跳过了

快速棕狐跳