implementing background-size; use parseBackgroundImage in render

This commit is contained in:
Andy Edinborough 2013-01-01 10:42:22 -06:00
parent 473ff45267
commit 3d3f923ed8
2 changed files with 110 additions and 56 deletions

View File

@ -152,11 +152,11 @@ _html2canvas.Util.Bounds = function getBounds (el) {
}
};
_html2canvas.Util.getCSS = function (el, attribute) {
_html2canvas.Util.getCSS = function (el, attribute, index) {
// return $(el).css(attribute);
var val,
isBackgroundSizePosition = !!attribute.match( /^background(Size|Position)$/ );
isBackgroundSizePosition = attribute.match( /^background(Size|Position)$/ );
function toPX( attribute, val ) {
var rsLeft = el.runtimeStyle && el.runtimeStyle[ attribute ],
@ -196,11 +196,8 @@ _html2canvas.Util.getCSS = function (el, attribute) {
}
return val;
}
if ( window.getComputedStyle ) {
if ( previousElement !== el ) {
computedCSS = document.defaultView.getComputedStyle(el, null);
@ -208,12 +205,16 @@ _html2canvas.Util.getCSS = function (el, attribute) {
val = computedCSS[ attribute ];
if ( isBackgroundSizePosition ) {
val = (val || '').split(',');
val = val[index || 0] || val[0] || 'auto';
val = val.split(' ');
if(attribute === 'backgroundSize' && (!val[0] || val[0].match(/cover|contain|auto/))) {
val = (val.split(",")[0] || "0 0").split(" ");
} else {
val[ 0 ] = ( val[0].indexOf( "%" ) === -1 ) ? toPX( attribute + "X", val[ 0 ] ) : val[ 0 ];
val[ 1 ] = ( val[1] === undefined ) ? val[0] : val[1]; // IE 9 doesn't return double digit always
val[ 1 ] = ( val[1].indexOf( "%" ) === -1 ) ? toPX( attribute + "Y", val[ 1 ] ) : val[ 1 ];
}
} else if ( /border(Top|Bottom)(Left|Right)Radius/.test( attribute) ) {
var arr = val.split(" ");
if ( arr.length <= 1 ) {
@ -252,18 +253,39 @@ _html2canvas.Util.getCSS = function (el, attribute) {
return val;
};
function resize(current_width, current_height, target_width, target_height, stretch_mode){
var target_ratio = target_width / target_height,
current_ratio = current_width / current_height,
output_width, output_height;
function backgroundBoundsFactory( prop, el, bounds, image ) {
if(!stretch_mode || stretch_mode === 'auto') {
output_width = target_width;
output_height = target_height;
} else {
if(target_ratio < current_ratio ^ stretch_mode === 'contain') {
output_height = target_height;
output_width = target_height * current_ratio;
} else {
output_width = target_width;
output_height = target_width / current_ratio;
}
}
return { width: output_width, height: output_height };
}
function backgroundBoundsFactory( prop, el, bounds, image, imageIndex ) {
// TODO add support for multi image backgrounds
var bgposition = _html2canvas.Util.getCSS( el, prop ) ,
var bgposition = _html2canvas.Util.getCSS( el, prop, imageIndex ) ,
topPos,
left,
percentage,
val;
if (bgposition.length === 1){
val = bgposition;
val = bgposition[0];
bgposition = [];
@ -273,28 +295,54 @@ function backgroundBoundsFactory( prop, el, bounds, image ) {
if (bgposition[0].toString().indexOf("%") !== -1){
percentage = (parseFloat(bgposition[0])/100);
left = ((bounds.width * percentage)-(image.width*percentage));
left = bounds.width * percentage;
if(prop !== 'backgroundSize') {
left -= image.width*percentage;
}
} else {
if(prop === 'backgroundSize') {
if(bgposition[0] === 'auto') { left = image.width; }
if(bgposition[1] === 'auto') { topPos = image.height; }
if(bgposition[0].match(/contain|cover/)) {
var resized = resize( image.width, image.height, bounds.width, bounds.height, bgposition[0] );
left = resized.width;
topPos = resized.height;
} else {
bgposition[0] = parseInt (bgposition[0], 10 );
}
} else {
left = parseInt( bgposition[0], 10 );
}
}
if(topPos === undefined) {
if (bgposition[1].toString().indexOf("%") !== -1){
percentage = (parseFloat(bgposition[1])/100);
topPos = ((bounds.height * percentage)-(image.height*percentage));
topPos = bounds.height * percentage;
if(prop !== 'backgroundSize') {
topPos -= image.height * percentage;
}
} else {
topPos = parseInt(bgposition[1],10);
}
}
return [left, topPos];
}
_html2canvas.Util.BackgroundPosition = function( el, bounds, image ) {
var result = backgroundBoundsFactory( 'backgroundPosition', el, bounds, image );
_html2canvas.Util.BackgroundPosition = function( el, bounds, image, imageIndex ) {
var result = backgroundBoundsFactory( 'backgroundPosition', el, bounds, image, imageIndex );
return { left: result[0], top: result[1] };
};
_html2canvas.Util.BackgroundSize = function( el, bounds, image ) {
var result = backgroundBoundsFactory( 'backgroundSize', el, bounds, image );
return { width: result[1], height: result[0] };
_html2canvas.Util.BackgroundSize = function( el, bounds, image, imageIndex ) {
var result = backgroundBoundsFactory( 'backgroundSize', el, bounds, image, imageIndex );
return { width: result[0], height: result[1] };
};
window._html2canvas = _html2canvas;
_html2canvas.Util.Extend = function (options, defaults) {
for (var key in options) {

View File

@ -637,24 +637,28 @@ _html2canvas.Parse = function (images, options) {
);
}
function renderBackgroundRepeating(el, bounds, ctx, image) {
var backgroundPosition = _html2canvas.Util.BackgroundPosition(el, bounds, image),
backgroundRepeat = getCSS(el, "backgroundRepeat").split(",")[0];
function renderBackgroundRepeating(el, bounds, ctx, image, imageIndex) {
var backgroundPosition = _html2canvas.Util.BackgroundPosition(el, bounds, image, imageIndex),
backgroundRepeat = getCSS(el, "backgroundRepeat").split(","),
backgroundSize = _html2canvas.Util.BackgroundSize(el, bounds, image, imageIndex);
backgroundRepeat = backgroundRepeat[imageIndex] || backgroundRepeat[0];
switch (backgroundRepeat) {
case "repeat-x":
renderBackgroundRepeatX(ctx, image, backgroundPosition, bounds.left, bounds.top, bounds.width, bounds.height);
renderBackgroundRepeatX(ctx, image, backgroundPosition, bounds.left, bounds.top, backgroundSize.width, backgroundSize.height);
break;
case "repeat-y":
renderBackgroundRepeatY(ctx, image, backgroundPosition, bounds.left, bounds.top, bounds.width, bounds.height);
renderBackgroundRepeatY(ctx, image, backgroundPosition, bounds.left, bounds.top, backgroundSize.width, backgroundSize.height);
break;
case "no-repeat":
renderBackgroundNoRepeat(ctx, image, backgroundPosition, bounds.left, bounds.top, bounds.width, bounds.height);
renderBackgroundNoRepeat(ctx, image, backgroundPosition, bounds.left, bounds.top, backgroundSize.width, backgroundSize.height);
break;
default:
renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);
renderBackgroundRepeat(ctx, image, backgroundPosition, { width: backgroundSize.width, height: backgroundSize.height });
break;
}
}
@ -662,22 +666,24 @@ _html2canvas.Parse = function (images, options) {
function renderBackgroundImage(element, bounds, ctx) {
// TODO add support for multi background-images
var backgroundImage = getCSS(element, "backgroundImage"),
backgroundImages = _html2canvas.Util.parseBackgroundImage(backgroundImage),
image;
if (!/data:image\/.*;base64,/i.test(backgroundImage) && !/^(-webkit|-moz|linear-gradient|-o-)/.test(backgroundImage)) {
backgroundImage = backgroundImage.split(",")[0];
for(var imageIndex = backgroundImages.length; imageIndex-- > 0;) {
backgroundImage = backgroundImages[imageIndex];
if (!backgroundImage.args || backgroundImage.args.length === 0) {
continue;
}
if (typeof backgroundImage !== "undefined" && /^(1|none)$/.test(backgroundImage) === false) {
image = loadImage(_html2canvas.Util.backgroundImage(backgroundImage));
image = loadImage(backgroundImage.method === 'url' ? backgroundImage.args[0] : backgroundImage.value);
// TODO add support for background-origin
if (image) {
renderBackgroundRepeating(element, bounds, ctx, image);
renderBackgroundRepeating(element, bounds, ctx, image, imageIndex);
} else {
h2clog("html2canvas: Error loading background:" + backgroundImage);
}
}
}