RFR: 8358820: Allow interpolation outside of range [0,1]

Nir Lisker nlisker at openjdk.org
Sun Jun 15 05:47:34 UTC 2025


On Fri, 6 Jun 2025 23:23:05 GMT, Michael Strauß <mstrauss at openjdk.org> wrote:

> JavaFX unnecessarily restricts interpolation in the following ways:
> 1. `Interpolatable` implementations often clamp intermediate values to the interpolation factor range [0,1].
> 2. `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:<br>
>    <img src="https://github.com/user-attachments/assets/368b6142-052d-4ead-8a59-cbddf4a19660" width="400"/><br>
>    The following function is also not representable, but would be very useful for [bouncy animations](https://easings.net/#easeOutBack):<br>
>    <img src="https://github.com/user-attachments/assets/af02b044-ae4c-4250-b181-72178ad9f3f3" width="400"/>
> 
> 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.
> 
> This PR includes the following changes:
> 1. The specification of `Interpolatable` is changed to require implementations to accept interpolation factors outside of [0,1].
> 2. All implementations of `Interpolatable` now correctly return intermediate values outside of [0,1].
> 3. `SplineInterpolator` now accepts control points with any Y coordinate.
> 
> Here's how the result looks like for the previously unrepresentable interpolation function `cubic-bezier(0.34, 2.2, 0.64, 1)`:<br>
> <img src="https://github.com/user-attachments/assets/72c10d0d-71b4-4bb5-b58c-ae377279b0fd" width="500"/>

I left just a couple of general comments. Most of the changes remove the clamping.

modules/javafx.graphics/src/main/java/com/sun/javafx/scene/layout/region/BorderImageSlices.java line 62:

> 60:         Objects.requireNonNull(endValue, "endValue cannot be null");
> 61: 
> 62:         if (t == 0 || equals(endValue)) {

`==` on floating point could produce unexpected results since there's +0 and -0. Here it doesn't seem to matter because it's an optimization, but I see more of these in the new code, so might be worth double checking.

modules/javafx.graphics/src/main/java/javafx/animation/Interpolatable.java line 44:

> 42:  *             <td>Two components are combined by linear interpolation such that the intermediate value is
> 43:  *                 produced by computing {@code (1 - t) * start + t * end}. This interpolation type is usually
> 44:  *                 applicable for numeric components.</td>

I think that the use of "start" and "end" is confusing now since they don't correspond to actual start and end. You can get values that are "after the end". It might be seen more as an extrapolation at this point. In general, this interface now also functions as an extrapolator.

-------------

PR Review: https://git.openjdk.org/jfx/pull/1822#pullrequestreview-2928973183
PR Review Comment: https://git.openjdk.org/jfx/pull/1822#discussion_r2147445913
PR Review Comment: https://git.openjdk.org/jfx/pull/1822#discussion_r2147434388


More information about the openjfx-dev mailing list