: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (!(fontName instanceof Name)) {
throw new FormatError("invalid font name");
let fontFile, subtype, length1, length2, length3;
fontFile = descriptor.get("FontFile", "FontFile2", "FontFile3");
if (!this.options.ignoreErrors) {
warn(`translateFont - fetching "${fontName.name}" font file: "${ex}".`);
fontFile = new NullStream();
let isInternalFont = false;
let glyphScaleFactors = null;
let systemFontInfo = null;
const subtypeEntry = fontFile.dict.get("Subtype");
if (subtypeEntry instanceof Name) {
subtype = subtypeEntry.name;
length1 = fontFile.dict.get("Length1");
length2 = fontFile.dict.get("Length2");
length3 = fontFile.dict.get("Length3");
} else if (cssFontInfo) {
const standardFontName = getXfaFontName(fontName.name);
cssFontInfo.fontFamily = `${cssFontInfo.fontFamily}-PdfJS-XFA`;
cssFontInfo.metrics = standardFontName.metrics || null;
glyphScaleFactors = standardFontName.factors || null;
fontFile = await this.fetchStandardFontData(standardFontName.name);
isInternalFont = !!fontFile;
baseDict = dict = getXfaFontDict(fontName.name);
} else if (!isType3Font) {
const standardFontName = getStandardFontName(fontName.name);
fontFile = await this.fetchStandardFontData(standardFontName);
isInternalFont = !!fontFile;
if (!isInternalFont && this.options.useSystemFonts) {
systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, fontName.name, standardFontName, type);
const fontMatrix = lookupMatrix(dict.getArray("FontMatrix"), FONT_IDENTITY_MATRIX);
const bbox = lookupNormalRect(descriptor.getArray("FontBBox") || dict.getArray("FontBBox"), undefined);
let ascent = descriptor.get("Ascent");
if (typeof ascent !== "number") {
let descent = descriptor.get("Descent");
if (typeof descent !== "number") {
let xHeight = descriptor.get("XHeight");
if (typeof xHeight !== "number") {
let capHeight = descriptor.get("CapHeight");
if (typeof capHeight !== "number") {
let flags = descriptor.get("Flags");
if (!Number.isInteger(flags)) {
let italicAngle = descriptor.get("ItalicAngle");
if (typeof italicAngle !== "number") {
loadedName: baseDict.loadedName,
scaleFactors: glyphScaleFactors,
const cidEncoding = baseDict.get("Encoding");
if (cidEncoding instanceof Name) {
properties.cidEncoding = cidEncoding.name;
const cMap = await CMapFactory.create({
fetchBuiltInCMap: this._fetchBuiltInCMapBound,
properties.vertical = properties.cMap.vertical;
const newProperties = await this.extractDataStructures(dict, properties);
this.extractWidths(dict, descriptor, newProperties);
return new Font(fontName.name, fontFile, newProperties);
static buildFontPaths(font, glyphs, handler, evaluatorOptions) {
function buildPath(fontChar) {
const glyphName = `${font.loadedName}_path_${fontChar}`;
if (font.renderer.hasBuiltPath(fontChar)) {
handler.send("commonobj", [glyphName, "FontPath", font.renderer.getPathJs(fontChar)]);
if (evaluatorOptions.ignoreErrors) {
warn(`buildFontPaths - ignoring ${glyphName} glyph: "${reason}".`);
for (const glyph of glyphs) {
buildPath(glyph.fontChar);
const accent = glyph.accent;
buildPath(accent.fontChar);
static get fallbackFontDict() {
dict.set("BaseFont", Name.get("Helvetica"));
dict.set("Type", Name.get("FallbackType"));
dict.set("Subtype", Name.get("FallbackType"));
dict.set("Encoding", Name.get("WinAnsiEncoding"));
return shadow(this, "fallbackFontDict", dict);
this.loadedName = loadedName;
this._evaluatorOptions = evaluatorOptions || DefaultPartialEvaluatorOptions;
this.type3Dependencies = font.isType3Font ? new Set() : null;
handler.send("commonobj", [this.loadedName, "Font", this.font.exportData(this._evaluatorOptions.fontExtraProperties)]);
this.font.disableFontFace = true;
PartialEvaluator.buildFontPaths(this.font, this.font.glyphCacheValues, handler, this._evaluatorOptions);
loadType3Data(evaluator, resources, task) {
if (!this.font.isType3Font) {
throw new Error("Must be a Type3 font.");
const type3Evaluator = evaluator.clone({
const type3FontRefs = new RefSet(evaluator.type3FontRefs);
if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) {
type3FontRefs.put(this.dict.objId);
type3Evaluator.type3FontRefs = type3FontRefs;
const translatedFont = this.font,
type3Dependencies = this.type3Dependencies;
let loadCharProcsPromise = Promise.resolve();
const charProcs = this.dict.get("CharProcs");
const fontResources = this.dict.get("Resources") || resources;
const charProcOperatorList = Object.create(null);
const fontBBox = Util.normalizeRect(translatedFont.bbox || [0, 0, 0, 0]),
width = fontBBox[2] - fontBBox[0],
height = fontBBox[3] - fontBBox[1];
const fontBBoxSize = Math.hypot(width, height);
for (const key of charProcs.getKeys()) {
loadCharProcsPromise = loadCharProcsPromise.then(() => {
const glyphStream = charProcs.get(key);
const operatorList = new OperatorList();
return type3Evaluator.getOperatorList({
resources: fontResources,
if (operatorList.fnArray[0] === OPS.setCharWidthAndBounds) {
this._removeType3ColorOperators(operatorList, fontBBoxSize);
charProcOperatorList[key] = operatorList.getIR();
for (const dependency of operatorList.dependencies) {
type3Dependencies.add(dependency);
}).catch(function (reason) {
warn(`Type3 font resource "${key}" is not available.`);
const dummyOperatorList = new OperatorList();
charProcOperatorList[key] = dummyOperatorList.getIR();
this.type3Loaded = loadCharProcsPromise.then(() => {
translatedFont.charProcOperatorList = charProcOperatorList;
translatedFont.isCharBBox = true;
translatedFont.bbox = this._bbox;
_removeType3ColorOperators(operatorList, fontBBoxSize = NaN) {
const charBBox = Util.normalizeRect(operatorList.argsArray[0].slice(2)),
width = charBBox[2] - charBBox[0],
height = charBBox[3] - charBBox[1];
const charBBoxSize = Math.hypot(width, height);
if (width === 0 || height === 0) {
operatorList.fnArray.splice(0, 1);
operatorList.argsArray.splice(0, 1);
} else if (fontBBoxSize === 0 || Math.round(charBBoxSize / fontBBoxSize) >= 10) {
this._bbox = [Infinity, Infinity, -Infinity, -Infinity];
this._bbox[0] = Math.min(this._bbox[0], charBBox[0]);
this._bbox[1] = Math.min(this._bbox[1], charBBox[1]);
this._bbox[2] = Math.max(this._bbox[2], charBBox[2]);
this._bbox[3] = Math.max(this._bbox[3], charBBox[3]);
ii = operatorList.length;
switch (operatorList.fnArray[i]) {
case OPS.setCharWidthAndBounds:
case OPS.setStrokeColorSpace:
case OPS.setFillColorSpace:
case OPS.setStrokeColorN:
case OPS.setStrokeRGBColor:
case OPS.setFillRGBColor:
case OPS.setStrokeCMYKColor:
case OPS.setFillCMYKColor:
case OPS.setRenderingIntent:
operatorList.fnArray.splice(i, 1);
operatorList.argsArray.splice(i, 1);
const [gStateObj] = operatorList.argsArray[i];
const [gStateKey] = gStateObj[j];
constructor(initialState = new EvalState()) {
this.state = initialState;
this.stateStack.push(this.state);
this.state = old.clone();
const prev = this.stateStack.pop();
this.state.ctm = Util.transform(this.state.ctm, args);
this.ctm = new Float32Array(IDENTITY_MATRIX);
this.fontMatrix = FONT_IDENTITY_MATRIX;
this.textMatrix = IDENTITY_MATRIX.slice();
this.textLineMatrix = IDENTITY_MATRIX.slice();
setTextMatrix(a, b, c, d, e, f) {
const m = this.textMatrix;
setTextLineMatrix(a, b, c, d, e, f) {
const m = this.textLineMatrix;
translateTextMatrix(x, y) {
const m = this.textMatrix;
m[4] = m[0] * x + m[2] * y + m[4];
m[5] = m[1] * x + m[3] * y + m[5];
translateTextLineMatrix(x, y) {
const m = this.textLineMatrix;
m[4] = m[0] * x + m[2] * y + m[4];
m[5] = m[1] * x + m[3] * y + m[5];
this.translateTextLineMatrix(0, -this.leading);
this.textMatrix = this.textLineMatrix.slice();
const clone = Object.create(this);
clone.textMatrix = this.textMatrix.slice();
clone.textLineMatrix = this.textLineMatrix.slice();
clone.fontMatrix = this.fontMatrix.slice();
this.ctm = new Float32Array(IDENTITY_MATRIX);
this.textRenderingMode = TextRenderingMode.FILL;
this.fillColorSpace = ColorSpace.singletons.gray;
this.strokeColorSpace = ColorSpace.singletons.gray;
return Object.create(this);
class EvaluatorPreprocessor {
return shadow(this, "opMap", Object.assign(Object.create(null), {
id: OPS.setRenderingIntent,