w3c / svgwg

SVG Working Group specifications
Other
710 stars 133 forks source link

Incorrect sweep-flag in circle/ellipse equivalent path #765

Open dalboris opened 4 years ago

dalboris commented 4 years ago

The equivalent path of a circle (similar for ellipses) is currently defined as:

https://svgwg.org/svg2-draft/shapes.html#CircleElement

The rx and ry parameters to the arc commands are both equal to the used value of the r property, after conversion to local user units, while the x-axis-rotation, the large-arc-flag, and the sweep-flag are all set to zero. The coordinates are computed as follows, where cx, cy, and r are the used values of the equivalent properties, converted to user units:

A move-to command to the point cx+r,cy;
arc to cx,cy+r;
arc to cx-r,cy;
arc to cx,cy-r;
arc with a segment-completing close path operation.

I think this is incorrect, that is, the sweep-flag should be 1, not 0, like it is for rounded rects for example (both are traced clockwise).

With the current equivalent paths, I get this for some of the examples in the spec, showing that:

image

dalboris commented 4 years ago

Minimal example: the current SVG 2 draft says that the equivalent path for:

<circle cx="0" cy="0" r="100" />

should be:

    M                100    0
    A 100 100 0 0 0   0   100
    A 100 100 0 0 0 -100    0
    A 100 100 0 0 0   0  -100
    A 100 100 0 0 0  100    0
    Z

(ignoring the segment-completing close path operation to make it a valid path data string)

See below how Chrome renders this path (left), compared to how Chrome renders the path if we change sweep-flag to 1 (right).

<?xml version="1.0" standalone="no"?>
<svg width="550px" height="300px" viewBox="0 0 550 300" xmlns="http://www.w3.org/2000/svg">
  <path transform="translate(150,150)" d="
    M                100    0
    A 100 100 0 0 0   0   100
    A 100 100 0 0 0 -100    0
    A 100 100 0 0 0   0  -100
    A 100 100 0 0 0  100    0
    Z" />
  <path transform="translate(400,150)" d = "
    M                100    0
    A 100 100 0 0 1    0  100
    A 100 100 0 0 1 -100    0
    A 100 100 0 0 1   0  -100
    A 100 100 0 0 1  100    0
    Z" />
</svg>

image

caribouW3 commented 7 months ago

You can draw a circle in different ways using paths, so that's a bit tricky.

<?xml version="1.0" standalone="no"?>
<svg width="550px" height="300px" viewBox="0 0 550 300" xmlns="http://www.w3.org/2000/svg">
   <path transform="translate(150,150)" d="
     M                100    0
    A 100 100 0 0 0   0   -100
    A 100 100 0 0 0 -100    0
    A 100 100 0 0 0   0  100
    A 100 100 0 0 0  100   0       Z" />
</svg>

draws a circle, with a sweep-flag set to 0. The example in the 2nd comment is not from the spec prose, so it's difficult to interpret this as a spec bug.

dalboris commented 6 months ago

@caribouW3 I think you overlooked some parts of the spec prose: the coordinates of the equivalent arc commands of a <circle> are mandated by the spec, so you cannot change them like you have done in your example.

In other words, the following example (that I provided earlier):

<path transform="translate(150,150)" d="
    M                100    0
    A 100 100 0 0 0   0   100
    A 100 100 0 0 0 -100    0
    A 100 100 0 0 0   0  -100
    A 100 100 0 0 0  100    0
    Z" />

image

is exactly what the current spec mandates as equivalent path for <circle cx="0" cy="0" r="100" /> (no room for interpretation), while the example that you provide does not.

The current spec prose is very specific (but wrong) and currently mandates that the equivalent path for a <circle> element is the following:

Where:

So with this circle: <circle cx="0" cy="0" r="100" />, we have:

And the above is not a circle but the star shape on the top of this comment.

I have exhaustively implemented these equivalent paths in my SVG renderer and I am very confident that the current prose is incorrect, and that the sweep-flag should be mandated to be set to one, as corrected by https://github.com/w3c/svgwg/pull/878.