Bug 798539 - Run the animation timer faster to improve panning smoothness. r=blassey,kats

This commit is contained in:
Benoit Girard 2012-10-11 12:58:53 -04:00
parent 9699c9ba99
commit d5e1965529
3 changed files with 25 additions and 63 deletions

View File

@ -604,9 +604,6 @@ pref("gfx.show_checkerboard_pattern", true);
pref("ui.scrolling.friction_slow", -1);
// This fraction in 1000ths of velocity remains after every animation frame when the velocity is high.
pref("ui.scrolling.friction_fast", -1);
// Below this velocity (in pixels per frame), the friction starts increasing from friction_fast
// to friction_slow.
pref("ui.scrolling.velocity_threshold", -1);
// The maximum velocity change factor between events, per ms, in 1000ths.
// Direction changes are excluded.
pref("ui.scrolling.max_event_acceleration", -1);
@ -617,9 +614,6 @@ pref("ui.scrolling.overscroll_snap_limit", -1);
// The minimum amount of space that must be present for an axis to be considered scrollable,
// in 1/1000ths of pixels.
pref("ui.scrolling.min_scrollable_distance", -1);
// A comma-separated list of float values in the range [0.0, 1.0) that are used as
// interpolation frames for zoom animations.
pref("ui.zooming.animation_frames", "");
// Enable accessibility mode if platform accessibility is enabled.
pref("accessibility.accessfu.activate", 2);

View File

@ -27,7 +27,6 @@ abstract class Axis {
private static final String PREF_SCROLLING_FRICTION_SLOW = "ui.scrolling.friction_slow";
private static final String PREF_SCROLLING_FRICTION_FAST = "ui.scrolling.friction_fast";
private static final String PREF_SCROLLING_VELOCITY_THRESHOLD = "ui.scrolling.velocity_threshold";
private static final String PREF_SCROLLING_MAX_EVENT_ACCELERATION = "ui.scrolling.max_event_acceleration";
private static final String PREF_SCROLLING_OVERSCROLL_DECEL_RATE = "ui.scrolling.overscroll_decel_rate";
private static final String PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT = "ui.scrolling.overscroll_snap_limit";
@ -67,7 +66,6 @@ abstract class Axis {
JSONArray prefs = new JSONArray();
prefs.put(PREF_SCROLLING_FRICTION_FAST);
prefs.put(PREF_SCROLLING_FRICTION_SLOW);
prefs.put(PREF_SCROLLING_VELOCITY_THRESHOLD);
prefs.put(PREF_SCROLLING_MAX_EVENT_ACCELERATION);
prefs.put(PREF_SCROLLING_OVERSCROLL_DECEL_RATE);
prefs.put(PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT);
@ -86,12 +84,22 @@ abstract class Axis {
});
}
static final float MS_PER_FRAME = 4.0f;
private static final float FRAMERATE_MULTIPLIER = (1000f/60f) / MS_PER_FRAME;
// The values we use for friction are based on a 16.6ms frame, adjust them to MS_PER_FRAME:
// FRICTION^1 = FRICTION_ADJUSTED^(16/MS_PER_FRAME)
// FRICTION_ADJUSTED = e ^ ((ln(FRICTION))/FRAMERATE_MULTIPLIER)
static float getFrameAdjustedFriction(float baseFriction) {
return (float)Math.pow(Math.E, (Math.log(baseFriction) / FRAMERATE_MULTIPLIER));
}
static void setPrefs(Map<String, Integer> prefs) {
FRICTION_SLOW = getFloatPref(prefs, PREF_SCROLLING_FRICTION_SLOW, 850);
FRICTION_FAST = getFloatPref(prefs, PREF_SCROLLING_FRICTION_FAST, 970);
VELOCITY_THRESHOLD = getIntPref(prefs, PREF_SCROLLING_VELOCITY_THRESHOLD, 10);
FRICTION_SLOW = getFrameAdjustedFriction(getFloatPref(prefs, PREF_SCROLLING_FRICTION_SLOW, 850));
FRICTION_FAST = getFrameAdjustedFriction(getFloatPref(prefs, PREF_SCROLLING_FRICTION_FAST, 970));
VELOCITY_THRESHOLD = 10 / FRAMERATE_MULTIPLIER;
MAX_EVENT_ACCELERATION = getFloatPref(prefs, PREF_SCROLLING_MAX_EVENT_ACCELERATION, 12);
OVERSCROLL_DECEL_RATE = getFloatPref(prefs, PREF_SCROLLING_OVERSCROLL_DECEL_RATE, 40);
OVERSCROLL_DECEL_RATE = getFrameAdjustedFriction(getFloatPref(prefs, PREF_SCROLLING_OVERSCROLL_DECEL_RATE, 40));
SNAP_LIMIT = getFloatPref(prefs, PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT, 300);
MIN_SCROLLABLE_DISTANCE = getFloatPref(prefs, PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE, 500);
Log.i(LOGTAG, "Prefs: " + FRICTION_SLOW + "," + FRICTION_FAST + "," + VELOCITY_THRESHOLD + ","
@ -103,9 +111,6 @@ abstract class Axis {
setPrefs(null);
}
// The number of milliseconds per frame assuming 60 fps
private static final float MS_PER_FRAME = 1000.0f / 60.0f;
private enum FlingStates {
STOPPED,
PANNING,
@ -182,7 +187,7 @@ abstract class Axis {
// If there's a direction change, or current velocity is very low,
// allow setting of the velocity outright. Otherwise, use the current
// velocity and a maximum change factor to set the new velocity.
boolean curVelocityIsLow = Math.abs(mVelocity) < 1.0f;
boolean curVelocityIsLow = Math.abs(mVelocity) < 1.0f / FRAMERATE_MULTIPLIER;
boolean directionChange = (mVelocity > 0) != (newVelocity > 0);
if (curVelocityIsLow || (directionChange && !FloatUtils.fuzzyEquals(newVelocity, 0.0f))) {
mVelocity = newVelocity;

View File

@ -46,8 +46,6 @@ public class PanZoomController
private static String MESSAGE_ZOOM_RECT = "Browser:ZoomToRect";
private static String MESSAGE_ZOOM_PAGE = "Browser:ZoomToPageWidth";
private static final String PREF_ZOOM_ANIMATION_FRAMES = "ui.zooming.animation_frames";
// Animation stops if the velocity is below this value when overscrolled or panning.
private static final float STOPPED_THRESHOLD = 4.0f;
@ -64,26 +62,6 @@ public class PanZoomController
// The maximum amount we allow you to zoom into a page
private static final float MAX_ZOOM = 4.0f;
/* 16 precomputed frames of the _ease-out_ animation from the CSS Transitions specification. */
private static float[] ZOOM_ANIMATION_FRAMES = new float[] {
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 enum PanZoomState {
NOTHING, /* no touch-start events received */
FLING, /* all touches removed, but we're still scrolling page */
@ -135,11 +113,6 @@ public class PanZoomController
registerEventListener(MESSAGE_ZOOM_RECT);
registerEventListener(MESSAGE_ZOOM_PAGE);
PrefsHelper.getPref(PREF_ZOOM_ANIMATION_FRAMES, new PrefsHelper.PrefHandlerBase() {
@Override public void prefValue(String pref, String value) {
setZoomAnimationFrames(value);
}
});
Axis.initPrefs();
}
@ -149,6 +122,13 @@ public class PanZoomController
mSubscroller.destroy();
}
private final static float easeOut(float t) {
// ease-out approx.
// -(t-1)^2+1
t = t-1;
return -t*t+1;
}
private void registerEventListener(String event) {
mEventDispatcher.registerEventListener(event, this);
}
@ -214,23 +194,6 @@ public class PanZoomController
}
}
private void setZoomAnimationFrames(String frames) {
try {
if (frames.length() > 0) {
StringTokenizer st = new StringTokenizer(frames, ",");
float[] values = new float[st.countTokens()];
for (int i = 0; i < values.length; i++) {
values[i] = Float.parseFloat(st.nextToken());
}
ZOOM_ANIMATION_FRAMES = values;
}
} catch (NumberFormatException e) {
Log.e(LOGTAG, "Error setting zoom animation frames", e);
} finally {
Log.i(LOGTAG, "Zoom animation frames: " + Arrays.toString(ZOOM_ANIMATION_FRAMES));
}
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: return onTouchStart(event);
@ -579,7 +542,7 @@ public class PanZoomController
mAnimationTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() { mTarget.post(runnable); }
}, 0, 1000L/60L);
}, 0, (int)Axis.MS_PER_FRAME);
}
/* Stops the fling or bounce animation. */
@ -679,7 +642,7 @@ public class PanZoomController
}
/* Perform the next frame of the bounce-back animation. */
if (mBounceFrame < ZOOM_ANIMATION_FRAMES.length) {
if (mBounceFrame < (int)(256f/Axis.MS_PER_FRAME)) {
advanceBounce();
return;
}
@ -693,7 +656,7 @@ public class PanZoomController
/* Performs one frame of a bounce animation. */
private void advanceBounce() {
synchronized (mTarget.getLock()) {
float t = ZOOM_ANIMATION_FRAMES[mBounceFrame];
float t = easeOut(mBounceFrame * Axis.MS_PER_FRAME / 256f);
ViewportMetrics newMetrics = mBounceStartMetrics.interpolate(mBounceEndMetrics, t);
mTarget.setViewportMetrics(newMetrics);
mBounceFrame++;