diff --git a/crates/expr/src/prelude.js b/crates/expr/src/prelude.js index 589dde55c..62d7f1b3a 100644 --- a/crates/expr/src/prelude.js +++ b/crates/expr/src/prelude.js @@ -251,13 +251,14 @@ function __cubicBezier(curve) { } // bezier(t, tMin, tMax, value1, value2, curve), or bezier(t, value1, value2, curve): the curve is -// the last argument; everything before it follows linear / ease. +// the sixth / fourth argument. Read it by position, not from the end: when it is missing or +// unusable, the interpolation falls back to linear without consuming the last value. function bezier() { - var curve = arguments[arguments.length - 1]; - var shape = __cubicBezier(curve); - var args = []; - for (var i = 0; i < arguments.length - 1; i++) args.push(arguments[i]); - return __interp(shape, args); + var a = arguments, n = a.length; + if (n >= 6) return __interp(__cubicBezier(a[5]), [a[0], a[1], a[2], a[3], a[4]]); + if (n === 5) return __interp(__lin, [a[0], a[1], a[2], a[3], a[4]]); + if (n === 4) return __interp(__cubicBezier(a[3]), [a[0], a[1], a[2]]); + return __interp(__lin, [a[0], a[1], a[2]]); } // --------------------------------------------------------------------------------------------- diff --git a/crates/expr/src/tests.rs b/crates/expr/src/tests.rs index b651802f8..4a13ebd8a 100644 --- a/crates/expr/src/tests.rs +++ b/crates/expr/src/tests.rs @@ -343,6 +343,12 @@ fn cubic_bezier_short_form_arrays_and_fallbacks() { // A curve that is not four finite numbers falls back to linear instead of throwing. assert_close!(f.num("bezier(0.5, 0, 1, 0, 100, [1, 0])", 0.0), 50.0); assert_close!(f.num("bezier(0.5, 0, 1, 0, 100, 'ease')", 0.0), 50.0); + // A missing or unusable curve must not consume the last value: read the curve by position. + assert_close!(f.num("bezier(0.5, 0, 1, 0, 100)", 0.0), 50.0); + assert_close!(f.num("bezier(0.5, 0, 100)", 0.0), 50.0); + assert_close!(f.num("bezier(0.5, 0, 100, [1, 0])", 0.0), 50.0); + let v = f.ev(f.shape, "contents/#1/contents/fill/color", "bezier(0.5, 0, 1, [0, 0, 0, 1], [1, 1, 1, 1])", 0.0).unwrap(); + assert_eq!(v, Value::Color([0.5, 0.5, 0.5, 1.0])); // Exactly four values are a curve; extra ones mean the curve is malformed, so linear. assert_close!(f.num("bezier(0.5, 0, 1, 0, 100, [0.42, 0, 0.58, 1, 0])", 0.0), 50.0); assert_close!(f.num("bezier(0.5, 0, 1, 0, 100, [0.42, 0, 0.58, 1, 2, 3])", 0.0), 50.0);