[whatwg] canvas CTM handling (was: CanvasRenderingContext2D with addPath, currentPath)
Rik Cabanier
cabanier at gmail.com
Tue Nov 5 12:50:08 PST 2013
changing the subject because we're not talking about paths anymore.
On Tue, Nov 5, 2013 at 10:14 AM, Dirk Schulze <dschulze at adobe.com> wrote:
>
> On Nov 5, 2013, at 6:56 PM, Rik Cabanier <cabanier at gmail.com> wrote:
>
>
>
>
> On Tue, Nov 5, 2013 at 4:29 AM, Dirk Schulze <dschulze at adobe.com> wrote:
>
>>
>> On Nov 5, 2013, at 5:22 AM, Rik Cabanier <cabanier at gmail.com> wrote:
>>
>> > On Mon, Nov 4, 2013 at 7:29 PM, Rik Cabanier <cabanier at gmail.com>
>> wrote:
>> >
>> >>
>> >>
>> >> On Mon, Nov 4, 2013 at 5:21 PM, Robert O'Callahan <
>> robert at ocallahan.org>wrote:
>> >>
>> >>> If you return a path in user-space, what do you get if you call
>> >>> getCurrentPath with a singular transform?
>> >>> ctx.moveTo(0,0);
>> >>> ctx.lineTo(1,1);
>> >>> ctx.scale(0,0);
>> >>> var p = ctx.getCurrentPath();
>> >>>
>> >>
>> >> I mixed up my terms :-)
>> >> getCurrentPath should return the path in device coordinates (not user).
>> >>
>> >> However, for your example, I'm unsure what the right solution is. The
>> >> canvas specification is silent on what the behavior is for
>> non-invertible
>> >> matrices.
>> >> I think setting scale(0,0) or another matrix operation that is not
>> >> reversible, should remove drawing operations from the state because:
>> >> - how would you stroke with such a matrix?
>> >> - how do patterns operate? the same for gradient fills.
>> >> - how would you pass this to the underlying graphics library?
>> >> - certain operators such as 'arc' rely on doing the transform in
>> reverse.
>> >>
>> >> I seem to remember that for SVG we decided that non-invertible matrices
>> >> don't draw either.
>> >>
>> >
>> > After pondering this some more and looking at the different
>> > implementations, I propose the following:
>> > if the user sets a non-invertible matrix, the canvas context should be
>> in a
>> > state that ignores all path drawing operations, stroke/fill calls and
>> all
>> > other ctm operations (apart from setTransform). setCurrentPath is also
>> > ignored and getCurrentPath should return an empty path.
>> > If the ctm becomes invertible again (from a setTransform or a restore),
>> > drawing operations pick up again with the currentPoint that was active
>> when
>> > the non-invertible matrix was set.
>>
>> This is not the behavior of current browsers as discussed in a different
>> threat about non-invertible CTMs. Firefox seems to add new path segments to
>> the coordinate origin. The behavior of WebKit is a bit different and
>> depends how the matrix got not-invertable.
>
>
> Yes, I was looking at the WebKit implementation since it looked the most
> sensible.
> I'm unsure why you say "how the matrix got not-invertable". There are
> checks all over the code to skip if the CTM is non-invertible, ie:
>
> void CanvasPathMethods::moveTo(float x, float y){
>
> ...
>
> if (!hasInvertibleTransform())
>
> return;
>
>
>
>> I am supportive for clear rules at this point. Ian’s response so far was
>> that it doesn’t need any further definition. That is why no implementation
>> changed the behavior since then.
>
>
> Is this the link:
> http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org//2013-January/038798.html
> I don't see any replies...
> You had an error in one of your examples which probably why you thought
> there was still drawing after scale(0,0), here are updated links:
>
> http://jsfiddle.net/Dghuh/5/
> http://jsfiddle.net/Dghuh/6/
>
>
> I need to check the code again, it might be a mistake in the examples. I
> was wondering about the mistake. Yes, WebKit has a lot of checks in the
> code to avoid drawing (helped to add them :)).
>
> Reply to my original post was on July 18 :) so you need to look a bit
> further into the future :P
>
I found Ian's reply:
http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-July/040149.html
What's lost in his reply is that Canvas is supposed to transform the
existing path to the new CTM when you change the matrix. All browsers are
doing that differently.
WebKit does that consistently.
Firefox jumps through strange hoops by transforming the path to device
space and then back to user space at fill/stroke time.
So for this case:
ctx.beginPath();ctx.lineTo();...
ctx.scale(0,0);
ctx.lineTo(...);
ctx.fill();
ctx.stroke();
- WebKit checks for a non-invertible matrix when setting scale and set the
context to a state that ignores drawing operators.
- Firefox will convert the internal path to device space at scale time and
will apply the non-invertible matrix to drawing operators. The stroke and
fill operator will try to apply the non-invertible matrix to the path which
fails and then draws nothing.
- IE seems to be doing the same as Firefox, except they ignore the
non-invertible CTM for fill and stroke.
Just looking at the complexity (and overhead) of the FF code compared to WK
and the fact that WK is easier to understand, I still think we should spec
that behavior.
It's very unlikely that anyone if building on the current behavior.
>
>
>> >
>> > I could be convinced that set/getCurrentPath should still work...
>> >
>> > so If I expand your example a bit:
>> >
>> > ctx.moveTo(0,0);
>> > ctx.lineTo(1,1);
>> > ctx.scale(0,0);
>> > var p = ctx.getCurrentPath(); // return empty path
>> >
>> > ctx.stroke(); // nothing happens
>> >
>> > ctx.setTransform(1,0,0,1,0,0);
>> > p = ctx.getCurrentPath(); // return path with moveto/lineto
>> > ctx.stroke(); // draw line
>> >
>> >
>> > This would match what WebKit and Blink are doing.
>> > Firefox gets in a bad state as soon as you set a non-invertible matrix
>> but
>> > we could fix that ;-)
>>
>> Again, the behavior is different depending on how you got to the
>> not-invertible CTM, which is obviously not great. I would be supportive of
>> not adding any path segments unless the CTM is invertible.
>>
>> > IE keeps drawing and even strokes when scale(0,0) is set.
>> >
>> > It would be nice to have interop…
>>
>> Yes!
>>
>> Greetings,
>> Dirk
>>
>>
>
>
More information about the whatwg
mailing list