[SVG] Handle empty path data in SMIL animations [chromium/src : main]

0 views
Skip to first unread message

Virali Purbey (Gerrit)

unread,
4:40 AM (10 hours ago) 4:40 AM
to Philip Rogers, Fredrik Söderquist, Divyansh Mangal, Vinay Singh, Ragvesh Sharma, Chromium LUCI CQ, chromium...@chromium.org, Dirk Schulze, Olga Gerchikov, Stephen Chenney, Menard, Alexis, android-bu...@system.gserviceaccount.com, kouhe...@chromium.org, blink-revie...@chromium.org, pdr+svgw...@chromium.org, blink-...@chromium.org, blink-revie...@chromium.org, fmalit...@chromium.org
Attention needed from Divyansh Mangal, Fredrik Söderquist and Vinay Singh

Virali Purbey added 12 comments

Patchset-level comments
File-level comment, Patchset 3:
Divyansh Mangal . resolved

Should we write some test for accumulate="sum" with empty base across repeats?

Virali Purbey

Good call. The existing `animate-path-additive-sum-empty-base.tentative.html` test covers `additive="sum"` with an empty base, but it doesn't test across repeats with `accumulate="sum"`. I'll add a test case for that.

Virali Purbey

Will cover in a separate CL as suggested by FS.

Commit Message
Line 9, Patchset 6:Chromium conflates an empty string d="" with the 'd' attribute being
absent, because `CalculateAnimationMode()` used `.empty()` which
returns true for both null (absent) and empty (present) strings.
This causes empty 'd' values to be silently ignored in animation
endpoints.
Fredrik Söderquist . resolved

Could we try fixing this across the board rather than adding a specific workaround?

Virali Purbey

Done. Replaced `.empty()` with `.IsNull()` in `CalculateAnimationMode()` and the from-string error-suppression checks in `CalculateFromAndToValues()` / `CalculateFromAndByValues()`. No attribute-specific virtual method needed, the observable change is path-only since empty string is only a valid value for path data.

Line 15, Patchset 3:An empty 'd' is a valid SVG path with zero segments, distinct
Divyansh Mangal . resolved

should we give a spec reference (or SVG WG issue if not available) corresponding to this?

Virali Purbey

Added SVG spec ref where the path data grammar is defined which allows an empty string (zero path commands). However, the SMIL interaction behavior is not explicitly specified. I'll file an SVG WG issue to clarify but this is an existing behavior in Firefox.

Virali Purbey

Done

File third_party/blink/renderer/core/svg/svg_animate_element.cc
Line 729, Patchset 6: // Empty paths can't be smoothly interpolated with non-empty paths.
if (GetAnimationMode() == kFromByAnimation &&
AttributeName() == svg_names::kDAttr) {
const auto& from_path = To<SVGPath>(*from_property_);
const auto& to_path = To<SVGPath>(*to_property_);
if (from_path.ByteStream().IsEmpty() != to_path.ByteStream().IsEmpty()) {
return false;
}
}
Fredrik Söderquist . resolved

I think we handle these cases in the animated type itself at the moment. Otherwise we could have `Add()` return false if the types couldn't be added. I think that's better done as a separate CL though. Regardless this is not a scalable approach (and quite ugly).

Virali Purbey

Agreed. Removed the SVGAnimateElement-level workaround. Incompatible empty paths are now handled entirely in `SVGPath::CalculateAnimatedValue()`, it returns early (base preserved) for additive/by cases and uses discrete for non-additive from-to. Will follow up with the `Add()` return-bool refactor in a separate CL.

File third_party/blink/renderer/core/svg/svg_path.cc
Line 140, Patchset 6: // Empty + by = by (additive identity).
Fredrik Söderquist . resolved

This seems to assume that "empty" is some form of "neutral value", but that doesn't match rendering of an empty path? Wouldn't it be better to stick to the old failure mode? I don't think it makes sense to have discrete animation for `by`.

Virali Purbey

Agreed. Reworked: when `is_additive` is true and paths are incompatible (one/both empty), the animation now fails (base preserved). Discrete is only used for non-additive from-to where the user explicitly specified both endpoints.

Line 179, Patchset 3: if (from_stream.IsEmpty() && to_stream.IsEmpty()) {
path_value_ = CSSPathValue::EmptyPathValue();
return;
}
Divyansh Mangal . resolved

For additive="sum" animations where both from/to are empty, won't this unconditionally replaces the underlying (base) value with empty, even though the animation's contribution is zero (identity). The additive step that would preserve the base is skipped, is that expected?

Atleast consider adding a test case that test something like below: 
```
<path d="<non-empty-d>">
<animate id="animation" attributeName="d"
from=""
to=""
additive="sum"/>
</path>
```

in above should the result be base value or empty throughout? (From the code it will be empty, but I am asking what's the expectation from spec )

Virali Purbey

You're right to flag this. When from/to are empty, the animation value is empty regardless of additive mode, the "both empty → empty" short-circuit fires before the additive step. Per SMIL, the animation function result is `f(t)=empty` and additive would compute `base + empty`.

Since empty paths have zero segments and can't be structurally added to a non-empty base, treating empty as the result is the safest behavior. I'll add the test case you suggested to document this explicitly.

Virali Purbey

Done

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-accumulate-sum-empty-base.tentative.html
Line 21, Patchset 6:// Test case: accumulate="sum" with empty base across repeats
Fredrik Söderquist . resolved

The base isn't expected to contribute here though? I don't think there's anything tentative about this test. We could land it spearately.

Virali Purbey

Acknowledged. Will land separately as suggested.

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-additive-sum-both-empty-over-base.tentative.html
Line 20, Patchset 6:// Test case: additive="sum" with both from and to empty over non-empty base should result in empty path
Fredrik Söderquist . resolved

I think this should just fail (no animate). Empty can't be added to non-empty.

Virali Purbey

Done. Test now expects base value preserved throughout (no animation).

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-additive-sum-empty-base.tentative.html
Line 20, Patchset 6:// Test case: additive animation with empty base should add to empty (= animation values)
Fredrik Söderquist . resolved

Ditto here.

Virali Purbey

Removed from this CL. Same pattern, will be addressed with the `Add()` return-bool follow-up.

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-by-animation-empty-base.tentative.html
Line 18, Patchset 6:// Test case: empty + by = by (identity for addition)
Fredrik Söderquist . resolved

Ditto.

Virali Purbey

Done. Test now expects base preserved (empty throughout), animation fails since empty can't be added to non-empty by value.

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-by-animation-no-base.tentative.html
Line 18, Patchset 6:// Test case: by animation with no base value should smoothly interpolate from empty to by value
Fredrik Söderquist . resolved

And ditto here I guess.

Virali Purbey

Done. Test now expects base preserved (empty throughout), animation fails since empty can't be added to non-empty by value.

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-from-by-animation-empty-by.tentative.html
Line 19, Patchset 6:// Test case: from + empty = from (identity for addition)
Fredrik Söderquist . resolved

And here. Empty can't be added -> failure.

Virali Purbey

Acknowledged. This case requires `Add()` to signal failure (currently it's void and a no-op for incompatible types).

Open in Gerrit

Related details

Attention is currently required from:
  • Divyansh Mangal
  • Fredrik Söderquist
  • Vinay Singh
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ie101abb4e567c9b16c1e49f40d21b7dabb72da8b
Gerrit-Change-Number: 7725305
Gerrit-PatchSet: 16
Gerrit-Owner: Virali Purbey <virali...@microsoft.com>
Gerrit-Reviewer: Divyansh Mangal <dma...@microsoft.com>
Gerrit-Reviewer: Fredrik Söderquist <f...@opera.com>
Gerrit-Reviewer: Vinay Singh <vinay...@microsoft.com>
Gerrit-Reviewer: Virali Purbey <virali...@microsoft.com>
Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
Gerrit-CC: Menard, Alexis <alexis...@intel.com>
Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
Gerrit-CC: Philip Rogers <p...@chromium.org>
Gerrit-CC: Ragvesh Sharma <rags...@microsoft.com>
Gerrit-CC: Stephen Chenney <sche...@chromium.org>
Gerrit-Attention: Vinay Singh <vinay...@microsoft.com>
Gerrit-Attention: Fredrik Söderquist <f...@opera.com>
Gerrit-Attention: Divyansh Mangal <dma...@microsoft.com>
Gerrit-Comment-Date: Tue, 05 May 2026 08:39:34 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Virali Purbey <virali...@microsoft.com>
Comment-In-Reply-To: Fredrik Söderquist <f...@opera.com>
Comment-In-Reply-To: Divyansh Mangal <dma...@microsoft.com>
satisfied_requirement
unsatisfied_requirement
open
diffy

Fredrik Söderquist (Gerrit)

unread,
8:28 AM (6 hours ago) 8:28 AM
to Virali Purbey, Philip Rogers, Divyansh Mangal, Vinay Singh, Ragvesh Sharma, Chromium LUCI CQ, chromium...@chromium.org, Dirk Schulze, Olga Gerchikov, Stephen Chenney, Menard, Alexis, android-bu...@system.gserviceaccount.com, kouhe...@chromium.org, blink-revie...@chromium.org, pdr+svgw...@chromium.org, blink-...@chromium.org, blink-revie...@chromium.org, fmalit...@chromium.org
Attention needed from Divyansh Mangal, Vinay Singh and Virali Purbey

Fredrik Söderquist added 6 comments

File third_party/blink/renderer/core/svg/svg_path.cc
Line 185, Patchset 17 (Latest): // Empty to: cannot animate toward an empty target path.
Fredrik Söderquist . unresolved

interpolate?

Line 186, Patchset 17 (Latest): if (to_stream.IsEmpty()) {
if (parameters.is_additive) {
// Additive with empty to: can't add empty result to base. No animation.
Fredrik Söderquist . unresolved

Could we perhaps reject this case first, and just have a common case for the discrete cases? I think that could simplify the logic a little.

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-from-by-animation-both-empty.tentative.html
Line 18, Patchset 17 (Latest):// from-by with both empty: Add() sees ByteStream().IsEmpty() (the by value is
Fredrik Söderquist . unresolved

Formulate in "abstract" terms, not in specific implementation terms.

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-from-by-animation-empty-by.tentative.html
Line 18, Patchset 17 (Latest):// from-by with empty by: Add() sees ByteStream().IsEmpty() (the by value is
Fredrik Söderquist . unresolved

Ditto.

File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-from-by-animation-empty-from.tentative.html
Line 18, Patchset 17 (Latest):// from-by with empty from: Add() sees empty other (identity no-op, returns
// true). CalculateAnimatedValue gets empty from vs non-empty to; from-by is
Fredrik Söderquist . unresolved

Ditto

Line 19, Patchset 17 (Latest):// true). CalculateAnimatedValue gets empty from vs non-empty to; from-by is
// not inherently additive, so discrete animation at 50%.
Fredrik Söderquist . unresolved

I think it is... the `by` can't be added to the `from` in this case, so I'd expect this to fail.

Open in Gerrit

Related details

Attention is currently required from:
  • Divyansh Mangal
  • Vinay Singh
  • Virali Purbey
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Ie101abb4e567c9b16c1e49f40d21b7dabb72da8b
    Gerrit-Change-Number: 7725305
    Gerrit-PatchSet: 17
    Gerrit-Owner: Virali Purbey <virali...@microsoft.com>
    Gerrit-Reviewer: Divyansh Mangal <dma...@microsoft.com>
    Gerrit-Reviewer: Fredrik Söderquist <f...@opera.com>
    Gerrit-Reviewer: Vinay Singh <vinay...@microsoft.com>
    Gerrit-Reviewer: Virali Purbey <virali...@microsoft.com>
    Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
    Gerrit-CC: Menard, Alexis <alexis...@intel.com>
    Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
    Gerrit-CC: Philip Rogers <p...@chromium.org>
    Gerrit-CC: Ragvesh Sharma <rags...@microsoft.com>
    Gerrit-CC: Stephen Chenney <sche...@chromium.org>
    Gerrit-Attention: Vinay Singh <vinay...@microsoft.com>
    Gerrit-Attention: Virali Purbey <virali...@microsoft.com>
    Gerrit-Attention: Divyansh Mangal <dma...@microsoft.com>
    Gerrit-Comment-Date: Tue, 05 May 2026 12:27:59 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Virali Purbey (Gerrit)

    unread,
    12:27 PM (2 hours ago) 12:27 PM
    to Philip Rogers, Fredrik Söderquist, Divyansh Mangal, Vinay Singh, Ragvesh Sharma, Chromium LUCI CQ, chromium...@chromium.org, Dirk Schulze, Olga Gerchikov, Stephen Chenney, Menard, Alexis, android-bu...@system.gserviceaccount.com, kouhe...@chromium.org, blink-revie...@chromium.org, pdr+svgw...@chromium.org, blink-...@chromium.org, blink-revie...@chromium.org, fmalit...@chromium.org
    Attention needed from Divyansh Mangal, Fredrik Söderquist and Vinay Singh

    Virali Purbey added 6 comments

    File third_party/blink/renderer/core/svg/svg_path.cc
    Line 185, Patchset 17: // Empty to: cannot animate toward an empty target path.
    Fredrik Söderquist . resolved

    interpolate?

    Virali Purbey

    Updated.

    Line 186, Patchset 17: if (to_stream.IsEmpty()) {

    if (parameters.is_additive) {
    // Additive with empty to: can't add empty result to base. No animation.
    Fredrik Söderquist . resolved

    Could we perhaps reject this case first, and just have a common case for the discrete cases? I think that could simplify the logic a little.

    Virali Purbey

    Tried updating the logic.

    File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-from-by-animation-both-empty.tentative.html
    Line 18, Patchset 17:// from-by with both empty: Add() sees ByteStream().IsEmpty() (the by value is
    Fredrik Söderquist . resolved

    Formulate in "abstract" terms, not in specific implementation terms.

    Virali Purbey

    Done

    File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-from-by-animation-empty-by.tentative.html
    Line 18, Patchset 17:// from-by with empty by: Add() sees ByteStream().IsEmpty() (the by value is
    Fredrik Söderquist . resolved

    Ditto.

    Virali Purbey

    Done

    File third_party/blink/web_tests/external/wpt/svg/animations/animate-path-from-by-animation-empty-from.tentative.html
    Line 18, Patchset 17:// from-by with empty from: Add() sees empty other (identity no-op, returns

    // true). CalculateAnimatedValue gets empty from vs non-empty to; from-by is
    Fredrik Söderquist . resolved

    Ditto

    Virali Purbey

    Done

    Line 19, Patchset 17:// true). CalculateAnimatedValue gets empty from vs non-empty to; from-by is

    // not inherently additive, so discrete animation at 50%.
    Fredrik Söderquist . resolved

    I think it is... the `by` can't be added to the `from` in this case, so I'd expect this to fail.

    Virali Purbey

    Sure. Updated the test.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Divyansh Mangal
    • Fredrik Söderquist
    • Vinay Singh
    Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: Ie101abb4e567c9b16c1e49f40d21b7dabb72da8b
      Gerrit-Change-Number: 7725305
      Gerrit-PatchSet: 18
      Gerrit-Owner: Virali Purbey <virali...@microsoft.com>
      Gerrit-Reviewer: Divyansh Mangal <dma...@microsoft.com>
      Gerrit-Reviewer: Fredrik Söderquist <f...@opera.com>
      Gerrit-Reviewer: Vinay Singh <vinay...@microsoft.com>
      Gerrit-Reviewer: Virali Purbey <virali...@microsoft.com>
      Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
      Gerrit-CC: Menard, Alexis <alexis...@intel.com>
      Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
      Gerrit-CC: Philip Rogers <p...@chromium.org>
      Gerrit-CC: Ragvesh Sharma <rags...@microsoft.com>
      Gerrit-CC: Stephen Chenney <sche...@chromium.org>
      Gerrit-Attention: Vinay Singh <vinay...@microsoft.com>
      Gerrit-Attention: Fredrik Söderquist <f...@opera.com>
      Gerrit-Attention: Divyansh Mangal <dma...@microsoft.com>
      Gerrit-Comment-Date: Tue, 05 May 2026 16:26:24 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Fredrik Söderquist <f...@opera.com>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy
      Reply all
      Reply to author
      Forward
      0 new messages