Add font import for Now, Gotham and Open Sauce One overrides; package fonts for Void
Font import: - Migration M6 adds user_fonts; files are stored content-addressed under the local data dir. New Rust commands inspect, import, list, read and remove fonts, refusing WOFF2, collections, variable fonts and restricted fsType, and unpacking WOFF1 to plain sfnt. - Imported fonts register in the render worker as user:<Face> families with an italic alias, and are pinned in the frozen render prefs so issued invoices can still re-render. Fonts referenced by issued invoices are hidden, never deleted. - Size and tracking compensations tuned for the substitutes apply only while the face is not overridden; default output and fingerprint goldens are unchanged. - Settings gets a Fonts section with a licence acknowledgement. Void packaging: - Install fonts to /usr/share/fonts/voiced with per-family OFL licences, set font_dirs, and add INSTALL/REMOVE scripts that run fc-cache. xbps-create carries both scripts (verified in a void-glibc container). - Fix xbps-create dependency specs in build-xbps.sh.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { MarginPreset, PageId } from "../engine/geometry";
|
||||
import { isUserFace, type UserFace } from "../fonts/userFontStore";
|
||||
|
||||
/** Page and template choices frozen with an invoice at issue (stored as JSON). */
|
||||
export interface RenderPrefsV1 {
|
||||
@@ -12,6 +13,11 @@ export interface RenderPrefsV1 {
|
||||
/** Templates without a reference logo placeholder (Linea, ...) show the logo only when this is true. */
|
||||
show?: boolean;
|
||||
};
|
||||
/**
|
||||
* User-imported fonts in use, per face (Now, Gotham, Open Sauce One): the sha256 of each file (one per weight/style).
|
||||
* Frozen with the invoice, which is what keeps those font files from being deleted. Absent: the bundled substitutes.
|
||||
*/
|
||||
fonts?: Partial<Record<UserFace, string[]>>;
|
||||
}
|
||||
|
||||
export const DEFAULT_PREFS: RenderPrefsV1 = {
|
||||
@@ -22,6 +28,7 @@ export const DEFAULT_PREFS: RenderPrefsV1 = {
|
||||
};
|
||||
|
||||
const PAGE_SIZE_IDS: readonly PageId[] = ["A4", "LETTER"];
|
||||
const FONT_ID = /^[0-9a-f]{16,64}$/;
|
||||
const MARGIN_IDS: readonly MarginPreset[] = ["template", "narrow", "normal"];
|
||||
|
||||
/** Tolerant: anything unreadable or out of range falls back to the default for that field. */
|
||||
@@ -49,6 +56,16 @@ export function parsePrefs(json: string | null | undefined): RenderPrefsV1 {
|
||||
if (typeof show === "boolean") out.show = show;
|
||||
if (Object.keys(out).length > 0) prefs.logo = out;
|
||||
}
|
||||
const fonts = o.fonts;
|
||||
if (typeof fonts === "object" && fonts !== null) {
|
||||
const out: NonNullable<RenderPrefsV1["fonts"]> = {};
|
||||
for (const [face, ids] of Object.entries(fonts as Record<string, unknown>)) {
|
||||
if (!isUserFace(face) || !Array.isArray(ids)) continue;
|
||||
const valid = ids.filter((id): id is string => typeof id === "string" && FONT_ID.test(id)).slice(0, 16);
|
||||
if (valid.length > 0) out[face] = valid;
|
||||
}
|
||||
if (Object.keys(out).length > 0) prefs.fonts = out;
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user