/** * Font manager for PDF generation. * * Manages three kinds of fonts: * 1. **Standard Type1 fonts** (Helvetica, Times, Courier) — always available, * used for Latin text (WinAnsi repertoire) when no embedded font is provided. * 2. **Embedded TrueType fonts** — user-provided .ttf files for full * Unicode support (CJK, Arabic, Hindi, etc.) * 3. **Type3 fallback fonts** — auto-generated vector-drawn glyphs for * Unicode characters outside WinAnsi when no embedded font is provided. * * When an embedded font is registered, ALL text uses the embedded font. * When no embedded font is provided, the system uses Type1 for WinAnsi * characters and Type3 for everything else. * * The manager tracks which Unicode code points are used so the font embedder * and Type3 builder can create minimal subsets when writing the PDF. */ import type { PdfWriter } from "../core/pdf-writer.js"; import { type EmbeddedFont } from "./font-embedder.js"; import type { TtfFont } from "./ttf-parser.js"; /** * Get the full PDF standard font name with style variant. */ export declare function resolvePdfFontName(fontFamily: string, bold: boolean, italic: boolean): string; /** * Manages PDF font resources for a document. * Supports standard Type1 fonts, embedded TrueType fonts, and auto-generated * Type3 fallback fonts for non-WinAnsi Unicode characters. */ export declare class FontManager { private type1Map; private resourceToType1; private nextType1Id; private embeddedFont; private embeddedResourceName; private usedCodePoints; private nextEmbeddedId; private type3CodePoints; private _type3Result; /** * Every distinct unknown font family passed to `resolveFont` since this * manager was constructed. A "family" counts as unknown when it isn't * in `FONT_FAMILY_MAP` and isn't the canonical "helvetica"/"times"/ * "courier" identifier. Populated as a set so a document that repeats * the same missing family across hundreds of text runs still produces * a single diagnostic. */ private _unknownFontFamilies; /** * Register an embedded TrueType font for use. * When set, all text rendering uses this font instead of standard fonts. */ registerEmbeddedFont(font: TtfFont): string; /** * Check if an embedded font is available. */ hasEmbeddedFont(): boolean; /** * Read-only view of the non-WinAnsi code points encountered so far when * no font is embedded. Used by callers (`PdfDocumentBuilder.build()`) * to decide whether to auto-discover a system font before the Type3 * fallback kicks in. Returns a defensive copy so consumers cannot * mutate the internal set. */ getType3CodePoints(): Set; /** * Read-only view of the font families `resolveFont` saw but could not * map to a standard Type1 (Helvetica/Times/Courier) base. Consumers * use this to emit one diagnostic per distinct missing family at * build time rather than one per text run. The set is deduplicated * and preserves the exact casing the caller supplied. */ getUnknownFontFamilies(): Set; /** * Get the embedded font's resource name (if registered). */ getEmbeddedResourceName(): string; /** * Resolve the resource name a draw-time-resolved Type1 resource should * actually render (and be measured) with, given the font manager's * *current* state. If an embedded font exists (possibly auto-discovered * at build time, after the text was drawn against a Type1 resource), the * embedded resource name is returned so both measurement and encoding go * through the CIDFont. Otherwise the original Type1 resource name is kept; * `measureText` handles Type3-fallback widths internally from that name. * * Centralises the routing rule shared by the deferred text renderer and * any deferred measurement (anchor alignment, word wrapping) so the two * never disagree. */ resolveRenderResourceName(type1ResourceName: string): string; /** * Record that a text string will be rendered, tracking its code points. * Must be called for every text string before writing the PDF. * * Two sets are maintained because font selection may be decided *after* * drawing (e.g. `PdfDocumentBuilder.build()` auto-discovers and embeds a * system font once it sees the accumulated non-WinAnsi code points): * * - `usedCodePoints` — every code point seen, always. If an embedded * font ends up being used (whether registered up front or * auto-discovered at build time), the subset must cover all of these, * including plain ASCII, so the CIDFont can encode the full run. * - `type3CodePoints` — non-WinAnsi code points only. Drives the * build-time decision to auto-embed a system font, and the Type3 * fallback when none is available. */ trackText(text: string): void; /** * Ensure a standard Type1 font is registered and return its resource name. */ ensureFont(pdfFontName: string): string; /** * Resolve an Excel font specification to a resource name. * If an embedded font is registered, returns the embedded font's resource name. * Otherwise, falls back to standard Type1 fonts. */ resolveFont(fontFamily: string, bold: boolean, italic: boolean): string; /** * Get the PDF font name for a given resource name. */ getPdfFontName(resourceName: string): string; /** * Check if Type3 fallback fonts are available (after writeFontResources). */ hasType3Fonts(): boolean; /** * Resolve the Type3 font resource name and char code for a code point. * Returns null if the code point is not in the Type3 encoding. */ resolveType3(codePoint: number): { resourceName: string; charCode: number; } | null; /** * Check if a code point needs Type3 rendering (non-WinAnsi, no embedded font). */ needsType3(codePoint: number): boolean; /** * Measure text width using the correct font metrics. * For mixed Type1/Type3 text, measures each character with the right font. */ measureText(text: string, resourceName: string, fontSize: number): number; /** * Get the font ascent in points. */ getFontAscent(resourceName: string, fontSize: number): number; /** * Get the font descent in points (negative value). */ getFontDescent(resourceName: string, fontSize: number): number; /** * Get the line height in points. */ getLineHeight(resourceName: string, fontSize: number): number; /** * Check if a resource name refers to an embedded font. */ isEmbeddedFont(resourceName: string): boolean; /** * Check if a resource name refers to a Type3 fallback font. */ isType3Resource(resourceName: string): boolean; /** * Encode text for the given font resource. * For embedded fonts, returns a hex string `<0012003A...>`. * For Type1 fonts, returns null (caller should use standard string encoding). * * IMPORTANT: Must be called AFTER writeFontResources(), which builds the * subset and produces the unicodeToCid mapping. */ encodeText(text: string, resourceName: string): string | null; /** * Encode a single character for a Type3 font. * Returns a hex string `` suitable for the Tj operator. */ encodeType3Char(codePoint: number): string | null; /** * Write all font resource objects to the PDF. * Returns a map from resource name → object number. */ writeFontResources(writer: PdfWriter): Map; /** Stored after writeFontResources is called */ private _embeddedResult; /** * Get the embedded font result (available after writeFontResources). */ getEmbeddedResult(): EmbeddedFont | null; /** * Build the Font sub-dictionary for a page's Resources dictionary. */ buildFontDictString(fontObjectMap: Map): string; /** * Get all registered fonts (Type1 only, for backward compat). */ getRegisteredFonts(): Array<{ resourceName: string; pdfFontName: string; }>; }