在Python中获取SVG文本大小

5 投票
2 回答
2219 浏览
提问于 2025-04-16 21:42

我正在用Python生成SVG图像(纯Python,没有使用外部库)。我想知道在正确放置文本元素之前,它的大小会是多少。有没有什么好的方法可以做到这一点?我查看了库,但没有找到类似getTextSize()的功能。

2 个回答

1

我之前也遇到过同样的问题,不过我用的是可变宽度的字体。我解决这个问题的方法是,先把我想要的文本元素(正确的字体和内容)写入一个svg文件,然后在我电脑上用Inkscape这个软件把它渲染成一个临时的png文件。接着,我读取这个png文件的尺寸(从文件头提取),然后删除临时的svg和png文件,最后用这个结果来放置文本和周围的元素。

我发现用90的DPI来渲染图形,能给我需要的准确数字,或者说是svgwrite整体使用的原始数字。-D是一个标志,用来确保只渲染可绘制的元素,也就是文本。

os.cmd(/cygdrive/c/Program\ Files\ \(x86\)/Inkscape/inkscape.exe -f work_temp.svg -e work_temp.png -d 90 -D)

我用这些函数来提取png的尺寸,具体可以在这个链接找到,注意我稍微调整了一下以适应python3(仍然可以在python2中使用)

def is_png(data):
    return (data[:8] == b'\x89PNG\r\n\x1a\n'and (data[12:16] == b'IHDR'))

def get_image_info(data):
    if is_png(data):
        w, h = struct.unpack('>LL', data[16:24])
        width = int(w)
        height = int(h)
    else:
        raise Exception('not a png image')
    return width, height

if __name__ == '__main__':
    with open('foo.png', 'rb') as f:
        data = f.read()

    print is_png(data)
    print get_image_info(data)

虽然这个方法有点笨重,但确实有效。

1

这件事可能会比较复杂。首先,你需要了解一下SVG规范中关于文本的章节。假设你想要获取普通的text元素的宽度,而不是textpath元素,至少你需要做以下几件事:

  • 解析字体选择属性间距属性,并读取xml:space属性,以及writing-mode属性(这个属性可以是从上到下,而不仅仅是从左到右和从右到左)。
  • 根据以上信息,打开正确的字体,读取字形数据,并提取你文本字符串中每个字形的宽度和高度。光是找到字体就可能是一项大工程,因为字体文件可能藏在很多地方。
  • (可选)查看字符串中是否有可能的连字(这取决于语言),如果字体中存在,就用正确的字形替换它们。
  • 将所有字符和空格的宽度加起来,空格的宽度取决于间距属性和(可选)可能的字距调整

一个可能的解决方案是使用pango库。你可以在py-gtk找到它的Python绑定。不幸的是,除了少数一些示例,Python绑定的文档相对较少。不过,它可以处理字体加载和确定Layout的范围等细节。

另一种方法是研究你浏览器中的SVG渲染器。但是,例如,Firefox对SVG文本的支持是有限的

研究TeX的处理方式也是很有启发性的,特别是关于字母的盒子胶水(用于间距)的概念(pdf)。

撰写回答