Bug 711959 - Adapt JavaPanZoomController to use the RenderTask mechanism. r=Cwiiis, kats

This commit is contained in:
Augustin Trancart 2013-09-04 14:07:11 -04:00
parent 0db487a266
commit 1d8dcbd4e7
3 changed files with 88 additions and 60 deletions

View File

@ -919,6 +919,19 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
return mView.post(action);
}
/** Implementation of PanZoomTarget */
@Override
public void postRenderTask(RenderTask task) {
mView.postRenderTask(task);
}
/** Implementation of PanZoomTarget */
@Override
public void removeRenderTask(RenderTask task) {
mView.removeRenderTask(task);
}
/** Implementation of PanZoomTarget */
@Override
public boolean postDelayed(Runnable action, long delayMillis) {

View File

@ -30,9 +30,6 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import java.util.Timer;
import java.util.TimerTask;
/*
* Handles the kinetic scrolling and zooming physics for a layer controller.
*
@ -77,8 +74,8 @@ class JavaPanZoomController
// The maximum zoom factor adjustment per frame of the AUTONAV animation
private static final float MAX_ZOOM_DELTA = 0.125f;
// Length of the bounce animation in ms
private static final int BOUNCE_ANIMATION_DURATION = 250;
// The number of time a bounce animation run at most.
private static final int BOUNCE_FRAME_NUMBER = 15;
private enum PanZoomState {
NOTHING, /* no touch-start events received */
@ -115,10 +112,8 @@ class JavaPanZoomController
private final TouchEventHandler mTouchEventHandler;
private final EventDispatcher mEventDispatcher;
/* The timer that handles flings or bounces. */
private Timer mAnimationTimer;
/* The runnable being scheduled by the animation timer. */
private AnimationRunnable mAnimationRunnable;
/* The task that handles flings, autonav or bounces. */
private PanZoomRenderTask mAnimationRenderTask;
/* The zoom focus at the first zoom event (in page coordinates). */
private PointF mLastZoomFocus;
/* The time the last motion event took place. */
@ -419,7 +414,7 @@ class JavaPanZoomController
private boolean handleTouchStart(MotionEvent event) {
// user is taking control of movement, so stop
// any auto-movement we have going
stopAnimationTimer();
stopAnimationTask();
switch (mState) {
case ANIMATED_ZOOM:
@ -606,7 +601,7 @@ class JavaPanZoomController
if (mState == PanZoomState.NOTHING) {
setState(PanZoomState.AUTONAV);
startAnimationTimer(new AutonavRunnable());
startAnimationRenderTask(new AutonavRenderTask());
}
if (mState == PanZoomState.AUTONAV) {
mX.setAutoscrollVelocity(velocityX);
@ -732,18 +727,18 @@ class JavaPanZoomController
private void fling() {
updatePosition();
stopAnimationTimer();
stopAnimationTask();
boolean stopped = stopped();
mX.startFling(stopped);
mY.startFling(stopped);
startAnimationTimer(new FlingRunnable());
startAnimationRenderTask(new FlingRenderTask());
}
/* Performs a bounce-back animation to the given viewport metrics. */
private void bounce(ImmutableViewportMetrics metrics, PanZoomState state) {
stopAnimationTimer();
stopAnimationTask();
ImmutableViewportMetrics bounceStartMetrics = getMetrics();
if (bounceStartMetrics.fuzzyEquals(metrics)) {
@ -758,7 +753,7 @@ class JavaPanZoomController
// setAnimationTarget to set the new final display port and not have it get
// clobbered by display ports from intermediate animation frames.
mTarget.setAnimationTarget(metrics);
startAnimationTimer(new BounceRunnable(bounceStartMetrics, metrics));
startAnimationRenderTask(new BounceRenderTask(bounceStartMetrics, metrics));
}
/* Performs a bounce-back animation to the nearest valid viewport metrics. */
@ -767,29 +762,22 @@ class JavaPanZoomController
}
/* Starts the fling or bounce animation. */
private void startAnimationTimer(final AnimationRunnable runnable) {
if (mAnimationTimer != null) {
Log.e(LOGTAG, "Attempted to start a new timer without canceling the old one!");
stopAnimationTimer();
private void startAnimationRenderTask(final PanZoomRenderTask task) {
if (mAnimationRenderTask != null) {
Log.e(LOGTAG, "Attempted to start a new task without canceling the old one!");
stopAnimationTask();
}
mAnimationTimer = new Timer("Animation Timer");
mAnimationRunnable = runnable;
mAnimationTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() { mTarget.post(runnable); }
}, 0, (int)Axis.MS_PER_FRAME);
mAnimationRenderTask = task;
mTarget.postRenderTask(mAnimationRenderTask);
}
/* Stops the fling or bounce animation. */
private void stopAnimationTimer() {
if (mAnimationTimer != null) {
mAnimationTimer.cancel();
mAnimationTimer = null;
}
if (mAnimationRunnable != null) {
mAnimationRunnable.terminate();
mAnimationRunnable = null;
private void stopAnimationTask() {
if (mAnimationRenderTask != null) {
mAnimationRenderTask.terminate();
mTarget.removeRenderTask(mAnimationRenderTask);
mAnimationRenderTask = null;
}
}
@ -830,33 +818,52 @@ class JavaPanZoomController
}
}
private abstract class AnimationRunnable implements Runnable {
private boolean mAnimationTerminated;
/**
* This class is an implementation of RenderTask which enforces its implementor to run in the UI thread.
*
*/
private abstract class PanZoomRenderTask extends RenderTask {
/* This should always run on the UI thread */
@Override
public final void run() {
/*
* Since the animation timer queues this runnable on the UI thread, it
* is possible that even when the animation timer is cancelled, there
* are multiple instances of this queued, so we need to have another
* mechanism to abort. This is done by using the mAnimationTerminated flag.
*/
if (mAnimationTerminated) {
return;
private final Runnable mRunnable = new Runnable() {
@Override
public final void run() {
if (mContinueAnimation) {
animateFrame();
}
}
animateFrame();
};
private boolean mContinueAnimation = true;
public PanZoomRenderTask() {
super(false);
}
@Override
protected final boolean internalRun(long timeDelta, long currentFrameStartTime) {
mTarget.post(mRunnable);
return mContinueAnimation;
}
/**
* The method subclasses must override. This method is run on the UI thread thanks to internalRun
*/
protected abstract void animateFrame();
/* This should always run on the UI thread */
protected final void terminate() {
mAnimationTerminated = true;
/**
* Terminate the animation.
*/
public void terminate() {
mContinueAnimation = false;
}
}
private class AutonavRunnable extends AnimationRunnable {
private class AutonavRenderTask extends PanZoomRenderTask {
public AutonavRenderTask() {
super();
}
@Override
protected void animateFrame() {
if (mState != PanZoomState.AUTONAV) {
@ -871,18 +878,19 @@ class JavaPanZoomController
}
}
/* The callback that performs the bounce animation. */
private class BounceRunnable extends AnimationRunnable {
/* The current frame of the bounce-back animation */
private int mBounceFrame;
/* The task that performs the bounce animation. */
private class BounceRenderTask extends PanZoomRenderTask {
/*
* The viewport metrics that represent the start and end of the bounce-back animation,
* respectively.
*/
private ImmutableViewportMetrics mBounceStartMetrics;
private ImmutableViewportMetrics mBounceEndMetrics;
private int mBounceFrame;
BounceRunnable(ImmutableViewportMetrics startMetrics, ImmutableViewportMetrics endMetrics) {
BounceRenderTask(ImmutableViewportMetrics startMetrics, ImmutableViewportMetrics endMetrics) {
super();
mBounceStartMetrics = startMetrics;
mBounceEndMetrics = endMetrics;
}
@ -900,7 +908,7 @@ class JavaPanZoomController
}
/* Perform the next frame of the bounce-back animation. */
if (mBounceFrame < (int)(BOUNCE_ANIMATION_DURATION / Axis.MS_PER_FRAME)) {
if (mBounceFrame < BOUNCE_FRAME_NUMBER) {
advanceBounce();
return;
}
@ -914,7 +922,7 @@ class JavaPanZoomController
/* Performs one frame of a bounce animation. */
private void advanceBounce() {
synchronized (mTarget.getLock()) {
float t = easeOut(mBounceFrame * Axis.MS_PER_FRAME / BOUNCE_ANIMATION_DURATION);
float t = easeOut(((float)mBounceFrame) / BOUNCE_FRAME_NUMBER);
ImmutableViewportMetrics newMetrics = mBounceStartMetrics.interpolate(mBounceEndMetrics, t);
mTarget.setViewportMetrics(newMetrics);
mBounceFrame++;
@ -931,7 +939,12 @@ class JavaPanZoomController
}
// The callback that performs the fling animation.
private class FlingRunnable extends AnimationRunnable {
private class FlingRenderTask extends PanZoomRenderTask {
public FlingRenderTask() {
super();
}
@Override
protected void animateFrame() {
/*
@ -983,7 +996,7 @@ class JavaPanZoomController
private void finishAnimation() {
checkMainThread();
stopAnimationTimer();
stopAnimationTask();
// Force a viewport synchronisation
mTarget.forceRedraw(null);

View File

@ -26,6 +26,8 @@ public interface PanZoomTarget {
public boolean post(Runnable action);
public boolean postDelayed(Runnable action, long delayMillis);
public void postRenderTask(RenderTask task);
public void removeRenderTask(RenderTask task);
public Object getLock();
public PointF convertViewPointToLayerPoint(PointF viewPoint);
}