diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 3896ed47e..6383ad556 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -2007,9 +2007,8 @@ class PartialEvaluator { localColorSpaceCache, }) .then(function (colorSpace) { - if (colorSpace) { - stateManager.state.fillColorSpace = colorSpace; - } + stateManager.state.fillColorSpace = + colorSpace || ColorSpace.singletons.gray; }) ); return; @@ -2033,9 +2032,8 @@ class PartialEvaluator { localColorSpaceCache, }) .then(function (colorSpace) { - if (colorSpace) { - stateManager.state.strokeColorSpace = colorSpace; - } + stateManager.state.strokeColorSpace = + colorSpace || ColorSpace.singletons.gray; }) ); return; @@ -2079,7 +2077,12 @@ class PartialEvaluator { args = ColorSpace.singletons.rgb.getRgb(args, 0); break; case OPS.setFillColorN: - cs = stateManager.state.fillColorSpace; + cs = stateManager.state.patternFillColorSpace; + if (!cs) { + args = []; + fn = OPS.setFillTransparent; + break; + } if (cs.name === "Pattern") { next( self.handleColorN( @@ -2101,7 +2104,12 @@ class PartialEvaluator { fn = OPS.setFillRGBColor; break; case OPS.setStrokeColorN: - cs = stateManager.state.strokeColorSpace; + cs = stateManager.state.patternStrokeColorSpace; + if (!cs) { + args = []; + fn = OPS.setStrokeTransparent; + break; + } if (cs.name === "Pattern") { next( self.handleColorN( @@ -4873,8 +4881,26 @@ class EvalState { this.ctm = new Float32Array(IDENTITY_MATRIX); this.font = null; this.textRenderingMode = TextRenderingMode.FILL; - this.fillColorSpace = ColorSpace.singletons.gray; - this.strokeColorSpace = ColorSpace.singletons.gray; + this._fillColorSpace = ColorSpace.singletons.gray; + this._strokeColorSpace = ColorSpace.singletons.gray; + this.patternFillColorSpace = null; + this.patternStrokeColorSpace = null; + } + + get fillColorSpace() { + return this._fillColorSpace; + } + + set fillColorSpace(colorSpace) { + this._fillColorSpace = this.patternFillColorSpace = colorSpace; + } + + get strokeColorSpace() { + return this._strokeColorSpace; + } + + set strokeColorSpace(colorSpace) { + this._strokeColorSpace = this.patternStrokeColorSpace = colorSpace; } clone() { diff --git a/src/display/canvas.js b/src/display/canvas.js index 247870f3b..5c0b05500 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -2386,15 +2386,24 @@ class CanvasGraphics { } setStrokeRGBColor(r, g, b) { - const color = Util.makeHexColor(r, g, b); - this.ctx.strokeStyle = color; - this.current.strokeColor = color; + this.ctx.strokeStyle = this.current.strokeColor = Util.makeHexColor( + r, + g, + b + ); + } + + setStrokeTransparent() { + this.ctx.strokeStyle = this.current.strokeColor = "transparent"; } setFillRGBColor(r, g, b) { - const color = Util.makeHexColor(r, g, b); - this.ctx.fillStyle = color; - this.current.fillColor = color; + this.ctx.fillStyle = this.current.fillColor = Util.makeHexColor(r, g, b); + this.current.patternFill = false; + } + + setFillTransparent() { + this.ctx.fillStyle = this.current.fillColor = "transparent"; this.current.patternFill = false; } diff --git a/src/shared/util.js b/src/shared/util.js index 292a66f52..8d2cad1a1 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -342,6 +342,8 @@ const OPS = { paintImageMaskXObjectRepeat: 89, paintSolidColorImageMask: 90, constructPath: 91, + setStrokeTransparent: 92, + setFillTransparent: 93, }; const PasswordResponses = { diff --git a/test/pdfs/issue18466.pdf.link b/test/pdfs/issue18466.pdf.link new file mode 100644 index 000000000..5004030f9 --- /dev/null +++ b/test/pdfs/issue18466.pdf.link @@ -0,0 +1 @@ +https://github.com/user-attachments/files/16319966/image2.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 5f1edf372..9270359ff 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -10170,5 +10170,13 @@ "firstPage": 1, "lastPage": 1, "type": "eq" + }, + { + "id": "issue18466", + "file": "pdfs/issue18466.pdf", + "md5": "251197bf19b237e084551d19f885c6b6", + "rounds": 1, + "link": true, + "type": "eq" } ]