Skip to content

Commit b8143b3

Browse files
committed
Reduce max size for pattern and limit group canvases
1 parent 5ca1c84 commit b8143b3

File tree

2 files changed

+43
-38
lines changed

2 files changed

+43
-38
lines changed

src/display/canvas.js

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -170,19 +170,24 @@ function addContextCurrentTransform(ctx) {
170170
var CachedCanvases = (function CachedCanvasesClosure() {
171171
var cache = {};
172172
return {
173-
getCanvas: function CachedCanvases_getCanvas(id, width, height) {
174-
var canvas;
173+
getCanvas: function CachedCanvases_getCanvas(id, width, height,
174+
trackTransform) {
175+
var canvasEntry;
175176
if (id in cache) {
176-
canvas = cache[id];
177-
canvas.width = width;
178-
canvas.height = height;
177+
canvasEntry = cache[id];
178+
canvasEntry.canvas.width = width;
179+
canvasEntry.canvas.height = height;
179180
// reset canvas transform for emulated mozCurrentTransform, if needed
180-
canvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);
181+
canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0);
181182
} else {
182-
canvas = createScratchCanvas(width, height);
183-
cache[id] = canvas;
183+
var canvas = createScratchCanvas(width, height);
184+
var ctx = canvas.getContext('2d');
185+
if (trackTransform) {
186+
addContextCurrentTransform(ctx);
187+
}
188+
cache[id] = canvasEntry = {canvas: canvas, context: ctx};
184189
}
185-
return canvas;
190+
return canvasEntry;
186191
},
187192
clear: function () {
188193
cache = {};
@@ -411,6 +416,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
411416
// spec 8.7.2 NOTE 1.
412417
this.baseTransform = null;
413418
this.baseTransformStack = [];
419+
this.groupLevel = 0;
414420
if (canvasCtx) {
415421
addContextCurrentTransform(canvasCtx);
416422
}
@@ -757,7 +763,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
757763
// for patterns, we transform to pattern space, calculate
758764
// the pattern, call stroke, and restore to user space
759765
ctx.save();
760-
ctx.strokeStyle = strokeColor.getPattern(ctx);
766+
ctx.strokeStyle = strokeColor.getPattern(ctx, this);
761767
ctx.stroke();
762768
ctx.restore();
763769
} else {
@@ -781,7 +787,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
781787
if (fillColor && fillColor.hasOwnProperty('type') &&
782788
fillColor.type === 'Pattern') {
783789
ctx.save();
784-
ctx.fillStyle = fillColor.getPattern(ctx);
790+
ctx.fillStyle = fillColor.getPattern(ctx, this);
785791
needRestore = true;
786792
}
787793

@@ -1405,7 +1411,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
14051411

14061412
this.save();
14071413
var pattern = Pattern.shadingFromIR(patternIR);
1408-
ctx.fillStyle = pattern.getPattern(ctx);
1414+
ctx.fillStyle = pattern.getPattern(ctx, this);
14091415

14101416
var inv = ctx.mozCurrentTransformInverse;
14111417
if (inv) {
@@ -1517,9 +1523,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
15171523
var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1);
15181524
var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1);
15191525

1520-
var scratchCanvas = createScratchCanvas(drawnWidth, drawnHeight);
1521-
var groupCtx = scratchCanvas.getContext('2d');
1522-
addContextCurrentTransform(groupCtx);
1526+
var scratchCanvas = CachedCanvases.getCanvas(
1527+
'groupAt' + this.groupLevel, drawnWidth, drawnHeight, true);
1528+
var groupCtx = scratchCanvas.context;
15231529
// Since we created a new canvas that is just the size of the bounding box
15241530
// we have to translate the group ctx.
15251531
var offsetX = bounds[0];
@@ -1531,7 +1537,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
15311537
// location.
15321538
currentCtx.setTransform(1, 0, 0, 1, 0, 0);
15331539
currentCtx.translate(offsetX, offsetY);
1534-
15351540
// The transparency group inherits all off the current graphics state
15361541
// except the blend mode, soft mask, and alpha constants.
15371542
copyCtxState(currentCtx, groupCtx);
@@ -1543,9 +1548,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
15431548
['CA', 1]
15441549
]);
15451550
this.groupStack.push(currentCtx);
1551+
this.groupLevel++;
15461552
},
15471553

15481554
endGroup: function CanvasGraphics_endGroup(group) {
1555+
this.groupLevel--;
15491556
var groupCtx = this.ctx;
15501557
this.ctx = this.groupStack.pop();
15511558
// Turn off image smoothing to avoid sub pixel interpolation which can
@@ -1638,7 +1645,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
16381645
}
16391646

16401647
var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
1641-
var maskCtx = maskCanvas.getContext('2d');
1648+
var maskCtx = maskCanvas.context;
16421649
maskCtx.save();
16431650

16441651
putBinaryImageData(maskCtx, img);
@@ -1648,12 +1655,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
16481655
var fillColor = this.current.fillColor;
16491656
maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
16501657
fillColor.type === 'Pattern') ?
1651-
fillColor.getPattern(maskCtx) : fillColor;
1658+
fillColor.getPattern(maskCtx, this) : fillColor;
16521659
maskCtx.fillRect(0, 0, width, height);
16531660

16541661
maskCtx.restore();
16551662

1656-
this.paintInlineImageXObject(maskCanvas);
1663+
this.paintInlineImageXObject(maskCanvas.canvas);
16571664
},
16581665

16591666
paintImageMaskXObjectGroup:
@@ -1665,7 +1672,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
16651672
var width = image.width, height = image.height;
16661673

16671674
var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
1668-
var maskCtx = maskCanvas.getContext('2d');
1675+
var maskCtx = maskCanvas.context;
16691676
maskCtx.save();
16701677

16711678
putBinaryImageData(maskCtx, image);
@@ -1675,15 +1682,15 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
16751682
var fillColor = this.current.fillColor;
16761683
maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
16771684
fillColor.type === 'Pattern') ?
1678-
fillColor.getPattern(maskCtx) : fillColor;
1685+
fillColor.getPattern(maskCtx, this) : fillColor;
16791686
maskCtx.fillRect(0, 0, width, height);
16801687

16811688
maskCtx.restore();
16821689

16831690
ctx.save();
16841691
ctx.transform.apply(ctx, image.transform);
16851692
ctx.scale(1, -1);
1686-
ctx.drawImage(maskCanvas, 0, 0, width, height,
1693+
ctx.drawImage(maskCanvas.canvas, 0, 0, width, height,
16871694
0, -1, 1, 1);
16881695
ctx.restore();
16891696
}
@@ -1718,9 +1725,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
17181725
imgToPaint = imgData;
17191726
} else {
17201727
var tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height);
1721-
var tmpCtx = tmpCanvas.getContext('2d');
1728+
var tmpCtx = tmpCanvas.context;
17221729
putBinaryImageData(tmpCtx, imgData);
1723-
imgToPaint = tmpCanvas;
1730+
imgToPaint = tmpCanvas.canvas;
17241731
}
17251732

17261733
var paintWidth = width, paintHeight = height;
@@ -1741,11 +1748,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
17411748
}
17421749
var tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId,
17431750
newWidth, newHeight);
1744-
tmpCtx = tmpCanvas.getContext('2d');
1751+
tmpCtx = tmpCanvas.context;
17451752
tmpCtx.clearRect(0, 0, newWidth, newHeight);
17461753
tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight,
17471754
0, 0, newWidth, newHeight);
1748-
imgToPaint = tmpCanvas;
1755+
imgToPaint = tmpCanvas.canvas;
17491756
paintWidth = newWidth;
17501757
paintHeight = newHeight;
17511758
tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1';
@@ -1773,15 +1780,15 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
17731780
var h = imgData.height;
17741781

17751782
var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h);
1776-
var tmpCtx = tmpCanvas.getContext('2d');
1783+
var tmpCtx = tmpCanvas.context;
17771784
putBinaryImageData(tmpCtx, imgData);
17781785

17791786
for (var i = 0, ii = map.length; i < ii; i++) {
17801787
var entry = map[i];
17811788
ctx.save();
17821789
ctx.transform.apply(ctx, entry.transform);
17831790
ctx.scale(1, -1);
1784-
ctx.drawImage(tmpCanvas, entry.x, entry.y, entry.w, entry.h,
1791+
ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h,
17851792
0, -1, 1, 1);
17861793
if (this.imageLayer) {
17871794
var position = this.getCanvasPosition(entry.x, entry.y);

src/shared/pattern.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ var TilingPattern = (function TilingPatternClosure() {
269269
UNCOLORED: 2
270270
};
271271

272-
var MAX_PATTERN_SIZE = 8192;
272+
var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
273273

274274
function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) {
275275
this.name = IR[1][0].name;
@@ -303,7 +303,7 @@ var TilingPattern = (function TilingPatternClosure() {
303303
};
304304

305305
TilingPattern.prototype = {
306-
createPatternCanvas: function TilinPattern_createPatternCanvas(tmpCanvas) {
306+
createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
307307
var operatorList = this.operatorList;
308308
var bbox = this.bbox;
309309
var xstep = this.xstep;
@@ -343,12 +343,10 @@ var TilingPattern = (function TilingPatternClosure() {
343343
height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])),
344344
MAX_PATTERN_SIZE);
345345

346-
tmpCanvas.width = width;
347-
tmpCanvas.height = height;
348-
349-
// set the new canvas element context as the graphics context
350-
var tmpCtx = tmpCanvas.getContext('2d');
346+
var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true);
347+
var tmpCtx = tmpCanvas.context;
351348
var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs);
349+
graphics.groupLevel = owner.groupLevel;
352350

353351
this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
354352

@@ -362,6 +360,7 @@ var TilingPattern = (function TilingPatternClosure() {
362360
this.clipBbox(graphics, bbox, x0, y0, x1, y1);
363361

364362
graphics.executeOperatorList(operatorList);
363+
return tmpCanvas.canvas;
365364
},
366365

367366
setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
@@ -408,9 +407,8 @@ var TilingPattern = (function TilingPatternClosure() {
408407
}
409408
},
410409

411-
getPattern: function TilingPattern_getPattern() {
412-
var temporaryPatternCanvas = CachedCanvases.getCanvas('pattern');
413-
this.createPatternCanvas(temporaryPatternCanvas);
410+
getPattern: function TilingPattern_getPattern(ctx, owner) {
411+
var temporaryPatternCanvas = this.createPatternCanvas(owner);
414412

415413
var ctx = this.ctx;
416414
ctx.setTransform.apply(ctx, this.baseTransform);

0 commit comments

Comments
 (0)