Last Comment Bug 571708 - Transformations confuse canvas drawing with radial gradient fills
: Transformations confuse canvas drawing with radial gradient fills
Status: NEW
Product: Core
Classification: Components
Component: Canvas: 2D (show other bugs)
: unspecified
: All All
: -- normal with 1 vote (vote)
: ---
Assigned To: Nobody; OK to take it and work on it
: Milan Sreckovic [:milan]
Depends on:
  Show dependency treegraph
Reported: 2010-06-12 14:17 PDT by Bjoern Hoehrmann
Modified: 2011-07-12 01:31 PDT (History)
7 users (show)
See Also:
Crash Signature:
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---

test case which exhibits strange behavior (645 bytes, text/html)
2011-07-06 21:00 PDT, Shaon Barman
no flags Details
test case which exhibits strange behavior (extra fillRect added) (643 bytes, text/html)
2011-07-06 21:02 PDT, Shaon Barman
no flags Details
Test for bug 571708 (2.62 KB, patch)
2011-07-08 11:26 PDT, Chris Jones [:cjones] inactive; ni?/f?/r? if you need me
no flags Details | Diff | Splinter Review

Description Bjoern Hoehrmann 2010-06-12 14:17:15 PDT
User-Agent:       Opera/9.80 (Windows NT 5.2; U; en) Presto/2.5.22 Version/10.51
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv: Gecko/20100611 Namoroka/3.6.6pre

<canvas id='can' width='640' height='480'></canvas>
onload = function() {

  var ctx = document.getElementById('can').getContext('2d');
  var grd = ctx.createRadialGradient(50, 50, 0, 50, 50, 50);
  grd.addColorStop(0.0, 'rgba(0,0,0,0.5)');
  grd.addColorStop(1.0, 'rgba(0,0,0,0)');
  ctx.fillStyle = grd;

  for (var i = 0; i < 100; ++i) {
    var x = Math.random()*640 - 50;
    var y = Math.random()*480 - 50;
    ctx.translate(x, y);
    ctx.fillRect(0, 0, 100, 100);
    ctx.translate(-x, -y);
    // ctx.fillStyle = grd;

The rendering changes dramatically depending on whether `ctx.fillStyle` is set in the loop or not; that however should have no effect.

Reproducible: Always
Comment 1 Boris Zbarsky [:bz] (still a bit busy) 2010-06-12 20:28:15 PDT
Indeed, seems like the rendering should be the one you see with the in-loop fillStyle.

vlad, do we need to DirtyAllStyles on transformation matrix changes or something?
Comment 2 Joe Drew (not getting mail) 2010-07-20 10:35:25 PDT
We should fix this, but it doesn't block.
Comment 3 Shaon Barman 2011-07-06 16:05:26 PDT
I also ran across a related bug in the following snippet.

    canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var grad = ctx.createRadialGradient(0,0,100,0,0,200);
    grad.addColorStop(0, 'red');
    grad.addColorStop(1, 'blue'); 
    ctx.fillStyle = grad;
//    ctx.fillRect(0,0,0,0); 

As it is, the gradient does not render properly, but when ctx.fillRect(0,0,0,0) is uncommented, then the gradient shows.
Comment 4 Andreas Gal :gal 2011-07-06 16:07:27 PDT
This behaves differently depending on platform, so this really should get fixed. Chris said the spec is not clear on this.
Comment 5 Chris Jones [:cjones] inactive; ni?/f?/r? if you need me 2011-07-06 20:04:25 PDT
I was wrong about the spec: on second reading, I found "The points in the radial gradient must be transformed as described by the current transformation matrix when rendering."  D2D produces what I believe to be correct results on this test, solid-blue rect filled from <x=300,y=300>.
Comment 6 Andreas Gal :gal 2011-07-06 20:49:29 PDT
Shaon, can you attach a test case people can click on so we can try a few platforms?
Comment 7 Shaon Barman 2011-07-06 21:00:48 PDT
Created attachment 544402 [details]
test case which exhibits strange behavior

the call to fillRect(0,0,0,0) causes the picture to render differently
Comment 8 Shaon Barman 2011-07-06 21:02:15 PDT
Created attachment 544403 [details]
test case which exhibits strange behavior (extra fillRect added)
Comment 9 Andreas Gal :gal 2011-07-06 21:02:56 PDT
I get a solid blue rect on macosx with nightly and safari. On what platform is the output different?
Comment 10 Andreas Gal :gal 2011-07-06 21:04:20 PDT
Ah ok so D2D is wrong too Chris. I see the fill now with Nightly (with the extra fillRect). Safari shows a solid blue rect, so the hack doesn't seem to work there.
Comment 11 Shaon Barman 2011-07-06 21:05:16 PDT
I am using Ubuntu. It shows with both the nightly build and Firefox 4.
Comment 12 Andreas Gal :gal 2011-07-06 21:07:16 PDT
No luck with macosx/chrome and macosx/opera either. Extra fillRect or not the result is a solid blue rect.
Comment 13 Chris Jones [:cjones] inactive; ni?/f?/r? if you need me 2011-07-07 05:21:21 PDT
The solid blue rect is the correct rendering, if I'm reading the spec and test correctly.

My D2D nightly shows that on both tests, but I do see the gradient drawn in the second test in FF4.  That suggests a canvas/cairo or a cairo bug.  Will ask around today.
Comment 14 Chris Jones [:cjones] inactive; ni?/f?/r? if you need me 2011-07-07 07:22:45 PDT
Some more notes
 - AFAICT from the spec, removing the transforms and fillRect(0,0,0,0) should result in the same behavior as leaving them all in.
 - In FF nightly: in all permutations of transforms/null-fill, only a solid blue box is drawn
 - In IE9: same
 - In FF5
   * with the transforms removed and null-fill or not, blue box
   * with transforms but no null-fill, blue box
   * with transforms and null-fill, gradient centered on <x=500,y=500>

I think we have a bug in the cairo canvas backend where we don't recreate the gradient pattern when the transform changes.  (Or don't create it lazily with the wrong transform.)  This may be a WONTFIX since the azure backend gets it right.
Comment 15 Chris Jones [:cjones] inactive; ni?/f?/r? if you need me 2011-07-08 11:26:01 PDT
Created attachment 544867 [details] [diff] [review]
Test for bug 571708

Note You need to log in before you can comment on or make changes to this bug.