UNPKG

pdf-lib

Version:

Library for creating and modifying PDF files in JavaScript

131 lines (130 loc) 6.96 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; } Object.defineProperty(exports, "__esModule", { value: true }); var fontkit_1 = __importDefault(require("@pdf-lib/fontkit")); var isNil_1 = __importDefault(require("lodash/isNil")); var isObject_1 = __importDefault(require("lodash/isObject")); var isString_1 = __importDefault(require("lodash/isString")); var range_1 = __importDefault(require("lodash/range")); var pako_1 = __importDefault(require("pako")); var PDFDocument_1 = __importDefault(require("../../pdf-document/PDFDocument")); var pdf_objects_1 = require("../../pdf-objects"); var utils_1 = require("../../../utils"); var validate_1 = require("../../../utils/validate"); /** @hidden */ var unsigned32Bit = '00000000000000000000000000000000'; // TODO: Make sure this works correctly. Setting any flag besides // Nonsymbolic to true seems to screw up the font... /* * Doing this by bit-twiddling a string, and then parsing it, gets around * JavaScript converting the results of bit-shifting ops back into 64-bit integers. */ // prettier-ignore /** @hidden */ var fontFlags = function (options) { var flags = unsigned32Bit; if (options.FixedPitch) flags = utils_1.setCharAt(flags, 32 - 1, '1'); if (options.Serif) flags = utils_1.setCharAt(flags, 32 - 2, '1'); if (options.Symbolic) flags = utils_1.setCharAt(flags, 32 - 3, '1'); if (options.Script) flags = utils_1.setCharAt(flags, 32 - 4, '1'); if (options.Nonsymbolic) flags = utils_1.setCharAt(flags, 32 - 6, '1'); if (options.Italic) flags = utils_1.setCharAt(flags, 32 - 7, '1'); if (options.AllCap) flags = utils_1.setCharAt(flags, 32 - 17, '1'); if (options.SmallCap) flags = utils_1.setCharAt(flags, 32 - 18, '1'); if (options.ForceBold) flags = utils_1.setCharAt(flags, 32 - 19, '1'); return parseInt(flags, 2); }; /** * This Factory supports TrueType and OpenType fonts. Note that the apparent * hardcoding of values for OpenType fonts does not actually affect TrueType * fonts. * * A note of thanks to the developers of https://github.com/devongovett/pdfkit, * as this class borrows heavily from: * https://github.com/devongovett/pdfkit/blob/e71edab0dd4657b5a767804ba86c94c58d01fbca/lib/font/embedded.coffee */ var PDFFontFactory = /** @class */ (function () { function PDFFontFactory(fontData, flagOptions) { var _this = this; /* TODO: This is hardcoded for "Simple Fonts" with non-modified encodings, need to broaden support to other fonts. */ this.embedFontIn = function (pdfDoc, name) { validate_1.validate(pdfDoc, validate_1.isInstance(PDFDocument_1.default), 'PDFFontFactory.embedFontIn: "pdfDoc" must be an instance of PDFDocument'); validate_1.validate(name, utils_1.or(isString_1.default, isNil_1.default), '"name" must be a string or undefined'); var randSuffix = "-rand_" + Math.floor(Math.random() * 10000); var fontName = name || _this.font.postscriptName + randSuffix || 'Font' + randSuffix; var deflatedFontData = pako_1.default.deflate(_this.fontData); var fontStreamDict = pdf_objects_1.PDFDictionary.from({ Subtype: pdf_objects_1.PDFName.from('OpenType'), Filter: pdf_objects_1.PDFName.from('FlateDecode'), Length: pdf_objects_1.PDFNumber.fromNumber(deflatedFontData.length), }, pdfDoc.index); var fontStream = pdfDoc.register(pdf_objects_1.PDFRawStream.from(fontStreamDict, deflatedFontData)); var _a = _this.font, italicAngle = _a.italicAngle, ascent = _a.ascent, descent = _a.descent, capHeight = _a.capHeight, xHeight = _a.xHeight, bbox = _a.bbox; var fontDescriptor = pdf_objects_1.PDFDictionary.from({ Type: pdf_objects_1.PDFName.from('FontDescriptor'), FontName: pdf_objects_1.PDFName.from(fontName), Flags: pdf_objects_1.PDFNumber.fromNumber(fontFlags(_this.flagOptions)), FontBBox: pdf_objects_1.PDFArray.fromArray([ pdf_objects_1.PDFNumber.fromNumber(bbox.minX * _this.scale), pdf_objects_1.PDFNumber.fromNumber(bbox.minY * _this.scale), pdf_objects_1.PDFNumber.fromNumber(bbox.maxX * _this.scale), pdf_objects_1.PDFNumber.fromNumber(bbox.maxY * _this.scale), ], pdfDoc.index), ItalicAngle: pdf_objects_1.PDFNumber.fromNumber(italicAngle), Ascent: pdf_objects_1.PDFNumber.fromNumber(ascent * _this.scale), Descent: pdf_objects_1.PDFNumber.fromNumber(descent * _this.scale), CapHeight: pdf_objects_1.PDFNumber.fromNumber((capHeight || ascent) * _this.scale), XHeight: pdf_objects_1.PDFNumber.fromNumber((xHeight || 0) * _this.scale), // Not sure how to compute/find this, nor is anybody else really: // https://stackoverflow.com/questions/35485179/stemv-value-of-the-truetype-font StemV: pdf_objects_1.PDFNumber.fromNumber(0), FontFile3: fontStream, }, pdfDoc.index); return pdfDoc.register(pdf_objects_1.PDFDictionary.from({ Type: pdf_objects_1.PDFName.from('Font'), Subtype: pdf_objects_1.PDFName.from('OpenType'), BaseFont: pdf_objects_1.PDFName.from(fontName), FirstChar: pdf_objects_1.PDFNumber.fromNumber(0), LastChar: pdf_objects_1.PDFNumber.fromNumber(255), Widths: _this.getWidths(pdfDoc.index), FontDescriptor: pdfDoc.register(fontDescriptor), }, pdfDoc.index)); }; /** @hidden */ this.getWidths = function (index) { return pdf_objects_1.PDFArray.fromArray(range_1.default(0, 256) .map(_this.getCodePointWidth) .map(pdf_objects_1.PDFNumber.fromNumber), index); }; this.getCodePointWidth = function (code) { return _this.font.characterSet.includes(code) ? _this.font.glyphForCodePoint(code).advanceWidth * _this.scale : 0; }; validate_1.validate(fontData, validate_1.isInstance(Uint8Array), '"fontData" must be a Uint8Array'); validate_1.validate(flagOptions, isObject_1.default, '"flagOptions" must be an Object'); this.fontData = fontData; this.flagOptions = flagOptions; this.font = fontkit_1.default.create(fontData); this.scale = 1000 / this.font.unitsPerEm; } PDFFontFactory.for = function (fontData, flagOptions) { return new PDFFontFactory(fontData, flagOptions); }; return PDFFontFactory; }()); exports.default = PDFFontFactory;