Skip to content

Instantly share code, notes, and snippets.

@Yoxem
Last active January 28, 2018 18:47
Show Gist options
  • Select an option

  • Save Yoxem/f51708186f7039dcf377ffd0c4dd2b11 to your computer and use it in GitHub Desktop.

Select an option

Save Yoxem/f51708186f7039dcf377ffd0c4dd2b11 to your computer and use it in GitHub Desktop.
a probably buggy line-wrapping test script try to mininize the badness (like the algorithm by D.E.Knuth)
#!/usr/bin/env python3
#-*-coding:utf-8-*-
from PIL import ImageFont
font_path = "/usr/share/fonts/truetype/freefont/FreeSerif.ttf"
font_size = 15
line_width = 360 # in px
font = ImageFont.truetype(font_path, font_size)
paragraph = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum a rhoncus nibh. Mauris quis elit ligula. Sed eget dolor nec arcu vulputate feugiat at a sapien. Donec aliquet dui ex, sit amet vestibulum dolor finibus sit amet. Vivamus pretium pretium dui. Donec feugiat ac nibh eget scelerisque. Pellentesque quis lacinia mi. Nam aliquam, mauris sed vehicula suscipit, arcu nulla fringilla diam, eget varius risus sapien in eros. Cras sem ante, dignissim pulvinar semper congue, luctus eget sapien."
# convert paragraph to word array
def para_split(para):
return para.split(" ")
word_array = para_split(paragraph)
word_width_array = [font.getsize(word)[0] for word in word_array] #store the width of each word
space_width = font.getsize(" ")[0] # the width of the halt-width space char
# the cost of the line from word_array[begin] to word_array[end]
def cost(word_width_array, begin, end, line_width, space_width):
word_width_sum = sum(word_width_array[begin:end+1])
space_width_sum = (end-begin) * space_width
cost = (line_width - word_width_sum - space_width_sum) ** 3
if cost < 0:
return float("infinity")
else:
return cost
linebreak = [] # store the (i+1)th word that a linebreak("\v\r") follows.
f_solve = [False for i in range(len(word_array))]
f_value = [float("infinity") for i in range(len(word_array))]
break_point_array = [0 for i in range(len(word_array))]
def f(x):
if f_solve[x] == True:
return f_value[x]
else:
raw = cost(word_width_array, 0, x, line_width, space_width)
if raw < float("infinity"):
f_solve[x] = True
f_value[x] = raw
return raw
else:
break_point = 0
min_cost = float("infinity")
for i in range(0,x):
raw = f(i) + cost(word_width_array, i+1, x, line_width, space_width)
if raw < min_cost:
min_cost = raw
break_point = i
f_solve[x] = True
f_value[x] = min_cost
break_point_array[x] = break_point
return min_cost
def break_point(x):
real_break_point_array = []
i = x
while i != 0:
real_break_point_array = [i] + real_break_point_array
i = break_point_array[i]
return real_break_point_array
def g(x):
return [f(x-1), break_point(x-1)]
def linebreak(text_array):
real_break_point_list = g(len(text_array))[1]
print(real_break_point_list)
for i in range(len(real_break_point_list)):
text_array.insert(real_break_point_list[i]+i+1,'\v\r')
return " ".join(text_array)
print(linebreak(word_array))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment