From fe299ba2b59de792f0660a0b5d9e5a1c627670bf Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Sun, 3 Aug 2025 16:42:00 -0600 Subject: [PATCH] Finish forum label generation --- forum_label.py | 67 ++++++++++++++++++++++++++++++++++++++++++++------ main.py | 65 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 117 insertions(+), 15 deletions(-) diff --git a/forum_label.py b/forum_label.py index 4f547d1..adfe90a 100644 --- a/forum_label.py +++ b/forum_label.py @@ -16,7 +16,7 @@ def print_forum_label(thread): url = 'https://forum.protospace.ca/t/{}/'.format(thread['id']) qr = qrcode.make(url, version=6, box_size=9) - im.paste(qr, (840, 325)) + im.paste(qr, (840, 150)) item_size = 150 @@ -24,14 +24,67 @@ def print_forum_label(thread): while w > 1200: item_size -= 5 font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', item_size) - w, h = draw.textsize(thread['title'], font=font) + w, h = draw.textsize(url, font=font) - x, y = (width - w) / 2, ((height - h) / 2) - 140 - draw.text((x, y), thread['title'], font=font, fill='black') + x, y = (width - w) / 2, ((height - h) / 2) + 300 + draw.text((x, y), url, font=font, fill='black') - font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 100) - draw.text((100, 410), 'Out of stock?', font=font, fill='black') - draw.text((150, 560), 'Scan here:', font=font, fill='black') + font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 80) + draw.text((120, 150), 'Forum Thread', font=font, fill='black') + + text = thread['title'] + + MARGIN = 50 + MAX_W, MAX_H, PAD = 900 - (MARGIN*2), 450 - (MARGIN*2), 5 + + def fit_text(text, font_size): + font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', font_size) + + for cols in range(100, 1, -4): + print('trying size', font_size, 'cols', cols) + + paragraph = textwrap.wrap(text, width=cols, break_long_words=False) + + total_h = -PAD + total_w = 0 + + for line in paragraph: + w, h = draw.textsize(line, font=font) + if w > total_w: + total_w = w + total_h += h + PAD + + if total_w <= MAX_W and total_h < MAX_H: + return True, paragraph, total_h + + return False, [], 0 + + font_size_range = [1, 500] + + # Thanks to Alex (UDIA) for the binary search algorithm + while abs(font_size_range[0] - font_size_range[1]) > 1: + font_size = sum(font_size_range) // 2 + image_fit, check_para, check_h = fit_text(text, font_size) + if image_fit: + print('Does fit') + font_size_range = [font_size, font_size_range[1]] + good_size = font_size + paragraph = check_para + total_h = check_h + else: + print('Does not fit') + font_size_range = [font_size_range[0], font_size] + + font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', good_size) + offset = height - MAX_H - MARGIN + start_h = -100 + offset + + current_h = start_h + for line in paragraph: + w, h = draw.textsize(line, font=font) + x, y = (MAX_W - w) / 2, current_h + draw.text((x+MARGIN, y), line, font=font, fill='black') + current_h += h + PAD im.save('tmp.png') diff --git a/main.py b/main.py index 26e6df3..c4001cf 100755 --- a/main.py +++ b/main.py @@ -470,12 +470,12 @@ def print_forum_label(thread): width, height = im.size draw = ImageDraw.Draw(im) - logging.info('Printing forum thread: %s', thread['title']) + logging.info('Printing forum thread ID: %s, title: %s', thread['id'], thread['title']) url = 'https://forum.protospace.ca/t/{}/'.format(thread['id']) qr = qrcode.make(url, version=6, box_size=9) - im.paste(qr, (840, 325)) + im.paste(qr, (840, 150)) item_size = 150 @@ -483,14 +483,63 @@ def print_forum_label(thread): while w > 1200: item_size -= 5 font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', item_size) - w, h = draw.textsize(item, font=font) + w, h = draw.textsize(url, font=font) - x, y = (width - w) / 2, ((height - h) / 2) - 140 - draw.text((x, y), item, font=font, fill='black') + x, y = (width - w) / 2, ((height - h) / 2) + 300 + draw.text((x, y), url, font=font, fill='black') - font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 100) - draw.text((100, 410), 'Out of stock?', font=font, fill='black') - draw.text((150, 560), 'Scan here:', font=font, fill='black') + font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 80) + draw.text((120, 150), 'Forum Thread', font=font, fill='black') + + text = thread['title'] + + MARGIN = 50 + MAX_W, MAX_H, PAD = 900 - (MARGIN*2), 450 - (MARGIN*2), 5 + + def fit_text(text, font_size): + font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', font_size) + + for cols in range(100, 1, -4): + paragraph = textwrap.wrap(text, width=cols, break_long_words=False) + + total_h = -PAD + total_w = 0 + + for line in paragraph: + w, h = draw.textsize(line, font=font) + if w > total_w: + total_w = w + total_h += h + PAD + + if total_w <= MAX_W and total_h < MAX_H: + return True, paragraph, total_h + + return False, [], 0 + + font_size_range = [1, 500] + + # Thanks to Alex (UDIA) for the binary search algorithm + while abs(font_size_range[0] - font_size_range[1]) > 1: + font_size = sum(font_size_range) // 2 + image_fit, check_para, check_h = fit_text(text, font_size) + if image_fit: + font_size_range = [font_size, font_size_range[1]] + good_size = font_size + paragraph = check_para + total_h = check_h + else: + font_size_range = [font_size_range[0], font_size] + + font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', good_size) + offset = height - MAX_H - MARGIN + start_h = -100 + offset + + current_h = start_h + for line in paragraph: + w, h = draw.textsize(line, font=font) + x, y = (MAX_W - w) / 2, current_h + draw.text((x+MARGIN, y), line, font=font, fill='black') + current_h += h + PAD im.save('tmp.png') os.system('lp -d dymo tmp.png > /dev/null 2>&1')