Bug 701594 - Part 3: Add viewport interpolation functions. r=kats
authorPatrick Walton <pwalton@mozilla.com>
Wed, 07 Dec 2011 10:44:36 -0800
changeset 83829 fe9f200f7d289c39647d46267370304402abf914
parent 83828 953247b411fa6bbb6c5c422d854c16086b247093
child 83830 1236e039a9e3adae6b0edb7191b5bcf22a1fe06b
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs701594
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 701594 - Part 3: Add viewport interpolation functions. r=kats
mobile/android/base/gfx/FloatSize.java
mobile/android/base/gfx/RectUtils.java
mobile/android/base/gfx/ViewportMetrics.java
mobile/android/base/ui/PanZoomController.java
--- a/mobile/android/base/gfx/FloatSize.java
+++ b/mobile/android/base/gfx/FloatSize.java
@@ -64,10 +64,19 @@ public class FloatSize {
     public boolean fuzzyEquals(FloatSize size) {
         return (FloatUtils.fuzzyEquals(size.width, width) &&
                 FloatUtils.fuzzyEquals(size.height, height));
     }
 
     public FloatSize scale(float factor) {
         return new FloatSize(width * factor, height * factor);
     }
+
+    /*
+     * Returns the size that represents a linear transition between this size and `to` at time `t`,
+     * which is on the scale [0, 1).
+     */
+    public FloatSize interpolate(FloatSize to, float t) {
+        return new FloatSize(FloatUtils.interpolate(width, to.width, t),
+                             FloatUtils.interpolate(height, to.height, t));
+    }
 }
 
--- a/mobile/android/base/gfx/RectUtils.java
+++ b/mobile/android/base/gfx/RectUtils.java
@@ -32,16 +32,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko.gfx;
 
+import org.mozilla.gecko.FloatUtils;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 public final class RectUtils {
     public static Rect create(JSONObject json) {
         try {
@@ -113,9 +114,20 @@ public final class RectUtils {
     */
     public static RectF restrict(RectF rect, RectF dest) {
         float width = Math.min(rect.width(), dest.width());
         float height = Math.min(rect.height(), dest.height());
         float x = Math.max(dest.left, Math.min(dest.right-width, rect.left));
         float y = Math.max(dest.top, Math.min(dest.bottom-height, rect.top));
         return new RectF(x, y, x+width, y+height);
     }
+
+    /*
+     * Returns the rect that represents a linear transition between `from` and `to` at time `t`,
+     * which is on the scale [0, 1).
+     */
+    public static RectF interpolate(RectF from, RectF to, float t) {
+        return new RectF(FloatUtils.interpolate(from.left, to.left, t),
+                         FloatUtils.interpolate(from.top, to.top, t),
+                         FloatUtils.interpolate(from.right, to.right, t),
+                         FloatUtils.interpolate(from.bottom, to.bottom, t));
+    }
 }
--- a/mobile/android/base/gfx/ViewportMetrics.java
+++ b/mobile/android/base/gfx/ViewportMetrics.java
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko.gfx;
 
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import org.mozilla.gecko.FloatUtils;
 import org.mozilla.gecko.gfx.FloatSize;
 import org.mozilla.gecko.gfx.LayerController;
 import org.mozilla.gecko.gfx.RectUtils;
 import org.json.JSONException;
 import org.json.JSONObject;
 import android.util.Log;
 
 /**
@@ -211,16 +212,30 @@ public class ViewportMetrics {
         origin.offset(focus.x, focus.y);
         origin = PointUtils.scale(origin, scaleFactor);
         origin.offset(-focus.x, -focus.y);
         setOrigin(origin);
 
         mZoomFactor = newZoomFactor;
     }
 
+    /*
+     * Returns the viewport metrics that represent a linear transition between `from` and `to` at
+     * time `t`, which is on the scale [0, 1). This function interpolates the viewport rect, the
+     * page size, the offset, and the zoom factor.
+     */
+    public ViewportMetrics interpolate(ViewportMetrics to, float t) {
+        ViewportMetrics result = new ViewportMetrics();
+        result.mPageSize = mPageSize.interpolate(to.mPageSize, t);
+        result.mZoomFactor = FloatUtils.interpolate(mZoomFactor, to.mZoomFactor, t);
+        result.mViewportRect = RectUtils.interpolate(mViewportRect, to.mViewportRect, t);
+        result.mViewportOffset = PointUtils.interpolate(mViewportOffset, to.mViewportOffset, t);
+        return result;
+    }
+
     public String toJSON() {
         return "{ \"x\" : " + mViewportRect.left +
                ", \"y\" : " + mViewportRect.top +
                ", \"width\" : " + mViewportRect.width() +
                ", \"height\" : " + mViewportRect.height() +
                ", \"pageWidth\" : " + mPageSize.width +
                ", \"pageHeight\" : " + mPageSize.height +
                ", \"offsetX\" : " + mViewportOffset.x +
--- a/mobile/android/base/ui/PanZoomController.java
+++ b/mobile/android/base/ui/PanZoomController.java
@@ -38,16 +38,17 @@
 package org.mozilla.gecko.ui;
 
 import org.json.JSONObject;
 import org.json.JSONException;
 import org.mozilla.gecko.gfx.FloatSize;
 import org.mozilla.gecko.gfx.LayerController;
 import org.mozilla.gecko.gfx.PointUtils;
 import org.mozilla.gecko.gfx.RectUtils;
+import org.mozilla.gecko.gfx.ViewportMetrics;
 import org.mozilla.gecko.FloatUtils;
 import org.mozilla.gecko.GeckoApp;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoEventListener;
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.util.Log;
@@ -747,16 +748,46 @@ public class PanZoomController
 
             if (mFlingState == FlingStates.PANNING)
                 displacement += lastTouchPos - touchPos;
             else
                 displacement += velocity;
         }
     }
 
+    /* Returns the nearest viewport metrics with no overscroll visible. */
+    private ViewportMetrics getValidViewportMetrics() {
+        ViewportMetrics viewportMetrics = new ViewportMetrics(mController.getViewportMetrics());
+
+        /* First, we adjust the zoom factor so that we can make no overscrolled area visible. */
+        float zoomFactor = viewportMetrics.getZoomFactor();
+        FloatSize pageSize = viewportMetrics.getPageSize();
+        RectF viewport = viewportMetrics.getViewport();
+
+        float minZoomFactor = 0.0f;
+        if (viewport.width() > pageSize.width) {
+            float scaleFactor = viewport.width() / pageSize.width;
+            minZoomFactor = (float)Math.max(minZoomFactor, zoomFactor * scaleFactor);
+        }
+        if (viewport.height() > pageSize.height) {
+            float scaleFactor = viewport.height() / pageSize.height;
+            minZoomFactor = (float)Math.max(minZoomFactor, zoomFactor * scaleFactor);
+        }
+
+        if (!FloatUtils.fuzzyEquals(minZoomFactor, 0.0f)) {
+            PointF center = new PointF(viewport.width() / 2.0f, viewport.height() / 2.0f);
+            viewportMetrics.scaleTo(minZoomFactor, center);
+        }
+
+        /* Now we pan to the right origin. */
+        viewportMetrics.setViewport(viewportMetrics.getClampedViewport());
+
+        return viewportMetrics;
+    }
+
     private class AxisX extends Axis {
         @Override
         public float getOrigin() { return mController.getOrigin().x; }
         @Override
         protected float getViewportLength() { return mController.getViewportSize().width; }
         @Override
         protected float getPageLength() { return mController.getPageSize().width; }
     }