Skip to content

feat(schema): text autofit via slot metrics (options: ["autofit"]) - #100

Merged
ajianaz merged 1 commit into
developfrom
feat/text-autofit
Sep 17, 2026
Merged

ajianaz merged 1 commit into
developfrom
feat/text-autofit

Conversation

@ajianaz

@ajianaz ajianaz commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

What

Closes #92 — text autofit, phase 1 (scale factor emission).

FieldSpec gains optional slot metrics (slot_width, slot_height,
font_size, line_height). A text field that opts in via
options: ["autofit"] and declares those metrics gets a
<field>_font_scale context variable (0.1–1.0): the factor the
template multiplies its static font-size with so the wrapped text fits
the slot.

  • Width estimate: longest wrapped line × font-size × 0.52 (Inter-like
    average advance width) vs slot_width
  • Height estimate: wrapped line count × line-height vs slot_height
  • line_height defaults to font-size × 1.3; scale clamped to 0.1–1.0
  • Templates consume it per field, e.g.
    font-size="{{ (52.0 * quote_font_scale) | round | int }}" — or keep
    the static size and ignore the variable entirely

No schema change is required for existing templates: without the
autofit option + slot metrics, nothing is emitted and renders are
unchanged.

Why

Shrink-to-fit is the single most-requested feature across commercial
image-generation APIs (Bannerbear makes it a per-layer setting; Robolly
and Placid ship equivalents). Cosy's char-based wrap + max-length
validation can't guarantee visual fit because glyph widths differ.
This gives template authors a deterministic, dependency-free escape
hatch while keeping full backward compatibility.

Testing

  • cargo test 11/11 suites pass; clippy -D warnings clean
  • Backward compat: social-quote default render md5-identical to the
    pre-change baseline
  • Autofit demo (social-quote slot 920×616, font 52/68): a 280-char
    quote triggers a scale < 1.0, reflows to 9 lines and clears the
    author line (no overlap, vision-verified); short default quote stays
    at scale 1.0
  • Follow-up (not in this PR): apply slot metrics + scale consumption to
    the bundled templates that benefit most (social-quote, quote-stack),
    and a deterministic quality-gate fixture asserting max-length content
    never overflows

Closes #92 (phase 1: scale factor emission).

Schema FieldSpec gains slot_width / slot_height / font_size /
line_height. When a text field opts in via options ["autofit"] and
declares slot metrics, the context gets <field>_font_scale (0.1..1.0):
the factor to multiply the template's font-size so the wrapped text
fits the slot. Width estimate = longest wrapped line x font-size x
0.52 (Inter-like average advance); height = lines x line_height.
line_height defaults to font-size x 1.3.

Templates opt in per field by multiplying their static font-size with
{{ field_font_scale }} (rounding to int). Without the autofit option
or slot metrics, nothing changes (backward compatible: default renders
md5-identical, full suite passes).

Autofit validation for social-quote (slot 920x616, font 52/68): a
280-char quote scales to 9 lines x reduced size and stays above the
author line without overlap.
@github-actions

Copy link
Copy Markdown

🔍 Cora AI Code Review

✅ No issues found. Code looks good!


Review powered by cora-code · BYOK · MIT

@ajianaz
ajianaz merged commit 2411ee3 into develop Sep 17, 2026
11 checks passed
@ajianaz
ajianaz deleted the feat/text-autofit branch September 17, 2026 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: text autofit / shrink-to-fit for text fields

1 participant