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

On Fri, Jun 24, 2011 at 10:52 PM, Robert O'Callahan
<robert at ocallahan.org> wrote:
> That's true if you call fillRect(), or fill() on a path that you've emitted
> while the current matrix is singular; the rectangle or path collapses to a
> single point (or line). I think it's completely clear browsers should draw
> nothing in those cases.
>
> However, my testcase emits a path while the matrix is non-singular, so the
> canvas-space path is definitely not collapsed to a point or line, then makes
> the matrix singular just for the fill operation. The question is then how
> the singular matrix affects the way the source color, gradient or pattern
> fills a non-empty path.

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.

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 . . .

On Fri, Jun 24, 2011 at 11:00 PM, Robert O'Callahan
<robert at ocallahan.org> 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.

What does everyone do today instead?  I'm guessing canvas doesn't
currently define how you should apply the transformation matrix
precisely, and in particular how to handle cases like this with
subpixel detail.  The same issue should arise for gradients with very
small stops (as Tab points out), or ones with large stops that are
scaled down a lot.

If e were exactly zero, though, the logical behavior in my
interpretation would be to paint nothing for any operation whatsoever,
since the determinant is zero.  But again, that's problematic.

Received on Sunday, 26 June 2011 15:14:57 UTC