diff --git a/CHANGELOG.md b/CHANGELOG.md index ad6b9729..d9e97eb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Unreleased +- Reuse the glyph width and kerning tables of a standard font across documents instead of building them again for every document that uses it, which made a short document using two standard fonts more than twice as slow to create - Fix `doc.table()` parsing a font passed as binary data (e.g. registered with `registerFont(name, uint8Array)`) again for every cell, when it restores the font after measuring and drawing the cell, which made tables with such fonts slower. A font loaded from the same `Uint8Array` is now reused without parsing it again - Add `lineBreak: 'whitespace'` to `doc.text()`, which breaks a line only at whitespace, a soft hyphen or a zero-width space. The Unicode line breaking rules the wrapper follows also allow a break after a hyphen or a slash, so `design-system` or `https://github.com/foliojs/pdfkit` could be cut at a line end, and a text extractor that joins the lines, such as a résumé parser, reads two words - Add an `objectStreams` option, which packs the objects that are not streams into compressed object streams and writes a cross-reference stream instead of the xref table, making documents with many such objects, e.g. tagged ones, much smaller. It requires a `pdfVersion` of `1.5` or higher, and cannot be used with encryption or PDF/A-1. Fixes #1810 diff --git a/lib/font/standard.js b/lib/font/standard.js index 57dd8b65..2a57483b 100644 --- a/lib/font/standard.js +++ b/lib/font/standard.js @@ -1,13 +1,21 @@ import AFMFont from './afm'; import PDFFont from '../font'; +// AFMFont only reads its data, so every document can share the one built for +// a given font data instead of rebuilding its glyph width and kerning tables. +const afmFonts = new WeakMap(); + class StandardFont extends PDFFont { constructor(document, fontData, id) { super(); this.document = document; this.name = fontData.name; this.id = id; - this.font = new AFMFont(fontData); + this.font = afmFonts.get(fontData); + if (!this.font) { + this.font = new AFMFont(fontData); + afmFonts.set(fontData, this.font); + } ({ ascender: this.ascender, descender: this.descender, diff --git a/tests/unit/font.spec.js b/tests/unit/font.spec.js index 64b7f0c0..83c26900 100644 --- a/tests/unit/font.spec.js +++ b/tests/unit/font.spec.js @@ -454,3 +454,13 @@ describe('binary font sources', () => { expect(doc._font.id).toBe(first.id); }); }); + +describe('standard font metrics', () => { + test('are shared across documents', () => { + const first = new PDFDocument().font('Helvetica-Bold')._font; + const second = new PDFDocument().font('Helvetica-Bold')._font; + + expect(second).not.toBe(first); + expect(second.font).toBe(first.font); + }); +});