Reduce max size for pattern and limit group canvases

This commit is contained in:
Yury Delendik 2013-08-16 09:50:48 -05:00
parent 5ca1c84564
commit b8143b394c
2 changed files with 43 additions and 38 deletions

View File

@ -170,19 +170,24 @@ function addContextCurrentTransform(ctx) {
var CachedCanvases = (function CachedCanvasesClosure() { var CachedCanvases = (function CachedCanvasesClosure() {
var cache = {}; var cache = {};
return { return {
getCanvas: function CachedCanvases_getCanvas(id, width, height) { getCanvas: function CachedCanvases_getCanvas(id, width, height,
var canvas; trackTransform) {
var canvasEntry;
if (id in cache) { if (id in cache) {
canvas = cache[id]; canvasEntry = cache[id];
canvas.width = width; canvasEntry.canvas.width = width;
canvas.height = height; canvasEntry.canvas.height = height;
// reset canvas transform for emulated mozCurrentTransform, if needed // 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 { } else {
canvas = createScratchCanvas(width, height); var canvas = createScratchCanvas(width, height);
cache[id] = canvas; var ctx = canvas.getContext('2d');
if (trackTransform) {
addContextCurrentTransform(ctx);
}
cache[id] = canvasEntry = {canvas: canvas, context: ctx};
} }
return canvas; return canvasEntry;
}, },
clear: function () { clear: function () {
cache = {}; cache = {};
@ -411,6 +416,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// spec 8.7.2 NOTE 1. // spec 8.7.2 NOTE 1.
this.baseTransform = null; this.baseTransform = null;
this.baseTransformStack = []; this.baseTransformStack = [];
this.groupLevel = 0;
if (canvasCtx) { if (canvasCtx) {
addContextCurrentTransform(canvasCtx); addContextCurrentTransform(canvasCtx);
} }
@ -757,7 +763,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// for patterns, we transform to pattern space, calculate // for patterns, we transform to pattern space, calculate
// the pattern, call stroke, and restore to user space // the pattern, call stroke, and restore to user space
ctx.save(); ctx.save();
ctx.strokeStyle = strokeColor.getPattern(ctx); ctx.strokeStyle = strokeColor.getPattern(ctx, this);
ctx.stroke(); ctx.stroke();
ctx.restore(); ctx.restore();
} else { } else {
@ -781,7 +787,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (fillColor && fillColor.hasOwnProperty('type') && if (fillColor && fillColor.hasOwnProperty('type') &&
fillColor.type === 'Pattern') { fillColor.type === 'Pattern') {
ctx.save(); ctx.save();
ctx.fillStyle = fillColor.getPattern(ctx); ctx.fillStyle = fillColor.getPattern(ctx, this);
needRestore = true; needRestore = true;
} }
@ -1405,7 +1411,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.save(); this.save();
var pattern = Pattern.shadingFromIR(patternIR); var pattern = Pattern.shadingFromIR(patternIR);
ctx.fillStyle = pattern.getPattern(ctx); ctx.fillStyle = pattern.getPattern(ctx, this);
var inv = ctx.mozCurrentTransformInverse; var inv = ctx.mozCurrentTransformInverse;
if (inv) { if (inv) {
@ -1517,9 +1523,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1); var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1);
var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1); var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1);
var scratchCanvas = createScratchCanvas(drawnWidth, drawnHeight); var scratchCanvas = CachedCanvases.getCanvas(
var groupCtx = scratchCanvas.getContext('2d'); 'groupAt' + this.groupLevel, drawnWidth, drawnHeight, true);
addContextCurrentTransform(groupCtx); var groupCtx = scratchCanvas.context;
// Since we created a new canvas that is just the size of the bounding box // Since we created a new canvas that is just the size of the bounding box
// we have to translate the group ctx. // we have to translate the group ctx.
var offsetX = bounds[0]; var offsetX = bounds[0];
@ -1531,7 +1537,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// location. // location.
currentCtx.setTransform(1, 0, 0, 1, 0, 0); currentCtx.setTransform(1, 0, 0, 1, 0, 0);
currentCtx.translate(offsetX, offsetY); currentCtx.translate(offsetX, offsetY);
// The transparency group inherits all off the current graphics state // The transparency group inherits all off the current graphics state
// except the blend mode, soft mask, and alpha constants. // except the blend mode, soft mask, and alpha constants.
copyCtxState(currentCtx, groupCtx); copyCtxState(currentCtx, groupCtx);
@ -1543,9 +1548,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
['CA', 1] ['CA', 1]
]); ]);
this.groupStack.push(currentCtx); this.groupStack.push(currentCtx);
this.groupLevel++;
}, },
endGroup: function CanvasGraphics_endGroup(group) { endGroup: function CanvasGraphics_endGroup(group) {
this.groupLevel--;
var groupCtx = this.ctx; var groupCtx = this.ctx;
this.ctx = this.groupStack.pop(); this.ctx = this.groupStack.pop();
// Turn off image smoothing to avoid sub pixel interpolation which can // 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 maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
var maskCtx = maskCanvas.getContext('2d'); var maskCtx = maskCanvas.context;
maskCtx.save(); maskCtx.save();
putBinaryImageData(maskCtx, img); putBinaryImageData(maskCtx, img);
@ -1648,12 +1655,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var fillColor = this.current.fillColor; var fillColor = this.current.fillColor;
maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
fillColor.type === 'Pattern') ? fillColor.type === 'Pattern') ?
fillColor.getPattern(maskCtx) : fillColor; fillColor.getPattern(maskCtx, this) : fillColor;
maskCtx.fillRect(0, 0, width, height); maskCtx.fillRect(0, 0, width, height);
maskCtx.restore(); maskCtx.restore();
this.paintInlineImageXObject(maskCanvas); this.paintInlineImageXObject(maskCanvas.canvas);
}, },
paintImageMaskXObjectGroup: paintImageMaskXObjectGroup:
@ -1665,7 +1672,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var width = image.width, height = image.height; var width = image.width, height = image.height;
var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
var maskCtx = maskCanvas.getContext('2d'); var maskCtx = maskCanvas.context;
maskCtx.save(); maskCtx.save();
putBinaryImageData(maskCtx, image); putBinaryImageData(maskCtx, image);
@ -1675,7 +1682,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var fillColor = this.current.fillColor; var fillColor = this.current.fillColor;
maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
fillColor.type === 'Pattern') ? fillColor.type === 'Pattern') ?
fillColor.getPattern(maskCtx) : fillColor; fillColor.getPattern(maskCtx, this) : fillColor;
maskCtx.fillRect(0, 0, width, height); maskCtx.fillRect(0, 0, width, height);
maskCtx.restore(); maskCtx.restore();
@ -1683,7 +1690,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
ctx.save(); ctx.save();
ctx.transform.apply(ctx, image.transform); ctx.transform.apply(ctx, image.transform);
ctx.scale(1, -1); ctx.scale(1, -1);
ctx.drawImage(maskCanvas, 0, 0, width, height, ctx.drawImage(maskCanvas.canvas, 0, 0, width, height,
0, -1, 1, 1); 0, -1, 1, 1);
ctx.restore(); ctx.restore();
} }
@ -1718,9 +1725,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
imgToPaint = imgData; imgToPaint = imgData;
} else { } else {
var tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height); var tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height);
var tmpCtx = tmpCanvas.getContext('2d'); var tmpCtx = tmpCanvas.context;
putBinaryImageData(tmpCtx, imgData); putBinaryImageData(tmpCtx, imgData);
imgToPaint = tmpCanvas; imgToPaint = tmpCanvas.canvas;
} }
var paintWidth = width, paintHeight = height; var paintWidth = width, paintHeight = height;
@ -1741,11 +1748,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
} }
var tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId, var tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId,
newWidth, newHeight); newWidth, newHeight);
tmpCtx = tmpCanvas.getContext('2d'); tmpCtx = tmpCanvas.context;
tmpCtx.clearRect(0, 0, newWidth, newHeight); tmpCtx.clearRect(0, 0, newWidth, newHeight);
tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight,
0, 0, newWidth, newHeight); 0, 0, newWidth, newHeight);
imgToPaint = tmpCanvas; imgToPaint = tmpCanvas.canvas;
paintWidth = newWidth; paintWidth = newWidth;
paintHeight = newHeight; paintHeight = newHeight;
tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1'; tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1';
@ -1773,7 +1780,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var h = imgData.height; var h = imgData.height;
var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h); var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h);
var tmpCtx = tmpCanvas.getContext('2d'); var tmpCtx = tmpCanvas.context;
putBinaryImageData(tmpCtx, imgData); putBinaryImageData(tmpCtx, imgData);
for (var i = 0, ii = map.length; i < ii; i++) { for (var i = 0, ii = map.length; i < ii; i++) {
@ -1781,7 +1788,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
ctx.save(); ctx.save();
ctx.transform.apply(ctx, entry.transform); ctx.transform.apply(ctx, entry.transform);
ctx.scale(1, -1); 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); 0, -1, 1, 1);
if (this.imageLayer) { if (this.imageLayer) {
var position = this.getCanvasPosition(entry.x, entry.y); var position = this.getCanvasPosition(entry.x, entry.y);

View File

@ -269,7 +269,7 @@ var TilingPattern = (function TilingPatternClosure() {
UNCOLORED: 2 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) { function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) {
this.name = IR[1][0].name; this.name = IR[1][0].name;
@ -303,7 +303,7 @@ var TilingPattern = (function TilingPatternClosure() {
}; };
TilingPattern.prototype = { TilingPattern.prototype = {
createPatternCanvas: function TilinPattern_createPatternCanvas(tmpCanvas) { createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
var operatorList = this.operatorList; var operatorList = this.operatorList;
var bbox = this.bbox; var bbox = this.bbox;
var xstep = this.xstep; var xstep = this.xstep;
@ -343,12 +343,10 @@ var TilingPattern = (function TilingPatternClosure() {
height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])), height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])),
MAX_PATTERN_SIZE); MAX_PATTERN_SIZE);
tmpCanvas.width = width; var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true);
tmpCanvas.height = height; var tmpCtx = tmpCanvas.context;
// set the new canvas element context as the graphics context
var tmpCtx = tmpCanvas.getContext('2d');
var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs); var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs);
graphics.groupLevel = owner.groupLevel;
this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color); this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color);
@ -362,6 +360,7 @@ var TilingPattern = (function TilingPatternClosure() {
this.clipBbox(graphics, bbox, x0, y0, x1, y1); this.clipBbox(graphics, bbox, x0, y0, x1, y1);
graphics.executeOperatorList(operatorList); graphics.executeOperatorList(operatorList);
return tmpCanvas.canvas;
}, },
setScale: function TilingPattern_setScale(width, height, xstep, ystep) { setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
@ -408,9 +407,8 @@ var TilingPattern = (function TilingPatternClosure() {
} }
}, },
getPattern: function TilingPattern_getPattern() { getPattern: function TilingPattern_getPattern(ctx, owner) {
var temporaryPatternCanvas = CachedCanvases.getCanvas('pattern'); var temporaryPatternCanvas = this.createPatternCanvas(owner);
this.createPatternCanvas(temporaryPatternCanvas);
var ctx = this.ctx; var ctx = this.ctx;
ctx.setTransform.apply(ctx, this.baseTransform); ctx.setTransform.apply(ctx, this.baseTransform);