Merge pull request #12099 from Snuffleupagus/hasBlendModes-RefSet
Use a `RefSet`, rather than a plain Object, for tracking already processed nodes in `PartialEvaluator.hasBlendModes`
This commit is contained in:
commit
7d26f4147f
@ -44,6 +44,7 @@ import {
|
||||
isStream,
|
||||
Name,
|
||||
Ref,
|
||||
RefSet,
|
||||
} from "./primitives.js";
|
||||
import {
|
||||
ErrorFont,
|
||||
@ -237,9 +238,9 @@ class PartialEvaluator {
|
||||
return false;
|
||||
}
|
||||
|
||||
var processed = Object.create(null);
|
||||
const processed = new RefSet();
|
||||
if (resources.objId) {
|
||||
processed[resources.objId] = true;
|
||||
processed.put(resources.objId);
|
||||
}
|
||||
|
||||
var nodes = [resources],
|
||||
@ -249,13 +250,10 @@ class PartialEvaluator {
|
||||
// First check the current resources for blend modes.
|
||||
var graphicStates = node.get("ExtGState");
|
||||
if (graphicStates instanceof Dict) {
|
||||
var graphicStatesKeys = graphicStates.getKeys();
|
||||
for (let i = 0, ii = graphicStatesKeys.length; i < ii; i++) {
|
||||
const key = graphicStatesKeys[i];
|
||||
|
||||
for (const key of graphicStates.getKeys()) {
|
||||
let graphicState = graphicStates.getRaw(key);
|
||||
if (graphicState instanceof Ref) {
|
||||
if (processed[graphicState.toString()]) {
|
||||
if (processed.has(graphicState)) {
|
||||
continue; // The ExtGState has already been processed.
|
||||
}
|
||||
try {
|
||||
@ -264,27 +262,18 @@ class PartialEvaluator {
|
||||
if (ex instanceof MissingDataException) {
|
||||
throw ex;
|
||||
}
|
||||
if (this.options.ignoreErrors) {
|
||||
if (graphicState instanceof Ref) {
|
||||
// Avoid parsing a corrupt ExtGState more than once.
|
||||
processed[graphicState.toString()] = true;
|
||||
}
|
||||
// Error(s) in the ExtGState -- sending unsupported feature
|
||||
// notification and allow parsing/rendering to continue.
|
||||
this.handler.send("UnsupportedFeature", {
|
||||
featureId: UNSUPPORTED_FEATURES.errorExtGState,
|
||||
});
|
||||
warn(`hasBlendModes - ignoring ExtGState: "${ex}".`);
|
||||
processed.put(graphicState);
|
||||
|
||||
info(`hasBlendModes - ignoring ExtGState: "${ex}".`);
|
||||
continue;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
if (!(graphicState instanceof Dict)) {
|
||||
continue;
|
||||
}
|
||||
if (graphicState.objId) {
|
||||
processed[graphicState.objId] = true;
|
||||
processed.put(graphicState.objId);
|
||||
}
|
||||
|
||||
const bm = graphicState.get("BM");
|
||||
@ -295,8 +284,8 @@ class PartialEvaluator {
|
||||
continue;
|
||||
}
|
||||
if (bm !== undefined && Array.isArray(bm)) {
|
||||
for (let j = 0, jj = bm.length; j < jj; j++) {
|
||||
if (bm[j] instanceof Name && bm[j].name !== "Normal") {
|
||||
for (const element of bm) {
|
||||
if (element instanceof Name && element.name !== "Normal") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -308,13 +297,10 @@ class PartialEvaluator {
|
||||
if (!(xObjects instanceof Dict)) {
|
||||
continue;
|
||||
}
|
||||
var xObjectsKeys = xObjects.getKeys();
|
||||
for (let i = 0, ii = xObjectsKeys.length; i < ii; i++) {
|
||||
const key = xObjectsKeys[i];
|
||||
|
||||
for (const key of xObjects.getKeys()) {
|
||||
var xObject = xObjects.getRaw(key);
|
||||
if (xObject instanceof Ref) {
|
||||
if (processed[xObject.toString()]) {
|
||||
if (processed.has(xObject)) {
|
||||
// The XObject has already been processed, and by avoiding a
|
||||
// redundant `xref.fetch` we can *significantly* reduce the load
|
||||
// time for badly generated PDF files (fixes issue6961.pdf).
|
||||
@ -326,41 +312,31 @@ class PartialEvaluator {
|
||||
if (ex instanceof MissingDataException) {
|
||||
throw ex;
|
||||
}
|
||||
if (this.options.ignoreErrors) {
|
||||
if (xObject instanceof Ref) {
|
||||
// Avoid parsing a corrupt XObject more than once.
|
||||
processed[xObject.toString()] = true;
|
||||
}
|
||||
// Error(s) in the XObject -- sending unsupported feature
|
||||
// notification and allow parsing/rendering to continue.
|
||||
this.handler.send("UnsupportedFeature", {
|
||||
featureId: UNSUPPORTED_FEATURES.errorXObject,
|
||||
});
|
||||
warn(`hasBlendModes - ignoring XObject: "${ex}".`);
|
||||
processed.put(xObject);
|
||||
|
||||
info(`hasBlendModes - ignoring XObject: "${ex}".`);
|
||||
continue;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
if (!isStream(xObject)) {
|
||||
continue;
|
||||
}
|
||||
if (xObject.dict.objId) {
|
||||
if (processed[xObject.dict.objId]) {
|
||||
continue; // Stream has objId and was processed already.
|
||||
}
|
||||
processed[xObject.dict.objId] = true;
|
||||
processed.put(xObject.dict.objId);
|
||||
}
|
||||
var xResources = xObject.dict.get("Resources");
|
||||
if (!(xResources instanceof Dict)) {
|
||||
continue;
|
||||
}
|
||||
// Checking objId to detect an infinite loop.
|
||||
if (
|
||||
xResources instanceof Dict &&
|
||||
(!xResources.objId || !processed[xResources.objId])
|
||||
) {
|
||||
if (xResources.objId && processed.has(xResources.objId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodes.push(xResources);
|
||||
if (xResources.objId) {
|
||||
processed[xResources.objId] = true;
|
||||
}
|
||||
processed.put(xResources.objId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user