diff --git a/src/canvas.js b/src/canvas.js index ef433ce8f..0b1bed490 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -407,6 +407,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { this.imageLayer = imageLayer; this.groupStack = []; this.processingType3 = null; + // Patterns are painted relative to the initial page/form transform, see pdf + // spec 8.7.2 NOTE 1. + this.baseTransform = null; + this.baseTransformStack = []; if (canvasCtx) { addContextCurrentTransform(canvasCtx); } @@ -509,6 +513,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { } var transform = viewport.transform; + this.baseTransform = transform.slice(); this.ctx.save(); this.ctx.transform.apply(this.ctx, transform); @@ -1318,7 +1323,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { color = base.getRgb(args, 0); } var pattern = new TilingPattern(IR, color, this.ctx, this.objs, - this.commonObjs); + this.commonObjs, this.baseTransform); } else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') { var pattern = Pattern.shadingFromIR(IR); } else { @@ -1453,10 +1458,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { bbox) { this.save(); this.current.paintFormXObjectDepth++; + this.baseTransformStack.push(this.baseTransform); if (matrix && isArray(matrix) && 6 == matrix.length) this.transform.apply(this, matrix); + this.baseTransform = this.ctx.mozCurrentTransform; + if (bbox && isArray(bbox) && 4 == bbox.length) { var width = bbox[2] - bbox[0]; var height = bbox[3] - bbox[1]; @@ -1473,6 +1481,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { // some pdf don't close all restores inside object // closing those for them } while (this.current.paintFormXObjectDepth >= depth); + this.baseTransform = this.baseTransformStack.pop(); }, beginGroup: function CanvasGraphics_beginGroup(group) { diff --git a/src/pattern.js b/src/pattern.js index af0489945..6f7db2722 100644 --- a/src/pattern.js +++ b/src/pattern.js @@ -271,7 +271,7 @@ var TilingPattern = (function TilingPatternClosure() { var MAX_PATTERN_SIZE = 8192; - function TilingPattern(IR, color, ctx, objs, commonObjs) { + function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) { this.name = IR[1][0].name; this.operatorList = IR[2]; this.matrix = IR[3] || [1, 0, 0, 1, 0, 0]; @@ -283,7 +283,7 @@ var TilingPattern = (function TilingPatternClosure() { this.color = color; this.objs = objs; this.commonObjs = commonObjs; - this.curMatrix = ctx.mozCurrentTransform; + this.baseTransform = baseTransform; this.type = 'Pattern'; this.ctx = ctx; } @@ -328,7 +328,8 @@ var TilingPattern = (function TilingPatternClosure() { // Obtain scale from matrix and current transformation matrix. var matrixScale = Util.singularValueDecompose2dScale(this.matrix); - var curMatrixScale = Util.singularValueDecompose2dScale(this.curMatrix); + var curMatrixScale = Util.singularValueDecompose2dScale( + this.baseTransform); var combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]]; @@ -412,7 +413,7 @@ var TilingPattern = (function TilingPatternClosure() { this.createPatternCanvas(temporaryPatternCanvas); var ctx = this.ctx; - ctx.setTransform.apply(ctx, this.curMatrix); + ctx.setTransform.apply(ctx, this.baseTransform); ctx.transform.apply(ctx, this.matrix); this.scaleToContext(); diff --git a/test/pdfs/issue3458.pdf b/test/pdfs/issue3458.pdf new file mode 100644 index 000000000..86c68a812 Binary files /dev/null and b/test/pdfs/issue3458.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 66bf4630f..298cb09ba 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -935,6 +935,13 @@ "type": "eq", "about": "Rotated transparency group with blend mode." }, + { "id": "issue3458.pdf", + "file": "pdfs/issue3458.pdf", + "md5": "dab8bd3ad1acfc8dc82a8381a3c8ff94", + "rounds": 1, + "type": "eq", + "about": "Pattern with current transform different than base transform." + }, { "id": "issue2462", "file": "pdfs/issue2462.pdf", "md5": "d4e3dddfdd35464c71cf0310bff29b42",