Add Ledger and Band template families with decor primitives

Crimson Grid, Tangerine Ledger, Slate Band and Teal Swoosh are rebuilt from
the reference PDFs with grid and band tables that survive page breaks,
full-bleed fixed bands, pennant tabs, gradient corner swooshes with
keep-outs, Carbon icon circles, and the user's logo in the measured slot
(knockout or white chip on the dark Slate band). Adds static Poppins
500-700 and Inter fonts. Thumbnails regenerated for all eight templates;
the item-count sweeps run in their own test file.
This commit is contained in:
2026-10-04 08:34:18 +05:30
parent aa7a407944
commit 9de9a6ffee
57 changed files with 4078 additions and 217 deletions
+41 -1
View File
@@ -12,7 +12,7 @@ import { setupPdfTest } from "../testing/setup";
/** Fixtures and helpers shared by the template harness and the sample renderer. */
export type LogoKind = "none" | "real" | "wide" | "square";
export type LogoKind = "none" | "real" | "wide" | "square" | "knockout";
export interface FixtureSpec {
name: string;
@@ -130,6 +130,33 @@ export function solidPng(w: number, h: number): Buffer {
]);
}
/** A transparent-margin w x h PNG in one colour: the shape of a logo that has alpha, so it can have a white knockout. */
function inkPng(w: number, h: number, rgb: [number, number, number]): Buffer {
const row = Buffer.alloc(1 + w * 4);
const raw = Buffer.alloc(row.length * h);
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
const inside = x >= w * 0.08 && x < w * 0.92 && y >= h * 0.12 && y < h * 0.88;
const o = y * row.length + 1 + x * 4;
raw[o] = rgb[0];
raw[o + 1] = rgb[1];
raw[o + 2] = rgb[2];
raw[o + 3] = inside ? 255 : 0;
}
}
const ihdr = Buffer.alloc(13);
ihdr.writeUInt32BE(w, 0);
ihdr.writeUInt32BE(h, 4);
ihdr[8] = 8;
ihdr[9] = 6;
return Buffer.concat([
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
chunk("IHDR", ihdr),
chunk("IDAT", deflateSync(raw)),
chunk("IEND", Buffer.alloc(0)),
]);
}
const dataUri = (png: Buffer) => `data:image/png;base64,${png.toString("base64")}`;
const cache = new Map<string, LogoInput>();
@@ -142,6 +169,19 @@ export function fixtureLogo(kind: LogoKind): LogoInput | null {
const png = readFileSync(path.resolve(process.cwd(), "public/brand/sample-wordmark-logo.png"));
const [width, height] = [png.readUInt32BE(16), png.readUInt32BE(20)];
hit = { dataUri: dataUri(png), width, height, aspect: width / height, density: 0.21, kind: "wordmark", includesName: true };
} else if (kind === "knockout") {
// A wordmark with alpha: navy print image plus its white knockout, as the logo pipeline writes them.
hit = {
dataUri: dataUri(inkPng(460, 100, [24, 52, 120])),
knockoutDataUri: dataUri(inkPng(460, 100, [255, 255, 255])),
hasKnockout: true,
width: 460,
height: 100,
aspect: 4.6,
density: 0.6,
kind: "wordmark",
includesName: true,
};
} else if (kind === "wide") {
// The trimmed Test Vendor ink box is 4.6:1.
hit = { dataUri: dataUri(solidPng(460, 100)), width: 460, height: 100, aspect: 4.6, density: 1, kind: "wordmark", includesName: true };