我希望提取文本对象的像素大小(svgwrite.Drawing.Text),因为它在使用给定样式进行格式化后会显示在文件中。我的字体是固定宽度的(Courier New)。
我需要它的原因是我想要在SVG文件中打印一个字符串,然后在结果文本上映射一些信息:例如我有一个字符串" ABCDEF"外部智者告诉我" BCD"部分应该标记。然后我需要知道有多少像素(单位?)被符号" A"和符号" BCD"在两个维度中,然后绘制一个彩色矩形,或透明框架,或严格在" BCD"部分。
所以我有以下代码,我希望使用" w = text1.width "提取宽度,但它没有这种方式。提前感谢您尝试回答我的问题。
import svgwrite
my_svg = svgwrite.Drawing(filename = "dasha.svg", size = ("800px", "600px"))
text_style = "font-size:%ipx; font-family:%s" % (12, "Courier New")
text1 = my_svg.text("HELLO WORLD", insert=(0, 0), fill="black", style=text_style)
my_svg.add(text1)
my_svg.save()
UPD1 [22.06.2014] :我目前使用的中间解决方案是在Inkscape中手动测量具有特定字体和大小的字母的高度和宽度。我尽我所能,但我不确定这些值是否完美,现在我无法改变程序中的字体大小。
答案 0 :(得分:4)
我想用特定字体确定svgwrite中文本的宽度。 我最终使用了http://blog.mathieu-leplatre.info/text-extents-with-python-cairo.html中的以下解决方案:
def textwidth(text, fontsize=14):
try:
import cairo
except Exception, e:
return len(str) * fontsize
surface = cairo.SVGSurface('undefined.svg', 1280, 200)
cr = cairo.Context(surface)
cr.select_font_face('Arial', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
cr.set_font_size(fontsize)
xbearing, ybearing, width, height, xadvance, yadvance = cr.text_extents(text)
return width
它引入了cairo作为依赖,但它是迄今为止我发现的最清晰的独立于平台的解决方案。
答案 1 :(得分:1)
我有同样的问题,但我有一个可变宽度的字体。我通过获取我想要的文本元素(正确的字体和内容),将其写入svg文件,并使用安装在我的PC上的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数字,在link找到,注意我的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)
它很笨重,但它有效
答案 2 :(得分:0)
我最终使用了Tkinter:
try:
# for Python2
import Tkinter
except ImportError:
# for Python3
import tkinter as Tkinter
try:
import tkFont
except ImportError:
import tkinter.font as tkFont
def get_text_metrics(family, size, text):
# initialize Tk so that font metrics will work
tk_root = Tkinter.Tk()
font = None
key = (family, size)
font = tkFont.Font(family=family, size=size)
assert font is not None
(w, h) = (font.measure(text), font.metrics('linespace'))
return (w, h)
答案 3 :(得分:-1)
我不是svg的专家,但我的理解是,很难确定svg中的字符和文本宽度。这意味着svgwrite也无法做到这一点。我所做的是为字符选择一个固定的宽度,并从前一个字符的开头分别创建一个固定宽度的每个字符。您也可以考虑使用text_anchor ='middle'来对齐字符串,即每个字符。对于以点为中心的字符,可以创建一个框以使该点居中。
另见http://www.w3.org/TR/SVG/text.html 其中说“在很多情况下,从字符到字形的映射算法都是系统相关的,导致在不同的用户环境中查看文本的呈现可能(通常略有不同)。如果SVG内容的作者需要精确选择字体和字形,然后建议必要的字体(可能是子集,只包括给定文档所需的字形)可用作SVG内容中嵌入的SVG字体或WebFonts([CSS2],第15.1节) )发布在与SVG内容相同的Web位置。“