From b8143b394c0c0f8c47ac4bb77638545bde9436df Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 16 Aug 2013 09:50:48 -0500 Subject: [PATCH] Reduce max size for pattern and limit group canvases --- src/display/canvas.js | 63 ++++++++++++++++++++++++------------------- src/shared/pattern.js | 18 ++++++------- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/display/canvas.js b/src/display/canvas.js index 2e2b6b0dd..e4a5f8099 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -170,19 +170,24 @@ function addContextCurrentTransform(ctx) { var CachedCanvases = (function CachedCanvasesClosure() { var cache = {}; return { - getCanvas: function CachedCanvases_getCanvas(id, width, height) { - var canvas; + getCanvas: function CachedCanvases_getCanvas(id, width, height, + trackTransform) { + var canvasEntry; if (id in cache) { - canvas = cache[id]; - canvas.width = width; - canvas.height = height; + canvasEntry = cache[id]; + canvasEntry.canvas.width = width; + canvasEntry.canvas.height = height; // reset canvas transform for emulated mozCurrentTransform, if needed - canvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0); + canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0); } else { - canvas = createScratchCanvas(width, height); - cache[id] = canvas; + var canvas = createScratchCanvas(width, height); + var ctx = canvas.getContext('2d'); + if (trackTransform) { + addContextCurrentTransform(ctx); + } + cache[id] = canvasEntry = {canvas: canvas, context: ctx}; } - return canvas; + return canvasEntry; }, clear: function () { cache = {}; @@ -411,6 +416,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { // spec 8.7.2 NOTE 1. this.baseTransform = null; this.baseTransformStack = []; + this.groupLevel = 0; if (canvasCtx) { addContextCurrentTransform(canvasCtx); } @@ -757,7 +763,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { // for patterns, we transform to pattern space, calculate // the pattern, call stroke, and restore to user space ctx.save(); - ctx.strokeStyle = strokeColor.getPattern(ctx); + ctx.strokeStyle = strokeColor.getPattern(ctx, this); ctx.stroke(); ctx.restore(); } else { @@ -781,7 +787,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { if (fillColor && fillColor.hasOwnProperty('type') && fillColor.type === 'Pattern') { ctx.save(); - ctx.fillStyle = fillColor.getPattern(ctx); + ctx.fillStyle = fillColor.getPattern(ctx, this); needRestore = true; } @@ -1405,7 +1411,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { this.save(); var pattern = Pattern.shadingFromIR(patternIR); - ctx.fillStyle = pattern.getPattern(ctx); + ctx.fillStyle = pattern.getPattern(ctx, this); var inv = ctx.mozCurrentTransformInverse; if (inv) { @@ -1517,9 +1523,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1); var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1); - var scratchCanvas = createScratchCanvas(drawnWidth, drawnHeight); - var groupCtx = scratchCanvas.getContext('2d'); - addContextCurrentTransform(groupCtx); + var scratchCanvas = CachedCanvases.getCanvas( + 'groupAt' + this.groupLevel, drawnWidth, drawnHeight, true); + var groupCtx = scratchCanvas.context; // Since we created a new canvas that is just the size of the bounding box // we have to translate the group ctx. var offsetX = bounds[0]; @@ -1531,7 +1537,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { // location. currentCtx.setTransform(1, 0, 0, 1, 0, 0); currentCtx.translate(offsetX, offsetY); - // The transparency group inherits all off the current graphics state // except the blend mode, soft mask, and alpha constants. copyCtxState(currentCtx, groupCtx); @@ -1543,9 +1548,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { ['CA', 1] ]); this.groupStack.push(currentCtx); + this.groupLevel++; }, endGroup: function CanvasGraphics_endGroup(group) { + this.groupLevel--; var groupCtx = this.ctx; this.ctx = this.groupStack.pop(); // Turn off image smoothing to avoid sub pixel interpolation which can @@ -1638,7 +1645,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { } var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); - var maskCtx = maskCanvas.getContext('2d'); + var maskCtx = maskCanvas.context; maskCtx.save(); putBinaryImageData(maskCtx, img); @@ -1648,12 +1655,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var fillColor = this.current.fillColor; maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && fillColor.type === 'Pattern') ? - fillColor.getPattern(maskCtx) : fillColor; + fillColor.getPattern(maskCtx, this) : fillColor; maskCtx.fillRect(0, 0, width, height); maskCtx.restore(); - this.paintInlineImageXObject(maskCanvas); + this.paintInlineImageXObject(maskCanvas.canvas); }, paintImageMaskXObjectGroup: @@ -1665,7 +1672,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var width = image.width, height = image.height; var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); - var maskCtx = maskCanvas.getContext('2d'); + var maskCtx = maskCanvas.context; maskCtx.save(); putBinaryImageData(maskCtx, image); @@ -1675,7 +1682,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var fillColor = this.current.fillColor; maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && fillColor.type === 'Pattern') ? - fillColor.getPattern(maskCtx) : fillColor; + fillColor.getPattern(maskCtx, this) : fillColor; maskCtx.fillRect(0, 0, width, height); maskCtx.restore(); @@ -1683,7 +1690,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { ctx.save(); ctx.transform.apply(ctx, image.transform); ctx.scale(1, -1); - ctx.drawImage(maskCanvas, 0, 0, width, height, + ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1); ctx.restore(); } @@ -1718,9 +1725,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { imgToPaint = imgData; } else { var tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height); - var tmpCtx = tmpCanvas.getContext('2d'); + var tmpCtx = tmpCanvas.context; putBinaryImageData(tmpCtx, imgData); - imgToPaint = tmpCanvas; + imgToPaint = tmpCanvas.canvas; } var paintWidth = width, paintHeight = height; @@ -1741,11 +1748,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { } var tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight); - tmpCtx = tmpCanvas.getContext('2d'); + tmpCtx = tmpCanvas.context; tmpCtx.clearRect(0, 0, newWidth, newHeight); tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight); - imgToPaint = tmpCanvas; + imgToPaint = tmpCanvas.canvas; paintWidth = newWidth; paintHeight = newHeight; tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1'; @@ -1773,7 +1780,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var h = imgData.height; var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h); - var tmpCtx = tmpCanvas.getContext('2d'); + var tmpCtx = tmpCanvas.context; putBinaryImageData(tmpCtx, imgData); for (var i = 0, ii = map.length; i < ii; i++) { @@ -1781,7 +1788,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { ctx.save(); ctx.transform.apply(ctx, entry.transform); ctx.scale(1, -1); - ctx.drawImage(tmpCanvas, entry.x, entry.y, entry.w, entry.h, + ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1); if (this.imageLayer) { var position = this.getCanvasPosition(entry.x, entry.y); diff --git a/src/shared/pattern.js b/src/shared/pattern.js index 530489a06..b2c5456fb 100644 --- a/src/shared/pattern.js +++ b/src/shared/pattern.js @@ -269,7 +269,7 @@ var TilingPattern = (function TilingPatternClosure() { UNCOLORED: 2 }; - var MAX_PATTERN_SIZE = 8192; + var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) { this.name = IR[1][0].name; @@ -303,7 +303,7 @@ var TilingPattern = (function TilingPatternClosure() { }; TilingPattern.prototype = { - createPatternCanvas: function TilinPattern_createPatternCanvas(tmpCanvas) { + createPatternCanvas: function TilinPattern_createPatternCanvas(owner) { var operatorList = this.operatorList; var bbox = this.bbox; var xstep = this.xstep; @@ -343,12 +343,10 @@ var TilingPattern = (function TilingPatternClosure() { height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])), MAX_PATTERN_SIZE); - tmpCanvas.width = width; - tmpCanvas.height = height; - - // set the new canvas element context as the graphics context - var tmpCtx = tmpCanvas.getContext('2d'); + var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true); + var tmpCtx = tmpCanvas.context; var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs); + graphics.groupLevel = owner.groupLevel; this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color); @@ -362,6 +360,7 @@ var TilingPattern = (function TilingPatternClosure() { this.clipBbox(graphics, bbox, x0, y0, x1, y1); graphics.executeOperatorList(operatorList); + return tmpCanvas.canvas; }, setScale: function TilingPattern_setScale(width, height, xstep, ystep) { @@ -408,9 +407,8 @@ var TilingPattern = (function TilingPatternClosure() { } }, - getPattern: function TilingPattern_getPattern() { - var temporaryPatternCanvas = CachedCanvases.getCanvas('pattern'); - this.createPatternCanvas(temporaryPatternCanvas); + getPattern: function TilingPattern_getPattern(ctx, owner) { + var temporaryPatternCanvas = this.createPatternCanvas(owner); var ctx = this.ctx; ctx.setTransform.apply(ctx, this.baseTransform);