简体   繁体   English

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

[英]How to implement text wrapping in svgwrite?

I'm using svgwrite in python to generate output based off my Tensorflow model to output simulated handwritten text.我在 python 中使用 svgwrite 根据我的 Tensorflow 模型生成输出以输出模拟手写文本。 My current setup requires an array of strings to represent line breaks however the generated text size isn't consistent and sometimes renders awkward spacing after the last word in the line such as我当前的设置需要一个字符串数组来表示换行符,但是生成的文本大小不一致,有时会在行中的最后一个单词之后呈现尴尬的间距,例如这

Is it possible to add text-wrapping to a single long line that would automatically add line breaks when the current line reaches the max width given?是否可以将文本换行添加到单个长行中,当当前行达到给定的最大宽度时会自动添加换行符? A Google Search brought me to the svgwrite page and suggested to use TextArea but the examples given are HTML. 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()

This is my current solution in python which outputs the example above这是我当前在 python 中的解决方案,它输出上面的示例

You could try working directly on the text :您可以尝试直接处理文本:

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)
    

You can then use new_lines as you used lines before.然后,您可以像之前使用的lines一样使用new_lines

so you simply want to wrap a text with a predefined number of max.所以你只想用预定义的最大数量包装文本。 characters?人物?
I guess python's native textwrap is what you're searching for我猜你正在寻找 python 的原生textwrap

The textwrap module provides some convenience functions, as well as TextWrapper, the class that does all the work. textwrap 模块提供了一些方便的功能,以及完成所有工作的类 TextWrapper。 If you're just wrapping or filling one or two text strings, the convenience functions should be good enough;如果你只是包装或填充一两个文本字符串,便利功能应该足够了; otherwise, you should use an instance of TextWrapper for efficiency.否则,您应该使用 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.']

or if you directly want to join the resulting list of strings with newlines:或者,如果您直接想用换行符连接结果字符串列表:

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.'

update: justification of rendered text:更新:渲染文本的理由:

the "actual" justification of the rendered text is achieved by specifying the "textLength" property (see here and here for more details and options).渲染文本的“实际”对齐是通过指定“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