mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
switched background rendering to use patterns
This commit is contained in:
parent
65b4bdf282
commit
053a0a4787
@ -323,18 +323,16 @@
|
||||
_html2canvas.Generate.Gradient = function(src, bounds) {
|
||||
var canvas = document.createElement('canvas'),
|
||||
ctx = canvas.getContext('2d'),
|
||||
gradient, grad, i, len, img;
|
||||
gradient, grad, i, len;
|
||||
|
||||
canvas.width = bounds.width;
|
||||
canvas.height = bounds.height;
|
||||
|
||||
// TODO: add support for multi defined background gradients (like radial gradient example in background.html)
|
||||
// TODO: add support for multi defined background gradients
|
||||
gradient = _html2canvas.Generate.parseGradient(src, bounds);
|
||||
|
||||
img = new Image();
|
||||
|
||||
if(gradient){
|
||||
if(gradient.type === 'linear'){
|
||||
if(gradient) {
|
||||
if(gradient.type === 'linear') {
|
||||
grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
|
||||
|
||||
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
||||
@ -349,8 +347,7 @@
|
||||
ctx.fillStyle = grad;
|
||||
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
||||
|
||||
img.src = canvas.toDataURL();
|
||||
} else if(gradient.type === 'circle'){
|
||||
} else if(gradient.type === 'circle') {
|
||||
|
||||
grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
|
||||
|
||||
@ -366,8 +363,7 @@
|
||||
ctx.fillStyle = grad;
|
||||
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
||||
|
||||
img.src = canvas.toDataURL();
|
||||
} else if(gradient.type === 'ellipse'){
|
||||
} else if(gradient.type === 'ellipse') {
|
||||
|
||||
// draw circle
|
||||
var canvasRadial = document.createElement('canvas'),
|
||||
@ -393,21 +389,12 @@
|
||||
|
||||
ctx.fillStyle = gradient.colorStops[i - 1].color;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawImage(canvasRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
|
||||
|
||||
imgRadial = new Image();
|
||||
imgRadial.onload = function() { // wait until the image is filled
|
||||
|
||||
// transform circle to ellipse
|
||||
ctx.drawImage(imgRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
|
||||
|
||||
img.src = canvas.toDataURL();
|
||||
|
||||
};
|
||||
imgRadial.src = canvasRadial.toDataURL();
|
||||
}
|
||||
}
|
||||
|
||||
return img;
|
||||
return canvas;
|
||||
};
|
||||
|
||||
_html2canvas.Generate.ListAlpha = function(number) {
|
||||
|
139
src/Parse.js
139
src/Parse.js
@ -740,118 +740,27 @@ _html2canvas.Parse = function (images, options) {
|
||||
numDraws+=1;
|
||||
}
|
||||
|
||||
function renderBackgroundSlice (ctx, image, x, y, width, height, elx, ely){
|
||||
var sourceX = (elx - x > 0) ? elx-x :0,
|
||||
sourceY= (ely - y > 0) ? ely-y : 0;
|
||||
|
||||
drawImage(
|
||||
ctx,
|
||||
image,
|
||||
Math.floor(sourceX), // source X
|
||||
Math.floor(sourceY), // source Y
|
||||
Math.ceil(width-sourceX), // source Width
|
||||
Math.ceil(height-sourceY), // source Height
|
||||
Math.ceil(x+sourceX), // destination X
|
||||
Math.ceil(y+sourceY), // destination Y
|
||||
Math.ceil(width-sourceX), // destination width
|
||||
Math.ceil(height-sourceY) // destination height
|
||||
);
|
||||
}
|
||||
|
||||
function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {
|
||||
var bgy,
|
||||
height,
|
||||
add,
|
||||
h;
|
||||
var offsetX = Math.round(bounds.left + backgroundPosition.left),
|
||||
offsetY = Math.round(bounds.top + backgroundPosition.top);
|
||||
|
||||
backgroundPosition.top -= Math.ceil(backgroundPosition.top / image.height) * image.height;
|
||||
|
||||
for(bgy = (bounds.top + backgroundPosition.top); bgy < (bounds.height + bounds.top); bgy = Math.floor(bgy+image.height) - add) {
|
||||
h = Math.min(image.height,(bounds.height + bounds.top) - bgy);
|
||||
|
||||
height = (Math.floor(bgy + image.height) > h + bgy) ? (h + bgy) - bgy : image.height;
|
||||
|
||||
if (bgy < bounds.top){
|
||||
add = bounds.top - bgy;
|
||||
bgy = bounds.top;
|
||||
} else {
|
||||
add = 0;
|
||||
}
|
||||
|
||||
renderBackgroundRepeatX(ctx, image, backgroundPosition, bounds.left, bgy, bounds.width, height);
|
||||
|
||||
if (add > 0){
|
||||
backgroundPosition.top += add;
|
||||
}
|
||||
}
|
||||
ctx.createPattern(image);
|
||||
ctx.translate(offsetX, offsetY);
|
||||
ctx.fill();
|
||||
ctx.translate(-offsetX, -offsetY);
|
||||
}
|
||||
|
||||
function renderBackgroundNoRepeat(ctx, image, backgroundPosition, x, y, w, h) {
|
||||
var bgdw = w - backgroundPosition.left,
|
||||
bgdh = h - backgroundPosition.top,
|
||||
bgsx = backgroundPosition.left,
|
||||
bgsy = backgroundPosition.top,
|
||||
bgdx = backgroundPosition.left + x,
|
||||
bgdy = backgroundPosition.top + y;
|
||||
|
||||
if (bgsx<0){
|
||||
bgsx = Math.abs(bgsx);
|
||||
bgdx += bgsx;
|
||||
bgdw = Math.min(w,image.width-bgsx);
|
||||
} else {
|
||||
bgdw = Math.min(bgdw,image.width);
|
||||
bgsx = 0;
|
||||
}
|
||||
|
||||
if (bgsy < 0){
|
||||
bgsy = Math.abs(bgsy);
|
||||
bgdy += bgsy;
|
||||
bgdh = Math.min(h, image.height - bgsy);
|
||||
} else {
|
||||
bgdh = Math.min(bgdh, image.height);
|
||||
bgsy = 0;
|
||||
}
|
||||
|
||||
if (bgdh > 0 && bgdw > 0){
|
||||
drawImage(
|
||||
ctx,
|
||||
image,
|
||||
bgsx,
|
||||
bgsy,
|
||||
bgdw,
|
||||
bgdh,
|
||||
bgdx,
|
||||
bgdy,
|
||||
bgdw,
|
||||
bgdh
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function renderBackgroundRepeatY (ctx, image, backgroundPosition, x, y, w, h){
|
||||
var height,
|
||||
width = Math.min(image.width, w),
|
||||
bgy;
|
||||
|
||||
backgroundPosition.top -= Math.ceil(backgroundPosition.top / image.height) * image.height;
|
||||
|
||||
for (bgy = y + backgroundPosition.top; bgy < h + y; bgy = Math.round(bgy + image.height)){
|
||||
height = (Math.floor(bgy + image.height) > h + y) ? (h+y) - bgy : image.height;
|
||||
renderBackgroundSlice(ctx, image, x + backgroundPosition.left, bgy,width, height, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
function renderBackgroundRepeatX(ctx, image, backgroundPosition, x, y, w, h){
|
||||
var height = Math.min(image.height, h),
|
||||
width,
|
||||
bgx;
|
||||
|
||||
backgroundPosition.left -= Math.ceil(backgroundPosition.left / image.width) * image.width;
|
||||
|
||||
for (bgx = x + backgroundPosition.left; bgx < w + x; bgx = Math.round(bgx + image.width)) {
|
||||
width = (Math.floor(bgx + image.width) > w + x) ? (w + x) - bgx : image.width;
|
||||
renderBackgroundSlice(ctx, image, bgx,(y + backgroundPosition.top), width, height, x, y);
|
||||
}
|
||||
function backgroundRepeatShape(ctx, image, backgroundPosition, bounds, left, top, width, height) {
|
||||
var args = [];
|
||||
args.push(["line", Math.round(left), Math.round(top)]);
|
||||
args.push(["line", Math.round(left + width), Math.round(top)]);
|
||||
args.push(["line", Math.round(left + width), Math.round(height + top)]);
|
||||
args.push(["line", Math.round(left), Math.round(height + top)]);
|
||||
createShape(ctx, args);
|
||||
ctx.save();
|
||||
ctx.clip();
|
||||
renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
function renderBackgroundColor(ctx, backgroundBounds, bgcolor) {
|
||||
@ -870,15 +779,18 @@ _html2canvas.Parse = function (images, options) {
|
||||
backgroundRepeat = getCSS(el, "backgroundRepeat").split(",")[0];
|
||||
switch (backgroundRepeat) {
|
||||
case "repeat-x":
|
||||
renderBackgroundRepeatX(ctx, image, backgroundPosition, bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
|
||||
bounds.left, bounds.top + backgroundPosition.top, 99999, image.height);
|
||||
break;
|
||||
|
||||
case "repeat-y":
|
||||
renderBackgroundRepeatY(ctx, image, backgroundPosition, bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
|
||||
bounds.left + backgroundPosition.left, bounds.top, image.width, 99999);
|
||||
break;
|
||||
|
||||
case "no-repeat":
|
||||
renderBackgroundNoRepeat(ctx, image, backgroundPosition, bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
backgroundRepeatShape(ctx, image, backgroundPosition, bounds,
|
||||
bounds.left + backgroundPosition.left, bounds.top + backgroundPosition.top, image.width, image.height);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -960,8 +872,9 @@ _html2canvas.Parse = function (images, options) {
|
||||
borders = stack.borders,
|
||||
ctx = stack.ctx,
|
||||
backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),
|
||||
borderData = parseBorders(element, bounds, borders),
|
||||
clipPath = createShape(ctx, borderData.clip);
|
||||
borderData = parseBorders(element, bounds, borders);
|
||||
|
||||
createShape(ctx, borderData.clip);
|
||||
|
||||
ctx.save();
|
||||
ctx.clip();
|
||||
|
@ -119,16 +119,14 @@ _html2canvas.Preload = function( options ) {
|
||||
// opera throws exception on external-content.html
|
||||
try {
|
||||
background_image = _html2canvas.Util.getCSS(el, 'backgroundImage');
|
||||
}catch(e) {
|
||||
} catch(e) {
|
||||
h2clog("html2canvas: failed to get background-image - Exception: " + e.message);
|
||||
}
|
||||
if ( background_image && background_image !== "1" && background_image !== "none" ) {
|
||||
|
||||
if (background_image && background_image !== "1" && background_image !== "none") {
|
||||
// TODO add multi image background support
|
||||
|
||||
if (/^(-webkit|-o|-moz|-ms|linear)-/.test( background_image )) {
|
||||
|
||||
img = _html2canvas.Generate.Gradient( background_image, _html2canvas.Util.Bounds( el ) );
|
||||
img = _html2canvas.Generate.Gradient(background_image, _html2canvas.Util.Bounds( el ) );
|
||||
|
||||
if ( img !== undefined ){
|
||||
images[background_image] = {
|
||||
|
14
src/Queue.js
14
src/Queue.js
@ -11,6 +11,13 @@ function h2cRenderContext(width, height) {
|
||||
'arguments': arguments
|
||||
});
|
||||
},
|
||||
translate: function() {
|
||||
storage.push({
|
||||
type: "function",
|
||||
name: "translate",
|
||||
'arguments': arguments
|
||||
});
|
||||
},
|
||||
fill: function() {
|
||||
storage.push({
|
||||
type: "function",
|
||||
@ -39,6 +46,13 @@ function h2cRenderContext(width, height) {
|
||||
'arguments': arguments
|
||||
});
|
||||
},
|
||||
createPattern: function() {
|
||||
storage.push({
|
||||
type: "function",
|
||||
name: "createPattern",
|
||||
'arguments': arguments
|
||||
});
|
||||
},
|
||||
drawShape: function() {
|
||||
|
||||
var shape = [];
|
||||
|
@ -145,6 +145,8 @@ _html2canvas.Renderer.Canvas = function( options ) {
|
||||
if (!usingFlashcanvas || renderItem['arguments'][0] + renderItem['arguments'][2] < flashMaxSize && renderItem['arguments'][1] + renderItem['arguments'][3] < flashMaxSize) {
|
||||
ctx.fillRect.apply( ctx, renderItem['arguments'] );
|
||||
}
|
||||
} else if (renderItem.name === "createPattern") {
|
||||
ctx.fillStyle = ctx.createPattern(renderItem['arguments'][0], "repeat");
|
||||
} else if (renderItem.name === "drawShape") {
|
||||
createShape(renderItem['arguments']);
|
||||
} else if (renderItem.name === "fillText") {
|
||||
|
@ -13,7 +13,7 @@ var h2cSelector, h2cOptions;
|
||||
document.write(srcStart + '/tests/assets/jquery.plugin.html2canvas.js' + scrEnd);
|
||||
var html2canvas = ['Core', 'Generate', 'Parse', 'Preload', 'Queue', 'Renderer', 'Util', 'Support', 'Font', 'renderers/Canvas'], i;
|
||||
for (i = 0; i < html2canvas.length; ++i) {
|
||||
document.write(srcStart + '/src/' + html2canvas[i] + '.js' + scrEnd);
|
||||
document.write(srcStart + '/src/' + html2canvas[i] + '.js?' + Math.random() + scrEnd);
|
||||
}
|
||||
window.onload = function() {
|
||||
h2cSelector = [document.body];
|
||||
|
Loading…
Reference in New Issue
Block a user