refactored text rendering

This commit is contained in:
Niklas von Hertzen 2012-12-30 04:15:51 +02:00
parent cb43e09899
commit 45853a083c
2 changed files with 54 additions and 83 deletions

View File

@ -243,101 +243,72 @@ _html2canvas.Parse = function (images, options) {
} }
} }
function renderText(el, textNode, stack) { function getTextBounds(state, text, textDecoration, isLast) {
var ctx = stack.ctx, var bounds;
color = getCSS(el, "color"),
text_decoration = getCSS(el, "textDecoration"),
text_align = getCSS(el, "textAlign"),
letter_spacing = getCSS(el, "letterSpacing"),
bounds,
text,
metrics,
renderList,
listLen,
newTextNode,
textValue,
textOffset = 0,
oldTextNode,
c,
range,
parent,
wrapElement,
backupText;
textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, "textTransform"));
text = trimText(textNode.nodeValue);
if (text.length > 0){
text_align = text_align.replace(["-webkit-auto"],["auto"]);
renderList = (!options.letterRendering && /^(left|right|justify|auto)$/.test(text_align) && noLetterSpacing(letter_spacing)) ?
textNode.nodeValue.split(/(\b| )/)
: textNode.nodeValue.split("");
metrics = setTextVariables(ctx, el, text_decoration, color);
oldTextNode = textNode;
for ( c=0, listLen = renderList.length; c < listLen; c+=1 ) {
textValue = null;
if (support.rangeBounds) { if (support.rangeBounds) {
// getBoundingClientRect is supported for ranges if (textDecoration !== "none" || trimText(text).length !== 0) {
if (text_decoration !== "none" || trimText(renderList[c]).length !== 0) { bounds = textRangeBounds(text, state.node, state.textOffset);
textValue = renderList[c]; }
if (doc.createRange){ state.textOffset += text.length;
range = doc.createRange(); } else if (state.node && typeof state.node.nodeValue === "string" ){
var newTextNode = (isLast) ? state.node.splitText(text.length) : null;
bounds = textWrapperBounds(state.node);
state.node = newTextNode;
}
return bounds;
}
function textRangeBounds(text, textNode, textOffset) {
var range = doc.createRange();
range.setStart(textNode, textOffset); range.setStart(textNode, textOffset);
range.setEnd(textNode, textOffset + textValue.length); range.setEnd(textNode, textOffset + text.length);
} else { return range.getBoundingClientRect();
// TODO add IE support
range = body.createTextRange();
} }
if (range.getBoundingClientRect()) { function textWrapperBounds(oldTextNode) {
bounds = range.getBoundingClientRect(); var parent = oldTextNode.parentNode,
} else { wrapElement = doc.createElement('wrapper'),
bounds = {};
}
}
} else {
// it isn't supported, so let's wrap it inside an element instead and get the bounds there
// IE 9 bug
if (!oldTextNode || typeof oldTextNode.nodeValue !== "string" ){
continue;
}
newTextNode = (i < listLen-1) ? oldTextNode.splitText(renderList[c].length) : null;
parent = oldTextNode.parentNode;
wrapElement = doc.createElement('wrapper');
backupText = oldTextNode.cloneNode(true); backupText = oldTextNode.cloneNode(true);
wrapElement.appendChild(oldTextNode.cloneNode(true)); wrapElement.appendChild(oldTextNode.cloneNode(true));
parent.replaceChild(wrapElement, oldTextNode); parent.replaceChild(wrapElement, oldTextNode);
bounds = _html2canvas.Util.Bounds(wrapElement); var bounds = _html2canvas.Util.Bounds(wrapElement);
textValue = oldTextNode.nodeValue;
oldTextNode = newTextNode;
parent.replaceChild(backupText, wrapElement); parent.replaceChild(backupText, wrapElement);
return bounds;
} }
if (textValue !== null) { function renderText(el, textNode, stack) {
drawText(textValue, bounds.left, bounds.bottom, ctx); var ctx = stack.ctx,
color = getCSS(el, "color"),
textDecoration = getCSS(el, "textDecoration"),
textAlign = getCSS(el, "textAlign"),
metrics,
textList,
state = {
node: textNode,
textOffset: 0
};
if (trimText(textNode.nodeValue).length > 0) {
textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, "textTransform"));
textAlign = textAlign.replace(["-webkit-auto"],["auto"]);
textList = (!options.letterRendering && /^(left|right|justify|auto)$/.test(textAlign) && noLetterSpacing(getCSS(el, "letterSpacing"))) ?
textNode.nodeValue.split(/(\b| )/)
: textNode.nodeValue.split("");
metrics = setTextVariables(ctx, el, textDecoration, color);
textList.forEach(function(text, index) {
var bounds = getTextBounds(state, text, textDecoration, (index < textList.length - 1));
if (bounds) {
drawText(text, bounds.left, bounds.bottom, ctx);
renderTextDecoration(textDecoration, bounds, metrics, color);
} }
renderTextDecoration(text_decoration, bounds, metrics, color); });
textOffset += renderList[c].length;
} }
}
} }
function listPosition (element, val) { function listPosition (element, val) {