Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
dalboris opened this issue Dec 10, 2019 · 3 comments · Fixed by #878
Closed

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

dalboris opened this issue Dec 10, 2019 · 3 comments · Fixed by #878

Comments

@dalboris
Copy link

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:

  • Path-data elliptical arcs are drawn correctly
  • Rounded rects using 1 as sweep-flag are rendered correctly
  • Circles and ellipses using 0 as sweep-flag are rendered incorrectly

image

@dalboris
Copy link
Author

dalboris commented Dec 10, 2019

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
Copy link
Member

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
Copy link
Author

dalboris commented May 9, 2024

@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:

  • 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.

Where:

  • cx, cy, and r refer to the parameters of the <circle> element
  • All arc flags are set to zero
  • The rx and ry parameters of the arc commands are equal to the r parameter of the <circle> element

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

  • Move to cx+r, cy = 0+100, 0
  • Arc to cx,cy+r = 0, 0+100
  • Arc to cx-r,cy = 0-100, 0
  • Arc to cx,cy-r = 0, 0-100
  • Segment-completing arc: 0+100, 0 (same coordinate as the move to command)

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 #878.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants