[whatwg] <canvas> drawing with singular transforms and zero-sized gradients

Ian Hickson ian at hixie.ch
Wed Sep 21 15:19:24 PDT 2011

On Fri, 24 Jun 2011, Robert O'Callahan wrote:
> Consider this testcase:
> http://people.mozilla.org/~roc/SingularCanvasMatrix.html
> It sets up a rectangle to fill, then sets the current matrix to a singular
> matrix (yy=0 in this case), then fills with different fillStyles. It's not
> clear from the spec how this is supposed to behave

I've clarified the spec so that hopefully it is now defined, if maybe 
still not really clear.

The spec now says that solid colours aren't affect by the transformation 
matrix, gradients are (this was already defined), and patterns are 
affected _after_ the repetition is applied.

Thus solid colours should fill fine, but canvases and patterns would do 
fill nothing (though while still applying globalCompositeOperator), 
because they are scaled to an image with one dimension having zero width.

> For CanvasPatterns, I can't see any reasonable way to define any 
> rendering, so I suggest they should just paint nothing when the current 
> transform is singular. This needs a spec update I think.

That's effectively what I specced (though by saying that the pattern is 
scaled after being repeated, so there's no question of how you repeat a 
zero-width image).

> For linear CanvasGradients, I think we can follow the spec and simply 
> transform the gradient points. That would mean drawing the horizontal 
> gradient normally and drawing nothing for the vertical gradient. This 
> wouldn't need a spec change.


> I'm not sure what to do about radial CanvasGradients. We can transform 
> the center points but the effect on the radii can't be described by 
> simply transforming points. Perhaps the most logical approach would be 
> to fill with the "outside" color (black in my testcase). This needs a 
> spec update.

Would it make more sense to define that what is transformed is the 
resulting radial gradient, rather than the points while the gradient is 
drawn? (I'm not really sure what the latter really means.) I've changed 
the spec to do this.

> For solid colors I think it's logical to just fill with the color. This 
> wouldn't need a spec change.

It needed a change to indicate that the transformation matrix doesn't 

I've also added some text to define that the color of a fill or stroke 
where the pattern or radial gradient has been collapsed to a point is 
transparent black.

On Sun, 26 Jun 2011, Aryeh Gregor wrote:
> I'm thinking of the source color, gradient, or pattern conceptually 
> filling the plane (possibly almost all transparent in the case of a 
> pattern), then being transformed by the matrix, then being clipped to 
> fill the shape before being painted.  Thus in my mind it's still being 
> collapsed before being painted, even if it's just a solid color.  That 
> way a solid color is conceptually the same as a gradient with all color 
> stops the same, or a solid-colored image.

That makes sense. It's not how the spec is written.

> It seems like a useful invariant if the different styles behave the same 
> reliably when they should logically be the same.  That way authors can 
> learn about patterns first (which is very concrete -- "give it an 
> image"), then understand gradients and solid colors as special cases of 
> patterns, and be consistently right.  Authors might be surprised by the 
> behavior in this particular case, but it's a fairly pathological case 
> anyway, and it doesn't seem worthwhile to trade away consistency to get 
> more intuitive behavior in this special case.
> I guess one big problem with this approach is you have a singularity at 
> determinant zero, and that's really awkward because you can't rely on 
> floating-point equality comparisons unless you allow some tolerance for 
> rounding error, and in that case equality is no longer transitive. By my 
> theory, a transformation matrix with determinant zero should result in 
> solid colors doing nothing, but one with determinant e for any e > 0 
> should result in the color being painted.  This is obviously bad.
> So this is probably my pure math background showing through rather than 
> a very useful contribution to the discussion.  If the API were designed 
> for mathematicians, now . . .

I could see an argument either way.

On Mon, 27 Jun 2011, Robert O'Callahan wrote:
> Gradients already aren't continuous where the start and end points are 
> equal.

That's an interesting point. Legacy reasons? I haven't changed this, but 
it is inconsistent.

On Sat, 25 Jun 2011, Robert O'Callahan wrote:
> If you set up a path covering the entire canvas, call ctx.scale(e, e) 
> for infinitesimal e, and then fill with an image pattern, conceptually 
> you're scaling the image to be incredibly small and then repeating it a 
> very large number of times to fill the canvas. So I guess the logical 
> behavior for e=0 would be to compute the average color of the image 
> pixels and do a solid fill with that color, which would give you that 
> consistency you're asking for. But is that worth implementing? No-one 
> does that today.

I've gotten around this by defining that the scaling happens after the 

Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

More information about the whatwg mailing list