mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Added support for some list-style-type's with list-style-position: inside
This commit is contained in:
@ -168,6 +168,9 @@ html2canvas.prototype.newElement = function(el,parentStack){
|
||||
this.renderFormValue(el,bounds,stack);
|
||||
}
|
||||
break;
|
||||
case "LI":
|
||||
this.drawListItem(el,stack,bgbounds);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
121
src/Lists.js
Normal file
121
src/Lists.js
Normal file
@ -0,0 +1,121 @@
|
||||
html2canvas.prototype.drawListItem = function(element,stack,elBounds){
|
||||
|
||||
|
||||
var position = this.getCSS(element,"list-style-position",false);
|
||||
|
||||
|
||||
var item = this.getListItem(element),
|
||||
x,
|
||||
y;
|
||||
|
||||
var type = this.getCSS(element,"list-style-type",false);
|
||||
|
||||
if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)){
|
||||
// TODO remove jQuery dependency
|
||||
var currentIndex = $(element).index()+1,
|
||||
text;
|
||||
|
||||
if (type == "decimal"){
|
||||
text = currentIndex;
|
||||
}else if (type == "decimal-leading-zero"){
|
||||
if (currentIndex.toString().length == 1){
|
||||
text = currentIndex = "0" + currentIndex.toString();
|
||||
}else{
|
||||
text = currentIndex.toString();
|
||||
}
|
||||
|
||||
}else if (type == "upper-roman"){
|
||||
text = this.getListRoman(currentIndex);
|
||||
}else if (type == "lower-roman"){
|
||||
text = this.getListRoman(currentIndex).toLowerCase();
|
||||
}else if (type == "lower-alpha"){
|
||||
text = this.getListAlpha(currentIndex).toLowerCase();
|
||||
}else if (type == "upper-alpha"){
|
||||
text = this.getListAlpha(currentIndex);
|
||||
}
|
||||
|
||||
text += ". ";
|
||||
var listBounds = this.getListPosition(element,text);
|
||||
|
||||
if (position == "inside"){
|
||||
this.setFont(stack.ctx,element,false);
|
||||
x = elBounds.left;
|
||||
}else{
|
||||
return; /* TODO really need to figure out some more accurate way to try and find the position.
|
||||
as defined in http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-position, it does not even have a specified "correct" position, so each browser
|
||||
may display it whatever way it feels like.
|
||||
"The position of the list-item marker adjacent to floats is undefined in CSS 2.1. CSS 2.1 does not specify the precise location of the marker box or its position in the painting order"
|
||||
*/
|
||||
this.setFont(stack.ctx,element,true);
|
||||
x = elBounds.left-10;
|
||||
}
|
||||
|
||||
y = listBounds.bottom;
|
||||
|
||||
|
||||
this.printText(text, x, y, stack.ctx);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
html2canvas.prototype.getListPosition = function(element,val){
|
||||
var boundElement = document.createElement("boundelement");
|
||||
boundElement.style.display = "inline";
|
||||
//boundElement.style.width = "1px";
|
||||
//boundElement.style.height = "1px";
|
||||
|
||||
var type = element.style.listStyleType;
|
||||
element.style.listStyleType = "none";
|
||||
|
||||
boundElement.appendChild(document.createTextNode(val));
|
||||
|
||||
|
||||
element.insertBefore(boundElement,element.firstChild);
|
||||
|
||||
|
||||
var bounds = this.getBounds(boundElement);
|
||||
element.removeChild(boundElement);
|
||||
element.style.listStyleType = type;
|
||||
return bounds;
|
||||
|
||||
|
||||
}
|
||||
|
||||
html2canvas.prototype.getListItem = function(element){
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
html2canvas.prototype.getListAlpha = function(number){
|
||||
var tmp = "";
|
||||
do{
|
||||
var modulus = number % 26;
|
||||
tmp = String.fromCharCode((modulus) + 64) + tmp;
|
||||
number = number / 26;
|
||||
}while((number*26) > 26);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
html2canvas.prototype.getListRoman = function(number){
|
||||
var romanArray = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"],
|
||||
decimal = [1000,900,500,400,100,90,50,40,10,9,5,4,1],
|
||||
roman = "";
|
||||
|
||||
if (number <= 0 || number >= 4000) return;
|
||||
for (var v=0; v<romanArray.length; v++) {
|
||||
while (number >= decimal[v]) {
|
||||
number -= decimal[v];
|
||||
roman += romanArray[v];
|
||||
}
|
||||
}
|
||||
|
||||
return roman;
|
||||
|
||||
|
||||
}
|
171
src/Text.js
171
src/Text.js
@ -5,9 +5,7 @@ html2canvas.prototype.newText = function(el,textNode,stack,form){
|
||||
var size = this.getCSS(el,"font-size");
|
||||
var color = this.getCSS(el,"color");
|
||||
|
||||
var bold = this.getCSS(el,"font-weight");
|
||||
var font_style = this.getCSS(el,"font-style");
|
||||
var font_variant = this.getCSS(el,"font-variant");
|
||||
|
||||
|
||||
var text_decoration = this.getCSS(el,"text-decoration");
|
||||
var text_align = this.getCSS(el,"text-align");
|
||||
@ -21,14 +19,7 @@ html2canvas.prototype.newText = function(el,textNode,stack,form){
|
||||
|
||||
//text = $.trim(text);
|
||||
if (text.length>0){
|
||||
switch(bold){
|
||||
case 401:
|
||||
bold = "bold";
|
||||
break;
|
||||
case 400:
|
||||
bold = "normal";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (text_decoration!="none"){
|
||||
@ -36,8 +27,7 @@ html2canvas.prototype.newText = function(el,textNode,stack,form){
|
||||
|
||||
}
|
||||
|
||||
var font = font_variant+" "+bold+" "+font_style+" "+size+" "+family,
|
||||
renderList,
|
||||
var renderList,
|
||||
renderWords = false;
|
||||
|
||||
|
||||
@ -54,12 +44,8 @@ html2canvas.prototype.newText = function(el,textNode,stack,form){
|
||||
renderList = textNode.nodeValue.split("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
this.setContextVariable(ctx,"fillStyle",color);
|
||||
this.setContextVariable(ctx,"font",font);
|
||||
this.setFont(ctx,el,false);
|
||||
|
||||
|
||||
/*
|
||||
if (stack.clip){
|
||||
@ -71,81 +57,81 @@ html2canvas.prototype.newText = function(el,textNode,stack,form){
|
||||
|
||||
|
||||
|
||||
var oldTextNode = textNode;
|
||||
for(var c=0;c<renderList.length;c++){
|
||||
var oldTextNode = textNode;
|
||||
for(var c=0;c<renderList.length;c++){
|
||||
|
||||
|
||||
// IE 9 bug
|
||||
if (typeof oldTextNode.nodeValue != "string"){
|
||||
continue;
|
||||
}
|
||||
// IE 9 bug
|
||||
if (typeof oldTextNode.nodeValue != "string"){
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO only do the splitting for non-range prints
|
||||
var newTextNode = oldTextNode.splitText(renderList[c].length);
|
||||
// TODO only do the splitting for non-range prints
|
||||
var newTextNode = oldTextNode.splitText(renderList[c].length);
|
||||
|
||||
if (text_decoration!="none" || this.trim(oldTextNode.nodeValue).length != 0){
|
||||
if (text_decoration!="none" || this.trim(oldTextNode.nodeValue).length != 0){
|
||||
|
||||
|
||||
|
||||
|
||||
if (this.support.rangeBounds){
|
||||
// getBoundingClientRect is supported for ranges
|
||||
if (document.createRange){
|
||||
var range = document.createRange();
|
||||
range.selectNode(oldTextNode);
|
||||
}else{
|
||||
// TODO add IE support
|
||||
var range = document.body.createTextRange();
|
||||
}
|
||||
if (range.getBoundingClientRect()){
|
||||
var bounds = range.getBoundingClientRect();
|
||||
}else{
|
||||
var bounds = {};
|
||||
}
|
||||
if (this.support.rangeBounds){
|
||||
// getBoundingClientRect is supported for ranges
|
||||
if (document.createRange){
|
||||
var range = document.createRange();
|
||||
range.selectNode(oldTextNode);
|
||||
}else{
|
||||
// it isn't supported, so let's wrap it inside an element instead and the bounds there
|
||||
|
||||
var parent = oldTextNode.parentNode;
|
||||
var wrapElement = document.createElement('wrapper');
|
||||
var backupText = oldTextNode.cloneNode(true);
|
||||
wrapElement.appendChild(oldTextNode.cloneNode(true));
|
||||
parent.replaceChild(wrapElement,oldTextNode);
|
||||
|
||||
var bounds = this.getBounds(wrapElement);
|
||||
|
||||
parent.replaceChild(backupText,wrapElement);
|
||||
// TODO add IE support
|
||||
var range = document.body.createTextRange();
|
||||
}
|
||||
if (range.getBoundingClientRect()){
|
||||
var bounds = range.getBoundingClientRect();
|
||||
}else{
|
||||
var bounds = {};
|
||||
}
|
||||
}else{
|
||||
// it isn't supported, so let's wrap it inside an element instead and the bounds there
|
||||
|
||||
var parent = oldTextNode.parentNode;
|
||||
var wrapElement = document.createElement('wrapper');
|
||||
var backupText = oldTextNode.cloneNode(true);
|
||||
wrapElement.appendChild(oldTextNode.cloneNode(true));
|
||||
parent.replaceChild(wrapElement,oldTextNode);
|
||||
|
||||
var bounds = this.getBounds(wrapElement);
|
||||
|
||||
parent.replaceChild(backupText,wrapElement);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// console.log(range);
|
||||
// console.log("'"+oldTextNode.nodeValue+"'"+bounds.left)
|
||||
this.printText(oldTextNode.nodeValue,bounds.left,bounds.bottom,ctx);
|
||||
// console.log(range);
|
||||
// console.log("'"+oldTextNode.nodeValue+"'"+bounds.left)
|
||||
this.printText(oldTextNode.nodeValue,bounds.left,bounds.bottom,ctx);
|
||||
|
||||
switch(text_decoration) {
|
||||
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.newRect(ctx,bounds.left,Math.round(bounds.top+metrics.baseline+metrics.lineWidth),bounds.width,1,color);
|
||||
break;
|
||||
case "overline":
|
||||
this.newRect(ctx,bounds.left,bounds.top,bounds.width,1,color);
|
||||
break;
|
||||
case "line-through":
|
||||
// TODO try and find exact position for line-through
|
||||
this.newRect(ctx,bounds.left,Math.ceil(bounds.top+metrics.middle+metrics.lineWidth),bounds.width,1,color);
|
||||
break;
|
||||
switch(text_decoration) {
|
||||
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.newRect(ctx,bounds.left,Math.round(bounds.top+metrics.baseline+metrics.lineWidth),bounds.width,1,color);
|
||||
break;
|
||||
case "overline":
|
||||
this.newRect(ctx,bounds.left,bounds.top,bounds.width,1,color);
|
||||
break;
|
||||
case "line-through":
|
||||
// TODO try and find exact position for line-through
|
||||
this.newRect(ctx,bounds.left,Math.ceil(bounds.top+metrics.middle+metrics.lineWidth),bounds.width,1,color);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
oldTextNode = newTextNode;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
oldTextNode = newTextNode;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -153,6 +139,39 @@ html2canvas.prototype.newText = function(el,textNode,stack,form){
|
||||
|
||||
}
|
||||
|
||||
html2canvas.prototype.setFont = function(ctx,el,align){
|
||||
|
||||
var family = this.getCSS(el,"font-family");
|
||||
var size = this.getCSS(el,"font-size");
|
||||
var color = this.getCSS(el,"color");
|
||||
|
||||
var bold = this.getCSS(el,"font-weight");
|
||||
var font_style = this.getCSS(el,"font-style");
|
||||
var font_variant = this.getCSS(el,"font-variant");
|
||||
|
||||
switch(bold){
|
||||
case 401:
|
||||
bold = "bold";
|
||||
break;
|
||||
case 400:
|
||||
bold = "normal";
|
||||
break;
|
||||
}
|
||||
|
||||
var font = font_variant+" "+bold+" "+font_style+" "+size+" "+family;
|
||||
|
||||
|
||||
this.setContextVariable(ctx,"fillStyle",color);
|
||||
this.setContextVariable(ctx,"font",font);
|
||||
if (align){
|
||||
this.setContextVariable(ctx,"textAlign","right");
|
||||
}else{
|
||||
this.setContextVariable(ctx,"textAlign","left");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function to find baseline for font with a specicic size
|
||||
*/
|
||||
|
Reference in New Issue
Block a user