: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
warn('Invalid "Length1" property in Type1 font -- trying to recover.');
stream.pos = streamStartPos;
const SCAN_BLOCK_LENGTH = 2048;
const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
block = findBlock(scanBytes, EEXEC_SIGNATURE, 0);
if (block.length === 0) {
stream.pos += block.length;
actualLength = stream.pos - streamStartPos;
stream.pos = streamStartPos;
stream: new Stream(stream.getBytes(actualLength)),
warn('Unable to recover "Length1" property in Type1 font -- using as is.');
stream: new Stream(stream.getBytes(suggestedLength)),
function getEexecBlock(stream, suggestedLength) {
const eexecBytes = stream.getBytes();
if (eexecBytes.length === 0) {
throw new FormatError("getEexecBlock - no font program found.");
stream: new Stream(eexecBytes),
length: eexecBytes.length
constructor(name, file, properties) {
const PFB_HEADER_SIZE = 6;
let headerBlockLength = properties.length1;
let eexecBlockLength = properties.length2;
let pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
const pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
file.skip(PFB_HEADER_SIZE);
headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
const headerBlock = getHeaderBlock(file, headerBlockLength);
const headerBlockParser = new Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED);
headerBlockParser.extractFontHeader(properties);
pfbHeader = file.getBytes(PFB_HEADER_SIZE);
eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
const eexecBlock = getEexecBlock(file, eexecBlockLength);
const eexecBlockParser = new Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED);
const data = eexecBlockParser.extractFontProgram(properties);
for (const key in data.properties) {
properties[key] = data.properties[key];
const charstrings = data.charstrings;
const type2Charstrings = this.getType2Charstrings(charstrings);
const subrs = this.getType2Subrs(data.subrs);
this.charstrings = charstrings;
this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties);
this.seacs = this.getSeacs(data.charstrings);
return this.charstrings.length + 1;
const charset = [".notdef"];
getGlyphMapping(properties) {
const charstrings = this.charstrings;
if (properties.composite) {
const charCodeToGlyphId = Object.create(null);
for (let glyphId = 0, charstringsLen = charstrings.length; glyphId < charstringsLen; glyphId++) {
const charCode = properties.cMap.charCodeOf(glyphId);
charCodeToGlyphId[charCode] = glyphId + 1;
return charCodeToGlyphId;
const glyphNames = [".notdef"];
let builtInEncoding, glyphId;
for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
glyphNames.push(charstrings[glyphId].glyphName);
const encoding = properties.builtInEncoding;
builtInEncoding = Object.create(null);
for (const charCode in encoding) {
glyphId = glyphNames.indexOf(encoding[charCode]);
builtInEncoding[charCode] = glyphId;
return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
if (id < 0 || id >= this.numGlyphs) {
const glyph = this.charstrings[id - 1];
return glyph.charstring.length > 0;
for (let i = 0, ii = charstrings.length; i < ii; i++) {
const charstring = charstrings[i];
seacMap[i + 1] = charstring.seac;
getType2Charstrings(type1Charstrings) {
const type2Charstrings = [];
for (const type1Charstring of type1Charstrings) {
type2Charstrings.push(type1Charstring.charstring);
getType2Subrs(type1Subrs) {
const count = type1Subrs.length;
} else if (count < 33769) {
for (i = 0; i < bias; i++) {
for (i = 0; i < count; i++) {
type2Subrs.push(type1Subrs[i]);
wrap(name, glyphs, charstrings, subrs, properties) {
cff.header = new CFFHeader(1, 0, 4, 4);
const topDict = new CFFTopDict();
topDict.setByName("version", 391);
topDict.setByName("Notice", 392);
topDict.setByName("FullName", 393);
topDict.setByName("FamilyName", 394);
topDict.setByName("Weight", 395);
topDict.setByName("Encoding", null);
topDict.setByName("FontMatrix", properties.fontMatrix);
topDict.setByName("FontBBox", properties.bbox);
topDict.setByName("charset", null);
topDict.setByName("CharStrings", null);
topDict.setByName("Private", null);
const strings = new CFFStrings();
strings.add("Version 0.11");
strings.add("See original notice");
cff.globalSubrIndex = new CFFIndex();
const count = glyphs.length;
const charsetArray = [".notdef"];
for (i = 0; i < count; i++) {
const glyphName = charstrings[i].glyphName;
const index = CFFStandardStrings.indexOf(glyphName);
charsetArray.push(glyphName);
cff.charset = new CFFCharset(false, 0, charsetArray);
const charStringsIndex = new CFFIndex();
charStringsIndex.add([0x8b, 0x0e]);
for (i = 0; i < count; i++) {
charStringsIndex.add(glyphs[i]);
cff.charStrings = charStringsIndex;
const privateDict = new CFFPrivateDict();
privateDict.setByName("Subrs", null);
const fields = ["BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StemSnapH", "StemSnapV", "BlueShift", "BlueFuzz", "BlueScale", "LanguageGroup", "ExpansionFactor", "ForceBold", "StdHW", "StdVW"];
for (i = 0, ii = fields.length; i < ii; i++) {
if (!(field in properties.privateData)) {
const value = properties.privateData[field];
if (Array.isArray(value)) {
for (let j = value.length - 1; j > 0; j--) {
value[j] -= value[j - 1];
privateDict.setByName(field, value);
cff.topDict.privateDict = privateDict;
const subrIndex = new CFFIndex();
for (i = 0, ii = subrs.length; i < ii; i++) {
privateDict.subrsIndex = subrIndex;
const compiler = new CFFCompiler(cff);
return compiler.compile();
;// CONCATENATED MODULE: ./src/core/fonts.js
const PRIVATE_USE_AREAS = [[0xe000, 0xf8ff], [0x100000, 0x10fffd]];
const PDF_GLYPH_SPACE_UNITS = 1000;
const EXPORT_DATA_PROPERTIES = ["ascent", "bbox", "black", "bold", "charProcOperatorList", "composite", "cssFontInfo", "data", "defaultVMetrics", "defaultWidth", "descent", "fallbackName", "fontMatrix", "isInvalidPDFjsFont", "isType3Font", "italic", "loadedName", "mimetype", "missingFile", "name", "remeasure", "subtype", "systemFontInfo", "type", "vertical"];
const EXPORT_DATA_EXTRA_PROPERTIES = ["cMap", "defaultEncoding", "differences", "isMonospace", "isSerifFont", "isSymbolicFont", "seacMap", "toFontChar", "toUnicode", "vmetrics", "widths"];
function adjustWidths(properties) {
if (!properties.fontMatrix) {
if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) {
const scale = 0.001 / properties.fontMatrix[0];
const glyphsWidths = properties.widths;
for (const glyph in glyphsWidths) {
glyphsWidths[glyph] *= scale;
properties.defaultWidth *= scale;
function adjustTrueTypeToUnicode(properties, isSymbolicFont, nameRecords) {
if (properties.isInternalFont) {
if (properties.hasIncludedToUnicodeMap) {
if (properties.hasEncoding) {
if (properties.toUnicode instanceof IdentityToUnicodeMap) {
if (nameRecords.length === 0) {
if (properties.defaultEncoding === WinAnsiEncoding) {
for (const r of nameRecords) {
if (!isWinNameRecord(r)) {
const encoding = WinAnsiEncoding;
glyphsUnicodeMap = getGlyphsUnicode();
for (const charCode in encoding) {
const glyphName = encoding[charCode];
const unicode = glyphsUnicodeMap[glyphName];
if (unicode === undefined) {
toUnicode[charCode] = String.fromCharCode(unicode);
if (toUnicode.length > 0) {
properties.toUnicode.amend(toUnicode);
function adjustType1ToUnicode(properties, builtInEncoding) {
if (properties.isInternalFont) {
if (properties.hasIncludedToUnicodeMap) {
if (builtInEncoding === properties.defaultEncoding) {
if (properties.toUnicode instanceof IdentityToUnicodeMap) {
glyphsUnicodeMap = getGlyphsUnicode();
for (const charCode in builtInEncoding) {
if (properties.hasEncoding) {
if (properties.baseEncodingName || properties.differences[charCode] !== undefined) {
const glyphName = builtInEncoding[charCode];
const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
toUnicode[charCode] = String.fromCharCode(unicode);
if (toUnicode.length > 0) {
properties.toUnicode.amend(toUnicode);
function amendFallbackToUnicode(properties) {
if (!properties.fallbackToUnicode) {
if (properties.toUnicode instanceof IdentityToUnicodeMap) {
for (const charCode in properties.fallbackToUnicode) {
if (properties.toUnicode.has(charCode)) {
toUnicode[charCode] = properties.fallbackToUnicode[charCode];
if (toUnicode.length > 0) {
properties.toUnicode.amend(toUnicode);
constructor(originalCharCode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {
this.originalCharCode = originalCharCode;
this.fontChar = fontChar;
this.operatorListId = operatorListId;
this.isInFont = isInFont;
return shadow(this, "category", getCharUnicodeCategory(this.unicode), true);
function writeSignedInt16(bytes, index, value) {
bytes[index + 1] = value;
bytes[index] = value >>> 8;
function signedInt16(b0, b1) {
const value = (b0 << 8) + b1;
return value & 1 << 15 ? value - 0x10000 : value;
function writeUint32(bytes, index, value) {
bytes[index + 3] = value & 0xff;
bytes[index + 2] = value >>> 8;
bytes[index + 1] = value >>> 16;
bytes[index] = value >>> 24;
function int32(b0, b1, b2, b3) {
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
function string16(value) {
return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
function safeString16(value) {
} else if (value < -0x8000) {
return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
function isTrueTypeFile(file) {
const header = file.peekBytes(4);
return readUint32(header, 0) === 0x00010000 || bytesToString(header) === "true";
function isTrueTypeCollectionFile(file) {
const header = file.peekBytes(4);
return bytesToString(header) === "ttcf";
function isOpenTypeFile(file) {
const header = file.peekBytes(4);
return bytesToString(header) === "OTTO";
function isType1File(file) {
const header = file.peekBytes(2);
if (header[0] === 0x25 && header[1] === 0x21) {
if (header[0] === 0x80 && header[1] === 0x01) {
function isCFFFile(file) {
const header = file.peekBytes(4);
if (header[0] >= 1 && header[3] >= 1 && header[3] <= 4) {
function getFontFileType(file, {
let fileType, fileSubtype;
if (isTrueTypeFile(file) || isTrueTypeCollectionFile(file)) {
fileType = composite ? "CIDFontType2" : "TrueType";
} else if (isOpenTypeFile(file)) {
fileType = composite ? "CIDFontType2" : "OpenType";
} else if (isType1File(file)) {
fileType = "CIDFontType0";
fileType = type === "MMType1" ? "MMType1" : "Type1";
} else if (isCFFFile(file)) {
fileType = "CIDFontType0";
fileSubtype = "CIDFontType0C";
fileType = type === "MMType1" ? "MMType1" : "Type1";
warn("getFontFileType: Unable to detect correct font file Type/Subtype.");
return [fileType, fileSubtype];
function applyStandardFontGlyphMap(map, glyphMap) {
for (const charCode in glyphMap) {
map[+charCode] = glyphMap[charCode];
function buildToFontChar(encoding, glyphsUnicodeMap, differences) {
for (let i = 0, ii = encoding.length; i < ii; i++) {
unicode = getUnicodeForGlyph(encoding[i], glyphsUnicodeMap);
for (const charCode in differences) {
unicode = getUnicodeForGlyph(differences[charCode], glyphsUnicodeMap);