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:
@@ -2,6 +2,7 @@ import { create, type Font } from "fontkit";
|
||||
import { FONT_MANIFEST } from "../fonts/manifest";
|
||||
import { familySources, FONT_STACK, stack, type FamilySource } from "../fonts/stack";
|
||||
import { resolveFace, roleToken, type RoleName, type TypeToken } from "../fonts/roles";
|
||||
import { userFamilySources } from "../fonts/userFontStore";
|
||||
|
||||
export interface MeasureInput {
|
||||
text: string;
|
||||
@@ -29,6 +30,29 @@ export interface Measurer {
|
||||
missing(text: string, face?: string): number[];
|
||||
}
|
||||
|
||||
const userFonts = new Map<string, Font>();
|
||||
|
||||
/**
|
||||
* The fontkit font of a user-imported family at a weight and style (the file react-pdf resolves for it), or
|
||||
* undefined when `familyName` is not a user family. Parsed once per file and shared by every measurer.
|
||||
*/
|
||||
export function userFontkitFont(familyName: string, weight: number, italic: boolean): Font | null | undefined {
|
||||
const sources = userFamilySources(familyName);
|
||||
if (sources.length === 0) return undefined;
|
||||
const src = resolveSource(
|
||||
sources.map((s) => ({ file: s.id, fontWeight: s.fontWeight, fontStyle: s.fontStyle })),
|
||||
weight,
|
||||
italic ? "italic" : "normal",
|
||||
);
|
||||
if (!src) return null;
|
||||
let font = userFonts.get(src.file);
|
||||
if (!font) {
|
||||
font = create((sources.find((s) => s.id === src.file) as { bytes: Uint8Array }).bytes) as Font;
|
||||
userFonts.set(src.file, font);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
/** react-pdf's FontFamily.resolve, so the measurer reads the same file the renderer embeds. */
|
||||
function resolveSource(sources: FamilySource[], weight: number, style: "normal" | "italic"): FamilySource | undefined {
|
||||
const styled = sources.filter((s) => s.fontStyle === style);
|
||||
@@ -57,6 +81,8 @@ export function createMeasurer(loadBytes: (file: string) => Uint8Array): Measure
|
||||
const fonts = new Map<string, Font>();
|
||||
|
||||
function load(familyName: string, weight: number, italic: boolean): Font | null {
|
||||
const own = userFontkitFont(familyName, weight, italic);
|
||||
if (own !== undefined) return own;
|
||||
const fam = FONT_MANIFEST.families.find((f) => f.family === familyName);
|
||||
if (!fam) return null;
|
||||
const src = resolveSource(familySources(fam), weight, italic ? "italic" : "normal");
|
||||
|
||||
Reference in New Issue
Block a user