Minimal TrueType subset for PDF Type0 / FontFile2 embedding.
Module embedSubsetForPdf | Source packages/front/office/fonts/src/embed-pdf/subsetForPdf.js | Deps fontErrors, fontSfnt, tableHead, tableHhea, tableMaxp, tableHmtx, tableLoca, embedFontDescriptor, cmapToUnicode, fontWriter, plus the sibling sub-modules embedClosure, embedCmapBuilder, embedGlyphRewriter, embedHash | Worker-safe yes
Computes the composite-glyph closure covering a set of code points, renumbers gids, re-encodes glyf/loca/hmtx/cmap/post/name/head, and also produces the FontDescriptor + ToUnicode CMap for the PDF Font dictionary.
Rewritten tables (vs. a verbatim copy of the source font's bytes):
glyf,loca,hmtx,cmap,head,hhea,maxp— recomputed for the renumbered/reduced glyph set (see Algorithm above).post— the 32-byte header is preserved bit-for-bit for the fields shared across versions (italicAngle, underline, isFixedPitch, memory hints); the version tag itself is forced to3.0(no glyph names) unless the source is already3.0, in which case the whole table is copied verbatim. A sourcepostshorter than 32 bytes, or absent, yields noposttable in the subset.name,OS/2— copied verbatim from the source font (unmodified).
Exports
| Symbol | Type | Description |
|---|---|---|
subsetForPdf |
function | (font, codePoints, opts?) => { subsetBytes, gidMap, glyphMap, encoding, widths, toUnicodeCmap, postScriptName, fontDescriptor }. |
embedSubsetForPdf |
factory | Factory. |
Usage
embedSubsetForPdf depends on four sub-modules (embedClosure, embedCmapBuilder, embedGlyphRewriter, embedHash). The package's modules array registers all four, placed before embedSubsetForPdf, so a runtime seeded with fw_require and modules resolves it with no further registration:
import fw from '@awacloud/fw';
import { fw_require, modules } from '@awacloud/fonts';
for (const m of [...fw_require, ...modules]) fw.runtime.register(m);
const font = fw.runtime.resolve('fonts').read(bytes); // bytes: Uint8Array of a TrueType font
const { subsetForPdf } = fw.runtime.resolve('embedSubsetForPdf');
const subset = subsetForPdf(font, new Set([0x41, 0x42, 0x4F]));
// subset.subsetBytes ready for FontFile2
Notes
gid 0(.notdef) is always kept.- A deterministic 6-letter prefix (e.g.
ABCDEF+) is added to the PostScript name per PDF convention. - Composites are recursively expanded before renumbering.
encodingis alwaysnull— Type0/Identity-H addressing goes through the rebuiltcmap, not a PDF/Encodingentry.widthsis a per-new-gid advance-width array, in the same order as the renumbered glyphs (suitable for the PDF/Wentry).- A font without
glyf/locatables (for example a CFF-flavoured OpenType font) is rejected withContractError('fonts/subset-bad-font'); variable-font tables and the GSUB/GPOS layout tables are not carried through to the subset. - A source
posttable is never copied verbatim unless it is already version 3.0: a v1.0/v2.0/v4.0postcarries glyph-name data keyed to the SOURCE font's gid count/order, which the subset's renumbered/reduced glyph set invalidates —fonts.read()on the resulting bytes would otherwise throwfonts/post-num-mismatch.