Fonts & images
Load fonts and image bytes for PDF rendering, including SVG charts and offline assets.
Pass fonts through fonts and image bytes through images. The renderer fetches neither on its own. Font URL loaders and googleFonts() make their own requests, and you fetch document images before rendering.
Fonts
import { } from "takumi-pdf";
import { } from "@takumi-rs/helpers";
const = await (, {
: [...(await (["Inter"])), { : "Brand Sans", : 700, : }],
: ["Brand Sans", "Inter", "sans-serif"],
});fonts takes font URLs, raw bytes, descriptors, or googleFonts() entries. fontFamilies sets the fallback chain. A reused renderer loads each font once.
For offline renders, bundle font files. Google Fonts requests use the shared fetch limits and retries.
Coverage
The renderer does not read system fonts. Its only built-in font is Geist, a last-resort face for Latin text. By default, a character that no registered font covers fails the render, and the error names the character and its codepoint.
Register fonts for every script you use. Google Fonts can split accented letters between its latin and latin-ext subsets.
Family names
Quote a family name when one of its words starts with a digit, such as fontFamily: '"Source Serif 4"'. Unquoted, Source Serif 4 is not a valid font-family value. The declaration is dropped and the text falls back to the next family.
Uncovered text
uncoveredText sets what happens to a character that no registered font covers:
| Value | Result |
|---|---|
"error" (default) | Fails the render, naming each character and its codepoint. |
"placeholder" | Draws the font's glyph 0, which the font may leave empty. |
"blank" | Draws nothing. |
Neither "placeholder" nor "blank" reflows the line. The character keeps the width it had during layout.
import { } from "takumi-pdf";
const = await (, { : "placeholder" });Standards forbid the placeholder
Every PDF/A level and both PDF/UA levels forbid glyph 0. "placeholder" fails the render with any pdfa level, tagged: "ua1", or tagged: "ua2". The error names the uncovered characters and the standard. Use "blank" there. See PDF/A and PDF/UA.
What copied text keeps
Whether an uncovered character survives in copied text depends on its shaping cluster. This holds for "placeholder" and "blank" alike.
| Uncovered character | Copied text |
|---|---|
| On its own | Nothing. A PDF carries no Unicode mapping for glyph 0. |
| A combining mark on a covered letter | The mark, through the letter it shares a cluster with. |
Images
Pass the bytes for each image URL in the document. The renderer does not fetch them:
import { } from "takumi-pdf";
const = await ();
if (!.) throw new (`Logo request failed: ${.}`);
const = new (await .());
const = await (, {
: [{ : , : }],
});To fetch every remote image in a tree at once, use prepareImages().
Formats
| Source | In the PDF |
|---|---|
| SVG | Vector paths and gradients. Parts vectors cannot express, such as filters and embedded bitmaps, rasterize at 2× their placed size. |
| PNG | Embedded as an image |
| JPEG | Embedded as the bytes you passed, keeping their compression |
| WebP | Embedded as an image |
| GIF | Rejected: the PDF build ships no GIF decoder |
Identical raster images are embedded once.
Filters
A CSS color filter on an image needs decoded pixels, and the PDF build decodes only PNG. A filtered JPEG or WebP image fails the render.
PDF output also rejects filter: blur() and drop-shadow(), naming the function in the error. Bake those effects into a raster image before rendering.
Last updated on