w3c / svgwg

SVG Working Group specifications
Other
696 stars 132 forks source link

The interpolation of large_arc_flag/sweep_flag of Elliptical Arc in SVG Path #543

Open BorisChiou opened 5 years ago

BorisChiou commented 5 years ago

There is an existed problem about the interpolation on the flags of elliptical arc curves, i.e. large_arc_flag and sweep_flag. These two flags could determine the arc among 4 different combinations. The current spec [1] mentions that

Flags and booleans must be interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true.

If two flags are matched, everything is fine. If not, it seems we have to interpolate the flags as real number, and then set the flag as true if its interpolated value is not equal to zero. However, the current wpt of offset-path [2] conflicts this. That is, it flips the flags by comparing it with 0.5. I believe this is the behavior in Blink. In Firefox, if the boolean values don't match, treat the whole path as not interpolable and fall back to discrete animation. The reason is in Bug 653928, i.e. Firefox guys thought the behavior (i.e. interpolation between different flag values) in the spec is useless if the flags don't match.

Just want to know which way is better and does the spec make sense? (Probably this is about mathematics.) It'd be better to have a useful and consistent behavior on different browsers.

cc: @birtles @ericwilligers

birtles commented 5 years ago

cc @jwatt who had concerns about the behavior specified in SVG.

tabatkins commented 5 years ago

I think in general the "flip at .5" behavior is far more preferable; it avoids privileging one value over another. (We purposely do this in exactly one case in CSS, the visibility property, but that's motivated by specific use-cases. I don't see a reason for preferring one value over another for the arc or sweep flags.)

This also, then, just falls out of the CSS definition of how to interpolate things that aren't otherwise interpolable, and matches the now-generic CSS treatment of non-integer values in integer contexts (both in animation, and as the result of a math function like calc()).

birtles commented 5 years ago

This also, then, just falls out of the CSS definition of how to interpolate things that aren't otherwise interpolable, and matches the now-generic CSS treatment of non-integer values in integer contexts (both in animation, and as the result of a math function like calc()).

I think it still needs to be specced since we need to clarify whether the "fall-back to 50% flip" applies to the individual command or to the value as a whole. My understanding is that in the absence of any other text, it would apply to the value as a whole, but we want it to apply to the command here. Let me see if I can make up a PR later today. (I'll be away next week so if I don't get to it, feel free to do it for me!)

(My take on the 50% flip behavior is that it's rarely desirable and that step-end is often more useful. But that ship has sailed so I'm quite happy to apply the 50% flip behavior here.)

ewilligers commented 5 years ago

@tabatkins - you haven't addressed the second question about whether the whole path should flip at 0.5 or if the non-arc-flag numbers should interpolate smoothly.

e.g. offset-rotate from auto 0deg to 180deg flips the entire value at 0.5, there is is no auto 45deg at 0.25. Similarly, offset-path from ray(0deg closest-side) to ray(180deg farthest-corner) flips the entire value at 0.5, there is is no ray(45deg closest-side) at 0.25.

Should paths do the same if the arc flags are inconsistent? SMIL interpolates other numbers in the path smoothly even if there is an arc flag change. Blink does too for CSS animation of d and offset-path.

tabatkins commented 5 years ago

I didn't address it because I wasn't intending to; that's a separate question. ^_^

The spec does indeed need to clarify the resolution at which path interpolation-validity (and thus, fallback) is checked.

I think it's reasonable to say that an arc command with mismatched flags doesn't interpolate smoothly at all, and just flips the entire command at .5.

My take on the 50% flip behavior is that it's rarely desirable and that step-end is often more useful.

Note that the current specced behavior (and that of visibility) isn't step-end either...

birtles commented 5 years ago

My take on the 50% flip behavior is that it's rarely desirable and that step-end is often more useful.

Note that the current specced behavior (and that of visibility) isn't step-end either...

Yep, visibility is separate and I understand the use cases for that. I'm suggesting for other properties step-end is a better default behavior. But again, I suspect it's too late to change that.

tabatkins commented 5 years ago

Yeah, I would prefer we not try to revisit that decision. ^_^

ewilligers commented 5 years ago

I think it still needs to be specced since we need to clarify whether the "fall-back to 50% flip" applies to the individual command or to the value as a whole. My understanding is that in the absence of any other text, it would apply to the value as a whole, but we want it to apply to the command here.

I think it's reasonable to say that an arc command with mismatched flags doesn't interpolate smoothly at all, and just flips the entire command at .5.

Flipping an arc command (i.e. the radius, etc), but not the path as a whole, is non-trivial and not useful as the path will also contain other commands.

In an animation from M ... A ... 0 0 100 200 L 103 204 to M ... A ... 1 1 900 800 L 903 804 the line direction and length should be constant.

Flipping only the flag is reasonable, flipping the entire path is reasonable, flipping just the arc command is not.

birtles commented 5 years ago

Flipping only the flag is reasonable, flipping the entire path is reasonable, flipping just the arc command is not.

I had in mind flipping just the value, but are you suggesting we flip the path?

ewilligers commented 5 years ago

In an animation from M ... A ... 0 0 100 200 L 103 204 to M ... A ... 1 1 900 800 L 903 804 , what should we have at 25%? Flipping the flag (Blink behavior) means M ... A ... 0 0 300 350 L 303 354 and discrete animation of the path would mean M ... A ... 0 0 100 200 L 103 204 . I claim both are reasonable but flipping the entire arc command to give M ... A ... 0 0 100 200 L 303 354 is not reasonable (it is more complex to implement, surprising for authors and breaks the consistency of semantics between absolute and relative commands).

birtles commented 5 years ago

I don't think it makes too much difference in Gecko at which granularity we check for interpolability and I don't have a good sense which is more useful default for authors (I can imagine cases where each would be desirable).

In the past I think we've tended towards a coarse granularity, i.e. if one part can't be interpolated → the whole property can't be interpolated. (If I recall correctly we specifically made Servo more coarse-grained.)

That said I somewhat lean towards localizing the application of 50% flip behavior, i.e. flip the flag. Each of the alternative behaviors can be emulated by repeating values as necessary but repeating values to get the flip behavior seems more intuitive than the reverse: repeating values to avoid the flip behavior. (And for the case of applying the 50% flip to the whole path, in some limited circumstances that can be achieved with a step timing function.)

ewilligers commented 5 years ago

That said I somewhat lean towards localizing the application of 50% flip behavior

We can phrase it as interpolating an integer, clamped between 0 and 1.

BorisChiou commented 5 years ago

Either way is ok to me. For now, I let Gecko fall back the entire path to use the discrete animation if the arc flags don't match. I'm happy to change this behavior after spec is updated or everyone agrees to apply the 50% flip to arc flags.

css-meeting-bot commented 5 years ago

The SVG Working Group just discussed The interpolation of large_arc_flag, and agreed to the following:

The full IRC log of that discussion <krit> topic: The interpolation of large_arc_flag
<krit> GitHub: https://github.com/w3c/svgwg/issues/543
<krit> krit: thought SMIL animates it half way already? What is the difference?
<krit> chris: it affectively is a boolean that gets flipped.
<krit> krit: doesn't the flip at 0.5 happen already?
<krit> AmeliaBR: no, SVG SMIL defines that integers get interpolated as number and everything not 1 gets set to 0.
<AmeliaBR> s/not 1 gets set to 0/not 0 gets set to 1/
<krit> AmeliaBR: would a change here affect that all SMIL animated integers would animate the half-way flip?
<krit> krit: this is likely for WebKit and Blink.
<krit> krit: Many SVG 1,1 tests may fail if implementations change for all SMIL integer animations.
<krit> chris: but likely not the tests on WebPlatform.
<krit> krit: probably not.
<krit> chris: we have the option to change the test then or remove it as obsolete.
<krit> krit: I am nor sure if implementations would care about the change.
<krit> AmeliaBR: we could allow to use both ways recommending the half-way flip.
<krit> Tavmjong: did anyone test it yet.
<krit> krit: I see that Brian is participating in the issue as well. Is that something that the web animation spec can do it.
<krit> AmeliaBR: There is no other spec that defines how to interpolate path.
<krit> chris: I think the motion spec might define it.
<krit> chris: ppl using path Interpolation probably don't use elliptic path segments.
<krit> AmeliaBR: likely but we need to define it still.
<krit> krit: any preferences?
<krit> chris: My preference is flipping at 0.5.
<krit> Tavmjong: me too.
<krit> AmeliaBR: most sensible.
<krit> AmeliaBR: Likely no serious web compatibility issue.
<krit> AmeliaBR: but there should be a note that the behavior changed,
<krit> AmeliaBR: Motion path is deferring to SVG 1.1
<krit> krit: do we still have the animation chapter? Think we removed it.
<krit> AmeliaBR: defined in the path chapter. That needs to be written as an abstract data type instead of a certain property.
<krit> AmeliaBR: change needs to happen in https://svgwg.org/svg2-draft/paths.html#TheDProperty 7th paragraph
<krit> AmeliaBR: We also need to add interpolation for the path() function.
<krit> chris: I can take that and do the edit.
<krit> AmeliaBR: Check with Eric.
<krit> chris: yes will add ppl to the PR reviewer list.
<krit> RESOLUTION: Flipping boolean and integers half way for path interpolation
AmeliaBR commented 5 years ago

The edits for this issue need to be integrated with spec edits related to #321, which also deals with how to animate path strings.

@ewilligers: Eric, @svgeesus offered to draft initial edits, but I'm sure he'd appreciate your suggestions. My one suggestion: move the text to a dedicated section, which can be linked to and which is generally about how to interpolate two path strings rather than specifically about how to interpolate the d attribute.

svgeesus commented 5 years ago

My one suggestion: move the text to a dedicated section, which can be linked to and which is generally about how to interpolate two path strings rather than specifically about how to interpolate the d attribute.

I agree, that makes sense.

svgeesus commented 5 years ago

Reminder to self to draft text with the flip flag at 50% behaviour.

tabatkins commented 5 years ago

All you have to do is specify that the flags interpolate as <integer>.