[whatwg] <canvas> paths without a current point.

Currently the spec says that if you call lineTo(), quadraticCurveTo(),
bezierCurveTo(), etc without a "current point" (having called moveTo()
first), they should do nothing.

The compatibility problem we've run into is that since Firefox just
calls directly into Cairo, they don't follow this behavior and they
inherit the Cairo behavior.  For lineTo(), this means if there is no
current point (there was no call to moveTo first), it is equivalent to
calling moveTo(), and then lineTo() (creating a zero length line).

This has led people to write code like this:

for (...) {
  ctx.lineTo(...);
}

I understand why that style is desirable, it's much simpler than
writing (the correct):

for (...) {
  if (i == 0) {
    ctx.moveTo(...);
  } else {
    ctx.lineTo(...);
  }
}

It happens to look ok in Firefox, so people don't notice it's wrong.

Things get more interesting when you make a Bezier curve.  The Cairo
behavior (and thus the Firefox behavior) is to moveTo() to the first
control point.  Since the control points of a Bezier don't generally
lie on the path, this is behavior looks quite odd.

While the current spec is most pure, I am interested in opinions of
bending it a little to meet somewhere in the middle.

I just committed a patch to WebKit so that if a current point doesn't
exist, moveTo() is called on the endpoint (of a line or a curve), but
no line or curve is emitted.  This means WebKit went from following
the spec to violating the spec, but working on pages that people
expect to work.

This behavior still works for multiple calls to lineTo without a
moveTo, the first lineTo doesn't create a zero-length line, it just
does the moveTo().  Further calls actually start creating lines.  This
also avoids the control point problem, as you don't emit the first
curve, just set the endpoint as the current point.

I haven't looked at arcTo(), so I'm not sure how it should behave.

Thoughts?

Thanks
Dean

Received on Thursday, 16 July 2009 08:44:10 UTC