Add the Neutral template family, template picker and text-only logo allowances

Linea (the vendor's original format.pdf design), Monogram and Serenity are
rebuilt from the reference PDFs as one parametric family on the engine, with
the user's logo in the measured slot, a home for every GST field and
A4/Letter support. Adds static Montserrat, Open Sans and Poppins fonts and
a generated Ms Madi outline for Serenity's vertical word. Text-only logo
placeholders (Monolith, Tangerine) use a doc-derived allowance box. A
Carbon TemplatePicker with committed thumbnails opens from the page
setup controls.
This commit is contained in:
2026-10-04 07:27:12 +05:30
parent eddf27629f
commit aa7a407944
61 changed files with 3278 additions and 110 deletions
+11 -2
View File
@@ -136,7 +136,14 @@ async function main() {
for (const id of ids) {
const slot = slotFor(id);
const page = await renderPage(TEMPLATE_PDF[id]);
const L = slot.lockup;
// The region covers the placeholder and, for a text-only one, its (larger) allowance.
const L = slot.textOnly
? { x: Math.min(slot.lockup.x, slot.allowance.x), y: Math.min(slot.lockup.y, slot.allowance.y), w: 0, h: 0 }
: slot.lockup;
if (slot.textOnly) {
L.w = Math.max(slot.lockup.x + slot.lockup.w, slot.allowance.x + slot.allowance.w) - L.x;
L.h = Math.max(slot.lockup.y + slot.lockup.h, slot.allowance.y + slot.allowance.h) - L.y;
}
const region = {
x: Math.max(0, Math.floor(L.x - PAD)),
y: Math.max(0, Math.floor(L.y - PAD)),
@@ -158,7 +165,7 @@ async function main() {
ctx.font = "bold 16px sans-serif";
ctx.fillText("Logo placement sign-off sheet (reference placeholder, then four test logos)", 8, 22);
ctx.font = "12px sans-serif";
ctx.fillText("Red outline = measured placeholder box, blue = mark box. Dashed = opt-in area (no reference placeholder). Green = logo box as placed.", 8, 40);
ctx.fillText("Red = measured placeholder box, blue = mark box, orange dashed = allowance of a text-only placeholder, red dashed = opt-in area (no reference placeholder). Green = logo box as placed.", 8, 40);
const heads = ["reference placeholder", ...logos.map((l) => `${l.label} (${l.aspect.toFixed(2)}:1, d ${l.density.toFixed(2)})`)];
ctx.font = "bold 11px sans-serif";
heads.forEach((t, i) => ctx.fillText(t, LABEL_W + GUTTER + i * (cellW + GUTTER), HEAD_H - 6));
@@ -182,6 +189,7 @@ async function main() {
const lines = [
slot.optIn ? "opt-in, off by default" : "reference placeholder",
`lockup ${f(slot.lockup)}`,
...(slot.textOnly ? [`text-only: allowance ${f(slot.allowance)}`] : []),
`mark ${f(slot.mark)}`,
`density ${slot.lockupDensity.toFixed(2)} / ${slot.markDensity.toFixed(2)}`,
`${slot.anchor}, ${slot.vAlign}${slot.darkSurface ? ", dark surface" : ""}`,
@@ -214,6 +222,7 @@ async function main() {
if (slot.optIn) box(ctx, slot.lockup, region, "#dd0000", true);
else {
box(ctx, slot.lockup, region, "#dd0000");
if (slot.textOnly) box(ctx, slot.allowance, region, "#e08a00", true);
if (slot.mark && slot.mark !== slot.lockup && slot.mark.w !== slot.lockup.w) box(ctx, slot.mark, region, "#0066cc");
}
c.restore();