From a72a8e921f10da5dfdc72bb6907f3a3acd648825 Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Sat, 3 Oct 2015 17:02:19 +0200 Subject: [PATCH] Avoid extreme sizing / scaling in tiling pattern The new test file (tiling-pattern-large-steps.pdf) was manually created, to have the following characteristics: - Large xstep and ystep (90000) - Page width is 4000 (which is larger than MAX_PATTERN_SIZE) - Visually, the page consists of a red rectangle with a black border, surrounded by a 50 unit white padding. - Before patch: blurry; After patch: sharp Fixes #6496 Fixes #5698 Fixes #1434 Fixes #2825 --- src/display/pattern_helper.js | 21 ++++-- test/pdfs/.gitignore | 1 + test/pdfs/tiling-pattern-large-steps.pdf | 90 ++++++++++++++++++++++++ test/test_manifest.json | 8 +++ 4 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 test/pdfs/tiling-pattern-large-steps.pdf diff --git a/src/display/pattern_helper.js b/src/display/pattern_helper.js index 0b19f718a..bd5676647 100644 --- a/src/display/pattern_helper.js +++ b/src/display/pattern_helper.js @@ -342,8 +342,10 @@ var TilingPattern = (function TilingPatternClosure() { // Use width and height values that are as close as possible to the end // result when the pattern is used. Too low value makes the pattern look // blurry. Too large value makes it look too crispy. - var dimx = this.getSizeAndScale(xstep, combinedScale[0]); - var dimy = this.getSizeAndScale(ystep, combinedScale[1]); + var dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width, + combinedScale[0]); + var dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height, + combinedScale[1]); var tmpCanvas = owner.cachedCanvases.getCanvas('pattern', dimx.size, dimy.size, true); @@ -368,12 +370,21 @@ var TilingPattern = (function TilingPatternClosure() { return tmpCanvas.canvas; }, - getSizeAndScale: function TilingPattern_getSizeAndScale(step, scale) { + getSizeAndScale: + function TilingPattern_getSizeAndScale(step, realOutputSize, scale) { // xstep / ystep may be negative -- normalize. step = Math.abs(step); // MAX_PATTERN_SIZE is used to avoid OOM situation. - var size = Math.min(Math.ceil(step * scale), MAX_PATTERN_SIZE); - scale = size / step; + // Use the destination canvas's size if it is bigger than the hard-coded + // limit of MAX_PATTERN_SIZE to avoid clipping patterns that cover the + // whole canvas. + var maxSize = Math.max(MAX_PATTERN_SIZE, realOutputSize); + var size = Math.ceil(step * scale); + if (size >= maxSize) { + size = maxSize; + } else { + scale = size / step; + } return { scale, size, }; }, diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 259a95710..9ad2ef029 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -340,3 +340,4 @@ !issue9972-1.pdf !issue9972-2.pdf !issue9972-3.pdf +!tiling-pattern-large-steps.pdf diff --git a/test/pdfs/tiling-pattern-large-steps.pdf b/test/pdfs/tiling-pattern-large-steps.pdf new file mode 100644 index 000000000..366d03ead --- /dev/null +++ b/test/pdfs/tiling-pattern-large-steps.pdf @@ -0,0 +1,90 @@ +%PDF-1.4 +% A 4000 x 400 PDF with a red square rectangle and 50 units of padding at all sides. +1 0 obj +<< +/Type /Catalog +/Pages 2 0 R +>> +endobj +2 0 obj +<< +/Type /Pages +/Kids [3 0 R] +/Count 1 +>> +endobj +3 0 obj +<< +/Type /Page +/MediaBox [0.0 0.0 4000 400] +/Parent 2 0 R +/Resources 4 0 R +/Contents 5 0 R +>> +endobj +4 0 obj +<< +/Pattern 6 0 R +/ColorSpace 7 0 R +>> +endobj +5 0 obj +<< +/Length 36 +>> +stream +50 50 3950 350 re +/cs1 cs +/p1 scn +f +endstream +endobj +6 0 obj +<< +/p1 8 0 R +>> +endobj +7 0 obj +<< +/cs1 [/Pattern /DeviceRGB] +>> +endobj +8 0 obj +<< +/Length 43 +/Type /Pattern +/PatternType 1 +/Resources << +>> +/BBox [0 0 3950 350] +/PaintType 1 +/TilingType 1 +/XStep 90000 +/YStep 90000 +>> +stream +/DeviceRGB cs +1 0 0 sc +50 50 3950 300 re +B +endstream +endobj +xref +0 9 +0000000000 65535 f +0000000094 00000 n +0000000143 00000 n +0000000200 00000 n +0000000309 00000 n +0000000363 00000 n +0000000448 00000 n +0000000479 00000 n +0000000527 00000 n +trailer +<< +/Root 1 0 R +/Size 9 +>> +startxref +740 +%%EOF diff --git a/test/test_manifest.json b/test/test_manifest.json index c188d388e..0afd79a98 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -2996,6 +2996,14 @@ "link": false, "type": "eq" }, + { + "id": "tiling-pattern-large-steps", + "file": "pdfs/tiling-pattern-large-steps.pdf", + "md5": "569aac1303c97004aab6a720d9b259b4", + "rounds": 1, + "link": false, + "type": "eq" + }, { "id": "issue6151", "file": "pdfs/issue6151.pdf", "md5": "926f8c6b25e6f0978759f7947d70e079",