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
|
||||
},
|
||||
"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) {
|
||||
var documentElement = ownerDocument.documentElement.cloneNode(true),
|
||||
container = ownerDocument.createElement("iframe");
|
||||
@ -51,7 +55,7 @@ function createWindowClone(ownerDocument, width, height) {
|
||||
return new Promise(function(resolve) {
|
||||
var loadedTimer = function() {
|
||||
/* 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") {
|
||||
documentClone.body.removeChild(div);
|
||||
@ -75,8 +79,8 @@ function createWindowClone(ownerDocument, width, height) {
|
||||
div.className = "html2canvas-ready-test";
|
||||
documentClone.body.appendChild(div);
|
||||
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);
|
||||
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) {
|
||||
return container.visible = container.isElementVisible();
|
||||
});
|
||||
this.fontMetrics = new FontMetrics();
|
||||
log("Fetched nodes");
|
||||
this.images = imageLoader.fetch(this.nodes.filter(isElement));
|
||||
log("Creating stacking contexts");
|
||||
@ -196,16 +197,28 @@ NodeParser.prototype.paintText = function(container) {
|
||||
textList.map(this.parseTextBounds(container), this).forEach(function(bounds, index) {
|
||||
if (bounds) {
|
||||
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);
|
||||
};
|
||||
|
||||
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) {
|
||||
var nodeBounds = container.bounds;
|
||||
var radius = getBorderRadiusData(container);
|
||||
|
Loading…
Reference in New Issue
Block a user