mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
156 lines
5.6 KiB
JavaScript
156 lines
5.6 KiB
JavaScript
function CanvasRenderer(width, height) {
|
|
Renderer.apply(this, arguments);
|
|
this.canvas = this.document.createElement("canvas");
|
|
this.canvas.width = width;
|
|
this.canvas.height = height;
|
|
this.ctx = this.canvas.getContext("2d");
|
|
this.taintCtx = this.document.createElement("canvas").getContext("2d");
|
|
this.ctx.textBaseline = "bottom";
|
|
this.variables = {};
|
|
log("Initialized CanvasRenderer with size", width, "x", height);
|
|
}
|
|
|
|
CanvasRenderer.prototype = Object.create(Renderer.prototype);
|
|
|
|
CanvasRenderer.prototype.setFillStyle = function(color) {
|
|
this.ctx.fillStyle = color;
|
|
return this.ctx;
|
|
};
|
|
|
|
CanvasRenderer.prototype.rectangle = function(left, top, width, height, color) {
|
|
this.setFillStyle(color).fillRect(left, top, width, height);
|
|
};
|
|
|
|
CanvasRenderer.prototype.drawShape = function(shape, color) {
|
|
this.shape(shape);
|
|
this.setFillStyle(color).fill();
|
|
};
|
|
|
|
CanvasRenderer.prototype.taints = function(imageContainer) {
|
|
if (imageContainer.tainted === null) {
|
|
this.taintCtx.drawImage(imageContainer.image, 0, 0);
|
|
try {
|
|
this.taintCtx.getImageData(0, 0, 1, 1);
|
|
imageContainer.tainted = false;
|
|
} catch(e) {
|
|
this.taintCtx = document.createElement("canvas").getContext("2d");
|
|
imageContainer.tainted = true;
|
|
}
|
|
}
|
|
|
|
return imageContainer.tainted;
|
|
};
|
|
|
|
CanvasRenderer.prototype.drawImage = function(imageContainer, sx, sy, sw, sh, dx, dy, dw, dh) {
|
|
if (!this.taints(imageContainer) || this.options.allowTaint) {
|
|
this.ctx.drawImage(imageContainer.image, sx, sy, sw, sh, dx, dy, dw, dh);
|
|
}
|
|
};
|
|
|
|
CanvasRenderer.prototype.clip = function(shapes, callback, context) {
|
|
this.ctx.save();
|
|
shapes.filter(hasEntries).forEach(function(shape) {
|
|
this.shape(shape).clip();
|
|
}, this);
|
|
callback.call(context);
|
|
this.ctx.restore();
|
|
};
|
|
|
|
CanvasRenderer.prototype.shape = function(shape) {
|
|
this.ctx.beginPath();
|
|
shape.forEach(function(point, index) {
|
|
this.ctx[(index === 0) ? "moveTo" : point[0] + "To" ].apply(this.ctx, point.slice(1));
|
|
}, this);
|
|
this.ctx.closePath();
|
|
return this.ctx;
|
|
};
|
|
|
|
CanvasRenderer.prototype.font = function(color, style, variant, weight, size, family) {
|
|
this.setFillStyle(color).font = [style, variant, weight, size, family].join(" ");
|
|
};
|
|
|
|
CanvasRenderer.prototype.fontShadow = function(color, offsetX, offsetY, blur) {
|
|
this.setVariable("shadowColor", color)
|
|
.setVariable("shadowOffsetY", offsetX)
|
|
.setVariable("shadowOffsetX", offsetY)
|
|
.setVariable("shadowBlur", blur);
|
|
};
|
|
|
|
CanvasRenderer.prototype.clearShadow = function() {
|
|
this.setVariable("shadowColor", "rgba(0,0,0,0)");
|
|
};
|
|
|
|
CanvasRenderer.prototype.setOpacity = function(opacity) {
|
|
this.ctx.globalAlpha = opacity;
|
|
};
|
|
|
|
CanvasRenderer.prototype.setTransform = function(transform) {
|
|
this.ctx.translate(transform.origin[0], transform.origin[1]);
|
|
this.ctx.transform.apply(this.ctx, transform.matrix);
|
|
this.ctx.translate(-transform.origin[0], -transform.origin[1]);
|
|
};
|
|
|
|
CanvasRenderer.prototype.setVariable = function(property, value) {
|
|
if (this.variables[property] !== value) {
|
|
this.variables[property] = this.ctx[property] = value;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
CanvasRenderer.prototype.text = function(text, left, bottom) {
|
|
this.ctx.fillText(text, left, bottom);
|
|
};
|
|
|
|
CanvasRenderer.prototype.backgroundRepeatShape = function(imageContainer, backgroundPosition, size, bounds, left, top, width, height, borderData) {
|
|
var shape = [
|
|
["line", Math.round(left), Math.round(top)],
|
|
["line", Math.round(left + width), Math.round(top)],
|
|
["line", Math.round(left + width), Math.round(height + top)],
|
|
["line", Math.round(left), Math.round(height + top)]
|
|
];
|
|
this.clip([shape], function() {
|
|
this.renderBackgroundRepeat(imageContainer, backgroundPosition, size, bounds, borderData[3], borderData[0]);
|
|
}, this);
|
|
};
|
|
|
|
CanvasRenderer.prototype.renderBackgroundRepeat = function(imageContainer, backgroundPosition, size, bounds, borderLeft, borderTop) {
|
|
var offsetX = Math.round(bounds.left + backgroundPosition.left + borderLeft), offsetY = Math.round(bounds.top + backgroundPosition.top + borderTop);
|
|
this.setFillStyle(this.ctx.createPattern(this.resizeImage(imageContainer, size), "repeat"));
|
|
this.ctx.translate(offsetX, offsetY);
|
|
this.ctx.fill();
|
|
this.ctx.translate(-offsetX, -offsetY);
|
|
};
|
|
|
|
CanvasRenderer.prototype.renderBackgroundGradient = function(gradientImage, bounds) {
|
|
if (gradientImage instanceof LinearGradientContainer) {
|
|
var gradient = this.ctx.createLinearGradient(
|
|
bounds.left + bounds.width * gradientImage.x0,
|
|
bounds.top + bounds.height * gradientImage.y0,
|
|
bounds.left + bounds.width * gradientImage.x1,
|
|
bounds.top + bounds.height * gradientImage.y1);
|
|
gradientImage.colorStops.forEach(function(colorStop) {
|
|
gradient.addColorStop(colorStop.stop, colorStop.color);
|
|
});
|
|
this.rectangle(bounds.left, bounds.top, bounds.width, bounds.height, gradient);
|
|
}
|
|
};
|
|
|
|
CanvasRenderer.prototype.resizeImage = function(imageContainer, size) {
|
|
var image = imageContainer.image;
|
|
if(image.width === size.width && image.height === size.height) {
|
|
return image;
|
|
}
|
|
|
|
var ctx, canvas = document.createElement('canvas');
|
|
canvas.width = size.width;
|
|
canvas.height = size.height;
|
|
ctx = canvas.getContext("2d");
|
|
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, size.width, size.height );
|
|
return canvas;
|
|
};
|
|
|
|
function hasEntries(array) {
|
|
return array.length > 0;
|
|
}
|