diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 84cce0b28a9a2..f22f75a8bfa02 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -175,7 +175,7 @@ function addLocallyCachedImageOps(opList, data) { if (data.objId) { opList.addDependency(data.objId); } - opList.addImageOps(data.fn, data.args, data.optionalContent); + opList.addImageOps(data.fn, data.args, data.optionalContent, data.hasMask); if (data.fn === OPS.paintImageMaskXObject && data.args[0]?.count > 0) { data.args[0].count++; @@ -730,13 +730,9 @@ class PartialEvaluator { } const SMALL_IMAGE_DIMENSIONS = 200; + const hasMask = dict.has("SMask") || dict.has("Mask"); // Inlining small images into the queue as RGB data - if ( - isInline && - w + h < SMALL_IMAGE_DIMENSIONS && - !dict.has("SMask") && - !dict.has("Mask") - ) { + if (isInline && w + h < SMALL_IMAGE_DIMENSIONS && !hasMask) { try { const imageObj = new PDFImage({ xref: this.xref, @@ -793,7 +789,12 @@ class PartialEvaluator { // Ensure that the dependency is added before the image is decoded. operatorList.addDependency(objId); args = [objId, w, h]; - operatorList.addImageOps(OPS.paintImageXObject, args, optionalContent); + operatorList.addImageOps( + OPS.paintImageXObject, + args, + optionalContent, + hasMask + ); if (cacheGlobally) { if (this.globalImageCache.hasDecodeFailed(imageRef)) { @@ -802,6 +803,7 @@ class PartialEvaluator { fn: OPS.paintImageXObject, args, optionalContent, + hasMask, byteSize: 0, // Data is `null`, since decoding failed previously. }); @@ -812,7 +814,7 @@ class PartialEvaluator { // For large (at least 500x500) or more complex images that we'll cache // globally, check if the image is still cached locally on the main-thread // to avoid having to re-parse the image (since that can be slow). - if (w * h > 250000 || dict.has("SMask") || dict.has("Mask")) { + if (w * h > 250000 || hasMask) { const localLength = await this.handler.sendWithPromise("commonobj", [ objId, "CopyLocalImage", @@ -825,6 +827,7 @@ class PartialEvaluator { fn: OPS.paintImageXObject, args, optionalContent, + hasMask, byteSize: 0, // Temporary entry, to avoid `setData` returning early. }); this.globalImageCache.addByteSize(imageRef, localLength); @@ -872,6 +875,7 @@ class PartialEvaluator { fn: OPS.paintImageXObject, args, optionalContent, + hasMask, }; localImageCache.set(cacheKey, imageRef, cacheData); @@ -884,6 +888,7 @@ class PartialEvaluator { fn: OPS.paintImageXObject, args, optionalContent, + hasMask, byteSize: 0, // Temporary entry, note `addByteSize` above. }); } @@ -1814,7 +1819,8 @@ class PartialEvaluator { operatorList.addImageOps( globalImage.fn, globalImage.args, - globalImage.optionalContent + globalImage.optionalContent, + globalImage.hasMask ); resolveXObject(); diff --git a/src/core/operator_list.js b/src/core/operator_list.js index 2fdc1bb9179e3..1212e6e939461 100644 --- a/src/core/operator_list.js +++ b/src/core/operator_list.js @@ -636,7 +636,11 @@ class OperatorList { } } - addImageOps(fn, args, optionalContent) { + addImageOps(fn, args, optionalContent, hasMask = false) { + if (hasMask) { + this.addOp(OPS.save); + this.addOp(OPS.setGState, [[["SMask", false]]]); + } if (optionalContent !== undefined) { this.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]); } @@ -646,6 +650,9 @@ class OperatorList { if (optionalContent !== undefined) { this.addOp(OPS.endMarkedContent, []); } + if (hasMask) { + this.addOp(OPS.restore); + } } addDependency(dependency) { diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index e619579ba44ec..b9b4efbd2fc69 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -232,6 +232,7 @@ !issue5954.pdf !issue6612.pdf !alphatrans.pdf +!issue14200.pdf !pattern_text_embedded_font.pdf !devicen.pdf !cmykjpeg.pdf diff --git a/test/pdfs/issue14200.pdf b/test/pdfs/issue14200.pdf new file mode 100644 index 0000000000000..1c8d1d6f2c0d4 Binary files /dev/null and b/test/pdfs/issue14200.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 966f9f183b420..6dd3446ed4cfc 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -5255,6 +5255,13 @@ "link": true, "type": "eq" }, + { + "id": "issue14200", + "file": "pdfs/issue14200.pdf", + "md5": "4dba2cde1c6e65abe53e66eefc97a7f1", + "rounds": 1, + "type": "eq" + }, { "id": "jbig2_huffman_1", "file": "pdfs/jbig2_huffman_1.pdf",