pdf-lib
Version:
Library for creating and modifying PDF files in JavaScript
131 lines (130 loc) • 6.96 kB
JavaScript
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;
;