- From: Philip Taylor <pjt47@cam.ac.uk>
- Date: Wed, 16 Jan 2008 01:24:53 +0000
- To: HTML WG <public-html@w3.org>

Some rough comments on the recent canvas changes (which made transformations take effect when paths are constructed, rather than when they're drawn, for compatibility with Firefox and Safari): "The transformation matrix can become infinite, at which point nothing is drawn anymore." - that doesn't really make sense now, since it's not a rule that can be applied when drawing. You could make the transformation matrix infinite, then make it finite again, then create some path, then fill, and it should probably draw the path. Or you could make it infinite, create a bit of path, make it finite, create more path, then draw, and it should probably draw just the second bit of path. At least that's what Safari does. Firefox throws exceptions whenever you pass in infinity to a method. I wouldn't mind if it was specified to always throw exceptions when passing infinity/NaN to a method, or maybe if it was explicitly undefined - implementation details already mean you can't get theoretically correct results when scaling by e.g. 10^38, so it's not much worse if infinity is treated the same way... createLinearGradient, createRadialGradient: How are those coordinates affected by the CTM? "The coordinates given in the arguments to these methods must be transformed according to the current transformation matrix before applying the calculations described below and before adding any points to the path." - that is true for moveTo, lineTo, quadraticCurveTo, bezierCurveTo. It is not true for the others: arcTo: Transforming the coordinates is not equivalent to transforming the whole path - e.g. a non-uniform scale should result in a path that's not a circular arc, since it'll be stretched in some direction. (See http://philip.html5.org/demos/canvas/scale-arcto.html in WebKit (nobody else is remotely near implementing arcTo properly).) So the curve should be calculated in a local space, then transformed back into canvas space with the CTM. That means (x0, y0) needs to be the last point in the subpath transformed from canvas space into local space (i.e. the inverse of the CTM), so that it's correct when transformed back. So I think arcTo could be defined like: """[No implicit transformation of the arguments, and then] Let the point (x0, y0) be the last point in the subpath, transformed by the inverse of the current transformation matrix. Blah blah The Arc blah blah. Blah. The Arc and the start and end tangent points must then be transformed by the current transformation matrix. Blah blah. Otherwise, the method must connect the last point in the subpath to the start tangent point by a straight line, then connect the start tangent point to the end tangent point by The Arc, and finally add the start and end tangent points to the subpath.""" (Of course the inverse of the CTM is undefined if e.g. you call scale(0, 0). That's an edge case that probably needs more investigation...) arc: Same problem as arcTo. """Consider a circle blah blah. The points at blah are the start and end points respectively. The arc is blah. The arc and the start and end points must then be transformed by the current transformation matrix.""" rect: The four corner coordinates are what need to be transformed, not the arguments to the method. """The rect(x, y, w, h) method must create a new subpath containing just the four points (x, y), (x+w, y), (x+w, y+h), (x, y+h), transformed by the current transformation matrix, with those four points connected by straight lines, and must then mark the subpath as closed. It must then create a new subpath with the point (x, y), transformed by the current transformation matrix, as the only point in the subpath." And also: "The stroke() method must stroke each subpath of the current path in turn, using the strokeStyle, lineWidth, lineJoin, and (if appropriate) miterLimit attributes." - that should also say something like "The line width must be scaled by the current transformation matrix." (that's not really true (it needs to at least be skewed as well, and I'm not sure of the exact details), but stroke drawing is totally underdefined anyway and so there's not much point being precise here now), since I think it's clearer to say it here (as it's directly relevant to the outcome of stroke()) rather than hidden in the '3.14.11.1.11. Drawing model' section. (Also, 'Drawing model' shouldn't need to say that fill/stroke styles etc are honoured, since the definitions of stroke() and fill() already say that.) "Paths, when filled or stroked, must be painted without affecting the current path, and must be subject to transformations, shadow effects, global alpha, clipping paths, and global composition operators." - remove the "transformations" since the paths aren't transformated when filling or stroking. "Note: The transformation is applied to the path when it is drawn, not when the path is constructed. Thus, a single path can be constructed and then drawn according to different transformations without recreating the path." - delete that since it's lying now. -- Philip Taylor pjt47@cam.ac.uk

Received on Wednesday, 16 January 2008 01:25:02 UTC