Disable implicit text wrapping

This commit is contained in:
Mikei386
2026-06-22 16:09:03 +02:00
parent df95f4d9d6
commit eb6f60da51
2 changed files with 18 additions and 37 deletions
+14 -19
View File
@@ -107,31 +107,18 @@ def object_box(obj: dict[str, Any], scale: float) -> tuple[int, int, int, int]:
return x, y, max(1, w), max(1, h) return x, y, max(1, w), max(1, h)
def wrap_text(draw: ImageDraw.ImageDraw, text: str, font, max_width: int) -> list[str]: def text_lines(text: str) -> list[str]:
lines: list[str] = [] return text.split("\n")
for raw_line in text.splitlines() or [""]:
current = ""
for word in raw_line.split(" "):
candidate = word if not current else f"{current} {word}"
if draw.textbbox((0, 0), candidate, font=font)[2] <= max_width:
current = candidate
continue
if current:
lines.append(current)
current = word
if current:
lines.append(current)
return lines
def draw_text(draw: ImageDraw.ImageDraw, obj: dict[str, Any], scale: float) -> None: def draw_text(image: Image.Image, draw: ImageDraw.ImageDraw, obj: dict[str, Any], scale: float) -> None:
x, y, w, h = object_box(obj, scale) x, y, w, h = object_box(obj, scale)
text = str(obj.get("text", "Text")) text = str(obj.get("text", "Text"))
font_size = scaled_mm_to_px(float(obj.get("fontSizeMm", 5)), scale) font_size = scaled_mm_to_px(float(obj.get("fontSizeMm", 5)), scale)
font = get_font(font_size, bool(obj.get("bold", False))) font = get_font(font_size, bool(obj.get("bold", False)))
align = obj.get("align", "left") align = obj.get("align", "left")
valign = obj.get("valign", "middle") valign = obj.get("valign", "middle")
lines = wrap_text(draw, text, font, w) lines = text_lines(text)
boxes = [draw.textbbox((0, 0), line, font=font) for line in lines] boxes = [draw.textbbox((0, 0), line, font=font) for line in lines]
line_heights = [box[3] - box[1] for box in boxes] line_heights = [box[3] - box[1] for box in boxes]
gap = max(1, round(font_size * 0.15)) gap = max(1, round(font_size * 0.15))
@@ -150,7 +137,15 @@ def draw_text(draw: ImageDraw.ImageDraw, obj: dict[str, Any], scale: float) -> N
cx = x + w - text_w cx = x + w - text_w
else: else:
cx = x cx = x
draw.text((cx, cy - box[1]), line, font=font, fill=1) text_layer = Image.new("1", image.size, 0)
text_draw = ImageDraw.Draw(text_layer)
text_draw.text((cx, cy - box[1]), line, font=font, fill=1)
clip = Image.new("1", image.size, 0)
clip_draw = ImageDraw.Draw(clip)
clip_draw.rectangle([x, y, x + w, y + h], fill=1)
clipped = Image.new("1", image.size, 0)
clipped.paste(text_layer, mask=clip)
image.paste(1, mask=clipped)
cy += line_h + gap cy += line_h + gap
@@ -283,7 +278,7 @@ def render_design_image(design: dict[str, Any]) -> Image.Image:
continue continue
obj_type = obj.get("type") obj_type = obj.get("type")
if obj_type == "text" or obj_type == "symbol": if obj_type == "text" or obj_type == "symbol":
draw_text(draw, obj, scale) draw_text(image, draw, obj, scale)
elif obj_type == "shape": elif obj_type == "shape":
draw_shape(draw, obj, scale) draw_shape(draw, obj, scale)
elif obj_type == "line": elif obj_type == "line":
+4 -18
View File
@@ -102,22 +102,8 @@ function clamp(value, min, max) {
return Math.min(max, Math.max(min, value)); return Math.min(max, Math.max(min, value));
} }
function wrapCanvasText(text, maxWidthPx) { function canvasTextLines(text) {
const lines = []; return String(text || "").split("\n");
for (const rawLine of String(text || "").split("\n")) {
let current = "";
for (const word of rawLine.split(" ")) {
const candidate = current ? `${current} ${word}` : word;
if (ctx.measureText(candidate).width <= maxWidthPx) {
current = candidate;
continue;
}
if (current) lines.push(current);
current = word;
}
lines.push(current);
}
return lines.length ? lines : [""];
} }
function textNaturalWidthMm(obj) { function textNaturalWidthMm(obj) {
@@ -149,7 +135,7 @@ function objectContentEndMm(obj) {
const { value } = objectFont(obj); const { value } = objectFont(obj);
ctx.save(); ctx.save();
ctx.font = value; ctx.font = value;
const lines = wrapCanvasText(obj.text || "", mmToPx(obj.w)); const lines = canvasTextLines(obj.text || "");
const textWidthMm = Math.max(...lines.map((line) => pxToMm(ctx.measureText(line).width)), 0); const textWidthMm = Math.max(...lines.map((line) => pxToMm(ctx.measureText(line).width)), 0);
ctx.restore(); ctx.restore();
@@ -255,7 +241,7 @@ function drawTextObject(obj) {
ctx.font = font; ctx.font = font;
ctx.textBaseline = "middle"; ctx.textBaseline = "middle";
ctx.textAlign = obj.align || "left"; ctx.textAlign = obj.align || "left";
const lines = wrapCanvasText(obj.text || "", w); const lines = canvasTextLines(obj.text || "");
const lineHeight = fontPx * 1.15; const lineHeight = fontPx * 1.15;
const total = lineHeight * lines.length; const total = lineHeight * lines.length;
let cy = y + h / 2 - total / 2 + lineHeight / 2; let cy = y + h / 2 - total / 2 + lineHeight / 2;