超过一定宽度时沿着空格打破一个字符串(Python)

时间:2017-05-07 05:29:57

标签: python textwrapping

我在基本图像上渲染文字。

一个核心要求是,只要字符的总宽度超过基本图像的宽度,字符串就会换行到下一行。我通过以下正确工作的片段来实现这一目标:

base_width, base_height = base_img.size
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", font_size)
line_width = 0
line_count = 1
lines = []
string = ""
for c in text:
    line_width += font.getsize(c)[0]
    string+=str(c)
    if line_width > base_width:
        lines.append(string)
        string = ""
        line_width = 0
        line_count += 1
if string:
    lines.append(string)

结果lines是通过分解原始字符串获得的子字符串列表。

现在我需要改进这个算法。

问题在于它打破了 mid-word 这一行。例如。字符串lorem ipsum可能最终为lines = ['lorem ip','sum']。相反,对我来说,理想的分手是更具人性化的lines = ['lorem ','ipsum']lines = ['lorem',' ipsum']

换句话说,我想要打破白色空间的线条,而不是中间的单词。有人可以给我一个说明性的例子,告诉我如何实现这一目标吗?似乎无法绕过它。

4 个答案:

答案 0 :(得分:1)

这是尝试使用最少的更改和大量的调试输出来使代码工作:

<label class="" for="Name">* Name <span class="error" id="ErrName"></span></label>
<input type="text" name="Name" id="Name" onblur="validation('Name')">

输出:

findLable

答案 1 :(得分:0)

以下是我如何解决问题的解决方案(重新编写原始代码):

select row_number from (select row_number() over(order by date desc), * from contest where date <= '2017-5-5' order by date LIMIT (select count(*) from contest where date <='2017-5-5' ) - 1) as new WHERE date = '2017-2-1'

答案 2 :(得分:0)

我无法理解这一点,所以这里有点紧凑:

#!python3
#coding=utf-8
""" Line break demo 3 """

def charwidth(char):
    return 5

def stringwidth(string):
    return sum( [charwidth(char) for char in string] )

text = "lorem ipsum dolor sit amet blablah"
limit = 60
words = text.split()
lines = [[]]
while( words ):
    word = words.pop(0)
    if stringwidth( " ".join(lines[-1]) ) + 1 + stringwidth(word) < limit:
        lines[-1].append(word)
    else:
        lines.append( [word] )

print( [" ".join(words) for words in lines ] )

答案 3 :(得分:0)

这是@ handle的第三个答案的修改版本,它也允许拆分长词。

此功能还允许指定最大行数,并在超出限制时使用“...”进行截断。

def text_width(text, font):
    return font.getsize(text)[0]

# Set max_lines to 0 for no limit
def wrap_text(text, font, max_width, max_lines=0):
    words = text.split()
    lines = []
    while(words):
        word = words.pop(0)
        # Append word if it's not too long
        if len(lines) > 0 and (text_width(" ".join(lines[-1]), font) + 1 + text_width(word,font)) < max_width:
            lines[-1].append(word)
        else:
            # Brute-force: chunkify word until it fits
            chunk = len(word)
            while chunk > 0:
                while (text_width(word[:chunk],font) > max_width and chunk > 1):
                    chunk -= 1
                lines.append( [word[:chunk]] )
                word = word[chunk:]
                chunk = len(word)
    lines = [" ".join(words) for words in lines]
    if max_lines and len(lines) > max_lines:
        lines[max_lines-1] = lines[max_lines-1][:-1] + "..."
    return "\n".join(lines[:max_lines])