Merge pull request #14825 from Snuffleupagus/issue-14824

Ensure that worker-thread image caching doesn't break optional content (issue 14824)
This commit is contained in:
Tim van der Meij 2022-04-23 13:19:56 +02:00 committed by GitHub
commit 752dee5caa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 78 additions and 33 deletions

View File

@ -592,12 +592,8 @@ class PartialEvaluator {
resources
);
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
}
const imageMask = dict.get("IM", "ImageMask") || false;
const interpolate = dict.get("I", "Interpolate");
let imgData, args;
if (imageMask) {
// This depends on a tmpCanvas being filled with the
@ -605,6 +601,7 @@ class PartialEvaluator {
// data can't be done here. Instead of creating a
// complete PDFImage, only read the information needed
// for later.
const interpolate = dict.get("I", "Interpolate");
const bitStrideLength = (w + 7) >> 3;
const imgArray = image.getBytes(
bitStrideLength * h,
@ -625,17 +622,19 @@ class PartialEvaluator {
imgData.cached = !!cacheKey;
args = [imgData];
operatorList.addOp(OPS.paintImageMaskXObject, args);
operatorList.addImageOps(
OPS.paintImageMaskXObject,
args,
optionalContent
);
if (cacheKey) {
localImageCache.set(cacheKey, imageRef, {
fn: OPS.paintImageMaskXObject,
args,
optionalContent,
});
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
return;
}
@ -651,17 +650,19 @@ class PartialEvaluator {
if (imgData.isSingleOpaquePixel) {
// Handles special case of mainly LaTeX documents which use image
// masks to draw lines with the current fill style.
operatorList.addOp(OPS.paintSolidColorImageMask, []);
operatorList.addImageOps(
OPS.paintSolidColorImageMask,
[],
optionalContent
);
if (cacheKey) {
localImageCache.set(cacheKey, imageRef, {
fn: OPS.paintSolidColorImageMask,
args: [],
optionalContent,
});
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
return;
}
@ -678,18 +679,19 @@ class PartialEvaluator {
count: 1,
},
];
operatorList.addImageOps(
OPS.paintImageMaskXObject,
args,
optionalContent
);
operatorList.addOp(OPS.paintImageMaskXObject, args);
if (cacheKey) {
localImageCache.set(cacheKey, imageRef, {
fn: OPS.paintImageMaskXObject,
args,
optionalContent,
});
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
return;
}
@ -710,11 +712,11 @@ class PartialEvaluator {
// We force the use of RGBA_32BPP images here, because we can't handle
// any other kind.
imgData = imageObj.createImageData(/* forceRGBA = */ true);
operatorList.addOp(OPS.paintInlineImageXObject, [imgData]);
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
operatorList.addImageOps(
OPS.paintInlineImageXObject,
[imgData],
optionalContent
);
return;
}
@ -762,11 +764,13 @@ class PartialEvaluator {
return this._sendImgData(objId, /* imgData = */ null, cacheGlobally);
});
operatorList.addOp(OPS.paintImageXObject, args);
operatorList.addImageOps(OPS.paintImageXObject, args, optionalContent);
if (cacheKey) {
localImageCache.set(cacheKey, imageRef, {
fn: OPS.paintImageXObject,
args,
optionalContent,
});
if (imageRef) {
@ -778,15 +782,12 @@ class PartialEvaluator {
objId,
fn: OPS.paintImageXObject,
args,
optionalContent,
byteSize: 0, // Temporary entry, note `addByteSize` above.
});
}
}
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
}
handleSMask(
@ -1700,7 +1701,12 @@ class PartialEvaluator {
if (isValidName) {
const localImage = localImageCache.getByName(name);
if (localImage) {
operatorList.addOp(localImage.fn, localImage.args);
operatorList.addImageOps(
localImage.fn,
localImage.args,
localImage.optionalContent
);
if (
localImage.fn === OPS.paintImageMaskXObject &&
localImage.args[0] &&
@ -1723,7 +1729,12 @@ class PartialEvaluator {
if (xobj instanceof Ref) {
const localImage = localImageCache.getByRef(xobj);
if (localImage) {
operatorList.addOp(localImage.fn, localImage.args);
operatorList.addImageOps(
localImage.fn,
localImage.args,
localImage.optionalContent
);
if (
localImage.fn === OPS.paintImageMaskXObject &&
localImage.args[0] &&
@ -1741,7 +1752,11 @@ class PartialEvaluator {
);
if (globalImage) {
operatorList.addDependency(globalImage.objId);
operatorList.addOp(globalImage.fn, globalImage.args);
operatorList.addImageOps(
globalImage.fn,
globalImage.args,
globalImage.optionalContent
);
resolveXObject();
return;
@ -1846,7 +1861,12 @@ class PartialEvaluator {
if (cacheKey) {
const localImage = localImageCache.getByName(cacheKey);
if (localImage) {
operatorList.addOp(localImage.fn, localImage.args);
operatorList.addImageOps(
localImage.fn,
localImage.args,
localImage.optionalContent
);
if (
localImage.fn === OPS.paintImageMaskXObject &&
localImage.args[0] &&

View File

@ -622,6 +622,18 @@ class OperatorList {
}
}
addImageOps(fn, args, optionalContent) {
if (optionalContent !== undefined) {
this.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
}
this.addOp(fn, args);
if (optionalContent !== undefined) {
this.addOp(OPS.endMarkedContent, []);
}
}
addDependency(dependency) {
if (this.dependencies.has(dependency)) {
return;

View File

@ -0,0 +1 @@
https://github.com/mozilla/pdf.js/files/8540275/PDF.pdf

View File

@ -2965,6 +2965,18 @@
"annotations": true,
"about": "LinkAnnotation with a relative link, and a /Catalog Base-URI."
},
{ "id": "issue14824",
"file": "pdfs/issue14824.pdf",
"md5": "7b8d061ab0a342e3606a3b3ba1925d5b",
"rounds": 1,
"link": true,
"lastPage": 4,
"type": "eq",
"optionalContent": {
"7R": false
},
"about": "Need to test *at least* three pages, since the `GlobalImageCache` is involved."
},
{ "id": "issue1127-text",
"file": "pdfs/issue1127.pdf",
"md5": "4fb2be5ffefeafda4ba977de2a1bb4d8",