繁体   English   中英

如何在 svgwrite 中实现文本换行?

[英]How to implement text wrapping in svgwrite?

我在 python 中使用 svgwrite 根据我的 Tensorflow 模型生成输出以输出模拟手写文本。 我当前的设置需要一个字符串数组来表示换行符,但是生成的文本大小不一致,有时会在行中的最后一个单词之后呈现尴尬的间距,例如这

是否可以将文本换行添加到单个长行中,当当前行达到给定的最大宽度时会自动添加换行符? Google 搜索将我带到 svgwrite 页面并建议使用TextArea,但给出的示例是 HTML。

    def _draw(self, strokes, lines, filename, stroke_colors=None, \
          stroke_widths=None, background_color='white'):

    lines = [
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
        "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris",
        "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in",
        "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
    ]

    stroke_colors = stroke_colors or ['black']*len(lines)
    stroke_widths = stroke_widths or [2]*len(lines)

    line_height = 35
    view_width = 152.4
    view_height = 101.6

    dwg = svgwrite.Drawing(filename=filename)
    dwg.viewbox(width=view_width, height=view_height)
    dwg.add(dwg.rect(insert=(0, 0), size=('153mm', '102mm'), fill=background_color))

    for i in range(3):
            
        
        initial_coord = np.array([30,-((i*450)+25)])
        strokesc = self._sample(lines, [1 for i in lines], [7 for i in lines]);
        
        for offsets, line, color, width in zip(strokesc, lines, stroke_colors, stroke_widths):

            if not line:
                initial_coord[1] -= line_height
                continue
            offsets[:, :2] *= random.randint(150, 190)/100
            strokesc = drawing.offsets_to_coords(offsets)
            strokesc = drawing.denoise(strokesc)
            strokesc[:, :2] = drawing.align(strokesc[:, :2])

            strokesc[:, 1] *= -1
            strokesc[:, :2] -= strokesc[:, :2].min() + initial_coord

            prev_eos = 1.0
            p = "M{},{} ".format(0, 0)
            for x, y, eos in zip(*strokesc.T):
                p += '{}{},{} '.format('M' if prev_eos == 1.0 else 'L', x, y)
                prev_eos = eos
            path = svgwrite.path.Path(p)
            path = path.stroke(color=color, width=width, linecap='round').fill("none")
            dwg.add(path)

            initial_coord[1] -= line_height

    dwg.save()

这是我当前在 python 中的解决方案,它输出上面的示例

您可以尝试直接处理文本:

my_text = sum(lines)
nb_lines = len(lines)


nb_words_per_line = len(my_text.split()) // nb_lines

new_lines = []
cmpt = 0
tmp = ""
for i, word in enumerate(my_text.split()):
    
    if cmpt%nb_words_per_line == 0:
        new_lines.append(tmp)
        tmp = ""
    tmp += word + " "

if tmp:
    new_lines.append(tmp)
    

然后,您可以像之前使用的lines一样使用new_lines

所以你只想用预定义的最大数量包装文本。 人物?
我猜你正在寻找 python 的原生textwrap

textwrap 模块提供了一些方便的功能,以及完成所有工作的类 TextWrapper。 如果你只是包装或填充一两个文本字符串,便利功能应该足够了; 否则,您应该使用 TextWrapper 实例以提高效率。

import textwrap

lines = [
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
    "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
    "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris",
    "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in",
    "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
]

textwrap.wrap(" ".join(lines), 40)

>>> Out:
>>> ['Lorem ipsum dolor sit amet, consectetur',
>>> 'adipiscing elit, sed do eiusmod tempor',
>>> 'incididunt ut labore et dolore magna',
>>> 'aliqua. Ut enim ad minim veniam, quis',
>>> 'nostrud exercitation ullamco laboris',
>>> 'nisi ut aliquip ex ea commodo consequat.',
>>> 'Duis aute irure dolor in reprehenderit',
>>> 'in voluptate velit esse cillum dolore eu',
>>> 'fugiat nulla pariatur.']

或者,如果您直接想用换行符连接结果字符串列表:

textwrap.fill(" ".join(lines), 40)
>>> Out:
>>> 'Lorem ipsum dolor sit amet, consectetur\nadipiscing elit, sed do eiusmod tempor\nincididunt ut labore et dolore magna\naliqua. Ut enim ad minim veniam, quis\nnostrud exercitation ullamco laboris\nnisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit\nin voluptate velit esse cillum dolore eu\nfugiat nulla pariatur.'

更新:渲染文本的理由:

渲染文本的“实际”对齐是通过指定“textLength”属性来实现的(有关更多详细信息和选项,请参见此处此处)。

import sys
import svgwrite

import textwrap

lines = [
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
    "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
    "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris",
    "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in",
    "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
]

# wrap text to max. 40 characters
usetext = textwrap.wrap(" ".join(lines), 40)

filename = sys.argv[0].rstrip('.py')

def create_svg(name):
    svg_width = 500
    svg_height = 300

    font_size = 20
    dwg = svgwrite.Drawing(name, (svg_width, svg_height), debug=True)
    # background will be white.
    dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white'))
    
    for i, line in enumerate(usetext):
        dwg.add(dwg.text(line, insert=(0,  font_size * (i + 4)),
                font_family="serif", font_size=font_size, fill='black',
                textLength=svg_width),
                )
    
    dwg.save()

if __name__ == '__main__':
    create_svg(filename + '.svg')

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM