UNPKG

pdf-lib

Version:

Library for creating and modifying PDF files in JavaScript

114 lines (113 loc) 5.26 kB
import sum from 'lodash/sum'; import { Encodings, Font, FontNames, } from '@pdf-lib/standard-fonts'; import PDFDocument from '../../pdf-document/PDFDocument'; import { PDFDictionary, PDFHexString, PDFName, } from '../../pdf-objects'; import values from 'lodash/values'; import { toCharCode, toHexString } from '../../../utils'; import { isInstance, oneOf, validate } from '../../../utils/validate'; /** * This Factory supports Standard fonts. * * A note of thanks to the developers of https://github.com/foliojs/pdfkit, * as this class borrows from: * https://github.com/foliojs/pdfkit/blob/f91bdd61c164a72ea06be1a43dc0a412afc3925f/lib/font/afm.coffee */ var PDFStandardFontFactory = /** @class */ (function () { function PDFStandardFontFactory(fontName) { var _this = this; /** * Embeds the font into a [[PDFDocument]]. * * @param pdfDoc A `PDFDocument` object into which the font will be embedded. * * @returns A `PDFIndirectReference` to the font dictionary that was * embedded in the `PDFDocument`. */ this.embedFontIn = function (pdfDoc) { validate(pdfDoc, isInstance(PDFDocument), 'PDFFontFactory.embedFontIn: "pdfDoc" must be an instance of PDFDocument'); var fontDict = PDFDictionary.from({ Type: PDFName.from('Font'), Subtype: PDFName.from('Type1'), BaseFont: PDFName.from(_this.font.FontName), }, pdfDoc.index); // ZapfDingbats and Symbol don't have explicit Encoding entries if (_this.encoding === Encodings.WinAnsi) { fontDict.set('Encoding', PDFName.from('WinAnsiEncoding')); } return pdfDoc.register(fontDict); }; /** * Encode the JavaScript string into this font. JavaScript encodes strings in * Unicode, but standard fonts use either WinAnsi, ZapfDingbats, or Symbol * encodings. This method should be used to encode text before passing the * encoded text to one of the text showing operators, such as [[drawText]] or * [[drawLinesOfText]]. * * @param text The string of text to be encoded. * * @returns A `PDFHexString` of the encoded text. */ this.encodeText = function (text) { return PDFHexString.fromString(_this.encodeTextAsGlyphs(text) .map(function (glyph) { return glyph.code; }) .map(toHexString) .join('')); }; /** * Measures the width of the JavaScript string when displayed as glyphs of * this font of a particular `size`. * * @param text The string of text to be measured. * @param size The size to be used when calculating the text's width. * * @returns A `number` representing the width of the text. */ this.widthOfTextAtSize = function (text, size) { var charNames = _this.encodeTextAsGlyphs(text).map(function (glyph) { return glyph.name; }); var widths = charNames.map(function (charName, idx) { var left = charName; var right = charNames[idx + 1]; var kernAmount = _this.font.getXAxisKerningForPair(left, right) || 0; return _this.widthOfGlyph(left) + kernAmount; }); var scale = size / 1000; return sum(widths) * scale; }; /** * Measures the height of this font at a particular size. Note that the height * of the font is independent of the particular glyphs being displayed, so * this method does not accept a `text` param, like * [[PDFStandardFontFactory.widthOfTextAtSize]] does. */ this.heightOfFontAtSize = function (size) { var _a = _this.font, Ascender = _a.Ascender, Descender = _a.Descender, FontBBox = _a.FontBBox; var yTop = Ascender || FontBBox[3]; var yBottom = Descender || FontBBox[1]; return ((yTop - yBottom) / 1000) * size; }; // We'll default to 250 if our font metrics don't specify a width this.widthOfGlyph = function (glyphName) { return _this.font.getWidthOfGlyph(glyphName) || 250; }; this.encodeTextAsGlyphs = function (text) { return text .split('') .map(toCharCode) .map(_this.encoding.encodeUnicodeCodePoint); }; validate(fontName, oneOf.apply(void 0, values(FontNames)), 'PDFDocument.embedFont: "fontName" must be one of the Standard 14 Fonts: ' + values(FontNames).join(', ')); this.fontName = fontName; this.font = Font.load(fontName); // prettier-ignore this.encoding = fontName === FontNames.ZapfDingbats ? Encodings.ZapfDingbats : fontName === FontNames.Symbol ? Encodings.Symbol : Encodings.WinAnsi; } PDFStandardFontFactory.for = function (fontName) { return new PDFStandardFontFactory(fontName); }; return PDFStandardFontFactory; }()); export default PDFStandardFontFactory;