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
This commit is contained in:
Rob Wu 2015-10-03 17:02:19 +02:00
parent 60d4685c10
commit a72a8e921f
4 changed files with 115 additions and 5 deletions

View File

@ -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, };
},

View File

@ -340,3 +340,4 @@
!issue9972-1.pdf
!issue9972-2.pdf
!issue9972-3.pdf
!tiling-pattern-large-steps.pdf

View File

@ -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

View File

@ -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",