reworked line breaks
This commit is contained in:
+10
-13
@@ -98,21 +98,18 @@ def fit_text(size, text):
|
||||
font_size = round(text.font_size * min(size)) + 1
|
||||
font = FONTS[text.font]
|
||||
t = ""
|
||||
while (text_size is None or text_size[1] >= max_height) and font_size > 1:
|
||||
while (text_size is None or text_size[0] >= max_width or text_size[1] >= max_height) and font_size > 1:
|
||||
font_size -= 1
|
||||
font = font.font_variant(size=font_size)
|
||||
words = text.text.split(" ")
|
||||
t = ""
|
||||
for word in words:
|
||||
spacer = " "
|
||||
if len(t) == 0:
|
||||
spacer = ""
|
||||
text_size = font.getsize_multiline(t + spacer + word, stroke_width=text.stroke_width * font_size)
|
||||
if text_size[0] >= max_width:
|
||||
t += "\n" + word
|
||||
else:
|
||||
t += spacer + word
|
||||
text_size = font.getsize_multiline(t, stroke_width=text.stroke_width * font_size)
|
||||
k = 0 # number of lines
|
||||
while k == 0 or (t is not None and text_size[0] >= max_width):
|
||||
k += 1
|
||||
t = utils.break_text(text.text, k)
|
||||
if t is not None:
|
||||
text_size = font.getsize_multiline(t, stroke_width=text.stroke_width * font_size)
|
||||
if t is None:
|
||||
# max break attained
|
||||
text_size = None # restart
|
||||
return t, font
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import re
|
||||
import sys
|
||||
import os.path as path
|
||||
from Levenshtein import distance
|
||||
|
||||
@@ -147,3 +148,84 @@ def find_nearest(word, wlist, threshold=5):
|
||||
if found[0] > threshold:
|
||||
return None
|
||||
return found[1]
|
||||
|
||||
|
||||
def safe_index(src, pattern, start=0):
|
||||
"""
|
||||
:param (list|str) src:
|
||||
:param pattern:
|
||||
:param (int) start:
|
||||
"""
|
||||
try:
|
||||
return src.index(pattern, start)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
def find_all(src, pattern):
|
||||
"""
|
||||
:param (str) src:
|
||||
:param (str) pattern:
|
||||
:rtype: list of int
|
||||
"""
|
||||
o = []
|
||||
i = safe_index(src, pattern)
|
||||
while i is not None:
|
||||
o += [i]
|
||||
i = safe_index(src, pattern, i + 1)
|
||||
return o
|
||||
|
||||
|
||||
def replace_at(src, pattern, indexes, remove):
|
||||
"""
|
||||
:param (str) src:
|
||||
:param (str) pattern:
|
||||
:param (list of int) indexes:
|
||||
:param (int) remove:
|
||||
:rtype: str
|
||||
"""
|
||||
o = ""
|
||||
last = 0
|
||||
for i in indexes:
|
||||
o += src[last:i] + pattern
|
||||
last = i + remove
|
||||
o += src[last:]
|
||||
return o
|
||||
|
||||
|
||||
def break_text(src, n):
|
||||
"""
|
||||
:param (str) src:
|
||||
:param (int) n:
|
||||
:rtype: str
|
||||
"""
|
||||
spaces = find_all(src, " ")
|
||||
if n - 1 > len(spaces):
|
||||
return None
|
||||
if n - 1 == len(spaces):
|
||||
return replace_at(src, "\n", spaces, 1)
|
||||
ideal = [k * (len(src) - 1) / n for k in range(1, n)]
|
||||
indexes = best_fit(ideal, spaces)
|
||||
return replace_at(src, "\n", indexes, 1)
|
||||
|
||||
|
||||
def best_fit(a, b):
|
||||
"""
|
||||
:param (list of float) a:
|
||||
:param (list of int) b:
|
||||
:rtype: list of int
|
||||
"""
|
||||
a = a[::]
|
||||
o = []
|
||||
dist = sys.maxsize
|
||||
for i, value in enumerate(b):
|
||||
if not len(a):
|
||||
break
|
||||
if dist < abs(value - a[0]):
|
||||
o += [b[i - 1]]
|
||||
a.pop(0)
|
||||
else:
|
||||
dist = abs(value - a[0])
|
||||
if len(a):
|
||||
o += [b[-1]]
|
||||
return o
|
||||
|
||||
Reference in New Issue
Block a user