Start implementing background gradients

This commit is contained in:
Niklas von Hertzen 2014-02-01 21:48:30 +02:00
parent 17731169e9
commit 9beae48cf0
9 changed files with 108 additions and 29 deletions

View File

@ -14,5 +14,5 @@
"jQuery": true
},
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise",
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "log", "smallImage"]
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "log", "smallImage"]
}

15
src/gradientcontainer.js Normal file
View File

@ -0,0 +1,15 @@
function GradientContainer(imageData) {
this.src = imageData.value;
this.colorStops = [];
this.type = null;
this.x0 = 0.5;
this.y0 = 0.5;
this.x1 = 0.5;
this.y1 = 0.5;
this.promise = Promise.resolve(true);
}
GradientContainer.prototype.TYPES = {
LINEAR: 1,
RADIAL: 2
};

View File

@ -12,7 +12,7 @@ ImageLoader.prototype.findImages = function(nodes) {
};
ImageLoader.prototype.findBackgroundImage = function(images, container) {
container.parseBackgroundImages().filter(this.isImageBackground).map(this.getBackgroundUrl).forEach(this.addImage(images, this.loadImage), this);
container.parseBackgroundImages().filter(this.hasImageBackground).forEach(this.addImage(images, this.loadImage), this);
return images;
};
@ -20,30 +20,33 @@ ImageLoader.prototype.addImage = function(images, callback) {
return function(newImage) {
if (!this.imageExists(images, newImage)) {
images.splice(0, 0, callback.apply(this, arguments));
log('Added image #' + (images.length), newImage.substring(0, 100));
log('Added image #' + (images.length), newImage);
}
};
};
ImageLoader.prototype.getBackgroundUrl = function(imageData) {
return imageData.args[0];
ImageLoader.prototype.hasImageBackground = function(imageData) {
return imageData.method !== "none";
};
ImageLoader.prototype.isImageBackground = function(imageData) {
return imageData.method === "url";
};
ImageLoader.prototype.loadImage = function(src) {
if (src.match(/data:image\/.*;base64,/i)) {
return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false);
} else if (this.isSameOrigin(src) || this.options.allowTaint === true) {
return new ImageContainer(src, false);
} else if (this.support.cors && !this.options.allowTaint && this.options.useCORS) {
return new ImageContainer(src, true);
} else if (this.options.proxy) {
return new ProxyImageContainer(src);
} else {
return new DummyImageContainer(src);
ImageLoader.prototype.loadImage = function(imageData) {
if (imageData.method === "url") {
var src = imageData.args[0];
if (src.match(/data:image\/.*;base64,/i)) {
return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false);
} else if (this.isSameOrigin(src) || this.options.allowTaint === true) {
return new ImageContainer(src, false);
} else if (this.support.cors && !this.options.allowTaint && this.options.useCORS) {
return new ImageContainer(src, true);
} else if (this.options.proxy) {
return new ProxyImageContainer(src);
} else {
return new DummyImageContainer(src);
}
} else if (imageData.method === "linear-gradient") {
return new LinearGradientContainer(imageData);
} else if (imageData.method === "gradient") {
return new WebkitGradientContainer(imageData);
}
};

View File

@ -0,0 +1,33 @@
function LinearGradientContainer(imageData) {
GradientContainer.apply(this, arguments);
this.type = this.TYPES.LINEAR;
imageData.args[0].split(" ").forEach(function(position) {
switch(position) {
case "left":
this.x0 = 0;
this.x1 = 1;
break;
case "top":
this.y0 = 0;
this.y1 = 1;
break;
case "right":
this.x0 = 1;
this.x1 = 0;
break;
case "bottom":
this.y0 = 1;
this.y1 = 0;
break;
}
}, this);
imageData.args.slice(1).forEach(function(colorStop) {
// console.log(colorStop, colorStop.match(this.stepRegExp));
}, this);
}
LinearGradientContainer.prototype = Object.create(GradientContainer.prototype);
LinearGradientContainer.prototype.stepRegExp = /((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/;

View File

@ -73,11 +73,13 @@ NodeParser.prototype.getBounds = function(node) {
if (node.getBoundingClientRect) {
var clientRect = node.getBoundingClientRect();
var isBody = node.nodeName === "BODY";
var width = isBody ? node.scrollWidth : node.offsetWidth;
return {
top: clientRect.top,
bottom: clientRect.bottom || (clientRect.top + clientRect.height),
right: clientRect.left + width,
left: clientRect.left,
width: isBody ? node.scrollWidth : node.offsetWidth,
width: width,
height: isBody ? node.scrollHeight : node.offsetHeight
};
}

View File

@ -51,13 +51,26 @@ Renderer.prototype.renderBorder = function(data) {
Renderer.prototype.renderBackgroundImage = function(container, bounds) {
var backgroundImages = container.parseBackgroundImages();
backgroundImages.reverse().forEach(function(backgroundImage, index, arr) {
if (backgroundImage.method === "url") {
var image = this.images.get(backgroundImage.args[0]);
if (image) {
this.renderBackgroundRepeating(container, bounds, image, arr.length - (index+1));
} else {
log("Error loading background-image", backgroundImage.args[0]);
}
switch(backgroundImage.method) {
case "url":
var image = this.images.get(backgroundImage.args[0]);
if (image) {
this.renderBackgroundRepeating(container, bounds, image, arr.length - (index+1));
} else {
log("Error loading background-image", backgroundImage.args[0]);
}
break;
case "linear-gradient":
case "gradient":
var gradientImage = this.images.get(backgroundImage.value);
if (gradientImage) {
this.renderBackgroundGradient(gradientImage, bounds);
} else {
log("Error loading background-image", backgroundImage.args[0]);
}
break;
default:
log("Unknown background-image type", backgroundImage.args[0]);
}
}, this);
};

View File

@ -96,6 +96,13 @@ CanvasRenderer.prototype.renderBackgroundRepeat = function(imageContainer, backg
this.ctx.translate(-offsetX, -offsetY);
};
CanvasRenderer.prototype.renderBackgroundGradient = function(gradientImage, bounds) {
if (gradientImage instanceof LinearGradientContainer) {
var gradient = this.ctx.createLinearGradient(bounds.left, bounds.top, bounds.right, bounds.bottom);
//console.log(gradientImage, bounds, gradient);
}
};
CanvasRenderer.prototype.resizeImage = function(imageContainer, size) {
var image = imageContainer.image;
if(image.width === size.width && image.height === size.height) {

View File

@ -0,0 +1,6 @@
function WebkitGradientContainer(imageData) {
GradientContainer.apply(this, arguments);
this.type = (imageData.args[0] === "linear") ? this.TYPES.LINEAR : this.TYPES.RADIAL;
}
WebkitGradientContainer.prototype = Object.create(GradientContainer.prototype);

View File

@ -11,7 +11,7 @@ var h2cSelector, h2cOptions;
document.write(srcStart + '/tests/assets/jquery-1.6.2.js' + scrEnd);
document.write(srcStart + '/tests/assets/jquery.plugin.html2canvas.js' + scrEnd);
var html2canvas = ['log', 'nodecontainer', 'stackingcontext', 'textcontainer', 'support', 'imagecontainer',
var html2canvas = ['log', 'nodecontainer', 'stackingcontext', 'textcontainer', 'support', 'imagecontainer', 'gradientcontainer', 'lineargradientcontainer', 'webkitgradientcontainer',
'imageloader', 'nodeparser', 'font', 'fontmetrics', 'core', 'renderer', 'promise', 'renderers/canvas'], i;
for (i = 0; i < html2canvas.length; ++i) {
document.write(srcStart + '/src/' + html2canvas[i] + '.js?' + Math.random() + scrEnd);