Add text fit safety margin

This commit is contained in:
Mikei386
2026-06-22 16:35:26 +02:00
parent 7243250abc
commit 1c2b2df3a0
2 changed files with 42 additions and 2 deletions
+40 -1
View File
@@ -43,6 +43,7 @@ PRINT_QUEUE_ENABLED = os.environ.get("PRINT_QUEUE_ENABLED", "1").lower() in {"1"
PRINT_QUEUE_RETRY_SECONDS = int(os.environ.get("PRINT_QUEUE_RETRY_SECONDS", "30"))
DPI = int(os.environ.get("LABEL_DPI", "180"))
PTOUCH_SUPPORTS_COPIES: bool | None = None
TEXT_FIT_EXTRA_MM = 6
TAPE_WIDTHS_MM = [3.5, 6, 9, 12, 18, 24]
PRINTABLE_TAPE_PX = {
@@ -111,6 +112,43 @@ def text_lines(text: str) -> list[str]:
return text.split("\n")
def text_natural_width_mm(obj: dict[str, Any], scale: float) -> float:
font_size = scaled_mm_to_px(float(obj.get("fontSizeMm", 5)), scale)
font = get_font(font_size, bool(obj.get("bold", False)))
scratch = Image.new("1", (1, 1), 0)
scratch_draw = ImageDraw.Draw(scratch)
widths = []
for line in text_lines(str(obj.get("text", "")) or " "):
box = scratch_draw.textbbox((0, 0), line or " ", font=font)
widths.append((box[2] - box[0]) / scale)
return max(2, max(widths, default=0) + TEXT_FIT_EXTRA_MM)
def autofit_text_objects_for_render(design: dict[str, Any], scale: float) -> dict[str, Any]:
if not bool(design.get("autoLength", True)):
return design
fitted = dict(design)
objects = []
margin = float(fitted.get("marginMm", 2))
for obj in fitted.get("objects", []):
if not isinstance(obj, dict):
objects.append(obj)
continue
item = dict(obj)
if item.get("type") in {"text", "symbol"} and not item.get("manualSize"):
item["w"] = text_natural_width_mm(item, scale)
objects.append(item)
fitted["objects"] = objects
length_end = margin
orientation = fitted.get("orientation", "landscape")
for obj in objects:
if not isinstance(obj, dict) or obj.get("hidden"):
continue
length_end = max(length_end, float(obj.get("y", 0)) + float(obj.get("h", 0)) if orientation == "portrait" else float(obj.get("x", 0)) + float(obj.get("w", 0)))
fitted["lengthMm"] = max(float(fitted.get("lengthMm", 70)), min(500, length_end + margin))
return fitted
def draw_text(image: Image.Image, draw: ImageDraw.ImageDraw, obj: dict[str, Any], scale: float) -> None:
x, y, w, h = object_box(obj, scale)
text = str(obj.get("text", "Text"))
@@ -261,6 +299,8 @@ def render_design_image(design: dict[str, Any]) -> Image.Image:
tape_width = float(design.get("tapeWidthMm", 24))
if tape_width not in TAPE_WIDTHS_MM:
raise ValueError("Ungueltige Bandbreite.")
scale = render_scale_for_tape(tape_width)
design = autofit_text_objects_for_render(design, scale)
length = clamp(float(design.get("lengthMm", 70)), 10, 500)
orientation = design.get("orientation", "landscape")
if orientation == "portrait":
@@ -268,7 +308,6 @@ def render_design_image(design: dict[str, Any]) -> Image.Image:
else:
canvas_w_mm, canvas_h_mm = length, tape_width
scale = render_scale_for_tape(tape_width)
image = new_label_image(scaled_mm_to_px(canvas_w_mm, scale), scaled_mm_to_px(canvas_h_mm, scale))
max_height_px = printable_px_for_tape(tape_width)
if image.height > max_height_px: