Bug 701594 - Part 1: Precompute the ease-out animation. r=kats

This commit is contained in:
Patrick Walton 2011-12-07 10:41:58 -08:00
Родитель e74361d640
Коммит 017d92c57f
3 изменённых файлов: 53 добавлений и 77 удалений

Просмотреть файл

@ -43,4 +43,13 @@ public final class FloatUtils {
public static boolean fuzzyEquals(float a, float b) {
return (Math.abs(a - b) < 1e-6);
}
/*
* Returns the value that represents a linear transition between `from` and `to` at time `t`,
* which is on the scale [0, 1). Thus with t = 0.0f, this returns `from`; with t = 1.0f, this
* returns `to`; with t = 0.5f, this returns the value halfway from `from` to `to`.
*/
public static float interpolate(float from, float to, float t) {
return from + (to - from) * t;
}
}

Просмотреть файл

@ -37,6 +37,7 @@
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.FloatUtils;
import android.graphics.Point;
import android.graphics.PointF;
import java.lang.Math;
@ -62,8 +63,8 @@ public final class PointUtils {
* of each of the original points (weight = 1 returns endPoint, weight = 0 returns startPoint)
*/
public static PointF interpolate(PointF startPoint, PointF endPoint, float weight) {
float x = (startPoint.x-endPoint.x)*weight + endPoint.x;
float y = (startPoint.y-endPoint.y)*weight + endPoint.y;
float x = FloatUtils.interpolate(startPoint.x, endPoint.x, weight);
float y = FloatUtils.interpolate(startPoint.y, endPoint.y, weight);
return new PointF(x, y);
}
}

Просмотреть файл

@ -80,11 +80,6 @@ public class PanZoomController
private static final float SNAP_LIMIT = 0.75f;
// The rate of deceleration when the surface has overscrolled.
private static final float OVERSCROLL_DECEL_RATE = 0.04f;
// The duration of animation when bouncing back.
private static final int SNAP_TIME = 240;
// The number of subdivisions we should consider when plotting the ease-out transition. Higher
// values make the animation more accurate, but slower to plot.
private static final int SUBDIVISION_COUNT = 1000;
// The distance the user has to pan before we recognize it as such (e.g. to avoid
// 1-pixel pans between the touch-down and touch-up of a click). In units of inches.
private static final float PAN_THRESHOLD = 0.1f;
@ -96,6 +91,26 @@ public class PanZoomController
// Length of time to spend zooming. in ms
public static final int ZOOM_DURATION = 200;
/* 16 precomputed frames of the _ease-out_ animation from the CSS Transitions specification. */
private static final float[] EASE_OUT_ANIMATION_FRAMES = {
0.00000f, /* 0 */
0.10211f, /* 1 */
0.19864f, /* 2 */
0.29043f, /* 3 */
0.37816f, /* 4 */
0.46155f, /* 5 */
0.54054f, /* 6 */
0.61496f, /* 7 */
0.68467f, /* 8 */
0.74910f, /* 9 */
0.80794f, /* 10 */
0.86069f, /* 11 */
0.90651f, /* 12 */
0.94471f, /* 13 */
0.97401f, /* 14 */
0.99309f, /* 15 */
};
private Timer mFlingTimer;
private Axis mX, mY;
/* The zoom focus at the first zoom event (in page coordinates). */
@ -599,7 +614,6 @@ public class PanZoomController
public boolean disableSnap; /* Whether overscroll snapping is disabled. */
private FlingStates mFlingState; /* The fling state we're in on this axis. */
private EaseOutAnimation mSnapAnim; /* The animation when the page is snapping back. */
/* These three need to be kept in sync with the layer controller. */
private float viewportPos;
@ -608,7 +622,11 @@ public class PanZoomController
private float mPageLength;
public float displacement;
private float mSnapPosition;
private int mSnapFrame;
private float mSnapPos, mSnapEndPos;
public Axis() { mSnapFrame = -1; }
public FlingStates getFlingState() { return mFlingState; }
@ -709,10 +727,12 @@ public class PanZoomController
public void startSnap() {
switch (getOverscroll()) {
case MINUS:
mSnapAnim = new EaseOutAnimation(0, getExcess());
mSnapFrame = 0;
mSnapEndPos = getExcess();
break;
case PLUS:
mSnapAnim = new EaseOutAnimation(0, -getExcess());
mSnapFrame = 0;
mSnapEndPos = -getExcess();
break;
default:
// no overscroll to deal with, so we're done
@ -721,20 +741,26 @@ public class PanZoomController
}
displacement = 0;
mSnapPosition = mSnapAnim.getPosition();
mSnapPos = 0.0f;
setFlingState(FlingStates.SNAPPING);
}
// Performs one frame of a snap-into-place operation.
private void snap() {
mSnapAnim.advance();
displacement += mSnapAnim.getPosition() - mSnapPosition;
mSnapPosition = mSnapAnim.getPosition();
mSnapFrame++;
if (mSnapFrame == EASE_OUT_ANIMATION_FRAMES.length) {
mSnapFrame = -1;
displacement += mSnapEndPos - mSnapPos;
mSnapPos = mSnapEndPos;
if (mSnapAnim.getFinished()) {
mSnapAnim = null;
setFlingState(FlingStates.STOPPED);
return;
}
float t = EASE_OUT_ANIMATION_FRAMES[mSnapFrame];
float newSnapPos = FloatUtils.interpolate(0.0f, mSnapEndPos, t);
displacement += newSnapPos - mSnapPos;
mSnapPos = newSnapPos;
}
// Performs displacement of the viewport position according to the current velocity.
@ -749,66 +775,6 @@ public class PanZoomController
}
}
private static class EaseOutAnimation {
private float[] mFrames;
private float mPosition;
private float mOrigin;
private float mDest;
private long mTimestamp;
private boolean mFinished;
public EaseOutAnimation(float position, float dest) {
mPosition = mOrigin = position;
mDest = dest;
mFrames = new float[SNAP_TIME];
mTimestamp = System.currentTimeMillis();
mFinished = false;
plot(position, dest, mFrames);
}
public float getPosition() { return mPosition; }
public boolean getFinished() { return mFinished; }
private void advance() {
int frame = (int)(System.currentTimeMillis() - mTimestamp);
if (frame >= SNAP_TIME) {
mPosition = mDest;
mFinished = true;
return;
}
mPosition = mFrames[frame];
}
private static void plot(float from, float to, float[] frames) {
int nextX = 0;
for (int i = 0; i < SUBDIVISION_COUNT; i++) {
float t = (float)i / (float)SUBDIVISION_COUNT;
float xPos = (3.0f*t*t - 2.0f*t*t*t) * (float)frames.length;
if ((int)xPos < nextX)
continue;
int oldX = nextX;
nextX = (int)xPos;
float yPos = 1.74f*t*t - 0.74f*t*t*t;
float framePos = from + (to - from) * yPos;
while (oldX < nextX)
frames[oldX++] = framePos;
if (nextX >= frames.length)
break;
}
// Pad out any remaining frames.
while (nextX < frames.length) {
frames[nextX] = frames[nextX - 1];
nextX++;
}
}
}
/*
* Zooming
*/