[Libreoffice-commits] core.git: 2 commits - android/experimental

Tomaž Vajngerl tomaz.vajngerl at collabora.com
Sun Sep 21 14:10:32 PDT 2014


 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java                     |    3 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/CheckerboardImage.java         |   43 ---
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java                  |    6 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java  |   27 +-
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/IntSize.java                   |   46 ---
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/Layer.java                     |   49 ---
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java           |    7 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java             |   20 -
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java        |   42 ---
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PanningPerfAPI.java            |   46 ---
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PointUtils.java                |   65 +---
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java                 |   98 ++-----
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java            |   57 ----
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java           |   88 ++----
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SubTile.java                   |    5 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TextLayer.java                 |   56 ----
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java                 |   66 +----
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewTransform.java             |   38 --
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewportMetrics.java           |   72 ++---
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/Axis.java                       |  132 +++++-----
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java |   99 ++-----
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SubdocumentScrollHelper.java    |   83 +++---
 22 files changed, 390 insertions(+), 758 deletions(-)

New commits:
commit 62a6a7d7d711209caf1237b0955e24a61b7bb21d
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Fri Sep 19 13:22:17 2014 +0200

    android: upgrade layers to newer code
    
    Change-Id: Ife0d7cfad8b416c9363321a2fd1f4e9a8a1f4325

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index c12170f..bc08b98 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -64,7 +64,8 @@ public class LOKitThread extends Thread {
         int pageHeight = mTileProvider.getPageHeight();
 
         mViewportMetrics = new ViewportMetrics();
-        mViewportMetrics.setPageSize(new FloatSize(pageWidth, pageHeight));
+        FloatSize size = new FloatSize(pageWidth, pageHeight);
+        mViewportMetrics.setPageSize(size, size);
 
         GeckoLayerClient layerClient = mApplication.getLayerClient();
         layerClient.beginDrawing(mViewportMetrics);
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/CheckerboardImage.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/CheckerboardImage.java
index 7af94fa..bf1cab7 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/CheckerboardImage.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/CheckerboardImage.java
@@ -1,39 +1,7 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2012
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
@@ -78,8 +46,8 @@ public class CheckerboardImage extends CairoImage {
     }
 
     /** Updates the checkerboard image. If showChecks is true, then create a
-     checkerboard image that is tinted to the color. Otherwise just return a flat
-     image of the color. */
+        checkerboard image that is tinted to the color. Otherwise just return a flat
+        image of the color. */
     public void update(boolean showChecks, int color) {
         mMainColor = color;
         mShowChecks = showChecks;
@@ -148,6 +116,7 @@ public class CheckerboardImage extends CairoImage {
         try {
             if (mBuffer != null) {
                 DirectBufferAllocator.free(mBuffer);
+                mBuffer = null;
             }
         } finally {
             super.finalize();
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java
index 4f788f6..c62947a 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java
@@ -38,11 +38,11 @@
 package org.mozilla.gecko.gfx;
 
 import android.opengl.GLSurfaceView;
-import android.view.SurfaceHolder;
-import javax.microedition.khronos.opengles.GL10;
-import java.util.concurrent.Future;
+
 import java.util.concurrent.LinkedBlockingQueue;
 
+import javax.microedition.khronos.opengles.GL10;
+
 // A GL thread managed by Java. It is not necessary to use this class to use the
 // FlexibleGLSurfaceView, but it can be helpful, especially if the GL rendering is to be done
 // entirely in Java.
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java
index b9eb34d..067c532 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ImmutableViewportMetrics.java
@@ -19,6 +19,8 @@ public class ImmutableViewportMetrics {
     // because Java doesn't have the concept of const classes
     public final float pageSizeWidth;
     public final float pageSizeHeight;
+    public final float cssPageSizeWidth;
+    public final float cssPageSizeHeight;
     public final float viewportRectBottom;
     public final float viewportRectLeft;
     public final float viewportRectRight;
@@ -36,6 +38,10 @@ public class ImmutableViewportMetrics {
         pageSizeWidth = pageSize.width;
         pageSizeHeight = pageSize.height;
 
+        FloatSize cssPageSize = m.getCssPageSize();
+        cssPageSizeWidth = cssPageSize.width;
+        cssPageSizeHeight = cssPageSize.height;
+
         zoomFactor = m.getZoomFactor();
     }
 
@@ -59,12 +65,27 @@ public class ImmutableViewportMetrics {
 
     public RectF getViewport() {
         return new RectF(viewportRectLeft,
-                viewportRectTop,
-                viewportRectRight,
-                viewportRectBottom);
+                         viewportRectTop,
+                         viewportRectRight,
+                         viewportRectBottom);
+    }
+
+    public RectF getCssViewport() {
+        return RectUtils.scale(getViewport(), 1/zoomFactor);
     }
 
     public FloatSize getPageSize() {
         return new FloatSize(pageSizeWidth, pageSizeHeight);
     }
+
+    public FloatSize getCssPageSize() {
+        return new FloatSize(cssPageSizeWidth, cssPageSizeHeight);
+    }
+
+    @Override
+    public String toString() {
+        return "ImmutableViewportMetrics v=(" + viewportRectLeft + "," + viewportRectTop + ","
+                + viewportRectRight + "," + viewportRectBottom + ") p=(" + pageSizeWidth + ","
+                + pageSizeHeight + ") z=" + zoomFactor;
+    }
 }
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/IntSize.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/IntSize.java
index ee43b1b..b0741d2 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/IntSize.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/IntSize.java
@@ -1,46 +1,12 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
-import org.mozilla.gecko.gfx.FloatSize;
 import org.json.JSONException;
 import org.json.JSONObject;
-import java.lang.Math;
 
 public class IntSize {
     public final int width, height;
@@ -79,7 +45,7 @@ public class IntSize {
 
     public IntSize scale(float factor) {
         return new IntSize(Math.round(width * factor),
-                           Math.round(height * factor));
+                Math.round(height * factor));
     }
 
     /* Returns the power of two that is greater than or equal to value */
@@ -96,6 +62,10 @@ public class IntSize {
         return value + 1;
     }
 
+    public static int nextPowerOfTwo(float value) {
+        return nextPowerOfTwo((int) value);
+    }
+
     public IntSize nextPowerOfTwo() {
         return new IntSize(nextPowerOfTwo(width), nextPowerOfTwo(height));
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/Layer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/Layer.java
index 7e575b5..0ab4e6a 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/Layer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/Layer.java
@@ -1,41 +1,7 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *   Chris Lord <chrislord.net at gmail.com>
- *   Arkady Blyakher <rkadyb at mit.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
@@ -56,6 +22,7 @@ public abstract class Layer {
 
     protected Rect mPosition;
     protected float mResolution;
+    protected boolean mUsesDefaultProgram = true;
 
     public Layer() {
         this(null);
@@ -166,6 +133,10 @@ public abstract class Layer {
         mNewResolution = newResolution;
     }
 
+    public boolean usesDefaultProgram() {
+        return mUsesDefaultProgram;
+    }
+
     /**
      * Subclasses may override this method to perform custom layer updates. This will be called
      * with the transaction lock held. Subclass implementations of this method must call the
@@ -186,15 +157,17 @@ public abstract class Layer {
     public static class RenderContext {
         public final RectF viewport;
         public final FloatSize pageSize;
+        public final IntSize screenSize;
         public final float zoomFactor;
         public final int positionHandle;
         public final int textureHandle;
         public final FloatBuffer coordBuffer;
 
-        public RenderContext(RectF aViewport, FloatSize aPageSize, float aZoomFactor,
+        public RenderContext(RectF aViewport, FloatSize aPageSize, IntSize aScreenSize, float aZoomFactor,
                              int aPositionHandle, int aTextureHandle, FloatBuffer aCoordBuffer) {
             viewport = aViewport;
             pageSize = aPageSize;
+            screenSize = aScreenSize;
             zoomFactor = aZoomFactor;
             positionHandle = aPositionHandle;
             textureHandle = aTextureHandle;
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java
index e9d0cb6..b9d80d9 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java
@@ -213,8 +213,9 @@ public class LayerController {
         if (size.width >= oldWidth && size.height >= oldHeight) {
             FloatSize pageSize = viewportMetrics.getPageSize();
             if (pageSize.width < size.width || pageSize.height < size.height) {
-                viewportMetrics.setPageSize(new FloatSize(Math.max(pageSize.width, size.width),
-                                                           Math.max(pageSize.height, size.height)));
+                FloatSize actualPageSize = new FloatSize(Math.max(pageSize.width, size.width),
+                                               Math.max(pageSize.height, size.height));
+                viewportMetrics.setPageSize(actualPageSize, actualPageSize);
             }
         }
 
@@ -260,7 +261,7 @@ public class LayerController {
             return;
 
         ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
-        viewportMetrics.setPageSize(size);
+        viewportMetrics.setPageSize(size, size);
         mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
 
         // Page size is owned by the layer client, so no need to notify it of
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
index 6ff9a8a..c82bab8 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
@@ -59,7 +59,7 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
-import java.util.ArrayList;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
@@ -92,7 +92,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
     private RenderContext mLastPageContext;
     private int mMaxTextureSize;
 
-    private ArrayList<Layer> mExtraLayers = new ArrayList<Layer>();
+    private CopyOnWriteArrayList<Layer> mExtraLayers = new CopyOnWriteArrayList<Layer>();
 
     // Dropped frames display
     private int[] mFrameTimings;
@@ -114,6 +114,9 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
     private int mSampleHandle;
     private int mTMatrixHandle;
 
+    private int mSurfaceWidth;
+    private int mSurfaceHeight;
+
     // column-major matrix applied to each vertex to shift the viewport from
     // one ranging from (-1, -1),(1,1) to (0,0),(1,1) and to scale all sizes by
     // a factor of 2 to fill up the screen
@@ -263,9 +266,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
     }
 
     public void addLayer(Layer layer) {
-        LayerController controller = mView.getController();
-
-        synchronized (controller) {
+        synchronized (mExtraLayers) {
             if (mExtraLayers.contains(layer)) {
                 mExtraLayers.remove(layer);
             }
@@ -275,9 +276,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
     }
 
     public void removeLayer(Layer layer) {
-        LayerController controller = mView.getController();
-
-        synchronized (controller) {
+        synchronized (mExtraLayers) {
             mExtraLayers.remove(layer);
         }
     }
@@ -331,11 +330,14 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
     }
 
     private RenderContext createContext(RectF viewport, FloatSize pageSize, float zoomFactor) {
-        return new RenderContext(viewport, pageSize, zoomFactor, mPositionHandle, mTextureHandle,
+        return new RenderContext(viewport, pageSize, new IntSize(mSurfaceWidth, mSurfaceHeight), zoomFactor, mPositionHandle, mTextureHandle,
                                  mCoordBuffer);
     }
 
     public void onSurfaceChanged(GL10 gl, final int width, final int height) {
+        mSurfaceWidth = width;
+        mSurfaceHeight = height;
+
         GLES20.glViewport(0, 0, width, height);
 
         if (mFrameRateLayer != null) {
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java
index 6f73f9c..f3201cf 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/NinePatchTileLayer.java
@@ -1,40 +1,7 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *   Arkady Blyakher <rkadyb at mit.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
@@ -136,6 +103,9 @@ public class NinePatchTileLayer extends TileLayer {
         coordBuffer.position(0);
         coordBuffer.put(coords);
 
+        // Unbind any the current array buffer so we can use client side buffers
+        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+
         // Vertex coordinates are x,y,z starting at position 0 into the buffer.
         coordBuffer.position(0);
         GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20, coordBuffer);
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PanningPerfAPI.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PanningPerfAPI.java
index c9414ac..f50b46a 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PanningPerfAPI.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PanningPerfAPI.java
@@ -1,48 +1,16 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Kartikaya Gupta <kgupta at mozilla.com>
- *   Chris Lord <chrislord.net at gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
-import java.util.ArrayList;
-import java.util.List;
 import android.os.SystemClock;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class PanningPerfAPI {
     private static final String LOGTAG = "GeckoPanningPerfAPI";
 
@@ -122,4 +90,4 @@ public class PanningPerfAPI {
             mCheckerboardAmounts.add(amount);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PointUtils.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PointUtils.java
index bff9f9f..cdacc31 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PointUtils.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/PointUtils.java
@@ -1,52 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Kartikaya Gupta <kgupta at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
 import android.graphics.Point;
 import android.graphics.PointF;
-import android.util.FloatMath;
 
-import org.json.JSONObject;
 import org.json.JSONException;
+import org.json.JSONObject;
 import org.mozilla.gecko.util.FloatUtils;
 
-import java.lang.Math;
-
 public final class PointUtils {
     public static PointF add(PointF one, PointF two) {
         return new PointF(one.x + two.x, one.y + two.y);
@@ -64,19 +29,19 @@ public final class PointUtils {
         return new Point(Math.round(point.x), Math.round(point.y));
     }
 
-   /* Returns a new point that is a linear interpolation between start and end points. weight conrols the weighting
-    * 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 = FloatUtils.interpolate(startPoint.x, endPoint.x, weight);
-       float y = FloatUtils.interpolate(startPoint.y, endPoint.y, weight);
-       return new PointF(x, y);
-   }
+    /* Returns a new point that is a linear interpolation between start and end points. weight conrols the weighting
+     * 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 = FloatUtils.interpolate(startPoint.x, endPoint.x, weight);
+        float y = FloatUtils.interpolate(startPoint.y, endPoint.y, weight);
+        return new PointF(x, y);
+    }
 
-   /* Computes the magnitude of the given vector. */
-   public static float distance(PointF point) {
+    /* Computes the magnitude of the given vector. */
+    public static float distance(PointF point) {
         return (float)Math.sqrt(point.x * point.x + point.y * point.y);
-   }
+    }
 
     /** Computes the scalar distance between two points. */
     public static float distance(PointF one, PointF two) {
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java
index 9a50497..92ea78f 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java
@@ -1,49 +1,18 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Kartikaya Gupta <kgupta at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
-import org.mozilla.gecko.util.FloatUtils;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
+
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.mozilla.gecko.util.FloatUtils;
 
 public final class RectUtils {
     public static Rect create(JSONObject json) {
@@ -58,31 +27,22 @@ public final class RectUtils {
         }
     }
 
-    public static Rect contract(Rect rect, int lessWidth, int lessHeight) {
-        float halfLessWidth = lessWidth / 2.0f;
-        float halfLessHeight = lessHeight / 2.0f;
-        return new Rect(Math.round(rect.left + halfLessWidth),
-                Math.round(rect.top + halfLessHeight),
-                Math.round(rect.right - halfLessWidth),
-                Math.round(rect.bottom - halfLessHeight));
-    }
-
-    public static RectF contract(RectF rect, float lessWidth, float lessHeight) {
-        float halfLessWidth = lessWidth / 2;
-        float halfLessHeight = lessHeight / 2;
-        return new RectF(rect.left + halfLessWidth,
-                rect.top + halfLessHeight,
-                rect.right - halfLessWidth,
-                rect.bottom - halfLessHeight);
-    }
-
     public static RectF expand(RectF rect, float moreWidth, float moreHeight) {
         float halfMoreWidth = moreWidth / 2;
         float halfMoreHeight = moreHeight / 2;
         return new RectF(rect.left - halfMoreWidth,
-                rect.top - halfMoreHeight,
-                rect.right + halfMoreWidth,
-                rect.bottom + halfMoreHeight);
+                         rect.top - halfMoreHeight,
+                         rect.right + halfMoreWidth,
+                         rect.bottom + halfMoreHeight);
+    }
+
+    public static RectF contract(RectF rect, float lessWidth, float lessHeight) {
+        float halfLessWidth = lessWidth / 2.0f;
+        float halfLessHeight = lessHeight / 2.0f;
+        return new RectF(rect.left + halfLessWidth,
+                         rect.top + halfLessHeight,
+                         rect.right - halfLessWidth,
+                         rect.bottom - halfLessHeight);
     }
 
     public static RectF intersect(RectF one, RectF two) {
@@ -97,14 +57,19 @@ public final class RectUtils {
         float x = rect.left * scale;
         float y = rect.top * scale;
         return new RectF(x, y,
-                x + (rect.width() * scale),
-                y + (rect.height() * scale));
+                         x + (rect.width() * scale),
+                         y + (rect.height() * scale));
     }
 
     /** Returns the nearest integer rect of the given rect. */
     public static Rect round(RectF rect) {
         return new Rect(Math.round(rect.left), Math.round(rect.top),
-                Math.round(rect.right), Math.round(rect.bottom));
+                        Math.round(rect.right), Math.round(rect.bottom));
+    }
+
+    public static Rect roundIn(RectF rect) {
+        return new Rect((int)Math.ceil(rect.left), (int)Math.ceil(rect.top),
+                        (int)Math.floor(rect.right), (int)Math.floor(rect.bottom));
     }
 
     public static IntSize getSize(Rect rect) {
@@ -125,13 +90,18 @@ public final class RectUtils {
      */
     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));
+                         FloatUtils.interpolate(from.top, to.top, t),
+                         FloatUtils.interpolate(from.right, to.right, t),
+                         FloatUtils.interpolate(from.bottom, to.bottom, t));
     }
 
     public static boolean fuzzyEquals(RectF a, RectF b) {
-        return FloatUtils.fuzzyEquals(a.top, b.top)
+        if (a == null && b == null)
+            return true;
+        else if ((a == null && b != null) || (a != null && b == null))
+            return false;
+        else
+            return FloatUtils.fuzzyEquals(a.top, b.top)
                 && FloatUtils.fuzzyEquals(a.left, b.left)
                 && FloatUtils.fuzzyEquals(a.right, b.right)
                 && FloatUtils.fuzzyEquals(a.bottom, b.bottom);
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java
index 4ea1c13..d3e00e1 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java
@@ -1,40 +1,7 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Kartikaya Gupta <kgupta at mozilla.com>
- *   Arkady Blyakher <rkadyb at mit.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
@@ -65,11 +32,9 @@ public class ScrollbarLayer extends TileLayer {
     private static final int CAP_RADIUS = (BAR_SIZE / 2);
 
     private final boolean mVertical;
-    private final ByteBuffer mBuffer;
     private final Bitmap mBitmap;
     private final Canvas mCanvas;
     private float mOpacity;
-    private boolean mFinalized = false;
 
     private LayerRenderer mRenderer;
     private int mProgram;
@@ -143,7 +108,6 @@ public class ScrollbarLayer extends TileLayer {
     private ScrollbarLayer(LayerRenderer renderer, CairoImage image, boolean vertical, ByteBuffer buffer) {
         super(image, TileLayer.PaintMode.NORMAL);
         mVertical = vertical;
-        mBuffer = buffer;
         mRenderer = renderer;
 
         IntSize size = image.getSize();
@@ -159,17 +123,7 @@ public class ScrollbarLayer extends TileLayer {
         mCanvas.drawColor(Color.argb(0, 0, 0, 0), PorterDuff.Mode.CLEAR);
         mCanvas.drawCircle(CAP_RADIUS, CAP_RADIUS, CAP_RADIUS, foregroundPaint);
 
-        mBitmap.copyPixelsToBuffer(mBuffer.asIntBuffer());
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            if (!mFinalized && mBuffer != null)
-                DirectBufferAllocator.free(mBuffer);
-            mFinalized = true;
-        } finally {
-            super.finalize();
-        }
+        mBitmap.copyPixelsToBuffer(buffer.asIntBuffer());
     }
 
     public static ScrollbarLayer create(LayerRenderer renderer, boolean vertical) {
@@ -307,6 +261,9 @@ public class ScrollbarLayer extends TileLayer {
         coordBuffer.position(0);
         coordBuffer.put(bodyCoords);
 
+        // Unbind any the current array buffer so we can use client side buffers
+        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+
         // Vertex coordinates are x,y,z starting at position 0 into the buffer.
         coordBuffer.position(0);
         GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20,
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java
index 35f50c7..160a40b 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java
@@ -1,40 +1,7 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *   Arkady Blyakher <rkadyb at mit.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
@@ -81,15 +48,24 @@ public class SingleTileLayer extends TileLayer {
             return;
 
         RectF bounds;
-        Rect position = getPosition();
+        RectF textureBounds;
         RectF viewport = context.viewport;
 
-        if (repeats() || stretches()) {
+        if (repeats()) {
+            // If we're repeating, we want to adjust the texture bounds so that
+            // the texture repeats the correct number of times when drawn at
+            // the size of the viewport.
+            bounds = getBounds(context);
+            textureBounds = new RectF(0.0f, 0.0f, bounds.width(), bounds.height());
             bounds = new RectF(0.0f, 0.0f, viewport.width(), viewport.height());
-            int width = Math.round(viewport.width());
-            int height = Math.round(viewport.height());
+        } else if (stretches()) {
+            // If we're stretching, we just want the bounds and texture bounds
+            // to fit to the page.
+            bounds = new RectF(0.0f, 0.0f, context.pageSize.width, context.pageSize.height);
+            textureBounds = bounds;
         } else {
             bounds = getBounds(context);
+            textureBounds = bounds;
         }
 
         Rect intBounds = new Rect();
@@ -112,30 +88,31 @@ public class SingleTileLayer extends TileLayer {
                                        Math.min(bounds.right, (float)subRect.right),
                                        Math.min(bounds.bottom, (float)subRect.bottom));
 
+            // This is the left/top/right/bottom of the rect, relative to the
+            // bottom-left of the layer, to use for texture coordinates.
             int[] cropRect = new int[] { Math.round(subRectF.left - bounds.left),
-                                         Math.round(subRectF.bottom - bounds.top),
+                                         Math.round(bounds.bottom - subRectF.top),
                                          Math.round(subRectF.right - bounds.left),
-                                         Math.round(subRectF.top - bounds.top) };
-
-            cropRect = new int[] { 0, 0, position.width(), position.height() };
+                                         Math.round(bounds.bottom - subRectF.bottom) };
 
-            float height = subRectF.height();
             float left = subRectF.left - viewport.left;
-            float top = viewport.height() - (subRectF.top + height - viewport.top);
+            float top = viewport.bottom - subRectF.bottom;
+            float right = left + subRectF.width();
+            float bottom = top + subRectF.height();
 
             float[] coords = {
                 //x, y, z, texture_x, texture_y
-                left/viewport.width(), top/viewport.height(), 0,
-                cropRect[0]/(float)position.width(), cropRect[1]/(float)position.height(),
+                left/viewport.width(), bottom/viewport.height(), 0,
+                cropRect[0]/textureBounds.width(), cropRect[1]/textureBounds.height(),
 
-                left/viewport.width(), (top+height)/viewport.height(), 0,
-                cropRect[0]/(float)position.width(), cropRect[3]/(float)position.height(),
+                left/viewport.width(), top/viewport.height(), 0,
+                cropRect[0]/textureBounds.width(), cropRect[3]/textureBounds.height(),
 
-                (left+subRectF.width())/viewport.width(), top/viewport.height(), 0,
-                cropRect[2]/(float)position.width(), cropRect[1]/(float)position.height(),
+                right/viewport.width(), bottom/viewport.height(), 0,
+                cropRect[2]/textureBounds.width(), cropRect[1]/textureBounds.height(),
 
-                (left+subRectF.width())/viewport.width(), (top+height)/viewport.height(), 0,
-                cropRect[2]/(float)position.width(), cropRect[3]/(float)position.height()
+                right/viewport.width(), top/viewport.height(), 0,
+                cropRect[2]/textureBounds.width(), cropRect[3]/textureBounds.height()
             };
 
             FloatBuffer coordBuffer = context.coordBuffer;
@@ -148,6 +125,9 @@ public class SingleTileLayer extends TileLayer {
             coordBuffer.position(0);
             coordBuffer.put(coords);
 
+            // Unbind any the current array buffer so we can use client side buffers
+            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+
             // Vertex coordinates are x,y,z starting at position 0 into the buffer.
             coordBuffer.position(0);
             GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20, coordBuffer);
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SubTile.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SubTile.java
index b2464bc..87d492d 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SubTile.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SubTile.java
@@ -1,3 +1,8 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 package org.mozilla.gecko.gfx;
 
 public class SubTile extends SingleTileLayer {
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TextLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TextLayer.java
index e3bd2f2..5ac7c97 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TextLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TextLayer.java
@@ -1,43 +1,10 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
-//import org.mozilla.gecko.GeckoAppShell;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -52,9 +19,8 @@ import java.nio.ByteBuffer;
  * Draws text on a layer. This is used for the frame rate meter.
  */
 public class TextLayer extends SingleTileLayer {
-    private final ByteBuffer mBuffer;
+    private final ByteBuffer mBuffer;   // this buffer is owned by the BufferedCairoImage
     private final IntSize mSize;
-    private boolean mFinalized = false;
 
     /*
      * This awkward pattern is necessary due to Java's restrictions on when one can call superclass
@@ -67,20 +33,10 @@ public class TextLayer extends SingleTileLayer {
         renderText(text);
     }
 
-    protected void finalize() throws Throwable {
-        try {
-            if (!mFinalized && mBuffer != null) {
-                DirectBufferAllocator.free(mBuffer);
-            }
-            mFinalized = true;
-        } finally {
-            super.finalize();
-        }
-    }
-
     public static TextLayer create(IntSize size, String text) {
         ByteBuffer buffer = DirectBufferAllocator.allocate(size.width * size.height * 4);
-        BufferedCairoImage image = new BufferedCairoImage(buffer, size.width, size.height, CairoImage.FORMAT_ARGB32);
+        BufferedCairoImage image = new BufferedCairoImage(buffer, size.width, size.height,
+                                                          CairoImage.FORMAT_ARGB32);
         return new TextLayer(buffer, image, size, text);
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
index e31cfb7..4f7ff9d 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
@@ -1,40 +1,7 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *   Arkady Blyakher <rkadyb at mit.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
@@ -51,10 +18,11 @@ public abstract class TileLayer extends Layer {
     private static final String LOGTAG = "GeckoTileLayer";
 
     private final Rect mDirtyRect;
-    private final CairoImage mImage;
     private IntSize mSize;
     private int[] mTextureIDs;
 
+    protected final CairoImage mImage;
+
     public enum PaintMode { NORMAL, REPEAT, STRETCH };
     private PaintMode mPaintMode;
 
@@ -74,16 +42,16 @@ public abstract class TileLayer extends Layer {
 
     @Override
     protected void finalize() throws Throwable {
-        if (mTextureIDs != null)
-            TextureReaper.get().add(mTextureIDs);
+        try {
+            if (mTextureIDs != null)
+                TextureReaper.get().add(mTextureIDs);
+        } finally {
+            super.finalize();
+        }
     }
 
-    @Override
-    public void setPosition(Rect newPosition) {
-        if (newPosition.width() != mImage.getSize().width || newPosition.height() != mImage.getSize().height) {
-            throw new RuntimeException("Error: changing the size of a tile layer is not allowed!");
-        }
-        super.setPosition(newPosition);
+    public void setPaintMode(PaintMode mode) {
+        mPaintMode = mode;
     }
 
     /**
@@ -106,10 +74,7 @@ public abstract class TileLayer extends Layer {
          *
          * XXX Currently, we don't pick a GLES 2.0 context, so always round.
          */
-        IntSize bufferSize = mImage.getSize();
-        IntSize textureSize = bufferSize;
-
-        textureSize = bufferSize.nextPowerOfTwo();
+        IntSize textureSize = mImage.getSize().nextPowerOfTwo();
 
         if (!textureSize.equals(mSize)) {
             mSize = textureSize;
@@ -172,6 +137,9 @@ public abstract class TileLayer extends Layer {
 
         bindAndSetGLParameters();
 
+        // XXX TexSubImage2D is too broken to rely on on Adreno, and very slow
+        //     on other chipsets, so we always upload the entire buffer.
+        IntSize bufferSize = mImage.getSize();
         GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, glInfo.internalFormat, mSize.width,
                             mSize.height, 0, glInfo.format, glInfo.type, imageBuffer);
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewTransform.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewTransform.java
index 9f443ea..edb45f5 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewTransform.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewTransform.java
@@ -1,39 +1,7 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewportMetrics.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewportMetrics.java
index 8c3004e..f21f499 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewportMetrics.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewportMetrics.java
@@ -1,40 +1,7 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2009-2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *   Chris Lord <chrislord.net at gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
@@ -55,6 +22,7 @@ public class ViewportMetrics {
     private static final String LOGTAG = "GeckoViewportMetrics";
 
     private FloatSize mPageSize;
+    private FloatSize mCssPageSize;
     private RectF mViewportRect;
     private float mZoomFactor;
 
@@ -63,18 +31,21 @@ public class ViewportMetrics {
         LibreOfficeMainActivity.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
 
         mPageSize = new FloatSize(metrics.widthPixels, metrics.heightPixels);
+        mCssPageSize = new FloatSize(metrics.widthPixels, metrics.heightPixels);
         mViewportRect = new RectF(0, 0, metrics.widthPixels, metrics.heightPixels);
         mZoomFactor = 1.0f;
     }
 
     public ViewportMetrics(ViewportMetrics viewport) {
         mPageSize = new FloatSize(viewport.getPageSize());
+        mCssPageSize = new FloatSize(viewport.getCssPageSize());
         mViewportRect = new RectF(viewport.getViewport());
         mZoomFactor = viewport.getZoomFactor();
     }
 
     public ViewportMetrics(ImmutableViewportMetrics viewport) {
         mPageSize = new FloatSize(viewport.pageSizeWidth, viewport.pageSizeHeight);
+        mCssPageSize = new FloatSize(viewport.cssPageSizeWidth, viewport.cssPageSizeHeight);
         mViewportRect = new RectF(viewport.viewportRectLeft,
                                   viewport.viewportRectTop,
                                   viewport.viewportRectRight,
@@ -90,9 +61,12 @@ public class ViewportMetrics {
         float height = (float)json.getDouble("height");
         float pageWidth = (float)json.getDouble("pageWidth");
         float pageHeight = (float)json.getDouble("pageHeight");
+        float cssPageWidth = (float)json.getDouble("cssPageWidth");
+        float cssPageHeight = (float)json.getDouble("cssPageHeight");
         float zoom = (float)json.getDouble("zoom");
 
         mPageSize = new FloatSize(pageWidth, pageHeight);
+        mCssPageSize = new FloatSize(cssPageWidth, cssPageHeight);
         mViewportRect = new RectF(x, y, x + width, y + height);
         mZoomFactor = zoom;
     }
@@ -109,6 +83,10 @@ public class ViewportMetrics {
         return mViewportRect;
     }
 
+    public RectF getCssViewport() {
+        return RectUtils.scale(mViewportRect, 1/mZoomFactor);
+    }
+
     /** Returns the viewport rectangle, clamped within the page-size. */
     public RectF getClampedViewport() {
         RectF clampedViewport = new RectF(mViewportRect);
@@ -133,12 +111,18 @@ public class ViewportMetrics {
         return mPageSize;
     }
 
+    public FloatSize getCssPageSize() {
+        return mCssPageSize;
+    }
+
+
     public float getZoomFactor() {
         return mZoomFactor;
     }
 
-    public void setPageSize(FloatSize pageSize) {
+    public void setPageSize(FloatSize pageSize, FloatSize cssPageSize) {
         mPageSize = pageSize;
+        mCssPageSize = cssPageSize;
     }
 
     public void setViewport(RectF viewport) {
@@ -165,14 +149,17 @@ public class ViewportMetrics {
      * after scaling.
      */
     public void scaleTo(float newZoomFactor, PointF focus) {
-        float scaleFactor = newZoomFactor / mZoomFactor;
-
-        mPageSize = mPageSize.scale(scaleFactor);
+        // mCssPageSize is invariant, since we're setting the scale factor
+        // here. The page size is based on the CSS page size.
+        mPageSize = mCssPageSize.scale(newZoomFactor);
 
+        float scaleFactor = newZoomFactor / mZoomFactor;
         PointF origin = getOrigin();
+
         origin.offset(focus.x, focus.y);
         origin = PointUtils.scale(origin, scaleFactor);
         origin.offset(-focus.x, -focus.y);
+
         setOrigin(origin);
 
         mZoomFactor = newZoomFactor;
@@ -186,6 +173,7 @@ public class ViewportMetrics {
     public ViewportMetrics interpolate(ViewportMetrics to, float t) {
         ViewportMetrics result = new ViewportMetrics();
         result.mPageSize = mPageSize.interpolate(to.mPageSize, t);
+        result.mCssPageSize = mCssPageSize.interpolate(to.mCssPageSize, t);
         result.mZoomFactor = FloatUtils.interpolate(mZoomFactor, to.mZoomFactor, t);
         result.mViewportRect = RectUtils.interpolate(mViewportRect, to.mViewportRect, t);
         return result;
@@ -193,6 +181,7 @@ public class ViewportMetrics {
 
     public boolean fuzzyEquals(ViewportMetrics other) {
         return mPageSize.fuzzyEquals(other.mPageSize)
+            && mCssPageSize.fuzzyEquals(other.mCssPageSize)
             && RectUtils.fuzzyEquals(mViewportRect, other.mViewportRect)
             && FloatUtils.fuzzyEquals(mZoomFactor, other.mZoomFactor);
     }
@@ -210,6 +199,8 @@ public class ViewportMetrics {
           .append(", \"height\" : ").append(height)
           .append(", \"pageWidth\" : ").append(mPageSize.width)
           .append(", \"pageHeight\" : ").append(mPageSize.height)
+          .append(", \"cssPageWidth\" : ").append(mCssPageSize.width)
+          .append(", \"cssPageHeight\" : ").append(mCssPageSize.height)
           .append(", \"zoom\" : ").append(mZoomFactor)
           .append(" }");
         return sb.toString();
@@ -220,6 +211,7 @@ public class ViewportMetrics {
         StringBuffer buff = new StringBuffer(128);
         buff.append("v=").append(mViewportRect.toString())
             .append(" p=").append(mPageSize.toString())
+            .append(" c=").append(mCssPageSize.toString())
             .append(" z=").append(mZoomFactor);
         return buff.toString();
     }
commit 9bc2a66b236985a049c4709405e9b66960f27fcb
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Fri Sep 19 12:48:11 2014 +0200

    android: upgrade gestures and scrolling to newer code
    
    Change-Id: I84b9f66036891f6ad384ee71d078c654511a6e38

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/Axis.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/Axis.java
index 521e60a..d5e3de8 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/Axis.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/Axis.java
@@ -1,45 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2012
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *   Kartikaya Gupta <kgupta at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.ui;
 
+import android.util.Log;
+
+import org.json.JSONArray;
 import org.mozilla.gecko.util.FloatUtils;
 
+import java.util.Map;
+
 /**
  * This class represents the physics for one axis of movement (i.e. either
  * horizontal or vertical). It tracks the different properties of movement
@@ -47,25 +19,73 @@ import org.mozilla.gecko.util.FloatUtils;
  * a particular axis.
  */
 abstract class Axis {
+    private static final String LOGTAG = "GeckoAxis";
+
+    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";
+    private static final String PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE = "ui.scrolling.min_scrollable_distance";
+
     // This fraction of velocity remains after every animation frame when the velocity is low.
-    private static final float FRICTION_SLOW = 0.85f;
+    private static float FRICTION_SLOW;
     // This fraction of velocity remains after every animation frame when the velocity is high.
-    private static final float FRICTION_FAST = 0.97f;
+    private static float FRICTION_FAST;
     // Below this velocity (in pixels per frame), the friction starts increasing from FRICTION_FAST
     // to FRICTION_SLOW.
-    private static final float VELOCITY_THRESHOLD = 10.0f;
+    private static float VELOCITY_THRESHOLD;
     // The maximum velocity change factor between events, per ms, in %.
     // Direction changes are excluded.
-    private static final float MAX_EVENT_ACCELERATION = 0.012f;
+    private static float MAX_EVENT_ACCELERATION;
 
     // The rate of deceleration when the surface has overscrolled.
-    private static final float OVERSCROLL_DECEL_RATE = 0.04f;
+    private static float OVERSCROLL_DECEL_RATE;
     // The percentage of the surface which can be overscrolled before it must snap back.
-    private static final float SNAP_LIMIT = 0.75f;
+    private static float SNAP_LIMIT;
 
     // The minimum amount of space that must be present for an axis to be considered scrollable,
     // in pixels.
-    private static final float MIN_SCROLLABLE_DISTANCE = 0.5f;
+    private static float MIN_SCROLLABLE_DISTANCE;
+
+    private static float getFloatPref(Map<String, Integer> prefs, String prefName, int defaultValue) {
+        Integer value = (prefs == null ? null : prefs.get(prefName));
+        return (float)(value == null || value < 0 ? defaultValue : value) / 1000f;
+    }
+
+    private static int getIntPref(Map<String, Integer> prefs, String prefName, int defaultValue) {
+        Integer value = (prefs == null ? null : prefs.get(prefName));
+        return (value == null || value < 0 ? defaultValue : value);
+    }
+
+    static void addPrefNames(JSONArray prefs) {
+        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);
+        prefs.put(PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE);
+    }
+
+    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);
+        MAX_EVENT_ACCELERATION = getFloatPref(prefs, PREF_SCROLLING_MAX_EVENT_ACCELERATION, 12);
+        OVERSCROLL_DECEL_RATE = 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 + ","
+                + MAX_EVENT_ACCELERATION + "," + OVERSCROLL_DECEL_RATE + "," + SNAP_LIMIT + "," + MIN_SCROLLABLE_DISTANCE);
+    }
+
+    static {
+        // set the scrolling parameters to default values on startup
+        setPrefs(null);
+    }
+
     // The number of milliseconds per frame assuming 60 fps
     private static final float MS_PER_FRAME = 1000.0f / 60.0f;
 
@@ -147,7 +167,7 @@ abstract class Axis {
     }
 
     private Overscroll getOverscroll() {
-        boolean minus = getOrigin() < 0.0f;
+        boolean minus = (getOrigin() < 0.0f);
         boolean plus = (getViewportEnd() > getPageLength());
         if (minus && plus) {
             return Overscroll.BOTH;
@@ -164,14 +184,10 @@ abstract class Axis {
     // overscrolled on this axis, returns 0.
     private float getExcess() {
         switch (getOverscroll()) {
-            case MINUS:
-                return -getOrigin();
-            case PLUS:
-                return getViewportEnd() - getPageLength();
-            case BOTH:
-                return getViewportEnd() - getPageLength() - getOrigin();
-            default:
-                return 0.0f;
+            case MINUS:     return -getOrigin();
+            case PLUS:      return getViewportEnd() - getPageLength();
+            case BOTH:      return getViewportEnd() - getPageLength() - getOrigin();
+            default:        return 0.0f;
         }
     }
 
@@ -180,7 +196,14 @@ abstract class Axis {
      * possible and this axis has not been scroll locked while panning. Otherwise, returns false.
      */
     private boolean scrollable() {
-        return getViewportLength() <= getPageLength() - MIN_SCROLLABLE_DISTANCE && !mScrollingDisabled;
+        // If we're scrolling a subdocument, ignore the viewport length restrictions (since those
+        // apply to the top-level document) and only take into account axis locking.
+        if (mSubscroller.scrolling()) {
+            return !mScrollingDisabled;
+        } else {
+            return getViewportLength() <= getPageLength() - MIN_SCROLLABLE_DISTANCE &&
+                    !mScrollingDisabled;
+        }
     }
 
     /*
@@ -257,8 +280,9 @@ abstract class Axis {
 
     // Performs displacement of the viewport position according to the current velocity.
     void displace() {
-        if (!mSubscroller.scrolling() && !scrollable())
+        if (!scrollable()) {
             return;
+        }
 
         if (mFlingState == FlingStates.PANNING)
             mDisplacement += (mLastTouchPos - mTouchPos) * getEdgeResistance();
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java
index 4f9e398..6f920ca 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java
@@ -1,47 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2012
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Patrick Walton <pcwalton at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.ui;
 
-import org.mozilla.gecko.gfx.PointUtils;
-import org.json.JSONException;
 import android.graphics.PointF;
 import android.util.Log;
 import android.view.MotionEvent;
+
+import org.json.JSONException;
+import org.mozilla.gecko.gfx.PointUtils;
+
 import java.util.LinkedList;
 import java.util.ListIterator;
 import java.util.Stack;
@@ -82,18 +52,18 @@ public class SimpleScaleGestureDetector {
     /** Forward touch events to this function. */
     public void onTouchEvent(MotionEvent event) {
         switch (event.getAction() & MotionEvent.ACTION_MASK) {
-            case MotionEvent.ACTION_DOWN:
-            case MotionEvent.ACTION_POINTER_DOWN:
-                onTouchStart(event);
-                break;
-            case MotionEvent.ACTION_MOVE:
-                onTouchMove(event);
-                break;
-            case MotionEvent.ACTION_POINTER_UP:
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                onTouchEnd(event);
-                break;
+        case MotionEvent.ACTION_DOWN:
+        case MotionEvent.ACTION_POINTER_DOWN:
+            onTouchStart(event);
+            break;
+        case MotionEvent.ACTION_MOVE:
+            onTouchMove(event);
+            break;
+        case MotionEvent.ACTION_POINTER_UP:
+        case MotionEvent.ACTION_UP:
+        case MotionEvent.ACTION_CANCEL:
+            onTouchEnd(event);
+            break;
         }
     }
 
@@ -103,7 +73,7 @@ public class SimpleScaleGestureDetector {
 
     private int getActionIndex(MotionEvent event) {
         return (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
-                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+            >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
     }
 
     private void onTouchStart(MotionEvent event) {
@@ -131,11 +101,12 @@ public class SimpleScaleGestureDetector {
     private void onTouchEnd(MotionEvent event) {
         mLastEventTime = event.getEventTime();
 
+        boolean isCancel = (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_CANCEL;
         int id = event.getPointerId(getActionIndex(event));
         ListIterator<PointerInfo> iterator = mPointerInfo.listIterator();
         while (iterator.hasNext()) {
             PointerInfo pointerInfo = iterator.next();
-            if (pointerInfo.getId() != id) {
+            if (!(isCancel || pointerInfo.getId() == id)) {
                 continue;
             }
 
@@ -156,11 +127,11 @@ public class SimpleScaleGestureDetector {
      */
     public float getFocusX() {
         switch (getPointersDown()) {
-            case 1:
-                return mPointerInfo.getFirst().getCurrent().x;
-            case 2:
-                PointerInfo pointerA = mPointerInfo.getFirst(), pointerB = mPointerInfo.getLast();
-                return (pointerA.getCurrent().x + pointerB.getCurrent().x) / 2.0f;
+        case 1:
+            return mPointerInfo.getFirst().getCurrent().x;
+        case 2:
+            PointerInfo pointerA = mPointerInfo.getFirst(), pointerB = mPointerInfo.getLast();
+            return (pointerA.getCurrent().x + pointerB.getCurrent().x) / 2.0f;
         }
 
         Log.e(LOGTAG, "No gesture taking place in getFocusX()!");
@@ -173,11 +144,11 @@ public class SimpleScaleGestureDetector {
      */
     public float getFocusY() {
         switch (getPointersDown()) {
-            case 1:
-                return mPointerInfo.getFirst().getCurrent().y;
-            case 2:
-                PointerInfo pointerA = mPointerInfo.getFirst(), pointerB = mPointerInfo.getLast();
-                return (pointerA.getCurrent().y + pointerB.getCurrent().y) / 2.0f;
+        case 1:
+            return mPointerInfo.getFirst().getCurrent().y;
+        case 2:
+            PointerInfo pointerA = mPointerInfo.getFirst(), pointerB = mPointerInfo.getLast();
+            return (pointerA.getCurrent().y + pointerB.getCurrent().y) / 2.0f;
         }
 
         Log.e(LOGTAG, "No gesture taking place in getFocusY()!");
@@ -225,9 +196,9 @@ public class SimpleScaleGestureDetector {
     /* Sends the requested scale gesture notification to the listener. */
     private void sendScaleGesture(EventType eventType) {
         switch (eventType) {
-            case BEGIN:     mListener.onScaleBegin(this);   break;
-            case CONTINUE:  mListener.onScale(this);        break;
-            case END:       mListener.onScaleEnd(this);     break;
+        case BEGIN:     mListener.onScaleBegin(this);   break;
+        case CONTINUE:  mListener.onScale(this);        break;
+        case END:       mListener.onScaleEnd(this);     break;
         }
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SubdocumentScrollHelper.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SubdocumentScrollHelper.java
index 30b4b30..8e7de55 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SubdocumentScrollHelper.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SubdocumentScrollHelper.java
@@ -1,74 +1,76 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Android code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2012
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Kartikaya Gupta <kgupta at mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.ui;
 
-
 import android.graphics.PointF;
 import android.os.Handler;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
 
-class SubdocumentScrollHelper  {
-    private static final String LOGTAG = SubdocumentScrollHelper.class.getSimpleName();
+class SubdocumentScrollHelper {
+    private static final String LOGTAG = "GeckoSubdocumentScrollHelper";
 
     private final PanZoomController mPanZoomController;
     private final Handler mUiHandler;
 
+    /* This is the amount of displacement we have accepted but not yet sent to JS; this is
+     * only valid when mOverrideScrollPending is true. */
+    private final PointF mPendingDisplacement;
+
+    /* When this is true, we're sending scroll events to JS to scroll the active subdocument. */
     private boolean mOverridePanning;
+
+    /* When this is true, we have received an ack for the last scroll event we sent to JS, and
+     * are ready to send the next scroll event. Note we only ever have one scroll event inflight
+     * at a time. */
     private boolean mOverrideScrollAck;
+
+    /* When this is true, we have a pending scroll that we need to send to JS; we were unable
+     * to send it when it was initially requested because mOverrideScrollAck was not true. */
     private boolean mOverrideScrollPending;
+
+    /* When this is true, the last scroll event we sent actually did some amount of scrolling on
+     * the subdocument; we use this to decide when we have reached the end of the subdocument. */
     private boolean mScrollSucceeded;
 
     SubdocumentScrollHelper(PanZoomController controller) {
         mPanZoomController = controller;
+        // mUiHandler will be bound to the UI thread since that's where this constructor runs
         mUiHandler = new Handler();
+        mPendingDisplacement = new PointF();
     }
 
     boolean scrollBy(PointF displacement) {
-        if (!mOverridePanning) {
+        if (! mOverridePanning) {
             return false;
         }
 
-        if (!mOverrideScrollAck) {
+        if (! mOverrideScrollAck) {
             mOverrideScrollPending = true;
+            mPendingDisplacement.x += displacement.x;
+            mPendingDisplacement.y += displacement.y;
             return true;
         }
 
+        JSONObject json = new JSONObject();
+        try {
+            json.put("x", displacement.x);
+            json.put("y", displacement.y);
+        } catch (JSONException e) {
+            Log.e(LOGTAG, "Error forming subwindow scroll message: ", e);
+        }
+
         mOverrideScrollAck = false;
         mOverrideScrollPending = false;
+        // clear the |mPendingDisplacement| after serializing |displacement| to
+        // JSON because they might be the same object
+        mPendingDisplacement.x = 0;
+        mPendingDisplacement.y = 0;
 
         return true;
     }
@@ -84,5 +86,4 @@ class SubdocumentScrollHelper  {
     boolean lastScrollSucceeded() {
         return mScrollSucceeded;
     }
-
 }


More information about the Libreoffice-commits mailing list