任何人都知道一种算法可以在字边界处打破文本以适合某个近似比率的矩形 - 例如60:40(宽度:高度)?
请注意,这不仅仅是宽度(例如80个字符或600像素等)和任意高度,它排除了我能找到的每个自动换行算法。
javascript的加分点,但这更多是关于算法而不是实现。
答案 0 :(得分:2)
这可以做到:
int lineHeight := getHeightOfTextLine()
int lines := 0
do {
lines += 1
int width = lines * lineHeight * ratio
String wrappedText := break(input, width)
} while(getNumberOfLines(wrappedText) != lines)
从一行开始,我只测试每个高度(lineHeight的倍数),如果我有一个具有给定比率的矩形可以保存文本。如果以计算出的宽度打破文本会导致字符串的行数超过允许的行数(对于运行)继续,否则我有一个解决方案。
答案 1 :(得分:1)
好吧,如果你开始使用一系列高度和高度每个单词的宽度然后你需要经历几种可能性,直到找到给定宽度的最小浪费(单词和空格之间的空格):高度
通常你会从
开始ratio := 6 / 4
noOfLines := totalWidth / ( ratio * lineHeight )
targetLineWidth := totalWidth / noOfLines
然后尝试确定在哪些单词之后放置换行符以最小化单词之间的空格。
如果您尝试最小化每行中的空间,最后一行可能会有额外的空间。 如果你首先确保即使是最后一行均匀分布,那么你应该很好地检查一些变化。
修改强>
如果你想弄清楚确切的字体指标,this q& a看起来很有用。
答案 2 :(得分:1)
这是使用textwrap
和Pillow
的Python实现,它还保留了现有的换行符:
from PIL import Image, ImageDraw
import textwrap
def get_text_with_linebreaks_to_fit_ratio(input_text, target_ratio):
width_in_nchar = 1
placeholder_img = Image.new('RGB', (1, 1), (255, 255, 255))
placeholder_img_D = ImageDraw.Draw(placeholder_img)
intermediary_text = input_text.split("\n") # splits on newlines
while True:
intermediary_text2 = [textwrap.wrap(element, width_in_nchar) for element in intermediary_text] # for each paragraph, cut it with a width of width_in_nchar
wrapped_text = [item for sublist in intermediary_text2 for item in sublist] # flattening the output list
wrapped_text_as_string = "".join([el+"\n" for el in wrapped_text])
a, b = placeholder_img.multiline_textsize(wrapped_text_as_string)
if a/b > target_ratio:
newest_ratio = a/b
break
old_ratio = a/b
width_in_nchar +=1
if newest_ratio - target_ratio> old_ratio - target_ratio: # if the last ratio we got is farther from target ratio than the previous ratio
width_in_nchar -=1 # then we go one step back
intermediary_text2 = [textwrap.wrap(element, width_in_nchar) for element in intermediary_text]
wrapped_text = [item for sublist in intermediary_text2 for item in sublist]
wrapped_text_as_string = "".join([el+"\n" for el in wrapped_text])
return {"as_string" : wrapped_text_as_string, "as_list" : wrapped_text}
然后查看输出:
input_text = """Lorem ipsum dolor sit amet, consectetur adipiscing elit. In pellentesque pharetra ex, at varius sem suscipit ac. Suspendisse luctus condimentum velit a laoreet. Donec dolor urna, tempus sed nulla vitae, dignissim varius neque. Etiam non vulputate diam. Nullam luctus nisi mauris, sit amet feugiat nisi dapibus in. Fusce in interdum nisi. Nullam mattis a odio non interdum.
Sed accumsan laoreet pretium. Nulla facilisi. Morbi in eros suscipit, commodo turpis id, dignissim lorem. Maecenas quis urna auctor, rutrum velit vel, efficitur sem. Donec vulputate viverra justo a accumsan. Phasellus posuere est consectetur, tincidunt lorem volutpat, porttitor erat. Sed at ipsum euismod eros blandit vestibulum.
Integer a auctor quam. Mauris scelerisque sapien quis elementum euismod. Curabitur sed est tortor. Nullam eget tristique purus, eget venenatis enim. Etiam sem quam, lacinia at quam sed, laoreet ultrices mauris. Nunc aliquam dui iaculis pretium fringilla. Maecenas in ante vel libero eleifend condimentum. Vivamus at venenatis libero. Pellentesque sagittis tristique risus a molestie. Fusce vitae leo sed mauris ultricies tincidunt venenatis in lacus. Integer finibus arcu porttitor, viverra massa in, bibendum lacus.
Donec gravida nisi in facilisis sollicitudin. In aliquam vulputate velit. Pellentesque semper vitae justo efficitur tincidunt. Maecenas sit amet arcu eget arcu congue lobortis quis quis massa. Sed fringilla iaculis augue sit amet sodales. Ut at diam id lorem dapibus dignissim non eu tellus. Morbi accumsan, massa cursus eleifend facilisis, sapien ligula fringilla augue, quis bibendum neque lorem tristique est. Aenean sed augue at elit condimentum lacinia quis eu lacus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Nullam quis nisl lacinia nulla congue eleifend vitae id neque. Quisque lacinia nulla in dui fermentum, non ullamcorper massa rutrum. Vestibulum varius blandit facilisis. Aenean bibendum lorem ac sem aliquet ultrices. Nam nunc metus, auctor vel metus ac, interdum vestibulum magna. Vivamus facilisis vulputate ligula. Interdum et malesuada fames ac ante ipsum primis in faucibus. Mauris volutpat tristique libero eu auctor. Ut ac vestibulum eros.
"""
wrapped_text_as_string = get_text_with_linebreaks_to_fit_ratio(input_text, 16/9)["as_string"]
img_width = 1000
img_height = 1000
img = Image.new('RGB', (img_width, img_height), (255, 255, 255))
img_D = ImageDraw.Draw(img)
img_D.multiline_text((10, 10), wrapped_text_as_string, fill=(0,0,0))
img.save("test_img.jpeg", 'jpeg', optimize=True, quality = 200)