Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a1f9df8 authored by George Mount's avatar George Mount Committed by Android (Google) Code Review
Browse files

Merge "Linearly complete overscroll stretch when close" into sc-dev

parents 953c65e2 22a9f9c8
Loading
Loading
Loading
Loading
+79 −43
Original line number Diff line number Diff line
@@ -97,12 +97,28 @@ public class EdgeEffect {
     */
    private static final double VELOCITY_THRESHOLD = 0.01;

    /**
     * The speed at which we should start linearly interpolating to the destination.
     * When using a spring, as it gets closer to the destination, the speed drops off exponentially.
     * Instead of landing very slowly, a better experience is achieved if the final
     * destination is arrived at quicker.
     */
    private static final float LINEAR_VELOCITY_TAKE_OVER = 200f;

    /**
     * The value threshold before the spring animation is considered close enough to
     * the destination to be settled. This should be around 0.01 pixel.
     */
    private static final double VALUE_THRESHOLD = 0.001;

    /**
     * The maximum distance at which we should start linearly interpolating to the destination.
     * When using a spring, as it gets closer to the destination, the speed drops off exponentially.
     * Instead of landing very slowly, a better experience is achieved if the final
     * destination is arrived at quicker.
     */
    private static final double LINEAR_DISTANCE_TAKE_OVER = 8.0;

    /**
     * The natural frequency of the stretch spring.
     */
@@ -587,6 +603,7 @@ public class EdgeEffect {
            if (mState == STATE_RECEDE) {
                updateSpring();
            }
            if (mDistance != 0f) {
                RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
                if (mTmpMatrix == null) {
                    mTmpMatrix = new Matrix();
@@ -637,6 +654,7 @@ public class EdgeEffect {
                        mHeight // max vertical stretch in pixels
                    );
                }
            }
        } else {
            // Animations have been disabled or this is TYPE_STRETCH and drawing into a Canvas
            // that isn't a Recording Canvas, so no effect can be shown. Just end the effect.
@@ -730,6 +748,26 @@ public class EdgeEffect {
        if (deltaT < 0.001f) {
            return; // Must have at least 1 ms difference
        }
        mStartTime = time;

        if (Math.abs(mVelocity) <= LINEAR_VELOCITY_TAKE_OVER
                && Math.abs(mDistance * mHeight) < LINEAR_DISTANCE_TAKE_OVER
                && Math.signum(mVelocity) == -Math.signum(mDistance)
        ) {
            // This is close. The spring will slowly reach the destination. Instead, we
            // will interpolate linearly so that it arrives at its destination quicker.
            mVelocity = Math.signum(mVelocity) * LINEAR_VELOCITY_TAKE_OVER;

            float targetDistance = mDistance + (mVelocity * deltaT / mHeight);
            if (Math.signum(targetDistance) != Math.signum(mDistance)) {
                // We have arrived
                mDistance = 0;
                mVelocity = 0;
            } else {
                mDistance = targetDistance;
            }
            return;
        }
        final double mDampedFreq = NATURAL_FREQUENCY * Math.sqrt(1 - DAMPING_RATIO * DAMPING_RATIO);

        // We're always underdamped, so we can use only those equations:
@@ -745,9 +783,7 @@ public class EdgeEffect {
                + mDampedFreq * sinCoeff * Math.cos(mDampedFreq * deltaT));
        mDistance = (float) distance / mHeight;
        mVelocity = (float) velocity;
        mStartTime = time;
        if (isAtEquilibrium()) {
            mState = STATE_IDLE;
            mDistance = 0;
            mVelocity = 0;
        }
+13 −3
Original line number Diff line number Diff line
@@ -40,9 +40,7 @@ public:

    StretchEffect() {}

    bool isEmpty() const {
        return MathUtils::isZero(mStretchDirection.x()) && MathUtils::isZero(mStretchDirection.y());
    }
    bool isEmpty() const { return isZero(mStretchDirection.x()) && isZero(mStretchDirection.y()); }

    void setEmpty() {
        *this = StretchEffect{};
@@ -118,6 +116,18 @@ public:
    }

private:
    // The epsilon for StretchEffect is less than in MathUtils because
    // the range is 0-1 for an entire screen and should be significantly
    // less than 1 pixel for a smooth stretch animation.
    inline static bool isZero(float value) {
        // Using fabsf is more performant as ARM computes
        // fabsf in a single instruction.
        return fabsf(value) <= NON_ZERO_EPSILON;
    }
    // This should be good for 1/25,000 of a screen and should be good for
    // screens with less than ~8000 pixels in one dimension with only 1/4 pixel
    // cut-off.
    static constexpr float NON_ZERO_EPSILON = 0.00004f;
    static sk_sp<SkRuntimeEffect> getStretchEffect();
    mutable SkVector mStretchDirection{0, 0};
    mutable std::unique_ptr<SkRuntimeShaderBuilder> mBuilder;