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) {
|
_html2canvas.Generate.Gradient = function(src, bounds) {
|
||||||
var canvas = document.createElement('canvas'),
|
var canvas = document.createElement('canvas'),
|
||||||
ctx = canvas.getContext('2d'),
|
ctx = canvas.getContext('2d'),
|
||||||
gradient, grad, i, len, img;
|
gradient, grad, i, len;
|
||||||
|
|
||||||
canvas.width = bounds.width;
|
canvas.width = bounds.width;
|
||||||
canvas.height = bounds.height;
|
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);
|
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);
|
grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
|
||||||
|
|
||||||
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
||||||
@ -349,8 +347,7 @@
|
|||||||
ctx.fillStyle = grad;
|
ctx.fillStyle = grad;
|
||||||
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
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);
|
grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
|
||||||
|
|
||||||
@ -366,8 +363,7 @@
|
|||||||
ctx.fillStyle = grad;
|
ctx.fillStyle = grad;
|
||||||
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
ctx.fillRect(0, 0, bounds.width, bounds.height);
|
||||||
|
|
||||||
img.src = canvas.toDataURL();
|
} else if(gradient.type === 'ellipse') {
|
||||||
} else if(gradient.type === 'ellipse'){
|
|
||||||
|
|
||||||
// draw circle
|
// draw circle
|
||||||
var canvasRadial = document.createElement('canvas'),
|
var canvasRadial = document.createElement('canvas'),
|
||||||
@ -378,7 +374,7 @@
|
|||||||
canvasRadial.width = canvasRadial.height = di;
|
canvasRadial.width = canvasRadial.height = di;
|
||||||
|
|
||||||
grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);
|
grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);
|
||||||
|
|
||||||
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
|
||||||
try {
|
try {
|
||||||
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
|
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
|
||||||
@ -393,21 +389,12 @@
|
|||||||
|
|
||||||
ctx.fillStyle = gradient.colorStops[i - 1].color;
|
ctx.fillStyle = gradient.colorStops[i - 1].color;
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
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) {
|
_html2canvas.Generate.ListAlpha = function(number) {
|
||||||
|
139
src/Parse.js
139
src/Parse.js
@ -740,118 +740,27 @@ _html2canvas.Parse = function (images, options) {
|
|||||||
numDraws+=1;
|
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) {
|
function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {
|
||||||
var bgy,
|
var offsetX = Math.round(bounds.left + backgroundPosition.left),
|
||||||
height,
|
offsetY = Math.round(bounds.top + backgroundPosition.top);
|
||||||
add,
|
|
||||||
h;
|
|
||||||
|
|
||||||
backgroundPosition.top -= Math.ceil(backgroundPosition.top / image.height) * image.height;
|
ctx.createPattern(image);
|
||||||
|
ctx.translate(offsetX, offsetY);
|
||||||
for(bgy = (bounds.top + backgroundPosition.top); bgy < (bounds.height + bounds.top); bgy = Math.floor(bgy+image.height) - add) {
|
ctx.fill();
|
||||||
h = Math.min(image.height,(bounds.height + bounds.top) - bgy);
|
ctx.translate(-offsetX, -offsetY);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderBackgroundNoRepeat(ctx, image, backgroundPosition, x, y, w, h) {
|
function backgroundRepeatShape(ctx, image, backgroundPosition, bounds, left, top, width, height) {
|
||||||
var bgdw = w - backgroundPosition.left,
|
var args = [];
|
||||||
bgdh = h - backgroundPosition.top,
|
args.push(["line", Math.round(left), Math.round(top)]);
|
||||||
bgsx = backgroundPosition.left,
|
args.push(["line", Math.round(left + width), Math.round(top)]);
|
||||||
bgsy = backgroundPosition.top,
|
args.push(["line", Math.round(left + width), Math.round(height + top)]);
|
||||||
bgdx = backgroundPosition.left + x,
|
args.push(["line", Math.round(left), Math.round(height + top)]);
|
||||||
bgdy = backgroundPosition.top + y;
|
createShape(ctx, args);
|
||||||
|
ctx.save();
|
||||||
if (bgsx<0){
|
ctx.clip();
|
||||||
bgsx = Math.abs(bgsx);
|
renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);
|
||||||
bgdx += bgsx;
|
ctx.restore();
|
||||||
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 renderBackgroundColor(ctx, backgroundBounds, bgcolor) {
|
function renderBackgroundColor(ctx, backgroundBounds, bgcolor) {
|
||||||
@ -870,15 +779,18 @@ _html2canvas.Parse = function (images, options) {
|
|||||||
backgroundRepeat = getCSS(el, "backgroundRepeat").split(",")[0];
|
backgroundRepeat = getCSS(el, "backgroundRepeat").split(",")[0];
|
||||||
switch (backgroundRepeat) {
|
switch (backgroundRepeat) {
|
||||||
case "repeat-x":
|
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;
|
break;
|
||||||
|
|
||||||
case "repeat-y":
|
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;
|
break;
|
||||||
|
|
||||||
case "no-repeat":
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -960,8 +872,9 @@ _html2canvas.Parse = function (images, options) {
|
|||||||
borders = stack.borders,
|
borders = stack.borders,
|
||||||
ctx = stack.ctx,
|
ctx = stack.ctx,
|
||||||
backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),
|
backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),
|
||||||
borderData = parseBorders(element, bounds, borders),
|
borderData = parseBorders(element, bounds, borders);
|
||||||
clipPath = createShape(ctx, borderData.clip);
|
|
||||||
|
createShape(ctx, borderData.clip);
|
||||||
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.clip();
|
ctx.clip();
|
||||||
|
@ -119,16 +119,14 @@ _html2canvas.Preload = function( options ) {
|
|||||||
// opera throws exception on external-content.html
|
// opera throws exception on external-content.html
|
||||||
try {
|
try {
|
||||||
background_image = _html2canvas.Util.getCSS(el, 'backgroundImage');
|
background_image = _html2canvas.Util.getCSS(el, 'backgroundImage');
|
||||||
}catch(e) {
|
} catch(e) {
|
||||||
h2clog("html2canvas: failed to get background-image - Exception: " + e.message);
|
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
|
// TODO add multi image background support
|
||||||
|
|
||||||
if (/^(-webkit|-o|-moz|-ms|linear)-/.test( background_image )) {
|
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 ){
|
if ( img !== undefined ){
|
||||||
images[background_image] = {
|
images[background_image] = {
|
||||||
|
14
src/Queue.js
14
src/Queue.js
@ -11,6 +11,13 @@ function h2cRenderContext(width, height) {
|
|||||||
'arguments': arguments
|
'arguments': arguments
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
translate: function() {
|
||||||
|
storage.push({
|
||||||
|
type: "function",
|
||||||
|
name: "translate",
|
||||||
|
'arguments': arguments
|
||||||
|
});
|
||||||
|
},
|
||||||
fill: function() {
|
fill: function() {
|
||||||
storage.push({
|
storage.push({
|
||||||
type: "function",
|
type: "function",
|
||||||
@ -39,6 +46,13 @@ function h2cRenderContext(width, height) {
|
|||||||
'arguments': arguments
|
'arguments': arguments
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
createPattern: function() {
|
||||||
|
storage.push({
|
||||||
|
type: "function",
|
||||||
|
name: "createPattern",
|
||||||
|
'arguments': arguments
|
||||||
|
});
|
||||||
|
},
|
||||||
drawShape: function() {
|
drawShape: function() {
|
||||||
|
|
||||||
var shape = [];
|
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) {
|
if (!usingFlashcanvas || renderItem['arguments'][0] + renderItem['arguments'][2] < flashMaxSize && renderItem['arguments'][1] + renderItem['arguments'][3] < flashMaxSize) {
|
||||||
ctx.fillRect.apply( ctx, renderItem['arguments'] );
|
ctx.fillRect.apply( ctx, renderItem['arguments'] );
|
||||||
}
|
}
|
||||||
|
} else if (renderItem.name === "createPattern") {
|
||||||
|
ctx.fillStyle = ctx.createPattern(renderItem['arguments'][0], "repeat");
|
||||||
} else if (renderItem.name === "drawShape") {
|
} else if (renderItem.name === "drawShape") {
|
||||||
createShape(renderItem['arguments']);
|
createShape(renderItem['arguments']);
|
||||||
} else if (renderItem.name === "fillText") {
|
} else if (renderItem.name === "fillText") {
|
||||||
|
@ -13,7 +13,7 @@ var h2cSelector, h2cOptions;
|
|||||||
document.write(srcStart + '/tests/assets/jquery.plugin.html2canvas.js' + scrEnd);
|
document.write(srcStart + '/tests/assets/jquery.plugin.html2canvas.js' + scrEnd);
|
||||||
var html2canvas = ['Core', 'Generate', 'Parse', 'Preload', 'Queue', 'Renderer', 'Util', 'Support', 'Font', 'renderers/Canvas'], i;
|
var html2canvas = ['Core', 'Generate', 'Parse', 'Preload', 'Queue', 'Renderer', 'Util', 'Support', 'Font', 'renderers/Canvas'], i;
|
||||||
for (i = 0; i < html2canvas.length; ++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() {
|
window.onload = function() {
|
||||||
h2cSelector = [document.body];
|
h2cSelector = [document.body];
|
||||||
|
Loading…
Reference in New Issue
Block a user