[whatwg] Canvas arc

For the 'arc' function:

What if startAngle = endAngle? What if endAngle > 2? + startAngle?
(The endAngle = 2? + startAngle case isn't interesting since
floating-point imprecision means it will never occur.)

In practice: (see the left half of
<http://canvex.lazyilluminati.com/misc/arc.html> for a (unhelpfully
unlabelled) random collection of examples)

If startAngle = endAngle:
  Firefox (2+3), Safari (3): Nothing is drawn.
  Opera (9.2+9.5): If anticlockwise = true, a full circle is drawn;
otherwise, nothing is drawn.

If endAngle > startAngle + 2?:
  Opera is weird and buggy and would require too much effort to analyse.
  Firefox and Safari mostly match:
  (Assume startAngle = 0 in all the following)

  If endAngle = 2? + ? [where ? is a small positive real number]:
    A full circle is drawn.
  If endAngle = 3? - ?:
    If anticlockwise, 0 to -? is drawn; otherwise a full circle is
drawn, and the 0 to ? part is drawn twice (i.e. drawn on top of
itself, which is visible due to antialiasing effects).
  If endAngle = 2n? - ? for integer n > 1:
    If anticlockwise, nothing is drawn; otherwise:
       Firefox: A full circle is drawn twice.
       Safari: A full circle is drawn n times.
  (Swapping startAngle vs endAngle is equivalent to swapping clockwise
vs anticlockwise.)

So, for FF/Safari: When startAngle -> endAngle is in the opposite
direction to the (anti)clockwise flag, the two angles are treated
modulo 2? and the arc is drawn between them in the appropriate
direction. When it's the same direction as the (anti)clockwise flag,
Safari extends the path all the way from startAngle to endAngle (going
round the whole circle multiple times if necessary), and Firefox does
the same except it skips all but the first full
going-round-the-whole-circle bit (so it goes round 1 <= n < 2 times,
if abs(startAngle-endAngle) > 2?).

It seems sensible to adopt either Firefox's or Safari's approach
(which differ only in the amount of overdraw). It's probably easier to
use Firefox's, so then Safari would just have to mod the angles a
little before drawing them, because I can't see any other reason to
choose one approach over the other, and I can't see any reason to
choose a totally different approach.

Talking about arcs is confusing when the arc is more than a full
circle and wraps around itself and isn't really a mathematical arc any
more, so I think it's necessary to not define the operation in terms
of arcs. The best I can think of is:

"""
Let da = endAngle - startAngle.
If anticlockwise is true, and da > 0 or da < -2?, then let d = (da % 2?) - 2?.
If anticlockwise is false, and da < 0 or da > 2?, then let d = (da % 2?) + 2?.
If neither of these cases applies, then let d = (da % 2?).
In this algorithm, the % operator is defined to have the same
semantics as the ECMAScript % operator.
The arc is defined by the points (radius*cos(a), radius*sin(a)) for
all a between startAngle and startAngle + d. The points at a =
startAngle and at a = startAngle + d are the path's start and end
points respectively.
"""

(The relevance of using the ECMAScript % operator is that (-3) % 2 =
-1, etc, so it handles negative numbers (and floating-point numbers)
in the way that is needed here, and I can't think of a better way to
say the same thing that's still as well-defined and not horribly
verbose.)

The right half of <http://canvex.lazyilluminati.com/misc/arc.html> is
implemented as above, and gives exactly the same behaviour as FF in
all the cases I have tried.

-- 
Philip Taylor
excors at gmail.com

Received on Tuesday, 3 July 2007 13:21:40 UTC