views:

395

answers:

2

I've been experimenting with the canvas tag and Javascript. I've made a page that takes Tweets from the Twitter public timeline and animates them into view. It works by using a canvas element in the background for the animation. When the animation is complete, it creates a div element with the same text over the top. I do this so that the tweet text is selectable and links are clickable.

Now, in Safari, Chrome and even Opera, the canvas text and div text look almost exactly the same. Yet in Firefox, the size of the text is different enough to make it 'jump' at the point it changes into the div.

Does anyone know how to make Firefox render the text the same on the canvas element and the div using CSS? Or is this a rendering inconsistency with the engine.

I have put the page on my website if you want to see what I mean.

Now for the code:

The CSS I'm using for rendering the div contains:

line-height: 21px; font-weight: 100; font-family: Georgia, "New Century Schoolbook", "Nimbus Roman No9 L", serif; font-size: 20px;

For rendering on the canvas I'm using:

this.context.font = this.scale + 'px Georgia';
this.context.fillStyle = "white";
this.context.strokeStyle = 'white';
this.context.fillText(this.text, 0, 0);
this.context.strokeText(this.text, 0, 0);

where this.scale is an animated scale factor that finishes at 20px exactly. So, to recap, I'm using the same font and ending up at the same px size, yet Firefox renders the text differently between Canvas and CSS.

(edit) Here's a screenshot example: alt text

First line is the text animating in using canvas, second line is the resulting div.

A: 

I cannot see that much difference between firefox and Chrome (apart from speed...).

Have you tried not to use strokeText? I think that text is usually rendered only using fill-operations.

Cool app, btw.!

MartinStettner
Thanks Martin! Yes, I have tried with and without strokeText. Without, the text appears much thinner and looks very different to the div in all three browsers. It seems that CSS text is both stroked and filled, or of a weight equivalent to that.Notice also the font-weight in the CSS, changing this to values less than 'bold' also didn't seem to make any difference. It's only in there because I was experimenting.
Dan Forys
If you look closely at the point the text starts to animate upwards, the character size jumps. It's especially noticeable in Firefox if you look at long tweets with characters at the right of the line. Cumulatively, there's quite a large jump in line length. At least there is on FF 3.6.3 on OSX.
Dan Forys
Interestingly, the rendering seems to differ between versions of Chrome as well. At home (Chrome [I'll check version later] on OSX snow leopard, the stroked *and* filled text looks the same as the div. At work, on Leopard Chrome 5.0.342.9 beta, the stroked and filled text is much fatter than the div. I think I need to investigate this more...
Dan Forys
At home I'm using 5.0.375.29 beta Chrome. Methinks I need to do a PPK style comparison of browsers/versions with screenshots.
Dan Forys
Disabling the strokeText in FF3.6.3 in Windows results in canvas text that looks identical to the CSS text. I wonder if this is an issue with the OS font support rather than Firefox?
Ant
I think it's dependent on how the browser implements the canvas text functions: For Windows, there are a several ways to write text (I suppose, the same is true for OSX). If the canvas functions use a different approach than the CSS rendering you can get different results (this might also affect antialiasing ...)
MartinStettner
A: 

Right, I have a test case.

I created a div and canvas element side by side with the same text. Turns out that the font rendering was a red herring. What differs with Firefox is the reporting of the character widths. My Twitter visualiser calculates the width of each character using measureText().width and places them accordingly. For some reason, the widths of the characters on Firefox are smaller.

Oddly, in the test case I measure two things:

  1. The total width of the entire text
  2. The sum of the widths of each character in the text

In Chrome, they both come out at 399px. In Firefox, the first comes out as 393px, the second at 367px.

Edit: The bug has been closed. Mozilla say it's invalid, I still say it's inconsistent with the other browsers. I'll have to find another way to do this, or enough info to convince Mozilla that it's a bug after all. Thanks for listening anyway!

Dan Forys
Ok, I can only guess that this is a Firefox Javascript bug. Have reported it: https://bugzilla.mozilla.org/show_bug.cgi?id=563758
Dan Forys
I can't duplicate this in FF3.6, so this is a recent change? Have you played with letter-spacing to see if you can get these to line up? That looks like the difference to me.
ndp
Also, if the OS functions respect e.g. kerning parameters, the total widht of a text might be different than the sum of the single character widhts. If you use fonts that support it, you might even get ligatures (i.e. special characters) for certain character combinations which you cannot simulate using your approach.
MartinStettner
Yes, I think my approach is wrong, but just happened to work in Webkit and Opera. Instead of working out the width of each individual character, I should have worked out the width of the entire string up to the current character, which allows for kerning etc. I have now updated my web page so that it uses that approach; and it seems to work fine on Firefox now. (I did the update yesterday, which is prob why ndp can't reproduce it)Thanks for your input :)
Dan Forys