ソースを参照

rework text fitting

Tobias Simetsreiter 4 年 前
コミット
5cfb47ddb2
2 ファイル変更56 行追加39 行削除
  1. 28 21
      simpilib/__init__.py
  2. 28 18
      simpilib/eink.py

+ 28 - 21
simpilib/__init__.py

@@ -1,42 +1,49 @@
 #!/usr/bin/env python3
 # -*- coding:utf-8 -*-
 
-def loadFontSize(text, draw, image, fontpath):
+def loadFontSize(text, imagesize, fontpath):
     from PIL import ImageFont
     fontsize = 1  # starting font size
-    img_fraction = (1,1) # fraction of screen covered
     font = ImageFont.truetype(fontpath, fontsize)
-    fsize = (0,0)
-    imgsize = (0.9,0.9)
-    longline = getLongestLine(text.splitlines())
+    splittext = text.splitlines()
     while True:
-        font_last = font
         fontsize += 1
         font = ImageFont.truetype(fontpath, fontsize)
-        fsize = draw.textsize(text, font=font)
-        imgsize = (img_fraction[0]*image.size[0], img_fraction[1]*image.size[1])
+        fsize = [0,0]
+        for l in splittext:
+            fs = font.getsize(l)
+            if fsize[0] < fs[0]:
+                fsize[0] = fs[0]
+            fsize[1] += fs[1]
+            fsize[1] += 2
+            print("Fs:", fsize,fs)
+        # fsize = draw.textsize(text, font=font)
 
-        if (fsize[0] > imgsize[0] or fsize[1] > imgsize[1]):
-                break
-        print("Fontsize:", fontsize, fsize, imgsize)
-    return font_last
+        if ((fsize[0] > imagesize[0]) or (fsize[1] > imagesize[1])):
+            break
+        print("Fontsize:", font.size, fsize, imagesize)
+
+    fontsize -= 1
+    font = ImageFont.truetype(fontpath, fontsize)
+    return font
 
 
-def wrapText(text, line_width_factor=5):
+def wrapText(text, aspect_ratio, font_factor=3):
     import textwrap
-    splittext = []
-    longestline = ""
-    iter_width = 400
-    while len(splittext)*line_width_factor < iter_width:
+    text = " ".join(text.split())
+    iter_width = len(text)
+    splittext = [text]
+    longestline = getLongestLine(splittext)
+    while len(longestline) > font_factor * aspect_ratio * len(splittext):
         iter_width -= 1
         splittext = textwrap.wrap(text, width=iter_width)
         longestline = getLongestLine(splittext)
-        print("Wrap:", iter_width, len(splittext))
+    print("Wrap:", iter_width, "Rows:",len(splittext))
     return "\n".join(splittext)
 
-def fitText(image, draw, fontpath, text):
-    text = wrapText(text, line_width_factor=4.5)
-    font = loadFontSize(text, draw, image, fontpath)
+def fitText(isize, fontpath, text):
+    text = wrapText(text, (isize[0]/isize[1]))
+    font = loadFontSize(text, isize, fontpath)
     return text, font
 
 

+ 28 - 18
simpilib/eink.py

@@ -35,14 +35,27 @@ def eink_quote_qr(args):
     url = simpilib.short_url(q["data"]["url"])
 
     smalltext = None
-    if text.find(" - ") > 0:
-        pos = text.rfind("-")
-        text = text[:pos]
-        smalltext = text[pos+1:]
+    import re
+    dashes = r"(.*)[\u002D\u058A\u05BE\u1400\u1806\u2010-\u2015\u2E17\u2E1A\u2E3A\u2E3B\u2E40\u301C\u3030\u30A0\uFE31\uFE32\uFE58\uFE63\uFF0D](.*)"
+    matches = re.match(dashes, text)
+    if matches:
+        groups = matches.groups()
+        if len(groups[1]) < 30:
+            text = groups[0]
+            smalltext = groups[1]
+
+    if not smalltext:
+        qt = r"(.*)\"(.*)\"(.*)"
+        matches = re.match(qt, text)
+        if matches:
+            groups = matches.groups()
+            if len(groups[0]) < 10 and len(groups[1]) > 10:
+                text = groups[1]
+                smalltext = groups[2].strip()
 
     print(text)
     print(smalltext)
-    eink_text_qr(q["data"]["title"], url, smalltext)
+    eink_text_qr(text, url, smalltext)
 
 def eink_text_qr(text, qrdata, smalltext=None):
     import simpilib
@@ -57,8 +70,8 @@ def eink_text_qr(text, qrdata, smalltext=None):
     qr.make()
     pic = qr.make_image().get_image()
 
-    text_image = Image.new('1', (base_image.width-pic.width, base_image.height), 0)
-    small_image = Image.new('1', (pic.width, base_image.height-pic.height), 0)
+    text_image = (base_image.width-pic.width, base_image.height)
+    small_image = (pic.width, base_image.height-pic.height)
 
     base_image.paste(pic, (base_image.width-pic.width,0), pic)
     draw = ImageDraw.Draw(base_image)
@@ -68,18 +81,16 @@ def eink_text_qr(text, qrdata, smalltext=None):
 
     epd.init(epd.PART_UPDATE)
 
-    text = simpilib.wrapText(text, line_width_factor=4.5)
-    font = simpilib.loadFontSize(text, draw, text_image, fontpath)
+    text, font = simpilib.fitText(text_image, fontpath, text)
 
-    draw.text((0,0), text, align="center", font = font, fill = 255)
-    epd.displayPartial(epd.getbuffer(base_image))
+    draw.text((0,0), text, align="center", font = font, fill = 255, spacing=2)
 
     if smalltext != None and len(smalltext) > 2:
-        smalltext = simpilib.wrapText(smalltext, line_width_factor=10)
-        smallfont = simpilib.loadFontSize(text, draw, small_image, fontpath)
-        draw.text((base_image.width-pic.width,0), smalltext, align="center", font = font, fill = 255)
-        epd.displayPartial(epd.getbuffer(base_image))
+        smalltext, smallfont = simpilib.fitText(small_image, fontpath, smalltext)
+
+        draw.text((base_image.width-pic.width, pic.height), smalltext, align="center", font = font, fill = 255, spacing=2)
 
+    epd.displayPartial(epd.getbuffer(base_image))
     epd.sleep()
     epd.Dev_exit()
 
@@ -103,8 +114,7 @@ def eink_text(args):
     image = Image.new('1', (epd.height, epd.width), 0)
     draw = ImageDraw.Draw(image)
 
-    text = simpilib.wrapText(args.text, line_width_factor=7)
-    font = simpilib.loadFontSize(text, draw, image, fontpath)
+    text, font = simpilib.fitText(image.size, fontpath, args.text)
 
     w, h = draw.textsize(text, font=font)
 
@@ -116,7 +126,7 @@ def eink_text(args):
     # -3 px to leave some space for low characters
 
     print("Drawing:", (w, h), (epd.height, epd.width), center)
-    draw.text(center, text, align="center", font = font, fill = 255)
+    draw.text(center, text, align="center", font = font, fill = 255, spacing=2)
 
     # epd.display(epd.getbuffer(image.rotate(180)))
     epd.display(epd.getbuffer(image))