tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit ba872e97641321bf4609d5f41086e0800d0b6db6
parent 4f38e3b955f0013dea44374eb0b9f318feec38f2
Author: Swarup Ukil <sukil@mozilla.com>
Date:   Wed, 10 Dec 2025 21:56:11 +0000

Bug 2003903 - Fix interpolation failures with <arc-sweep> and <arc-size> in shape(). r=emilio,firefox-style-system-reviewers

Per shape() spec, the arc keyword interpolation rules are meant to match
existing SVG <path> interpolation rules: flags are interpolated as fractions
between zero and one, with any non-zero value considered to be a value of one.
So path() should reasonably do the same for the arc flags at 0.125 and such.
https://drafts.csswg.org/css-shapes-1/#interpolating-shape
https://svgwg.org/specs/paths/#PathElement

Differential Revision: https://phabricator.services.mozilla.com/D275122

Diffstat:
Mlayout/style/test/test_transitions_per_property.html | 2+-
Mservo/components/style/values/generics/basic_shape.rs | 18++++++++++++------
Dtesting/web-platform/meta/css/css-masking/animations/clip-path-interpolation-shape.html.ini | 36------------------------------------
Dtesting/web-platform/meta/css/motion/animation/offset-path-interpolation-008.html.ini | 24------------------------
Mtesting/web-platform/tests/css/motion/animation/offset-path-interpolation-002.html | 11+++++++----
Mtesting/web-platform/tests/css/motion/animation/offset-path-interpolation-004.html | 7+++++--
Mtesting/web-platform/tests/svg/path/property/d-interpolation-relative-absolute.svg | 7+++++--
Mtesting/web-platform/tests/svg/path/property/d-interpolation-single.svg | 11+++++++----
8 files changed, 37 insertions(+), 79 deletions(-)

diff --git a/layout/style/test/test_transitions_per_property.html b/layout/style/test/test_transitions_per_property.html @@ -950,7 +950,7 @@ const pathFunctionTests = [ { start: "path('M 10 10 A 10 20 30 1 0 140 450')", end: "path('M 10 10 A 50 60 70 0 1 380 290')", - expected: ["path", '"M 10 10 A 20 30 40 1 0 200 410"'] + expected: ["path", '"M 10 10 A 20 30 40 1 1 200 410"'] }, // mix relative and absolute coordinates { diff --git a/servo/components/style/values/generics/basic_shape.rs b/servo/components/style/values/generics/basic_shape.rs @@ -1329,9 +1329,12 @@ impl Animate for ArcSweep { use num_traits::FromPrimitive; // If an arc command has different <arc-sweep> between its starting and ending list, then // the interpolated result uses cw for any progress value between 0 and 1. - (*self as i32) - .animate(&(*other as i32), procedure) - .map(|v| ArcSweep::from_u8((v > 0) as u8).unwrap_or(ArcSweep::Ccw)) + // Note: we cast progress from f64->f32->f64 to drop tiny noise near 0.0. + let progress = procedure.weights().1 as f32 as f64; + let procedure = Procedure::Interpolate { progress }; + (*self as i32 as f32) + .animate(&(*other as i32 as f32), procedure) + .map(|v| ArcSweep::from_u8((v > 0.) as u8).unwrap_or(ArcSweep::Ccw)) } } @@ -1375,9 +1378,12 @@ impl Animate for ArcSize { use num_traits::FromPrimitive; // If it has different <arc-size> keywords, then the interpolated result uses large for any // progress value between 0 and 1. - (*self as i32) - .animate(&(*other as i32), procedure) - .map(|v| ArcSize::from_u8((v > 0) as u8).unwrap_or(ArcSize::Small)) + // Note: we cast progress from f64->f32->f64 to drop tiny noise near 0.0. + let progress = procedure.weights().1 as f32 as f64; + let procedure = Procedure::Interpolate { progress }; + (*self as i32 as f32) + .animate(&(*other as i32 as f32), procedure) + .map(|v| ArcSize::from_u8((v > 0.) as u8).unwrap_or(ArcSize::Small)) } } diff --git a/testing/web-platform/meta/css/css-masking/animations/clip-path-interpolation-shape.html.ini b/testing/web-platform/meta/css/css-masking/animations/clip-path-interpolation-shape.html.ini @@ -1,36 +0,0 @@ -[clip-path-interpolation-shape.html] - [CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)\] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw)\]] - expected: FAIL - - [CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)\] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw)\]] - expected: FAIL - - [CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)\] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw)\]] - expected: FAIL - - [Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)\] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw)\]] - expected: FAIL - - [CSS Transitions: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")\] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw)\]] - expected: FAIL - - [CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")\] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw)\]] - expected: FAIL - - [CSS Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")\] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw)\]] - expected: FAIL - - [Web Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")\] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw)\]] - expected: FAIL - - [CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px, arc by 15% -5px of 30% cw rotate 30deg large, arc to 25% 20px of 10% small)\] to [shape(from 15% 15px, arc to 5% -25px of 15%, arc by 25% -15px of 12rem cw rotate 270deg small, arc to 15% 20px of 20% small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of calc(4.5% + 7px), arc by 18% -8px of calc(21% + 57.6px) rotate 102deg cw large, arc to 22% 20px of 13% cw)\]] - expected: FAIL - - [CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px, arc by 15% -5px of 30% cw rotate 30deg large, arc to 25% 20px of 10% small)\] to [shape(from 15% 15px, arc to 5% -25px of 15%, arc by 25% -15px of 12rem cw rotate 270deg small, arc to 15% 20px of 20% small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of calc(4.5% + 7px), arc by 18% -8px of calc(21% + 57.6px) rotate 102deg cw large, arc to 22% 20px of 13% cw)\]] - expected: FAIL - - [CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px, arc by 15% -5px of 30% cw rotate 30deg large, arc to 25% 20px of 10% small)\] to [shape(from 15% 15px, arc to 5% -25px of 15%, arc by 25% -15px of 12rem cw rotate 270deg small, arc to 15% 20px of 20% small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of calc(4.5% + 7px), arc by 18% -8px of calc(21% + 57.6px) rotate 102deg cw large, arc to 22% 20px of 13% cw)\]] - expected: FAIL - - [Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px, arc by 15% -5px of 30% cw rotate 30deg large, arc to 25% 20px of 10% small)\] to [shape(from 15% 15px, arc to 5% -25px of 15%, arc by 25% -15px of 12rem cw rotate 270deg small, arc to 15% 20px of 20% small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of calc(4.5% + 7px), arc by 18% -8px of calc(21% + 57.6px) rotate 102deg cw large, arc to 22% 20px of 13% cw)\]] - expected: FAIL diff --git a/testing/web-platform/meta/css/motion/animation/offset-path-interpolation-008.html.ini b/testing/web-platform/meta/css/motion/animation/offset-path-interpolation-008.html.ini @@ -1,24 +0,0 @@ -[offset-path-interpolation-008.html] - [CSS Transitions: property <offset-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)\] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw small )\]] - expected: FAIL - - [CSS Transitions with transition: all: property <offset-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)\] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw small )\]] - expected: FAIL - - [CSS Animations: property <offset-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)\] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw small )\]] - expected: FAIL - - [Web Animations: property <offset-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)\] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw small )\]] - expected: FAIL - - [CSS Transitions: property <offset-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")\] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px ccw small, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw small)\]] - expected: FAIL - - [CSS Transitions with transition: all: property <offset-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")\] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px ccw small, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw small)\]] - expected: FAIL - - [CSS Animations: property <offset-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")\] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px ccw small, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw small)\]] - expected: FAIL - - [Web Animations: property <offset-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")\] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)\] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px ccw small, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw small)\]] - expected: FAIL diff --git a/testing/web-platform/tests/css/motion/animation/offset-path-interpolation-002.html b/testing/web-platform/tests/css/motion/animation/offset-path-interpolation-002.html @@ -64,6 +64,9 @@ {at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"} ]); + // At progress 0.125/0.875, arc flags in path() should consider + // non-zero interpolated values as one to match <path> behaviour. + // https://svgwg.org/specs/paths/#PathElement test_interpolation({ property: 'offset-path', from: "path('M 100 400 A 10 20 30 1 0 140 450')", @@ -71,8 +74,8 @@ }, [ {at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"}, {at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"}, - {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"}, - {at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"}, + {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 1 170 430')"}, + {at: 0.875, expect: "path('M 275 225 A 45 55 65 1 1 350 310')"}, {at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"}, {at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"} ]); @@ -83,8 +86,8 @@ }, [ {at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"}, {at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"}, - {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"}, - {at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"}, + {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 1 170 430')"}, + {at: 0.875, expect: "path('M 275 225 A 45 55 65 1 1 350 310')"}, {at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"}, {at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"} ]); diff --git a/testing/web-platform/tests/css/motion/animation/offset-path-interpolation-004.html b/testing/web-platform/tests/css/motion/animation/offset-path-interpolation-004.html @@ -106,6 +106,9 @@ {at: 2, expect: "path('M 250 260 H 200 V 240 H 210 V 230 L 240 210')"} ]); + // At progress 0.125/0.875, arc flags in path() should consider + // non-zero interpolated values as one to match <path> behaviour. + // https://svgwg.org/specs/paths/#PathElement test_interpolation({ property: 'offset-path', from: "path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')", @@ -113,8 +116,8 @@ }, [ {at: -1, expect: "path('M 2 28 A -30 -60 -10 1 0 10 30 A 70 80 -10 1 1 310 160')"}, {at: 0, expect: "path('M 10 20 A 10 20 30 1 0 50 70 A 110 120 30 1 1 190 120')"}, - {at: 0.125, expect: "path('M 11 19 A 15 30 35 1 0 55 75 A 115 125 35 1 1 175 115')"}, - {at: 0.875, expect: "path('M 17 13 A 45 90 65 0 1 85 105 A 145 155 65 0 1 85 85')"}, + {at: 0.125, expect: "path('M 11 19 A 15 30 35 1 1 55 75 A 115 125 35 1 1 175 115')"}, + {at: 0.875, expect: "path('M 17 13 A 45 90 65 1 1 85 105 A 145 155 65 1 1 85 85')"}, {at: 1, expect: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')"}, {at: 2, expect: "path('M 26 4 A 90 180 110 0 1 130 150 A 190 200 110 0 1 -50 40')"} ]); diff --git a/testing/web-platform/tests/svg/path/property/d-interpolation-relative-absolute.svg b/testing/web-platform/tests/svg/path/property/d-interpolation-relative-absolute.svg @@ -106,6 +106,9 @@ {at: 2, expect: 'path("M 250 260 H 200 V 240 H 210 V 230 L 240 210 Z")'} ]); + // At progress 0.125/0.875, arc flags in path() should consider + // non-zero interpolated values as one to match <path> behaviour. + // https://svgwg.org/specs/paths/#PathElement test_interpolation({ property: 'd', from: 'path("m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50")', @@ -113,8 +116,8 @@ }, [ {at: -1, expect: 'path("M 2 28 A -30 -60 -10 1 0 10 30 A 70 80 -10 1 1 310 160")'}, {at: 0, expect: 'path("M 10 20 A 10 20 30 1 0 50 70 A 110 120 30 1 1 190 120")'}, - {at: 0.125, expect: 'path("M 11 19 A 15 30 35 1 0 55 75 A 115 125 35 1 1 175 115")'}, - {at: 0.875, expect: 'path("M 17 13 A 45 90 65 0 1 85 105 A 145 155 65 0 1 85 85")'}, + {at: 0.125, expect: 'path("M 11 19 A 15 30 35 1 1 55 75 A 115 125 35 1 1 175 115")'}, + {at: 0.875, expect: 'path("M 17 13 A 45 90 65 1 1 85 105 A 145 155 65 1 1 85 85")'}, {at: 1, expect: 'path("M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80")'}, {at: 2, expect: 'path("M 26 4 A 90 180 110 0 1 130 150 A 190 200 110 0 1 -50 40")'} ]); diff --git a/testing/web-platform/tests/svg/path/property/d-interpolation-single.svg b/testing/web-platform/tests/svg/path/property/d-interpolation-single.svg @@ -117,6 +117,9 @@ {at: 2, expect: 'path("M 20 10 Q 48 58 280 3800")'} ]); + // At progress 0.125/0.875, arc flags in path() should consider + // non-zero interpolated values as one to match <path> behaviour. + // https://svgwg.org/specs/paths/#PathElement test_interpolation({ property: 'd', from: 'path("M 100 400 A 10 20 30 1 0 140 450")', @@ -124,8 +127,8 @@ }, [ {at: -1, expect: 'path("M -100 600 A -30 -20 -10 1 0 -100 610")'}, {at: 0, expect: 'path("M 100 400 A 10 20 30 1 0 140 450")'}, - {at: 0.125, expect: 'path("M 125 375 A 15 25 35 1 0 170 430")'}, - {at: 0.875, expect: 'path("M 275 225 A 45 55 65 0 1 350 310")'}, + {at: 0.125, expect: 'path("M 125 375 A 15 25 35 1 1 170 430")'}, + {at: 0.875, expect: 'path("M 275 225 A 45 55 65 1 1 350 310")'}, {at: 1, expect: 'path("M 300 200 A 50 60 70 0 1 380 290")'}, {at: 2, expect: 'path("M 500 0 A 90 100 110 0 1 620 130")'} ]); @@ -136,8 +139,8 @@ }, [ {at: -1, expect: 'path("M -100 600 A -30 -20 -10 1 0 -100 610")'}, {at: 0, expect: 'path("M 100 400 A 10 20 30 1 0 140 450")'}, - {at: 0.125, expect: 'path("M 125 375 A 15 25 35 1 0 170 430")'}, - {at: 0.875, expect: 'path("M 275 225 A 45 55 65 0 1 350 310")'}, + {at: 0.125, expect: 'path("M 125 375 A 15 25 35 1 1 170 430")'}, + {at: 0.875, expect: 'path("M 275 225 A 45 55 65 1 1 350 310")'}, {at: 1, expect: 'path("M 300 200 A 50 60 70 0 1 380 290")'}, {at: 2, expect: 'path("M 500 0 A 90 100 110 0 1 620 130")'} ]);