Skip to content

Commit ba0306a

Browse files
committed
added support for font-metrics, to find baseline information for text (text-decoration:underline)
1 parent d1626c5 commit ba0306a

4 files changed

Lines changed: 195 additions & 44 deletions

File tree

build/html2canvas.js

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ function html2canvas(el, userOptions) {
5656
image;
5757
this.imagesLoaded = 0;
5858
this.images = [];
59+
this.fontData = [];
5960
this.ignoreElements = "IFRAME|OBJECT|PARAM";
6061

6162

@@ -581,10 +582,7 @@ html2canvas.prototype.preloadImage = function(src){
581582

582583

583584
html2canvas.prototype.newText = function(el,textNode){
584-
585-
586-
587-
585+
588586
var family = this.getCSS(el,"font-family");
589587
var size = this.getCSS(el,"font-size");
590588
var color = this.getCSS(el,"color");
@@ -608,15 +606,17 @@ html2canvas.prototype.newText = function(el,textNode){
608606
break;
609607
}
610608

609+
610+
if (text_decoration!="none"){
611+
var metrics = this.fontMetrics(family,size);
612+
613+
}
614+
611615

612616

613617
this.ctx.font = bold+" "+font_style+" "+size+" "+family;
614618
this.ctx.fillStyle = color;
615-
616-
617-
618-
619-
619+
620620
var oldTextNode = textNode;
621621
for(var c=0;c<text.length;c++){
622622
var newTextNode = oldTextNode.splitText(1);
@@ -656,16 +656,16 @@ html2canvas.prototype.newText = function(el,textNode){
656656

657657
switch(text_decoration) {
658658
case "underline":
659-
// guesstimate the y-position of the line
660-
// TODO try and find a more accurate way to find the baseline of the text
661-
this.newRect(bounds.left,Math.round(bounds.bottom-(bounds.height/7)),bounds.width,1,color);
659+
// Draws a line at the baseline of the font
660+
// 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
661+
this.newRect(bounds.left,Math.round(bounds.top+metrics.baseline+metrics.lineWidth),bounds.width,1,color);
662662
break;
663663
case "overline":
664664
this.newRect(bounds.left,bounds.top,bounds.width,1,color);
665665
break;
666666
case "line-through":
667667
// TODO try and find exact position for line-through
668-
this.newRect(bounds.left,Math.round(bounds.top+(bounds.height/2)),bounds.width,1,color);
668+
this.newRect(bounds.left,Math.ceil(bounds.top+metrics.middle+metrics.lineWidth),bounds.width,1,color);
669669
break;
670670

671671
}
@@ -681,11 +681,85 @@ html2canvas.prototype.newText = function(el,textNode){
681681

682682
}
683683

684+
/*
685+
* Function to find baseline for font with a specicic size
686+
*/
687+
html2canvas.prototype.fontMetrics = function(font,fontSize){
688+
689+
690+
var findMetrics = this.fontData.indexOf(font+"-"+fontSize);
691+
692+
if (findMetrics>-1){
693+
return this.fontData[findMetrics+1];
694+
}
695+
696+
var container = document.createElement('div');
697+
document.getElementsByTagName('body')[0].appendChild(container);
698+
699+
// jquery to speed this up, TODO remove jquery dependancy
700+
$(container).css({
701+
visibility:'hidden',
702+
fontFamily:font,
703+
fontSize:fontSize,
704+
margin:0,
705+
padding:0
706+
});
707+
708+
709+
710+
var img = document.createElement('img');
711+
img.src = "http://html2canvas.hertzen.com/images/8.jpg";
712+
img.width = 1;
713+
img.height = 1;
714+
715+
$(img).css({
716+
margin:0,
717+
padding:0
718+
});
719+
var span = document.createElement('span');
720+
721+
$(span).css({
722+
fontFamily:font,
723+
fontSize:fontSize,
724+
margin:0,
725+
padding:0
726+
});
727+
728+
729+
span.appendChild(document.createTextNode('Hidden Text'));
730+
container.appendChild(span);
731+
container.appendChild(img);
732+
var baseline = (img.offsetTop-span.offsetTop)+1;
733+
734+
container.removeChild(span);
735+
container.appendChild(document.createTextNode('Hidden Text'));
736+
737+
$(container).css('line-height','normal');
738+
$(img).css("vertical-align","super");
739+
var middle = (img.offsetTop-container.offsetTop)+1;
740+
741+
var metricsObj = {
742+
baseline: baseline,
743+
lineWidth: 1,
744+
middle: middle
745+
};
746+
747+
748+
this.fontData.push(font+"-"+fontSize);
749+
this.fontData.push(metricsObj);
750+
751+
$(container).remove();
752+
753+
754+
755+
return metricsObj;
756+
757+
}
684758

685759

686760
/*
687-
* Function to apply text-transform attribute to text
688-
*/
761+
* Function to apply text-transform attribute to text
762+
*/
689763
html2canvas.prototype.textTransform = function(text,transform){
690764
switch(transform){
691765
case "lowercase":

build/html2canvas.min.js

Lines changed: 17 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Core.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ function html2canvas(el, userOptions) {
2626
image;
2727
this.imagesLoaded = 0;
2828
this.images = [];
29+
this.fontData = [];
2930
this.ignoreElements = "IFRAME|OBJECT|PARAM";
3031

3132

0 commit comments

Comments
 (0)