Last active
January 28, 2018 18:47
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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