Summary
Allow interpolation outside of range [0,1], and accept cubic Bézier functions with control points outside of range [0,1] on the Y axis (output progress).
Problem
JavaFX unnecessarily restricts interpolation in the following ways:
Interpolatable
implementations often clamp intermediate values to the interpolation factor range [0,1].SplineInterpolator
doesn't accept Y coordinates outside of [0,1] for its control points. While this was probably done so that the computed interpolation factor doesn't exceed [0,1], the restriction goes far beyond that. For example, the following function is not representable, even though its values are all within the [0,1] range: <cubic-bezier-1.png>. The following function is also not representable, but would be very useful for bouncy animations: <cubic-bezier-2.png>.
Solution
Fortunately, there is no technical reason why JavaFX can't support the full range of animations that can be represented with a cubic Beziér interpolation function.
- The specification of Interpolatable is changed to require implementations to accept interpolation factors outside of [0,1].
- All implementations of Interpolatable now correctly return intermediate values outside of [0,1].
- SplineInterpolator accepts control points with any Y coordinate (it was never specified that it should reject Y coordinates outside of [0,1]).
Specification
--- a/modules/javafx.graphics/src/main/java/javafx/animation/Interpolatable.java
+++ b/modules/javafx.graphics/src/main/java/javafx/animation/Interpolatable.java
@@ -39,10 +39,10 @@
* {@link #interpolate(Object, double)} method.</td>
* </tr>
* <tr><td style="vertical-align: top"><a id="linear" style="white-space: nowrap">linear</a></td>
- * <td>Two components are combined by linear interpolation such that {@code t = 0} produces
- * the start value, {@code t = 1} produces the end value, and {@code 0 < t < 1} produces
- * {@code (1 - t) * start + t * end}. This interpolation type is usually applicable for
- * numeric components.</td>
+ * <td>Two components are combined by linear interpolation such that the intermediate value is
+ * produced by computing {@code (1 - t) * start + t * end}. Note that this formula produces
+ * values less than {@code start} for {@code t < 0} and values greater than {@code end} for
+ * {@code t > 1}. This interpolation type is usually applicable for numeric components.</td>
* </tr>
* <tr><td style="vertical-align: top"><a id="discrete" style="white-space: nowrap">discrete</a></td>
* <td>If two components cannot be meaningfully combined, the intermediate component value
@@ -70,8 +70,8 @@
/**
* Returns an intermediate value between the value of this {@code Interpolatable} and the specified
- * {@code endValue} using the linear interpolation factor {@code t}, ranging from 0 (inclusive)
- * to 1 (inclusive).
+ * {@code endValue} using the linear interpolation factor {@code t}. The interpolation factor can
+ * be any finite value.
* <p>
* The returned value might not be a new instance; the implementation might also return one of the
* two existing instances if the intermediate value would be equal to one of the existing values.
@@ -78,10 +78,8 @@
* However, this is an optimization and applications should not assume any particular identity
* of the returned value.
*
- * @implSpec An implementation is not required to reject interpolation factors less than 0 or larger
- * than 1, but this specification gives no meaning to values returned outside of this range.
- * For example, an implementation might clamp the interpolation factor to [0..1], or it might
- * continue the linear interpolation outside of this range.
+ * @implSpec An implementation must accept any interpolation factor, but it can return a clamped
+ * intermediate value that falls within its value range.
*
* @param endValue the target value
* @param t the interpolation factor
- csr of
-
JDK-8358820 Allow interpolation outside of range [0,1]
-
- Open
-