: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
localImageCache.set(cacheKey, imageRef, cacheData);
this._regionalImageCache.set(null, imageRef, cacheData);
this.globalImageCache.setData(imageRef, {
fn: OPS.paintImageXObject,
handleSMask(smask, resources, operatorList, task, stateManager, localColorSpaceCache) {
const smaskContent = smask.get("G");
subtype: smask.get("S").name,
backdrop: smask.get("BC")
const transferObj = smask.get("TR");
if (isPDFFunction(transferObj)) {
const transferFn = this._pdfFunctionFactory.create(transferObj);
const transferMap = new Uint8Array(256);
const tmp = new Float32Array(1);
for (let i = 0; i < 256; i++) {
transferFn(tmp, 0, tmp, 0);
transferMap[i] = tmp[0] * 255 | 0;
smaskOptions.transferMap = transferMap;
return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone(), localColorSpaceCache);
handleTransferFunction(tr) {
} else if (isPDFFunction(tr)) {
for (const entry of transferArray) {
const transferObj = this.xref.fetchIfRef(entry);
if (isName(transferObj, "Identity")) {
} else if (!isPDFFunction(transferObj)) {
const transferFn = this._pdfFunctionFactory.create(transferObj);
const transferMap = new Uint8Array(256),
tmp = new Float32Array(1);
for (let j = 0; j < 256; j++) {
transferFn(tmp, 0, tmp, 0);
transferMap[j] = tmp[0] * 255 | 0;
transferMaps.push(transferMap);
if (!(numFns === 1 || numFns === 4)) {
if (numEffectfulFns === 0) {
handleTilingType(fn, color, resources, pattern, patternDict, operatorList, task, localTilingPatternCache) {
const tilingOpList = new OperatorList();
const patternResources = Dict.merge({
dictArray: [patternDict.get("Resources"), resources]
return this.getOperatorList({
resources: patternResources,
operatorList: tilingOpList
const operatorListIR = tilingOpList.getIR();
const tilingPatternIR = getTilingPatternIR(operatorListIR, patternDict, color);
operatorList.addDependencies(tilingOpList.dependencies);
operatorList.addOp(fn, tilingPatternIR);
localTilingPatternCache.set(null, patternDict.objId, {
if (reason instanceof AbortException) {
if (this.options.ignoreErrors) {
warn(`handleTilingType - ignoring pattern: "${reason}".`);
async handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null, cssFontInfo = null) {
const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null;
let translated = await this.loadFont(fontName, fontRef, resources, fallbackFontDict, cssFontInfo);
if (translated.font.isType3Font) {
await translated.loadType3Data(this, resources, task);
operatorList.addDependencies(translated.type3Dependencies);
translated = new TranslatedFont({
loadedName: "g_font_error",
font: new ErrorFont(`Type3 font load error: ${reason}`),
evaluatorOptions: this.options
state.font = translated.font;
translated.send(this.handler);
return translated.loadedName;
handleText(chars, state) {
const glyphs = font.charsToGlyphs(chars);
const isAddToPathSet = !!(state.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);
if (isAddToPathSet || state.fillColorSpace.name === "Pattern" || font.disableFontFace || this.options.disableFontFace) {
PartialEvaluator.buildFontPaths(font, glyphs, this.handler, this.options);
const reason = new FormatError("Missing setFont (Tf) operator before text rendering operator.");
if (this.options.ignoreErrors) {
warn(`ensureStateFont: "${reason}".`);
const gStateRef = gState.objId;
let isSimpleGState = true;
let promise = Promise.resolve();
for (const key of gState.getKeys()) {
const value = gState.get(key);
gStateObj.push([key, value]);
promise = promise.then(() => this.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) {
operatorList.addDependency(loadedName);
gStateObj.push([key, [loadedName, value[1]]]);
gStateObj.push([key, normalizeBlendMode(value)]);
if (isName(value, "None")) {
gStateObj.push([key, false]);
if (value instanceof Dict) {
promise = promise.then(() => this.handleSMask(value, resources, operatorList, task, stateManager, localColorSpaceCache));
gStateObj.push([key, true]);
warn("Unsupported SMask type");
const transferMaps = this.handleTransferFunction(value);
gStateObj.push([key, transferMaps]);
info("graphic state operator " + key);
info("Unknown graphic state operator " + key);
if (gStateObj.length > 0) {
operatorList.addOp(OPS.setGState, [gStateObj]);
localGStateCache.set(cacheKey, gStateRef, gStateObj);
loadFont(fontName, font, resources, fallbackFontDict = null, cssFontInfo = null) {
const errorFont = async () => {
return new TranslatedFont({
loadedName: "g_font_error",
font: new ErrorFont(`Font "${fontName}" is not available.`),
evaluatorOptions: this.options
if (font instanceof Ref) {
const fontRes = resources.get("Font");
fontRef = fontRes.getRaw(fontName);
if (this.type3FontRefs?.has(fontRef)) {
if (this.fontCache.has(fontRef)) {
return this.fontCache.get(fontRef);
font = this.xref.fetchIfRef(fontRef);
warn(`loadFont - lookup failed: "${ex}".`);
if (!(font instanceof Dict)) {
if (!this.options.ignoreErrors && !this.parsingType3Font) {
warn(`Font "${fontName}" is not available.`);
warn(`Font "${fontName}" is not available -- attempting to fallback to a default font.`);
font = fallbackFontDict || PartialEvaluator.fallbackFontDict;
if (font.cacheKey && this.fontCache.has(font.cacheKey)) {
return this.fontCache.get(font.cacheKey);
} = Promise.withResolvers();
preEvaluatedFont = this.preEvaluateFont(font);
preEvaluatedFont.cssFontInfo = cssFontInfo;
warn(`loadFont - preEvaluateFont failed: "${reason}".`);
const fontRefIsRef = fontRef instanceof Ref;
if (hash && descriptor instanceof Dict) {
const fontAliases = descriptor.fontAliases ||= Object.create(null);
const aliasFontRef = fontAliases[hash].aliasRef;
if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) {
this.fontCache.putAlias(fontRef, aliasFontRef);
return this.fontCache.get(fontRef);
fontID: this.idFactory.createFontId()
fontAliases[hash].aliasRef = fontRef;
fontID = fontAliases[hash].fontID;
fontID = this.idFactory.createFontId();
assert(fontID?.startsWith("f"), 'The "fontID" must be (correctly) defined.');
this.fontCache.put(fontRef, promise);
font.cacheKey = `cacheKey_${fontID}`;
this.fontCache.put(font.cacheKey, promise);
font.loadedName = `${this.idFactory.getDocId()}_${fontID}`;
this.translateFont(preEvaluatedFont).then(translatedFont => {
resolve(new TranslatedFont({
loadedName: font.loadedName,
evaluatorOptions: this.options
warn(`loadFont - translateFont failed: "${reason}".`);
resolve(new TranslatedFont({
loadedName: font.loadedName,
font: new ErrorFont(reason instanceof Error ? reason.message : reason),
evaluatorOptions: this.options
buildPath(operatorList, fn, args, parsingText = false) {
const lastIndex = operatorList.length - 1;
if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== OPS.constructPath) {
warn(`Encountered path operator "${fn}" inside of a text object.`);
operatorList.addOp(OPS.save, null);
const x = args[0] + args[2];
const y = args[1] + args[3];
minMax = [Math.min(args[0], x), Math.min(args[1], y), Math.max(args[0], x), Math.max(args[1], y)];
minMax = [args[0], args[1], args[0], args[1]];
minMax = [Infinity, Infinity, -Infinity, -Infinity];
operatorList.addOp(OPS.constructPath, [[fn], args, minMax]);
operatorList.addOp(OPS.restore, null);
const opArgs = operatorList.argsArray[lastIndex];
const minMax = opArgs[2];
const x = args[0] + args[2];
const y = args[1] + args[3];
minMax[0] = Math.min(minMax[0], args[0], x);
minMax[1] = Math.min(minMax[1], args[1], y);
minMax[2] = Math.max(minMax[2], args[0], x);
minMax[3] = Math.max(minMax[3], args[1], y);
minMax[0] = Math.min(minMax[0], args[0]);
minMax[1] = Math.min(minMax[1], args[1]);
minMax[2] = Math.max(minMax[2], args[0]);
minMax[3] = Math.max(minMax[3], args[1]);
return ColorSpace.parseAsync({
pdfFunctionFactory: this._pdfFunctionFactory,
if (reason instanceof AbortException) {
if (this.options.ignoreErrors) {
warn(`parseColorSpace - ignoring ColorSpace: "${reason}".`);
let id = localShadingPatternCache.get(shading);
const shadingFill = Pattern.parseShading(shading, this.xref, resources, this._pdfFunctionFactory, localColorSpaceCache);
patternIR = shadingFill.getIR();
if (reason instanceof AbortException) {
if (this.options.ignoreErrors) {
warn(`parseShading - ignoring shading: "${reason}".`);
localShadingPatternCache.set(shading, null);
id = `pattern_${this.idFactory.createObjId()}`;
if (this.parsingType3Font) {
id = `${this.idFactory.getDocId()}_type3_${id}`;
localShadingPatternCache.set(shading, id);
if (this.parsingType3Font) {
this.handler.send("commonobj", [id, "Pattern", patternIR]);
this.handler.send("obj", [id, this.pageIndex, "Pattern", patternIR]);
handleColorN(operatorList, fn, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache) {
const patternName = args.pop();
if (patternName instanceof Name) {
const rawPattern = patterns.getRaw(patternName.name);
const localTilingPattern = rawPattern instanceof Ref && localTilingPatternCache.getByRef(rawPattern);
if (localTilingPattern) {
const color = cs.base ? cs.base.getRgb(args, 0) : null;
const tilingPatternIR = getTilingPatternIR(localTilingPattern.operatorListIR, localTilingPattern.dict, color);
operatorList.addOp(fn, tilingPatternIR);
const pattern = this.xref.fetchIfRef(rawPattern);
const dict = pattern instanceof BaseStream ? pattern.dict : pattern;
const typeNum = dict.get("PatternType");
if (typeNum === PatternType.TILING) {
const color = cs.base ? cs.base.getRgb(args, 0) : null;
return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task, localTilingPatternCache);
} else if (typeNum === PatternType.SHADING) {
const shading = dict.get("Shading");
const objId = this.parseShading({
const matrix = lookupMatrix(dict.getArray("Matrix"), null);
operatorList.addOp(fn, ["Shading", objId, matrix]);
throw new FormatError(`Unknown PatternType: ${typeNum}`);
throw new FormatError(`Unknown PatternName: ${patternName}`);
_parseVisibilityExpression(array, nestingCounter, currentResult) {
if (++nestingCounter > MAX_NESTING) {
warn("Visibility expression is too deeply nested");