3

I have a situation that I use a canvas element to draw a matrix effect and the color of the matrix code text is brighter and sharper in Firefox than Chrome:

Firefox fail translucent effect

As you can see, the text in Chrome is smoother, with some blur, which is what I want.

HTML5 matrix effect: http://thecodeplayer.com/walkthrough/matrix-rain-animation-html5-canvas-javascript

The only thing I can guess is that maybe Firefox does not like the way the translucent effect is achieved:

//Black BG for the canvas
//translucent BG to show the trail

this.ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
this.ctx.fillRect(0, 0, this.$c.width(), this.$c.height());

this.ctx.fillStyle = this.color; //green text

Why is that happening? Is there a way to fix that kind of behavior in firefox by a proper way other than detecting and setting a different color for each browser?

EDIT:

The drawing code with the translucent effect:

//drawing the characters
function draw()
{
    //Black BG for the canvas
    //translucent BG to show trail
    ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
    ctx.fillRect(0, 0, c.width, c.height);

    ctx.fillStyle = "#0F0"; //green text
    ctx.font = font_size + "px arial";
    //looping over drops
    for(var i = 0; i < drops.length; i++)
    {
        //a random chinese character to print
        var text = chinese[Math.floor(Math.random()*chinese.length)];
        //x = i*font_size, y = value of drops[i]*font_size
        ctx.fillText(text, i*font_size, drops[i]*font_size);

        //sending the drop back to the top randomly after it has crossed the screen
        //adding a randomness to the reset to make the drops scattered on the Y axis
        if(drops[i]*font_size > c.height && Math.random() > 0.975)
            drops[i] = 0;

        //incrementing Y coordinate
        drops[i]++;
    }
}

setInterval(draw, 33);

Latest firefox version: 49.0.2

EDIT2:

Checked it from another computer with Firefox 39 and an old 17" TFT screen. Firefox still has not the translucent effect and the letters are bright and sharp:

Firefox fail translucent effect

UPDATE:

It appears that this is a Windows Firefox/Chrome behavior and it does not occur on macOS versions. Here is an image link with both browsers opened on macOS Mountain Lion: macOS ML Screenshot

UPDATE2:

After some search and tests, it turns out it is a font issue and how Chrome renders the characters:

enter image description here

To me, that looks like a totally different font. Chrome renders the letters using pointy ends, but Firefox uses a more solid and bold effect. Just tried to change the font on the ctx.font like ctx.font = "normal normal " + font_size + "px arial" but it does not make any difference.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
Christos Lytras
  • 36,310
  • 4
  • 80
  • 113
  • Can't repro, on both chrome and FF I've got the first result. Also, there is no `this.$c.width()` in the linked code. – Kaiido Nov 09 '16 at 06:07
  • The code is a little bit changed and it uses jQuery, though the algorithm is identical. If you check the comments at the code, you'll see these same comments (`//translucent BG to show trail`) with just some class and jQuery additions. I will try to reproduce this on another computer and I'll report back. – Christos Lytras Nov 09 '16 at 07:41
  • The problem probably comes from your modifications, without being able to see it, we can't help you. Please, either add it all as a tack-snippet inside your question, or add a working fiddle where we can reproduce your issue. – Kaiido Nov 09 '16 at 08:00
  • No. The screenshots are both from the link I provide with the original plugin code. You don't see the result of my code there, but the actual plugin of the link that I give above http://thecodeplayer.com/walkthrough/matrix-rain-animation-html5-canvas-javascript – Christos Lytras Nov 09 '16 at 08:05
  • Well from this code, **nothing** should make your text translucent : it sets the text's font to opaque `#0F0` , and nothing modifies either the context's `globalAlpha` or its gCO. So either your chromes have a bug, or you're not telling us everything. Ps: [my chrome result](https://i.stack.imgur.com/KdwVq.png) and [FF one](https://i.stack.imgur.com/zq7PJ.png). – Kaiido Nov 09 '16 at 08:16
  • Before it sets the text to an opaque color, the code **does** fill the whole canvas rectangle area with a black 50% transparent color, which makes the whole thing to have a translucent BG effect look. Here is a screenshot from a 3rd computer that showing the firefox view at the top is different and sharper than the chrome at the bottom http://zikro.gr/img/matrix_firefox_effect.png. Maybe it’s your monitor and you can’t see it. A little bit odd to have a bugged chrome installation on 3 different computers, don't you think? – Christos Lytras Nov 09 '16 at 08:33
  • *"a translucent BG effect look"* no, this is not a BG, this is a FG (ForeGround), it just makes everything remaining from last drawings a bit darker at each draw, but it never makes your text translucent. And text being drawn after this fillRect (last line of text) is not concerned by this translucent foreground so should be `#0F0` just like in your FF screenshots and in my chrome's one. This is not related to my screen, the screenshots I provided are seen by your screen. – Kaiido Nov 09 '16 at 08:47
  • And it's not `50%` but `5%` btw, you should try setting it to `rgba(0,0,0,.1)` maybe your buggy chrome's implementations (I wonder which OS it is) don't support this precision of transparency. (My tests are made on osx). An other possibility is that your buggy chromes are rendering canvas' buffer since you are using a really small setInterval. Try converting it to a `requestAnimationFrame` loop. – Kaiido Nov 09 '16 at 08:50
  • Well, yes, this is close to a translucent effect look. The key to the whole thing is the transparent BG (**BACKGROUND**) fill / erase with a 5% black. It makes each last draw a bit darker every time it draws it. The small interval is not an issue. Here you can see it with 500ms interval http://codepen.io/clytras/pen/aBvBNv But this is **NOT** the point or the problem... I am asking here how can I have the text smooth like it displays on chrome for both browsers, firefox and chrome. I tested this on win8/win10 and it's most likely that your os v (whatever) is displaying this the wrong way. – Christos Lytras Nov 09 '16 at 09:18
  • And maybe it is a bug on windows chrome or a firefox bug. If you don't have a windows machine to check that, you cannot say that I have 3 buggy installations... How can you be so sure that I have a buggy installation and you have the bug free imac/whatever solid installation? – Christos Lytras Nov 09 '16 at 09:21
  • Because I know how to read the code. I know what should be the output. Last drawn characters should be `#0F0` or `r:0, g:255, b:0, a:255` . You should never have any pixel where a text has been filled with alpha value of less than 255. You can check it using `ctx.getImageData(x, y, w, h);` – Kaiido Nov 09 '16 at 09:28
  • Yes, I know how to read the code too. It's not about the code. The problem appears to be how chrome and/or firefox renders 2d graphics on the canvas element for windows. I also have an imac with osx mountain lion installed. I can confirm that this does not occur there and both browsers have the same behavior. Here is my screenshot of OSX-ML http://zikro.gr/img/osx-firefox-canvas-colors.png. So, I'll edit my question to point out that this happens only to windows installations. – Christos Lytras Nov 09 '16 at 09:59
  • 1
    @ChristoL. good finding about the font, I now wonder why I didn't thought of it yesterday. Arial doesn't have these glyphs, so chrome will fallback on a different font than Firefox does, and in osx, they just do fallback to the same (most likely Arial Unicode MS, which is a system font), for a solution, you'll have to load a webfont which has these glyphs so everyone uses it. – Kaiido Nov 10 '16 at 06:36
  • Yes, I thought to make the font a little bit bigger to see the details and then I saw that the font was different in chrome. I'm trying to do now that you are suggesting and load an external font. A first issue that I came across, is the font size of course. Chinese fonts are huge for web (> 5MB). I'll update when I make some progress on that. – Christos Lytras Nov 10 '16 at 08:11
  • Yes there are many chinese glyphs... You could find some font which only have some of these, or even create your own, with only the few glyphs you're interested in. A useful tool : https://github.com/fontforge/fontforge/, or as correctly stated in Paolo's answer, you could even just create a sprite of these glyphs. – Kaiido Nov 10 '16 at 08:28

2 Answers2

4

As you realized on your last update text rendering is not guaranted to produce identical (pixel-level) results across browsers and operative systems.

Factors involved are the browser, the OS and the font.

The algorythms to render the font may be (usually are) different.

Some browsers use the OS to render the font some others (on some OSes) render the font with their own rendering implementation.

The smaller is the font size the more evident are differences.

See also: https://stackoverflow.com/a/30878469

I confirm I get same results on Mac OS X 10.9.5 with the example provided.

But even on Mac OS X I've experienced font rendering differences when using different browsers.


In case you need to achieve pixel level consistency in the situation posted you can use small PNG-24 images (representing the text characters) instead of text. In fact only few different characters are used and this makes possible a "sprite" vs text solution.

Community
  • 1
  • 1
Paolo
  • 15,233
  • 27
  • 70
  • 91
  • I upvote this because it's totally true. I know browsers render fonts (along with many other things) depends on many factors like OS fonts. I'll dig this a bit more and try to find a way to make it look identical (maybe find a way to set the same font for the canvas element to render in both chrome and firefox). I'll mark this as an accepted answer if I end up with no solution on how to keep things display the same way. – Christos Lytras Nov 09 '16 at 21:50
  • Actually, in my knowledge, browsers don't use OS font rendering for canvas text drawings. e.g, you won't have TrueType smoothing on a canvas. **But** they can fallback on different fonts when the glyph is not available (like probably in this case). – Kaiido Nov 10 '16 at 06:32
  • yes for the sprite idea, could also work with svg to keep vectors advantages – Kaiido Nov 10 '16 at 08:30
0

I took the path of creating a new font to reduce the font size. I replaced Regular ASCII symbols with some Unicode Chinese symbols. I used some chars of this pointy curly font Sim Sun, which has almost all of the Chinese unicode characters and with original TTC filesize of 13.4MB (It’s for demonstration purpose only, I don’t know if it’s copyrighted or not):

I could use any random chinese characters, but I used this javascript console code to get the corresponding unicode hexadecimal values of the characters I already have:

$.each(chinese.split(''), function(index, char) {
    console.log(char, char.charCodeAt(0).toString(16));
});

Then I opened the font to a font editor, search/find by char hex code, copy/paste the chinese char to standar ASCII chars from A to Z and a to z:

enter image description here

I ended up with a font file size of 25KB (OTF). I used https://www.fontsquirrel.com to generate all CSS compatible fonts (EOT, SVG, TTF, WOFF, WOFF2, total size 180KB), downloaded the package and include the fonts and the CSS to a demonstration html file. Then I just changed the font-family name to the canvas c.getContext("2d") ctx object to the name of the new imported font simsun_matrixregular (the name of the imported font):

ctx.fillStyle = "#0F0"; //green text
ctx.font = font_size + "px simsun_matrixregular";

and changing the chinese string variable from real chinese characters, to ASCII [A-Za-z]:

//var chinese = "田由甲申甴电甶男甸甹町画甼甽甾甿畀畁畂畃畄畅畆畇畈畉畊畋界畍畎畏畐畑";
var chinese = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

and now everything is displaying properly! Chrome and Firefox in windows as Chrome and Safari in OSX, all display the same result! (Almost the same. At least very close)

Windows 10, Chrome/Firefox:

enter image description here

OSX 10.11, Chrome/Safari:

enter image description here

You can check the demo page and the source code here.

Caution, the font has to be fully loaded, else the browser will draw the corresponding ASCII characters [A-Za-z] until it loads the font:

enter image description here

Maybe this whole thing is an overkill and too much work for such a detail, but at least I want to know how to make something like this to have the same effect to all browsers.

Christos Lytras
  • 36,310
  • 4
  • 80
  • 113
  • All of your serial downvotes are reverted about 3 hours ago. I guess the report works well. by the way, I'm reverting my downvotes and turn them to upvote. last night I sleep very well. I'm light and happy now. – AmerllicA Apr 29 '20 at 06:58
  • @AmerllicA Nice man. This is a community we can learn much things, and yes I can learn things from you too. The answer you gave about `%SystemRoot%` enviroment variable was the cause for errors when running CRA was nice and I didn't know about it! The serial downvote revert worked for many posts but not for all. I edited some of your posts to upvote them. Don't overdo it with upvoting cause we'll get serial upvotes strike. – Christos Lytras Apr 29 '20 at 08:14