mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Add font metrics and text-decorations
This commit is contained in:
parent
1f90defbfa
commit
e27c41efd3
@ -14,5 +14,5 @@
|
|||||||
"jQuery": true
|
"jQuery": true
|
||||||
},
|
},
|
||||||
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise",
|
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise",
|
||||||
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "log"]
|
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "log", "smallImage"]
|
||||||
}
|
}
|
||||||
|
10
src/core.js
10
src/core.js
@ -37,6 +37,10 @@ function documentHeight () {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function smallImage() {
|
||||||
|
return "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
||||||
|
}
|
||||||
|
|
||||||
function createWindowClone(ownerDocument, width, height) {
|
function createWindowClone(ownerDocument, width, height) {
|
||||||
var documentElement = ownerDocument.documentElement.cloneNode(true),
|
var documentElement = ownerDocument.documentElement.cloneNode(true),
|
||||||
container = ownerDocument.createElement("iframe");
|
container = ownerDocument.createElement("iframe");
|
||||||
@ -51,7 +55,7 @@ function createWindowClone(ownerDocument, width, height) {
|
|||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
var loadedTimer = function() {
|
var loadedTimer = function() {
|
||||||
/* Chrome doesn't detect relative background-images assigned in style sheets when fetched through getComputedStyle,
|
/* Chrome doesn't detect relative background-images assigned in style sheets when fetched through getComputedStyle,
|
||||||
before a certain time has passed
|
before a certain time has passed
|
||||||
*/
|
*/
|
||||||
if (container.contentWindow.getComputedStyle(div, null)['backgroundImage'] !== "none") {
|
if (container.contentWindow.getComputedStyle(div, null)['backgroundImage'] !== "none") {
|
||||||
documentClone.body.removeChild(div);
|
documentClone.body.removeChild(div);
|
||||||
@ -75,8 +79,8 @@ function createWindowClone(ownerDocument, width, height) {
|
|||||||
div.className = "html2canvas-ready-test";
|
div.className = "html2canvas-ready-test";
|
||||||
documentClone.body.appendChild(div);
|
documentClone.body.appendChild(div);
|
||||||
var style = documentClone.createElement("style");
|
var style = documentClone.createElement("style");
|
||||||
style.innerHTML = "body div.html2canvas-ready-test { background-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); }";
|
style.innerHTML = "body div.html2canvas-ready-test { background-image:url(" + smallImage() + "); }";
|
||||||
documentClone.body.appendChild(style);
|
documentClone.body.appendChild(style);
|
||||||
window.setTimeout(loadedTimer, 1000);
|
window.setTimeout(loadedTimer, 10);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
48
src/font.js
Normal file
48
src/font.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
function Font(family, size) {
|
||||||
|
var container = document.createElement('div'),
|
||||||
|
img = document.createElement('img'),
|
||||||
|
span = document.createElement('span'),
|
||||||
|
sampleText = 'Hidden Text',
|
||||||
|
baseline,
|
||||||
|
middle;
|
||||||
|
|
||||||
|
container.style.visibility = "hidden";
|
||||||
|
container.style.fontFamily = family;
|
||||||
|
container.style.fontSize = size;
|
||||||
|
container.style.margin = 0;
|
||||||
|
container.style.padding = 0;
|
||||||
|
|
||||||
|
document.body.appendChild(container);
|
||||||
|
|
||||||
|
img.src = smallImage();
|
||||||
|
img.width = 1;
|
||||||
|
img.height = 1;
|
||||||
|
|
||||||
|
img.style.margin = 0;
|
||||||
|
img.style.padding = 0;
|
||||||
|
img.style.verticalAlign = "baseline";
|
||||||
|
|
||||||
|
span.style.fontFamily = family;
|
||||||
|
span.style.fontSize = size;
|
||||||
|
span.style.margin = 0;
|
||||||
|
span.style.padding = 0;
|
||||||
|
|
||||||
|
span.appendChild(document.createTextNode(sampleText));
|
||||||
|
container.appendChild(span);
|
||||||
|
container.appendChild(img);
|
||||||
|
baseline = (img.offsetTop - span.offsetTop) + 1;
|
||||||
|
|
||||||
|
container.removeChild(span);
|
||||||
|
container.appendChild(document.createTextNode(sampleText));
|
||||||
|
|
||||||
|
container.style.lineHeight = "normal";
|
||||||
|
img.style.verticalAlign = "super";
|
||||||
|
|
||||||
|
middle = (img.offsetTop-container.offsetTop) + 1;
|
||||||
|
|
||||||
|
document.body.removeChild(container);
|
||||||
|
|
||||||
|
this.baseline = baseline;
|
||||||
|
this.lineWidth = 1;
|
||||||
|
this.middle = middle;
|
||||||
|
}
|
10
src/fontmetrics.js
Normal file
10
src/fontmetrics.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
function FontMetrics() {
|
||||||
|
this.data = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
FontMetrics.prototype.getMetrics = function(family, size) {
|
||||||
|
if (this.data[family + "-" + size] === undefined) {
|
||||||
|
this.data[family + "-" + size] = new Font(family, size);
|
||||||
|
}
|
||||||
|
return this.data[family + "-" + size];
|
||||||
|
};
|
@ -10,6 +10,7 @@ function NodeParser(element, renderer, support, imageLoader, options) {
|
|||||||
this.nodes = [parent].concat(this.getChildren(parent)).filter(function(container) {
|
this.nodes = [parent].concat(this.getChildren(parent)).filter(function(container) {
|
||||||
return container.visible = container.isElementVisible();
|
return container.visible = container.isElementVisible();
|
||||||
});
|
});
|
||||||
|
this.fontMetrics = new FontMetrics();
|
||||||
log("Fetched nodes");
|
log("Fetched nodes");
|
||||||
this.images = imageLoader.fetch(this.nodes.filter(isElement));
|
this.images = imageLoader.fetch(this.nodes.filter(isElement));
|
||||||
log("Creating stacking contexts");
|
log("Creating stacking contexts");
|
||||||
@ -196,16 +197,28 @@ NodeParser.prototype.paintText = function(container) {
|
|||||||
textList.map(this.parseTextBounds(container), this).forEach(function(bounds, index) {
|
textList.map(this.parseTextBounds(container), this).forEach(function(bounds, index) {
|
||||||
if (bounds) {
|
if (bounds) {
|
||||||
this.renderer.text(textList[index], bounds.left, bounds.bottom);
|
this.renderer.text(textList[index], bounds.left, bounds.bottom);
|
||||||
// renderTextDecoration(ctx, textDecoration, bounds, metrics, color);
|
this.renderTextDecoration(container.parent, bounds, this.fontMetrics.getMetrics(family, size));
|
||||||
}
|
}
|
||||||
/* var bounds = getTextBounds(state, text, textDecoration, (index < textList.length - 1), stack.transform.matrix);
|
|
||||||
if (bounds) {
|
|
||||||
drawText(text, bounds.left, bounds.bottom, ctx);
|
|
||||||
renderTextDecoration(ctx, textDecoration, bounds, metrics, color);
|
|
||||||
} */
|
|
||||||
}, this);
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NodeParser.prototype.renderTextDecoration = function(container, bounds, metrics) {
|
||||||
|
switch(container.css("textDecoration").split(" ")[0]) {
|
||||||
|
case "underline":
|
||||||
|
// Draws a line at the baseline of the font
|
||||||
|
// TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size
|
||||||
|
this.renderer.rectangle(bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, container.css("color"));
|
||||||
|
break;
|
||||||
|
case "overline":
|
||||||
|
this.renderer.rectangle(bounds.left, Math.round(bounds.top), bounds.width, 1, container.css("color"));
|
||||||
|
break;
|
||||||
|
case "line-through":
|
||||||
|
// TODO try and find exact position for line-through
|
||||||
|
this.renderer.rectangle(bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, container.css("color"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
NodeParser.prototype.parseBorders = function(container) {
|
NodeParser.prototype.parseBorders = function(container) {
|
||||||
var nodeBounds = container.bounds;
|
var nodeBounds = container.bounds;
|
||||||
var radius = getBorderRadiusData(container);
|
var radius = getBorderRadiusData(container);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user