簡體   English   中英

使用svgwrite for python時如何確定文本寬度和高度?

[英]How to determine text width and height when using svgwrite for python?

我想提取文本對象 (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中手動測量具有特定字體和大小的字母的高度和寬度。 我盡我所能,但我不確定這些值是否完美,現在我無法在程序中更改字體大小。

我想以特定字體確定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作為依賴,但它是迄今為止我發現的最清晰的獨立於平台的解決方案。

我有同樣的問題,但我有一個可變寬度的字體。 我通過獲取我想要的文本元素(正確的字體和內容)解決了它,將其寫入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數字,在此鏈接中找到,注意我的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)

這很笨重但是很有效

我最終使用了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)

我不是svg的專家,但我的理解是,很難確定svg中的字符和文本寬度。 這意味着svgwrite也無法做到這一點。 我所做的是為字符選擇一個固定的寬度,並從前一個字符的開頭分別創建一個固定寬度的每個字符。 您也可以考慮使用text_anchor ='middle'來對齊字符串,即每個字符。 對於以點為中心的字符,可以創建一個框以使該點居中。

另請參閱http://www.w3.org/TR/SVG/text.html ,其中說“在許多情況下,從字符到字形的映射算法都依賴於系統,導致文本呈現的可能性很大在不同的用戶環境中查看時(通常略有不同)。如果SVG內容的作者需要精確選擇字體和字形,那么建議可以使用必要的字體(可能是子集,只包括給定文檔所需的字形)或者作為SVG內容中嵌入的SVG字體,或者作為與SVG內容在同一Web位置發布的WebFonts([CSS2],第15.1節)。“

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM