[Libreoffice-commits] core.git: 45 commits - android/Bootstrap android/default-document android/experimental solenv/bin

Tomaž Vajngerl tomaz.vajngerl at collabora.com
Sat Oct 4 08:49:58 PDT 2014


 android/Bootstrap/Makefile.shared                                                         |   11 
 android/Bootstrap/src/org/libreoffice/kit/Document.java                                   |    6 
 android/default-document/example.odt                                                      |binary
 android/experimental/LOAndroid3/res/layout/about.xml                                      |   48 +
 android/experimental/LOAndroid3/res/layout/activity_main.xml                              |   21 
 android/experimental/LOAndroid3/res/menu/main.xml                                         |    8 
 android/experimental/LOAndroid3/res/values/strings.xml                                    |   14 
 android/experimental/LOAndroid3/src/java/org/libreoffice/DocumentPartView.java            |    9 
 android/experimental/LOAndroid3/src/java/org/libreoffice/DocumentPartViewListAdpater.java |    6 
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java                     |   30 -
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java              |   37 +
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java                  |   38 -
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java                 |   53 -
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java           |  100 ++-
 android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java     |  130 ++++
 android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java            |   13 
 android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java                |    5 
 android/experimental/LOAndroid3/src/java/org/libreoffice/ViewFactory.java                 |   32 +
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java      |  202 +++++++
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLController.java          |   28 -
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java      |   44 -
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/Layer.java                 |   33 +
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java       |   20 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java         |    4 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java             |  156 ++++-
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/MultiTileLayer.java        |  273 ----------
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SingleTileLayer.java       |  104 ++-
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/SubTile.java               |   43 +
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java             |    7 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ViewTransform.java         |   19 
 solenv/bin/native-code.py                                                                 |    1 
 31 files changed, 922 insertions(+), 573 deletions(-)

New commits:
commit 6d5c352cb098daac139cb9c32df3420321eaaf3b
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Sat Oct 4 16:17:58 2014 +0200

    android: Better detection of HW accel. (needed by TextureView)
    
    Change-Id: I32b091d13d9236cee654819e701c583041f869bb

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
index 0a993a7..ad5ad66 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
@@ -20,6 +20,7 @@ import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.TextureView;
+import android.view.View;
 import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
@@ -27,6 +28,7 @@ import android.widget.FrameLayout;
 
 import org.libreoffice.LibreOfficeMainActivity;
 
+import java.lang.reflect.Method;
 import java.nio.IntBuffer;
 
 /**
@@ -61,21 +63,38 @@ public class LayerView extends FrameLayout {
     public static final int PAINT_BEFORE_FIRST = 1;
     public static final int PAINT_AFTER_FIRST = 2;
 
+    boolean shouldUseTextureView() {
+        // we can only use TextureView on ICS or higher
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+            Log.i(LOGTAG, "Not using TextureView: not on ICS+");
+            return false;
+        }
+
+        try {
+            // and then we can only use it if we have a hardware accelerated window
+            Method m = View.class.getMethod("isHardwareAccelerated", new Class[0]);
+            return (Boolean) m.invoke(this);
+        } catch (Exception e) {
+            Log.i(LOGTAG, "Not using TextureView: caught exception checking for hw accel: " + e.toString());
+            return false;
+        }
+    }
+
     public LayerView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+        if (shouldUseTextureView()) {
+            mTextureView = new TextureView(context);
+            mTextureView.setSurfaceTextureListener(new SurfaceTextureListener());
+
+            addView(mTextureView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        } else {
             mSurfaceView = new SurfaceView(context);
             addView(mSurfaceView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
 
             SurfaceHolder holder = mSurfaceView.getHolder();
             holder.addCallback(new SurfaceListener());
             holder.setFormat(PixelFormat.RGB_565);
-        } else {
-            mTextureView = new TextureView(context);
-            mTextureView.setSurfaceTextureListener(new SurfaceTextureListener());
-
-            addView(mTextureView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
         }
 
         mGLController = new GLController(this);
@@ -279,7 +298,7 @@ public class LayerView extends FrameLayout {
     }
 
     public Object getNativeWindow() {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+        if (mSurfaceView != null)
             return mSurfaceView.getHolder();
 
         return mTextureView.getSurfaceTexture();
commit dd8440a1c940e76626c23a40f62940aee5755e24
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Sat Oct 4 16:09:26 2014 +0200

    android: move getDrawable to LayerView (Fennec import)
    
    Change-Id: Idd15003939574963f836bfab1e0c5385957ab18b

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
index 583773b..eba732f 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
@@ -52,7 +52,7 @@ public class MockTileProvider implements TileProvider {
         tileNumber += 1; // 0 to 1 based numbering
 
         String imageName = "d" + tileNumber;
-        Bitmap bitmap = layerController.getDrawable(imageName);
+        Bitmap bitmap = layerController.getView().getDrawable(imageName);
 
         CairoImage image = new BufferedCairoImage(bitmap);
 
@@ -61,7 +61,7 @@ public class MockTileProvider implements TileProvider {
 
     @Override
     public Bitmap thumbnail(int size) {
-        return layerController.getDrawable("dummy_page");
+        return layerController.getView().getDrawable("dummy_page");
     }
 
     @Override
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 f35ee9d..c641c75 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
@@ -6,9 +6,6 @@
 package org.mozilla.gecko.gfx;
 
 import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.graphics.PointF;
 import android.graphics.RectF;
@@ -104,9 +101,6 @@ public class LayerController implements PanZoomTarget {
         return mViewportMetrics.getSize();
     }
 
-    public Bitmap getBackgroundPattern()    { return getDrawable("background"); }
-    public Bitmap getShadowPattern()        { return getDrawable("shadow"); }
-
     public PanZoomController getPanZoomController()                                 { return mPanZoomController; }
     public GestureDetector.OnGestureListener getGestureListener()                   { return mPanZoomController; }
     public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() {
@@ -114,14 +108,6 @@ public class LayerController implements PanZoomTarget {
     }
     public GestureDetector.OnDoubleTapListener getDoubleTapListener()               { return mPanZoomController; }
 
-    public Bitmap getDrawable(String name) {
-        Resources resources = mContext.getResources();
-        int resourceID = resources.getIdentifier(name, "drawable", mContext.getPackageName());
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inScaled = false;
-        return BitmapFactory.decodeResource(mContext.getResources(), resourceID, options);
-    }
-
     /**
      * The view calls this function to indicate that the viewport changed size. It must hold the
      * monitor while calling it.
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 dcedaae..b4975da 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
@@ -160,12 +160,12 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
 
         LayerController controller = view.getController();
 
-        CairoImage backgroundImage = new BufferedCairoImage(controller.getBackgroundPattern());
+        CairoImage backgroundImage = new BufferedCairoImage(view.getBackgroundPattern());
         mBackgroundLayer = new SingleTileLayer(true, backgroundImage);
 
         mScreenshotLayer = ScreenshotLayer.create();
 
-        CairoImage shadowImage = new BufferedCairoImage(controller.getShadowPattern());
+        CairoImage shadowImage = new BufferedCairoImage(view.getShadowPattern());
         mShadowLayer = new NinePatchTileLayer(shadowImage);
 
         mHorizScrollLayer = ScrollbarLayer.create(this, false);
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
index 505f933..0a993a7 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
@@ -7,7 +7,9 @@ package org.mozilla.gecko.gfx;
 
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.PixelFormat;
 import android.graphics.SurfaceTexture;
 import android.os.Build;
@@ -235,6 +237,23 @@ public class LayerView extends FrameLayout {
         return mGLController;
     }
 
+    public Bitmap getDrawable(String name) {
+        Context context = getContext();
+        Resources resources = context.getResources();
+        int resourceID = resources.getIdentifier(name, "drawable", context.getPackageName());
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inScaled = false;
+        return BitmapFactory.decodeResource(context.getResources(), resourceID, options);
+    }
+
+    Bitmap getBackgroundPattern() {
+        return getDrawable("background");
+    }
+
+    Bitmap getShadowPattern() {
+        return getDrawable("shadow");
+    }
+
     private void onSizeChanged(int width, int height) {
         mGLController.surfaceChanged(width, height);
 
commit 488d19de01670c37b638e67bec99dc178d4792a5
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Sat Oct 4 15:53:44 2014 +0200

    android: use TextureView instead of SurfaceView for ICS+ devices
    
    Change-Id: I4c5585d5eac4faf46ad9bed2d3992fe87b3d9a03

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLController.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLController.java
index 9bd7d2f..e296f47 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLController.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLController.java
@@ -5,8 +5,6 @@
 
 package org.mozilla.gecko.gfx;
 
-import android.view.SurfaceHolder;
-
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGL11;
 import javax.microedition.khronos.egl.EGLConfig;
@@ -119,8 +117,15 @@ public class GLController {
         return true;
     }
 
+    // This function is invoked by JNI
+    public synchronized void resumeCompositorIfValid() {
+        if (mSurfaceValid) {
+            mView.getListener().compositionResumeRequested(mWidth, mHeight);
+        }
+    }
+
     // Wait until we are allowed to use EGL functions on the Surface backing
-    // this window.
+    // this window. This function is invoked by JNI
     public synchronized void waitForValidSurface() {
         while (!mSurfaceValid) {
             try {
@@ -139,19 +144,16 @@ public class GLController {
         return mHeight;
     }
 
-    synchronized void surfaceCreated() {
-        mSurfaceValid = true;
-        notifyAll();
-    }
-
     synchronized void surfaceDestroyed() {
         mSurfaceValid = false;
         notifyAll();
     }
 
-    synchronized void sizeChanged(int newWidth, int newHeight) {
+    synchronized void surfaceChanged(int newWidth, int newHeight) {
         mWidth = newWidth;
         mHeight = newHeight;
+        mSurfaceValid = true;
+        notifyAll();
     }
 
     private void initEGL() {
@@ -218,8 +220,8 @@ public class GLController {
     }
 
     private void createEGLSurface() {
-        SurfaceHolder surfaceHolder = mView.getHolder();
-        mEGLSurface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, surfaceHolder, null);
+        Object window = mView.getNativeWindow();
+        mEGLSurface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, window, null);
         if (mEGLSurface == null || mEGLSurface == EGL10.EGL_NO_SURFACE) {
             throw new GLControllerException("EGL window surface could not be created! " +
                                             getEGLError());
@@ -248,8 +250,8 @@ public class GLController {
             initEGL();
         }
 
-        SurfaceHolder surfaceHolder = mView.getHolder();
-        EGLSurface surface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, surfaceHolder, null);
+        Object window = mView.getNativeWindow();
+        EGLSurface surface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, window, null);
         if (surface == null || surface == EGL10.EGL_NO_SURFACE) {
             throw new GLControllerException("EGL window surface could not be created! " +
                                             getEGLError());
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index cf4ba34..9b7dd39 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -227,23 +227,23 @@ public class GeckoLayerClient implements LayerView.Listener {
     }
 
     @Override
-    public void renderRequested() {
+    public void compositorCreated() {
+    }
 
+    @Override
+    public void renderRequested() {
     }
 
     @Override
     public void compositionPauseRequested() {
-
     }
 
     @Override
     public void compositionResumeRequested(int width, int height) {
-
     }
 
     @Override
     public void surfaceChanged(int width, int height) {
-        compositionResumeRequested(width, height);
         renderRequested();
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
index 874d10a..505f933 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
@@ -9,14 +9,19 @@ package org.mozilla.gecko.gfx;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.PixelFormat;
+import android.graphics.SurfaceTexture;
+import android.os.Build;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
+import android.view.TextureView;
+import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
+import android.widget.FrameLayout;
 
 import org.libreoffice.LibreOfficeMainActivity;
 
@@ -30,7 +35,7 @@ import java.nio.IntBuffer;
  *
  * Note that LayerView is accessed by Robocop via reflection.
  */
-public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
+public class LayerView extends FrameLayout {
     private static String LOGTAG = "GeckoLayerView";
 
     private LayerController mController;
@@ -43,6 +48,9 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
     /* Must be a PAINT_xxx constant */
     private int mPaintState = PAINT_NONE;
 
+    private SurfaceView mSurfaceView;
+    private TextureView mTextureView;
+
     private Listener mListener;
 
     /* Flags used to determine when to show the painted surface. The integer
@@ -54,9 +62,19 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
     public LayerView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        SurfaceHolder holder = getHolder();
-        holder.addCallback(this);
-        holder.setFormat(PixelFormat.RGB_565);
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+            mSurfaceView = new SurfaceView(context);
+            addView(mSurfaceView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+
+            SurfaceHolder holder = mSurfaceView.getHolder();
+            holder.addCallback(new SurfaceListener());
+            holder.setFormat(PixelFormat.RGB_565);
+        } else {
+            mTextureView = new TextureView(context);
+            mTextureView.setSurfaceTextureListener(new SurfaceTextureListener());
+
+            addView(mTextureView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        }
 
         mGLController = new GLController(this);
     }
@@ -217,10 +235,8 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
         return mGLController;
     }
 
-    /** Implementation of SurfaceHolder.Callback */
-    public synchronized void surfaceChanged(SurfaceHolder holder, int format, int width,
-                                            int height) {
-        mGLController.sizeChanged(width, height);
+    private void onSizeChanged(int width, int height) {
+        mGLController.surfaceChanged(width, height);
 
         if (mGLThread != null) {
             mGLThread.surfaceChanged(width, height);
@@ -231,16 +247,7 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
         }
     }
 
-    /** Implementation of SurfaceHolder.Callback */
-    public synchronized void surfaceCreated(SurfaceHolder holder) {
-        mGLController.surfaceCreated();
-        if (mGLThread != null) {
-            mGLThread.surfaceCreated();
-        }
-    }
-
-    /** Implementation of SurfaceHolder.Callback */
-    public synchronized void surfaceDestroyed(SurfaceHolder holder) {
+    private void onDestroyed() {
         mGLController.surfaceDestroyed();
 
         if (mGLThread != null) {
@@ -252,24 +259,73 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
         }
     }
 
+    public Object getNativeWindow() {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+            return mSurfaceView.getHolder();
+
+        return mTextureView.getSurfaceTexture();
+    }
+
     /** This function is invoked by Gecko (compositor thread) via JNI; be careful when modifying signature. */
     public static GLController registerCxxCompositor() {
         try {
             LayerView layerView = LibreOfficeMainActivity.mAppContext.getLayerController().getView();
+            layerView.mListener.compositorCreated();
             return layerView.getGLController();
         } catch (Exception e) {
-            Log.e(LOGTAG, "### Exception! " + e);
+            Log.e(LOGTAG, "Error registering compositor!", e);
             return null;
         }
     }
 
     public interface Listener {
+        void compositorCreated();
         void renderRequested();
         void compositionPauseRequested();
         void compositionResumeRequested(int width, int height);
         void surfaceChanged(int width, int height);
     }
 
+    private class SurfaceListener implements SurfaceHolder.Callback {
+        public void surfaceChanged(SurfaceHolder holder, int format, int width,
+                                                int height) {
+            onSizeChanged(width, height);
+        }
+
+        public void surfaceCreated(SurfaceHolder holder) {
+            if (mGLThread != null) {
+                mGLThread.surfaceCreated();
+            }
+        }
+
+        public void surfaceDestroyed(SurfaceHolder holder) {
+            onDestroyed();
+        }
+    }
+
+    private class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
+        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+            // We don't do this for surfaceCreated above because it is always followed by a surfaceChanged,
+            // but that is not the case here.
+            if (mGLThread != null) {
+                mGLThread.surfaceCreated();
+            }
+            onSizeChanged(width, height);
+        }
+
+        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+            onDestroyed();
+            return true; // allow Android to call release() on the SurfaceTexture, we are done drawing to it
+        }
+
+        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+            onSizeChanged(width, height);
+        }
+
+        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        }
+    }
+
     private GLThread mGLThread; // Protected by this class's monitor.
 
     public synchronized void createGLThread() {
commit 67be577f163831e460e19aee958bdcf7187b8a56
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Sat Oct 4 15:51:02 2014 +0200

    android: assure document close, introduce message box for errors
    
    Change-Id: I4d5607d5568ebf73a61067975c21e740020cc8f7

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index c904942..bd1b27b 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -8,7 +8,6 @@ import org.libreoffice.kit.LibreOfficeKit;
 import org.libreoffice.kit.Office;
 import org.mozilla.gecko.gfx.BufferedCairoImage;
 import org.mozilla.gecko.gfx.CairoImage;
-import org.mozilla.gecko.gfx.FloatSize;
 import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.gfx.LayerController;
 
@@ -16,13 +15,14 @@ import java.nio.ByteBuffer;
 
 public class LOKitTileProvider implements TileProvider {
     private static final String LOGTAG = LOKitTileProvider.class.getSimpleName();
-    public static int TILE_SIZE = 256;
-    public final Office mOffice;
-    public final Document mDocument;
+    private static int TILE_SIZE = 256;
+    private final Office mOffice;
+    private Document mDocument;
     private final LayerController mLayerController;
     private final float mTileWidth;
     private final float mTileHeight;
     private final String mInputFile;
+    private boolean mIsReady = false;
 
     private float mDPI;
     private float mWidthTwip;
@@ -70,6 +70,8 @@ public class LOKitTileProvider implements TileProvider {
                     LibreOfficeMainActivity.mAppContext.getDocumentPartViewListAdpater().notifyDataSetChanged();
                 }
             });
+
+            mIsReady = true;
         }
     }
 
@@ -108,8 +110,15 @@ public class LOKitTileProvider implements TileProvider {
         mWidthTwip = mDocument.getDocumentWidth();
         mHeightTwip = mDocument.getDocumentHeight();
 
-        if (mWidthTwip == 0 && mHeightTwip == 0) {
+        if (mWidthTwip == 0 || mHeightTwip == 0) {
             Log.e(LOGTAG, "Document size zero - last error: " + mOffice.getError());
+            LOKitShell.getMainHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    LibreOfficeMainActivity.mAppContext.showAlertDialog("Document has no size!");
+                }
+            });
+            return false;
         } else {
             Log.i(LOGTAG, "Document size: " + mDocument.getDocumentWidth() + " x " + mDocument.getDocumentHeight());
         }
@@ -129,7 +138,7 @@ public class LOKitTileProvider implements TileProvider {
 
     @Override
     public boolean isReady() {
-        return mDocument != null;
+        return mIsReady;
     }
 
     @Override
@@ -143,7 +152,7 @@ public class LOKitTileProvider implements TileProvider {
             float twipWidth = mTileWidth / zoom;
             float twipHeight = mTileHeight / zoom;
             long start = System.currentTimeMillis();
-            Log.i(LOGTAG, "paintTile TOP @ " + start + "(" + tileSize.width + " " + tileSize.height + " " + (int)twipX + " " + (int)twipY + " " + (int) twipWidth + " " + (int) twipHeight + ")");
+            Log.i(LOGTAG, "paintTile TOP @ " + start + "(" + tileSize.width + " " + tileSize.height + " " + (int) twipX + " " + (int) twipY + " " + (int) twipWidth + " " + (int) twipHeight + ")");
             mDocument.paintTile(buffer, tileSize.width, tileSize.height, (int) twipX, (int) twipY, (int) twipWidth, (int) twipHeight);
             long stop = System.currentTimeMillis();
             Log.i(LOGTAG, "paintTile TAIL @ " + stop + " - elapsed: " + (stop - start) + " ");
@@ -173,6 +182,8 @@ public class LOKitTileProvider implements TileProvider {
             widthPixel = (int) (heightPixel * ratio);
         }
 
+        Log.w(LOGTAG, "Thumbnail size: " + getPageWidth() + " " + getPageHeight() + " " + widthPixel + " " + heightPixel);
+
         ByteBuffer buffer = ByteBuffer.allocateDirect(widthPixel * heightPixel * 4);
         mDocument.paintTile(buffer, widthPixel, heightPixel, 0, 0, (int) mWidthTwip, (int) mHeightTwip);
 
@@ -189,10 +200,17 @@ public class LOKitTileProvider implements TileProvider {
         Log.i(LOGTAG, "Document destroyed: " + mInputFile);
         if (mDocument != null) {
             mDocument.destroy();
+            mDocument = null;
         }
     }
 
     @Override
+    protected void finalize() throws Throwable {
+        close();
+        super.finalize();
+    }
+
+    @Override
     public void changePart(int partIndex) {
         mDocument.setPart(partIndex);
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index aa4f70c..c5ecccb 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -2,6 +2,7 @@ package org.libreoffice;
 
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -132,7 +133,7 @@ public class LibreOfficeMainActivity extends Activity {
         mLayerController = new LayerController(this);
         mLayerController.setZoomConstraints(new ZoomConstraints(true));
         mLayerClient = new GeckoLayerClient(this);
-        LayerView layerView = (LayerView)findViewById(R.id.layer_view);
+        LayerView layerView = (LayerView) findViewById(R.id.layer_view);
         mLayerController.setView(layerView);
         mLayerController.setLayerClient(mLayerClient);
 
@@ -147,10 +148,28 @@ public class LibreOfficeMainActivity extends Activity {
 
     @Override
     protected void onPause() {
-        Log.i(LOGTAG, "Pause..");
+        Log.i(LOGTAG, "onPause..");
         super.onPause();
     }
 
+    @Override
+    protected void onStart() {
+        Log.i(LOGTAG, "onStart..");
+        super.onStop();
+    }
+
+    @Override
+    protected void onStop() {
+        Log.i(LOGTAG, "onStop..");
+        super.onStop();
+    }
+
+    @Override
+    protected void onDestroy() {
+        Log.i(LOGTAG, "onDestroy..");
+        super.onDestroy();
+    }
+
     public LOKitThread getLOKitThread() {
         return sLOKitThread;
     }
@@ -212,6 +231,22 @@ public class LibreOfficeMainActivity extends Activity {
         findViewById(R.id.loadingPanel).setVisibility(View.GONE);
     }
 
+    public void showAlertDialog(String s) {
+
+        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(LibreOfficeMainActivity.this);
+
+        alertDialogBuilder.setTitle("Error");
+        alertDialogBuilder.setMessage(s);
+        alertDialogBuilder.setNeutralButton("OK", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int id) {
+                finish();
+            }
+        });
+
+        AlertDialog alertDialog = alertDialogBuilder.create();
+        alertDialog.show();
+    }
+
     private class DocumentPartClickListener implements android.widget.AdapterView.OnItemClickListener {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
index 5de6a82..583773b 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
@@ -4,7 +4,6 @@ import android.graphics.Bitmap;
 
 import org.mozilla.gecko.gfx.BufferedCairoImage;
 import org.mozilla.gecko.gfx.CairoImage;
-import org.mozilla.gecko.gfx.FloatSize;
 import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.gfx.LayerController;
 
commit b43b980b1e44e3ad0b4c38d2d65cdb6dbfb77add
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Sat Oct 4 15:47:44 2014 +0200

    androdi: set TileProvider only when document is ready
    
    Change-Id: Iada0e4513cc00248f45c97bfecbc91590e80a437

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index 398389b..528f419 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -74,10 +74,10 @@ public class LOKitThread extends Thread {
         }
 
         mTileProvider = TileProviderFactory.create(mController, filename);
-        mLayerClient.setTileProvider(mTileProvider);
-
         boolean isReady = mTileProvider.isReady();
         if (isReady) {
+            mLayerClient.setTileProvider(mTileProvider);
+
             LOKitShell.showProgressSpinner();
             refresh();
             LOKitShell.hideProgressSpinner();
commit 450a4f46d9de0f2b2d7b4232e7fef380dacdfcd0
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Thu Oct 2 16:16:33 2014 +0200

    android: TileIdentifier - contains tile position and zoom
    
    Change-Id: Ia82dc1f99eff5117fe16df2b61c1a7230b52e07a

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
index 407cdc1..01ab8be 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
@@ -97,10 +97,10 @@ public class DynamicTileLayer extends Layer {
             tile.beginTransaction();
 
             Rect position = tile.getPosition();
-            float positionX = tile.x / tile.zoom;
-            float positionY = tile.y / tile.zoom;
-            float tileSizeWidth = tileSize.width / tile.zoom;
-            float tileSizeHeight = tileSize.height / tile.zoom;
+            float positionX = tile.id.x / tile.id.zoom;
+            float positionY = tile.id.y / tile.id.zoom;
+            float tileSizeWidth = tileSize.width / tile.id.zoom;
+            float tileSizeHeight = tileSize.height / tile.id.zoom;
             position.set((int) positionX, (int) positionY, (int) (positionX + tileSizeWidth + 1), (int) (positionY + tileSizeHeight + 1));
             tile.setPosition(position);
 
@@ -157,7 +157,7 @@ public class DynamicTileLayer extends Layer {
                 }
                 boolean contains = false;
                 for (SubTile tile : tiles) {
-                    if (tile.x == x && tile.y == y && tile.zoom == viewportMetrics.zoomFactor) {
+                    if (tile.id.x == x && tile.id.y == y && tile.id.zoom == viewportMetrics.zoomFactor) {
                         contains = true;
                     }
                 }
@@ -184,8 +184,8 @@ public class DynamicTileLayer extends Layer {
 
     private void markTiles(ImmutableViewportMetrics viewportMetrics) {
         for (SubTile tile : tiles) {
-            if (FloatUtils.fuzzyEquals(tile.zoom, viewportMetrics.zoomFactor)) {
-                RectF tileRect = new RectF(tile.x, tile.y, tile.x + tileSize.width, tile.y + tileSize.height);
+            if (FloatUtils.fuzzyEquals(tile.id.zoom, viewportMetrics.zoomFactor)) {
+                RectF tileRect = new RectF(tile.id.x, tile.id.y, tile.id.x + tileSize.width, tile.id.y + tileSize.height);
                 if (!RectF.intersects(currentViewport, tileRect)) {
                     tile.markForRemoval();
                 }
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 27f11fc..7e60af1 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
@@ -6,42 +6,49 @@
 package org.mozilla.gecko.gfx;
 
 public class SubTile extends SingleTileLayer {
-    public int x;
-    public int y;
-    public float zoom;
-
     public boolean markedForRemoval = false;
+    public final TileIdentifier id;
 
     public SubTile(CairoImage mImage, int x, int y, float zoom) {
         super(mImage);
-        this.x = x;
-        this.y = y;
-        this.zoom = zoom;
+        id = new TileIdentifier(x, y, zoom);
     }
 
     public void markForRemoval() {
         markedForRemoval = true;
     }
 
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SubTile subTile = (SubTile) o;
-
-        if (x != subTile.x) return false;
-        if (y != subTile.y) return false;
-        if (Float.compare(subTile.zoom, zoom) != 0) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = x;
-        result = 31 * result + y;
-        result = 31 * result + (zoom != +0.0f ? Float.floatToIntBits(zoom) : 0);
-        return result;
+    public static class TileIdentifier {
+        public int x;
+        public int y;
+        public float zoom;
+
+        public TileIdentifier(int x, int y, float zoom) {
+            this.x = x;
+            this.y = y;
+            this.zoom = zoom;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            TileIdentifier that = (TileIdentifier) o;
+
+            if (x != that.x) return false;
+            if (y != that.y) return false;
+            if (Float.compare(that.zoom, zoom) != 0) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = x;
+            result = 31 * result + y;
+            result = 31 * result + (zoom != +0.0f ? Float.floatToIntBits(zoom) : 0);
+            return result;
+        }
     }
 }
commit e910aa45d3d4fb92d2ac1e975f411785d5fc70ae
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Thu Oct 2 15:56:00 2014 +0200

    android: construct LayerView in xml GUI definition (activity_main)
    
    Change-Id: I6cd3c8dff2ca36f3d64559b218d005d5a6da9066

diff --git a/android/experimental/LOAndroid3/res/layout/activity_main.xml b/android/experimental/LOAndroid3/res/layout/activity_main.xml
index fd7d63b..1b1bb07 100644
--- a/android/experimental/LOAndroid3/res/layout/activity_main.xml
+++ b/android/experimental/LOAndroid3/res/layout/activity_main.xml
@@ -16,19 +16,25 @@
             android:id="@+id/gecko_layout"
             android:layout_width="fill_parent"
             android:layout_height="fill_parent"
-            android:layout_weight="1"/>
+            android:layout_weight="1">
+
+            <org.mozilla.gecko.gfx.LayerView
+                android:id="@+id/layer_view"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"/>
+        </RelativeLayout>
 
         <RelativeLayout
             android:id="@+id/loadingPanel"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:gravity="center"
-            android:background="#9333">
+            android:background="#9333"
+            android:gravity="center">
 
             <ProgressBar
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:indeterminate="true" />
+                android:indeterminate="true"/>
         </RelativeLayout>
 
         <View
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 8607ebf..aa4f70c 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -9,6 +9,7 @@ import android.os.Handler;
 import android.support.v4.widget.DrawerLayout;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -21,6 +22,7 @@ import android.widget.TextView;
 import org.mozilla.gecko.ZoomConstraints;
 import org.mozilla.gecko.gfx.GeckoLayerClient;
 import org.mozilla.gecko.gfx.LayerController;
+import org.mozilla.gecko.gfx.LayerView;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -96,6 +98,8 @@ public class LibreOfficeMainActivity extends Activity {
 
         mMainHandler = new Handler();
 
+        LayoutInflater.from(this).setFactory(ViewFactory.getInstance());
+
         if (getIntent().getData() != null) {
             mInputFile = getIntent().getData().getEncodedPath();
         } else {
@@ -128,8 +132,9 @@ public class LibreOfficeMainActivity extends Activity {
         mLayerController = new LayerController(this);
         mLayerController.setZoomConstraints(new ZoomConstraints(true));
         mLayerClient = new GeckoLayerClient(this);
+        LayerView layerView = (LayerView)findViewById(R.id.layer_view);
+        mLayerController.setView(layerView);
         mLayerController.setLayerClient(mLayerClient);
-        mGeckoLayout.addView(mLayerController.getView(), 0);
 
         LOKitShell.sendEvent(LOEventFactory.load(mInputFile));
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/ViewFactory.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/ViewFactory.java
new file mode 100644
index 0000000..c26ad22
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/ViewFactory.java
@@ -0,0 +1,32 @@
+package org.libreoffice;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import org.mozilla.gecko.gfx.LayerView;
+
+public class ViewFactory implements LayoutInflater.Factory {
+    private static final String LOGTAG = ViewFactory.class.getSimpleName();
+    private static final String LAYER_VIEW_ID = "org.mozilla.gecko.gfx.LayerView";
+    private static final ViewFactory INSTANCE = new ViewFactory();
+
+    private ViewFactory() {
+    }
+
+    public static LayoutInflater.Factory getInstance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public View onCreateView(String name, Context context, AttributeSet attrs) {
+        if (name.equals(LAYER_VIEW_ID)) {
+            Log.i(LOGTAG, "Creating custom Gecko view: " + name);
+            return new LayerView(context, attrs);
+        }
+
+        return null;
+    }
+}
\ No newline at end of file
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 2e6a4a0..f35ee9d 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
@@ -69,11 +69,15 @@ public class LayerController implements PanZoomTarget {
         DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
         mViewportMetrics = new ImmutableViewportMetrics(displayMetrics);
         mPanZoomController = new PanZoomController(this);
-        mView = new LayerView(context, this);
         mCheckerboardShouldShowChecks = true;
         mZoomConstraints = new ZoomConstraints(false);
     }
 
+    public void setView(LayerView v) {
+        mView = v;
+        mView.connect(this);
+    }
+
     public void setRoot(Layer layer) { mRootLayer = layer; }
 
     public void setLayerClient(GeckoLayerClient layerClient) {
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
index 38a09d8..874d10a 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java
@@ -9,6 +9,7 @@ package org.mozilla.gecko.gfx;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.PixelFormat;
+import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -32,7 +33,6 @@ import java.nio.IntBuffer;
 public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
     private static String LOGTAG = "GeckoLayerView";
 
-    private Context mContext;
     private LayerController mController;
     private TouchEventHandler mTouchEventHandler;
     private GLController mGLController;
@@ -51,18 +51,19 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
     public static final int PAINT_BEFORE_FIRST = 1;
     public static final int PAINT_AFTER_FIRST = 2;
 
-
-    public LayerView(Context context, LayerController controller) {
-        super(context);
+    public LayerView(Context context, AttributeSet attrs) {
+        super(context, attrs);
 
         SurfaceHolder holder = getHolder();
         holder.addCallback(this);
         holder.setFormat(PixelFormat.RGB_565);
 
         mGLController = new GLController(this);
-        mContext = context;
+    }
+
+    void connect(LayerController controller) {
         mController = controller;
-        mTouchEventHandler = new TouchEventHandler(context, this, mController);
+        mTouchEventHandler = new TouchEventHandler(getContext(), this, mController);
         mRenderer = new LayerRenderer(this);
         mInputConnectionHandler = null;
 
@@ -208,6 +209,10 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
         mListener = listener;
     }
 
+    Listener getListener() {
+        return mListener;
+    }
+
     public GLController getGLController() {
         return mGLController;
     }
@@ -267,10 +272,6 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
 
     private GLThread mGLThread; // Protected by this class's monitor.
 
-    /**
-     * Creates a Java GL thread. After this is called, the FlexibleGLSurfaceView may be used just
-     * like a GLSurfaceView. It is illegal to access the controller after this has been called.
-     */
     public synchronized void createGLThread() {
         if (mGLThread != null) {
             throw new LayerViewException ("createGLThread() called with a GL thread already in place!");
@@ -282,10 +283,6 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
         notifyAll();
     }
 
-    /**
-     * Destroys the Java GL thread. Returns a Thread that completes when the Java GL thread is
-     * fully shut down.
-     */
     public synchronized Thread destroyGLThread() {
         // Wait for the GL thread to be started.
         Log.e(LOGTAG, "### Waiting for GL thread to be created...");
commit fc8e1ac501f021ac6f99f944fd5d38297bc7a00d
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Thu Oct 2 15:50:53 2014 +0200

    android: use tile size and change the type to IntSize
    
    Change-Id: Id19c3517fc6fb59307c81a0c1c8868e0d0c777b4

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index 4fdf84f..c904942 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -9,6 +9,7 @@ import org.libreoffice.kit.Office;
 import org.mozilla.gecko.gfx.BufferedCairoImage;
 import org.mozilla.gecko.gfx.CairoImage;
 import org.mozilla.gecko.gfx.FloatSize;
+import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.gfx.LayerController;
 
 import java.nio.ByteBuffer;
@@ -132,9 +133,9 @@ public class LOKitTileProvider implements TileProvider {
     }
 
     @Override
-    public CairoImage createTile(float x, float y, FloatSize tileSize, float zoom) {
-        ByteBuffer buffer = ByteBuffer.allocateDirect(TILE_SIZE * TILE_SIZE * 4);
-        Bitmap bitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Bitmap.Config.ARGB_8888);
+    public CairoImage createTile(float x, float y, IntSize tileSize, float zoom) {
+        ByteBuffer buffer = ByteBuffer.allocateDirect(tileSize.width * tileSize.height * 4);
+        Bitmap bitmap = Bitmap.createBitmap(tileSize.width, tileSize.height, Bitmap.Config.ARGB_8888);
 
         if (mDocument != null) {
             float twipX = pixelToTwip(x, mDPI) / zoom;
@@ -142,8 +143,8 @@ public class LOKitTileProvider implements TileProvider {
             float twipWidth = mTileWidth / zoom;
             float twipHeight = mTileHeight / zoom;
             long start = System.currentTimeMillis();
-            Log.i(LOGTAG, "paintTile TOP @ " + start + "(" + TILE_SIZE + " " + TILE_SIZE + " " + (int)twipX + " " + (int)twipY + " " + (int) twipWidth + " " + (int) twipHeight + ")");
-            mDocument.paintTile(buffer, TILE_SIZE, TILE_SIZE, (int) twipX, (int) twipY, (int) twipWidth, (int) twipHeight);
+            Log.i(LOGTAG, "paintTile TOP @ " + start + "(" + tileSize.width + " " + tileSize.height + " " + (int)twipX + " " + (int)twipY + " " + (int) twipWidth + " " + (int) twipHeight + ")");
+            mDocument.paintTile(buffer, tileSize.width, tileSize.height, (int) twipX, (int) twipY, (int) twipWidth, (int) twipHeight);
             long stop = System.currentTimeMillis();
             Log.i(LOGTAG, "paintTile TAIL @ " + stop + " - elapsed: " + (stop - start) + " ");
         } else {
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
index 672973c..5de6a82 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
@@ -5,6 +5,7 @@ import android.graphics.Bitmap;
 import org.mozilla.gecko.gfx.BufferedCairoImage;
 import org.mozilla.gecko.gfx.CairoImage;
 import org.mozilla.gecko.gfx.FloatSize;
+import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.gfx.LayerController;
 
 public class MockTileProvider implements TileProvider {
@@ -45,7 +46,7 @@ public class MockTileProvider implements TileProvider {
     }
 
     @Override
-    public CairoImage createTile(float x, float y, FloatSize tileSize, float zoom) {
+    public CairoImage createTile(float x, float y, IntSize tileSize, float zoom) {
         int tiles = (int) (getPageWidth() / TILE_SIZE) + 1;
         int tileNumber = (int) ((y / TILE_SIZE) * tiles + (x / TILE_SIZE));
         tileNumber %= 9;
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
index ada2360..12a47f6 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
@@ -4,7 +4,7 @@ package org.libreoffice;
 import android.graphics.Bitmap;
 
 import org.mozilla.gecko.gfx.CairoImage;
-import org.mozilla.gecko.gfx.FloatSize;
+import org.mozilla.gecko.gfx.IntSize;
 
 public interface TileProvider {
     int getPageWidth();
@@ -13,7 +13,7 @@ public interface TileProvider {
 
     boolean isReady();
 
-    CairoImage createTile(float x, float y, FloatSize tileSize, float zoom);
+    CairoImage createTile(float x, float y, IntSize tileSize, float zoom);
 
     void changePart(int partIndex);
 
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
index 1ad8d38..407cdc1 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
@@ -17,14 +17,14 @@ public class DynamicTileLayer extends Layer {
 
     private final List<SubTile> tiles = new CopyOnWriteArrayList<SubTile>();
     private TileProvider tileProvider;
-    private final FloatSize tileSize;
+    private final IntSize tileSize;
     private RectF currentViewport = new RectF();
 
     public DynamicTileLayer() {
-        this.tileSize = new FloatSize(256, 256);
+        this.tileSize = new IntSize(256, 256);
     }
 
-    public DynamicTileLayer(FloatSize tileSize) {
+    public DynamicTileLayer(IntSize tileSize) {
         this.tileSize = tileSize;
     }
 
@@ -108,7 +108,7 @@ public class DynamicTileLayer extends Layer {
         }
     }
 
-    private RectF roundToTileSize(RectF input, FloatSize tileSize) {
+    private RectF roundToTileSize(RectF input, IntSize tileSize) {
         float minX = ((int)(input.left / tileSize.width)) * tileSize.width;
         float minY = ((int)(input.top / tileSize.height)) * tileSize.height;
         float maxX = ((int)(input.right / tileSize.width) + 1) * tileSize.width;
@@ -116,7 +116,7 @@ public class DynamicTileLayer extends Layer {
         return new RectF(minX, minY, maxX, maxY);
     }
 
-    private RectF inflate(RectF rect, FloatSize inflateSize) {
+    private RectF inflate(RectF rect, IntSize inflateSize) {
         RectF newRect = new RectF(rect);
         newRect.left -= inflateSize.width;
         newRect.left = newRect.left < 0.0f ? 0.0f : newRect.left;
commit 1b81aeb2548d3492e0c50dfbfa61b3000cf9b6cb
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Thu Oct 2 15:24:41 2014 +0200

    android: remove unused windowSizeChanged tracking
    
    Change-Id: I0d451d9fea83d70e69d07059e55a5e6067c45711

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index 23095ef..cf4ba34 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -42,7 +42,6 @@ import android.content.Context;
 import android.graphics.RectF;
 import android.util.DisplayMetrics;
 import android.util.Log;
-import android.view.View;
 
 import org.libreoffice.LOEvent;
 import org.libreoffice.LOEventFactory;
@@ -148,32 +147,24 @@ public class GeckoLayerClient implements LayerView.Listener {
     private void sendResizeEventIfNecessary(boolean force) {
         DisplayMetrics metrics = new DisplayMetrics();
         LibreOfficeMainActivity.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
-        View view = mLayerController.getView();
 
         IntSize newScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
-        IntSize newWindowSize = new IntSize(view.getWidth(), view.getHeight());
 
         // Return immediately if the screen size hasn't changed or the viewport
         // size is zero (which indicates that the rendering surface hasn't been
         // allocated yet).
         boolean screenSizeChanged = !mScreenSize.equals(newScreenSize);
-        boolean windowSizeChanged = !mWindowSize.equals(newWindowSize);
 
-        if (!force && !screenSizeChanged && !windowSizeChanged) {
+        if (!force && !screenSizeChanged) {
             return;
         }
 
         mScreenSize = newScreenSize;
-        mWindowSize = newWindowSize;
 
         if (screenSizeChanged) {
             Log.d(LOGTAG, "Screen-size changed to " + mScreenSize);
         }
 
-        if (windowSizeChanged) {
-            Log.d(LOGTAG, "Window-size changed to " + mWindowSize);
-        }
-
         LOEvent event = LOEventFactory.sizeChanged(metrics.widthPixels, metrics.heightPixels);
         LOKitShell.sendEvent(event);
     }
commit f33d88119830975e5de620470bee1804d6c98738
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Wed Oct 1 23:38:09 2014 +0200

    android: Better default document (when the app starts with no doc to load).
    
    Change-Id: Ie3cc30c29723133d5e320ad3848d13f06d133c78

diff --git a/android/Bootstrap/Makefile.shared b/android/Bootstrap/Makefile.shared
index 5dd9f4a..7ec1419 100644
--- a/android/Bootstrap/Makefile.shared
+++ b/android/Bootstrap/Makefile.shared
@@ -130,7 +130,7 @@ copy-stuff:
 	for F in program/services/services ure/share/misc/services; do \
 		sed -e 's!uri="vnd.sun.star.expand:$$LO_LIB_DIR/!uri="file://$$APP_DATA_DIR/lib/!g' <$(INSTDIR)/$$F.rdb >assets/$$F.rdb; \
 	done
-	cp $(SRC_ROOT)/odk/examples/java/DocumentHandling/test/test1.odt assets/example.odt
+	cp $(SRC_ROOT)/android/default-document/example.odt assets/example.odt
 	cp $(SRC_ROOT)/readlicense_oo/license/LICENSE assets/license.txt
 	cp $(SRC_ROOT)/readlicense_oo/license/NOTICE assets/notice.txt
 	cp $(WORKDIR)/ComponentTarget/i18npool/util/i18npool.component assets/ComponentTarget/i18npool/util
diff --git a/android/default-document/example.odt b/android/default-document/example.odt
new file mode 100644
index 0000000..2da7ce6
Binary files /dev/null and b/android/default-document/example.odt differ
commit 91569be0f9951fdfd8c928ba3e4f0956bc053577
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 23:37:14 2014 +0200

    android: Log calls to createTile
    
    Change-Id: Ia0e92c24f771d47235fee7a9dbddc65631af9082

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index 073876e..4fdf84f 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -141,7 +141,11 @@ public class LOKitTileProvider implements TileProvider {
             float twipY = pixelToTwip(y, mDPI) / zoom;
             float twipWidth = mTileWidth / zoom;
             float twipHeight = mTileHeight / zoom;
+            long start = System.currentTimeMillis();
+            Log.i(LOGTAG, "paintTile TOP @ " + start + "(" + TILE_SIZE + " " + TILE_SIZE + " " + (int)twipX + " " + (int)twipY + " " + (int) twipWidth + " " + (int) twipHeight + ")");
             mDocument.paintTile(buffer, TILE_SIZE, TILE_SIZE, (int) twipX, (int) twipY, (int) twipWidth, (int) twipHeight);
+            long stop = System.currentTimeMillis();
+            Log.i(LOGTAG, "paintTile TAIL @ " + stop + " - elapsed: " + (stop - start) + " ");
         } else {
             Log.e(LOGTAG, "Document is null!!");
         }
commit 34ea1ede6590399eb943d8f87c9ad473c6a71a68
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 23:08:27 2014 +0200

    android: show progress spinner also when switching parts
    
    Change-Id: Ie21e71aa03eddef620d470e01daf6f1936a5d7c7

diff --git a/android/experimental/LOAndroid3/res/layout/activity_main.xml b/android/experimental/LOAndroid3/res/layout/activity_main.xml
index 9ada4d3..fd7d63b 100644
--- a/android/experimental/LOAndroid3/res/layout/activity_main.xml
+++ b/android/experimental/LOAndroid3/res/layout/activity_main.xml
@@ -22,7 +22,8 @@
             android:id="@+id/loadingPanel"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:gravity="center" >
+            android:gravity="center"
+            android:background="#9333">
 
             <ProgressBar
                 android:layout_width="wrap_content"
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
index 332e0f8..7161f14 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
@@ -10,7 +10,7 @@ public class LOKitShell {
 
     public static float getDpi() {
         DisplayMetrics metrics = LibreOfficeMainActivity.mAppContext.getResources().getDisplayMetrics();
-        return  metrics.density * 160;
+        return metrics.density * 160;
     }
 
     public static void sendEvent(LOEvent event) {
@@ -27,4 +27,22 @@ public class LOKitShell {
     public static void queueRedraw() {
         LOKitShell.sendEvent(LOEventFactory.redraw());
     }
+
+    public static void showProgressSpinner() {
+        getMainHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                LibreOfficeMainActivity.mAppContext.showProgressSpinner();
+            }
+        });
+    }
+
+    public static void hideProgressSpinner() {
+        getMainHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                LibreOfficeMainActivity.mAppContext.hideProgressSpinner();
+            }
+        });
+    }
 }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index 31b9eb5..398389b 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -55,8 +55,10 @@ public class LOKitThread extends Thread {
     }
 
     private void changePart(int partIndex) {
+        LOKitShell.showProgressSpinner();
         mTileProvider.changePart(partIndex);
         refresh();
+        LOKitShell.hideProgressSpinner();
     }
 
     private boolean load(String filename) {
@@ -76,14 +78,9 @@ public class LOKitThread extends Thread {
 
         boolean isReady = mTileProvider.isReady();
         if (isReady) {
+            LOKitShell.showProgressSpinner();
             refresh();
-            LOKitShell.getMainHandler().post(new Runnable() {
-                @Override
-                public void run() {
-                    LibreOfficeMainActivity.mAppContext.hideProgressBar();
-                }
-            });
-
+            LOKitShell.hideProgressSpinner();
         }
         return isReady;
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 1fce7d4..8607ebf 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -199,11 +199,11 @@ public class LibreOfficeMainActivity extends Activity {
 
     }
 
-    public void showProgressBar() {
+    public void showProgressSpinner() {
         findViewById(R.id.loadingPanel).setVisibility(View.VISIBLE);
     }
 
-    public void hideProgressBar() {
+    public void hideProgressSpinner() {
         findViewById(R.id.loadingPanel).setVisibility(View.GONE);
     }
 
commit d885cf403c805eb6d4d23b9491feecbcecdcb43d
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Wed Oct 1 22:48:38 2014 +0200

    android: Fix typo.
    
    Change-Id: I22f7bbcc5bc5f58c30a5915c876736f664a42a61

diff --git a/android/experimental/LOAndroid3/res/values/strings.xml b/android/experimental/LOAndroid3/res/values/strings.xml
index d04f92e..f913e5e 100644
--- a/android/experimental/LOAndroid3/res/values/strings.xml
+++ b/android/experimental/LOAndroid3/res/values/strings.xml
@@ -4,8 +4,8 @@
     <string name="app_name">LibreOffice Viewer</string>
 
     <string name="app_about_name"><b>LibreOffice Viewer \'Beta\'</b></string>
-    <string name="app_description">LibreOffice Viewer is an document viewer based on LibreOffice</string>
-    <string name="app_credits">http://www.libreoffice.com</string>
+    <string name="app_description">LibreOffice Viewer is a document viewer based on LibreOffice</string>
+    <string name="app_credits">http://www.libreoffice.org</string>
 
     <string name="browser_app_name">LibreOffice Browser</string>
     <string name="menu_search">Search</string>
commit 623007c0fab937d6874487870e44bfac513244de
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 19:56:01 2014 +0200

    android: about dialog description, app names - viewer & browser
    
    Change-Id: I4f759b6a004ca8f12974f3d0daa9f1d78c015f2a

diff --git a/android/experimental/LOAndroid3/res/layout/about.xml b/android/experimental/LOAndroid3/res/layout/about.xml
index f1222dc..ec014a0 100644
--- a/android/experimental/LOAndroid3/res/layout/about.xml
+++ b/android/experimental/LOAndroid3/res/layout/about.xml
@@ -12,17 +12,18 @@
         android:layout_height="wrap_content"
         android:text="@string/app_description"
         android:textColor="@android:color/secondary_text_light"
-        android:textSize="16sp"/>
+        android:textSize="18sp"/>
 
     <TextView
         android:id="@+id/about_credits"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:autoLink="web"
+        android:paddingBottom="20dip"
         android:paddingTop="20dip"
         android:text="@string/app_credits"
         android:textColor="@android:color/secondary_text_light"
-        android:textSize="16dip"/>
+        android:textSize="18dip"/>
 
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                   android:layout_width="match_parent"
@@ -33,15 +34,15 @@
             android:id="@+id/about_license_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="License"
-            />
+            android:layout_marginRight="12dp"
+            android:text="License"/>
 
         <Button
             android:id="@+id/about_notice_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="Notice"
-            />
+            android:layout_marginRight="12dp"
+            android:text="Notice"/>
     </LinearLayout>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/android/experimental/LOAndroid3/res/values/strings.xml b/android/experimental/LOAndroid3/res/values/strings.xml
index 74dee00..d04f92e 100644
--- a/android/experimental/LOAndroid3/res/values/strings.xml
+++ b/android/experimental/LOAndroid3/res/values/strings.xml
@@ -1,11 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
 
-    <string name="app_name">LibreOffice</string>
-    <string name="app_description">Description</string>
-    <string name="app_credits">Credits</string>
+    <string name="app_name">LibreOffice Viewer</string>
 
-    <string name="browser_app_name">LibreOfficeUI</string>
+    <string name="app_about_name"><b>LibreOffice Viewer \'Beta\'</b></string>
+    <string name="app_description">LibreOffice Viewer is an document viewer based on LibreOffice</string>
+    <string name="app_credits">http://www.libreoffice.com</string>
+
+    <string name="browser_app_name">LibreOffice Browser</string>
     <string name="menu_search">Search</string>
     <string name="list_view">List</string>
     <string name="grid_view">Grid</string>
commit 3e31057f5a8336d84d1b321cfb1db6b008035148
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 19:54:08 2014 +0200

    android: clicking "Parts" in preferences opens the side drawer
    
    Change-Id: I3cfd0a31409f6a798c933dae4a47b75e93601f6b

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index a37438e..1fce7d4 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -63,9 +63,13 @@ public class LibreOfficeMainActivity extends Activity {
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         int id = item.getItemId();
-        if (id == R.id.action_about) {
-            showAbout();
-            return true;
+        switch (id) {
+            case R.id.action_about:
+                showAbout();
+                return true;
+            case R.id.action_parts:
+                mDrawerLayout.openDrawer(mDrawerList);
+                return true;
         }
         return super.onOptionsItemSelected(item);
     }
commit 32fe0017ee87d21eb4bf16efa42ab0328bb159e4
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 17:46:03 2014 +0200

    android: fix redrawing everyting on part change (via sidebar)
    
    Change-Id: If7aeeca3da65f44dfe1f9a5bc347baf4e3cadd82

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index 54478bf..31b9eb5 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -46,10 +46,11 @@ public class LOKitThread extends Thread {
             mApplication.getLayerController().getView().changeCheckerboardBitmap(bitmap, mTileProvider.getPageWidth(), mTileProvider.getPageHeight());
         }
 
-        mLayerClient.clearAllTiles();
-
+        mLayerClient.clearAndResetlayers();
+        draw();
         RectF rect = new RectF(0, 0, mTileProvider.getPageWidth(), mTileProvider.getPageHeight());
         mController.setPageRect(rect, rect);
+        mController.setViewportMetrics(mController.getViewportMetrics());
         mController.setForceRedraw();
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
index c6c7d7938..1ad8d38 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
@@ -195,7 +195,7 @@ public class DynamicTileLayer extends Layer {
         }
     }
 
-    public void clearAllTiles() {
+    public void clearAndReset() {
         tiles.clear();
         currentViewport = new RectF();
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index 5905d4a..23095ef 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -264,8 +264,8 @@ public class GeckoLayerClient implements LayerView.Listener {
         mRootLayer.reevaluateTiles(mLayerController.getViewportMetrics());
     }
 
-    public void clearAllTiles() {
-        mRootLayer.clearAllTiles();
+    public void clearAndResetlayers() {
+        mRootLayer.clearAndReset();
     }
 
     private class AdjustRunnable implements Runnable {
commit 20ca5ea8ab6d652fc70aa29038685845f6e3881b
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 17:41:02 2014 +0200

    android: null safeguards and cleanup unneeded calls
    
    Change-Id: I0ffcfb0fbaa03e5035bec9dd1ffed21f85972470

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
index 859a3d8..332e0f8 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
@@ -3,7 +3,6 @@ package org.libreoffice;
 
 import android.os.Handler;
 import android.util.DisplayMetrics;
-import android.util.Log;
 
 
 public class LOKitShell {
@@ -20,10 +19,6 @@ public class LOKitShell {
         }
     }
 
-    public static void viewSizeChanged() {
-        Log.i(LOGTAG, "viewSizeChanged");
-    }
-
     // Get a Handler for the main java thread
     public static Handler getMainHandler() {
         return LibreOfficeMainActivity.mAppContext.mMainHandler;
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
index 03da4bf..c6c7d7938 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
@@ -131,6 +131,10 @@ public class DynamicTileLayer extends Layer {
     }
 
     public void reevaluateTiles(ImmutableViewportMetrics viewportMetrics) {
+        if (tileProvider == null) {
+            return;
+        }
+
         RectF newCurrentViewPort = inflate(roundToTileSize(viewportMetrics.getViewport(), tileSize), tileSize);
 
         if (!currentViewport.equals(newCurrentViewPort)) {
@@ -193,5 +197,6 @@ public class DynamicTileLayer extends Layer {
 
     public void clearAllTiles() {
         tiles.clear();
+        currentViewport = new RectF();
     }
 }
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index 9ae462b..5905d4a 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -71,7 +71,6 @@ public class GeckoLayerClient implements LayerView.Listener {
     private ImmutableViewportMetrics mNewGeckoViewport;
     private Context mContext;
     private boolean mPendingViewportAdjust;
-    private boolean mViewportSizeChanged;
 
     public GeckoLayerClient(Context context) {
         mContext = context;
@@ -147,8 +146,6 @@ public class GeckoLayerClient implements LayerView.Listener {
 
     /* Informs Gecko that the screen size has changed. */
     private void sendResizeEventIfNecessary(boolean force) {
-        Log.e(LOGTAG, "### sendResizeEventIfNecessary " + force);
-
         DisplayMetrics metrics = new DisplayMetrics();
         LibreOfficeMainActivity.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
         View view = mLayerController.getView();
@@ -183,7 +180,6 @@ public class GeckoLayerClient implements LayerView.Listener {
 
     public void viewportSizeChanged() {
         sendResizeEventIfNecessary(true);
-        LOKitShell.viewSizeChanged();
     }
 
     void adjustViewport(DisplayPortMetrics displayPort) {
@@ -204,10 +200,6 @@ public class GeckoLayerClient implements LayerView.Listener {
         }
 
         LOKitShell.sendEvent(LOEventFactory.viewport(clampedMetrics));
-        if (mViewportSizeChanged) {
-            mViewportSizeChanged = false;
-            LOKitShell.viewSizeChanged();
-        }
     }
 
     /** This function is invoked by Gecko via JNI; be careful when modifying signature.
commit 52228bbd790bb5fb3958fa2ef84a4171f0ad199c
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 13:53:42 2014 +0200

    android: image in TileLayer can be null
    
    Change-Id: I4a910eb60f6fe81f97933d1b9e57bac6af4547c9

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 1ee1f1a..28ac487 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
@@ -28,7 +28,7 @@ public abstract class TileLayer extends Layer {
     private PaintMode mPaintMode;
 
     public TileLayer(CairoImage image, PaintMode paintMode) {
-        super(image.getSize());
+        super(image == null ? null : image.getSize());
 
         mPaintMode = paintMode;
         mImage = image;
commit 0d3e2ee5cdb685e68ec4a16f2218967f75a2dab5
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 13:53:11 2014 +0200

    android: SubTile - equals and hash
    
    Change-Id: I6e8cf220d108cefdf16f9b4553e2d2ecd7a5338c

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 5ab4f0d..27f11fc 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
@@ -22,4 +22,26 @@ public class SubTile extends SingleTileLayer {
     public void markForRemoval() {
         markedForRemoval = true;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        SubTile subTile = (SubTile) o;
+
+        if (x != subTile.x) return false;
+        if (y != subTile.y) return false;
+        if (Float.compare(subTile.zoom, zoom) != 0) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = x;
+        result = 31 * result + y;
+        result = 31 * result + (zoom != +0.0f ? Float.floatToIntBits(zoom) : 0);
+        return result;
+    }
 }
commit a55068030ebc354caf8d8282a5ff00db3ced8665
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 13:52:07 2014 +0200

    android: SingleTileLayer - less var. trashing (Fennec update)
    
    Change-Id: I8c32f6a43cad6dd3790a3e7dd0b990516a35ebca

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 cc1988f..0bc2716 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
@@ -23,14 +23,40 @@ public class SingleTileLayer extends TileLayer {
 
     private Rect mMask;
 
-    public SingleTileLayer(CairoImage image) { this(false, image); }
+    // To avoid excessive GC, declare some objects here that would otherwise
+    // be created and destroyed frequently during draw().
+    private final RectF mBounds;
+    private final RectF mTextureBounds;
+    private final RectF mViewport;
+    private final Rect mIntBounds;
+    private final Rect mSubRect;
+    private final RectF mSubRectF;
+    private final Region mMaskedBounds;
+    private final Rect mCropRect;
+    private final RectF mObjRectF;
+    private final float[] mCoords;
+
+    public SingleTileLayer(CairoImage image) {
+        this(false, image);
+    }
 
     public SingleTileLayer(boolean repeat, CairoImage image) {
-        super(image, repeat ? PaintMode.REPEAT : PaintMode.NORMAL);
+        this(image, repeat ? TileLayer.PaintMode.REPEAT : TileLayer.PaintMode.NORMAL);
     }
 
     public SingleTileLayer(CairoImage image, TileLayer.PaintMode paintMode) {
         super(image, paintMode);
+
+        mBounds = new RectF();
+        mTextureBounds = new RectF();
+        mViewport = new RectF();
+        mIntBounds = new Rect();
+        mSubRect = new Rect();
+        mSubRectF = new RectF();
+        mMaskedBounds = new Region();
+        mCropRect = new Rect();
+        mObjRectF = new RectF();
+        mCoords = new float[20];
     }
 
     /**
@@ -47,83 +73,69 @@ public class SingleTileLayer extends TileLayer {
         if (!initialized())
             return;
 
-        RectF bounds;
-        RectF textureBounds;
-        RectF viewport = context.viewport;
+        mViewport.set(context.viewport);
 
         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());
+            mBounds.set(getBounds(context));
+            mTextureBounds.set(0.0f, 0.0f, mBounds.width(), mBounds.height());
+            mBounds.set(0.0f, 0.0f, mViewport.width(), mViewport.height());
         } else if (stretches()) {
             // If we're stretching, we just want the bounds and texture bounds
             // to fit to the page.
-            bounds = new RectF(context.pageRect);
-            textureBounds = bounds;
+            mBounds.set(context.pageRect);
+            mTextureBounds.set(mBounds);
         } else {
-            bounds = getBounds(context);
-            textureBounds = bounds;
+            mBounds.set(getBounds(context));
+            mTextureBounds.set(mBounds);
         }
 
-        Rect intBounds = new Rect();
-        bounds.roundOut(intBounds);
-        Region maskedBounds = new Region(intBounds);
+        mBounds.roundOut(mIntBounds);
+        mMaskedBounds.set(mIntBounds);
         if (mMask != null) {
-            maskedBounds.op(mMask, Region.Op.DIFFERENCE);
-            if (maskedBounds.isEmpty())
+            mMaskedBounds.op(mMask, Region.Op.DIFFERENCE);
+            if (mMaskedBounds.isEmpty())
                 return;
         }
 
         // XXX Possible optimisation here, form this array so we can draw it in
         //     a single call.
-        RegionIterator i = new RegionIterator(maskedBounds);
-        for (Rect subRect = new Rect(); i.next(subRect);) {
+        RegionIterator i = new RegionIterator(mMaskedBounds);
+        while (i.next(mSubRect)) {
             // Compensate for rounding errors at the edge of the tile caused by
             // the roundOut above
-            RectF subRectF = new RectF(Math.max(bounds.left, (float)subRect.left),
-                                       Math.max(bounds.top, (float)subRect.top),
-                                       Math.min(bounds.right, (float)subRect.right),
-                                       Math.min(bounds.bottom, (float)subRect.bottom));
+            mSubRectF.set(Math.max(mBounds.left, (float)mSubRect.left),
+                          Math.max(mBounds.top, (float)mSubRect.top),
+                          Math.min(mBounds.right, (float)mSubRect.right),
+                          Math.min(mBounds.bottom, (float)mSubRect.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(bounds.bottom - subRectF.top),
-                                         Math.round(subRectF.right - bounds.left),
-                                         Math.round(bounds.bottom - subRectF.bottom) };
-
-            float left = subRectF.left - viewport.left;
-            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(), bottom/viewport.height(), 0,
-                cropRect[0]/textureBounds.width(), cropRect[1]/textureBounds.height(),
-
-                left/viewport.width(), top/viewport.height(), 0,
-                cropRect[0]/textureBounds.width(), cropRect[3]/textureBounds.height(),
+            mCropRect.set(Math.round(mSubRectF.left - mBounds.left),
+                          Math.round(mBounds.bottom - mSubRectF.top),
+                          Math.round(mSubRectF.right - mBounds.left),
+                          Math.round(mBounds.bottom - mSubRectF.bottom));
 
-                right/viewport.width(), bottom/viewport.height(), 0,
-                cropRect[2]/textureBounds.width(), cropRect[1]/textureBounds.height(),
+            mObjRectF.set(mSubRectF.left - mViewport.left,
+                          mViewport.bottom - mSubRectF.bottom,
+                          mSubRectF.right - mViewport.left,
+                          mViewport.bottom - mSubRectF.top);
 
-                right/viewport.width(), top/viewport.height(), 0,
-                cropRect[2]/textureBounds.width(), cropRect[3]/textureBounds.height()
-            };
+            fillRectCoordBuffer(mCoords, mObjRectF, mViewport.width(), mViewport.height(),
+                                mCropRect, mTextureBounds.width(), mTextureBounds.height());
 
             FloatBuffer coordBuffer = context.coordBuffer;
             int positionHandle = context.positionHandle;
             int textureHandle = context.textureHandle;
 
+            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getTextureID());
 
             // Make sure we are at position zero in the buffer
             coordBuffer.position(0);
-            coordBuffer.put(coords);
+            coordBuffer.put(mCoords);
 
             // Unbind any the current array buffer so we can use client side buffers
             GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
commit 7afb0e2491ac47021412529e3330f3924991d234
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Wed Oct 1 13:51:00 2014 +0200

    android: replace MultiTileLayer with new & simpler DynamicTileLayer
    
    Change-Id: Idec2246975a65f8ce664642a4ef49415e20ca187

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
new file mode 100644
index 0000000..03da4bf
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java
@@ -0,0 +1,197 @@
+package org.mozilla.gecko.gfx;
+
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.util.Log;
+
+import org.libreoffice.TileProvider;
+import org.mozilla.gecko.util.FloatUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class DynamicTileLayer extends Layer {
+    private static final String LOGTAG = DynamicTileLayer.class.getSimpleName();
+
+    private final List<SubTile> tiles = new CopyOnWriteArrayList<SubTile>();
+    private TileProvider tileProvider;
+    private final FloatSize tileSize;
+    private RectF currentViewport = new RectF();
+
+    public DynamicTileLayer() {
+        this.tileSize = new FloatSize(256, 256);
+    }
+
+    public DynamicTileLayer(FloatSize tileSize) {
+        this.tileSize = tileSize;
+    }
+
+    public void setTileProvider(TileProvider tileProvider) {
+        this.tileProvider = tileProvider;
+    }
+
+    public void invalidate() {
+        for (SubTile layer : tiles) {
+            layer.invalidate();
+        }
+    }
+
+    @Override
+    public void beginTransaction() {
+        super.beginTransaction();
+        for (SubTile tile : tiles) {
+            tile.beginTransaction();
+        }
+    }
+
+    @Override
+    public void endTransaction() {
+        for (SubTile tile : tiles) {
+            tile.endTransaction();
+        }
+        super.endTransaction();
+    }
+
+    @Override
+    public void draw(RenderContext context) {
+        for (SubTile tile : tiles) {
+            if (RectF.intersects(tile.getBounds(context), context.viewport)) {
+                tile.draw(context);
+            }
+        }
+    }
+
+    @Override
+    protected void performUpdates(RenderContext context) {
+        super.performUpdates(context);
+
+        refreshTileMetrics();
+
+        for (SubTile tile : tiles) {
+            tile.performUpdates(context);
+        }
+    }
+
+    @Override
+    public Region getValidRegion(RenderContext context) {
+        Region validRegion = new Region();
+        for (SubTile tile : tiles) {
+            validRegion.op(tile.getValidRegion(context), Region.Op.UNION);
+        }
+
+        return validRegion;
+    }
+
+    @Override
+    public void setResolution(float newResolution) {
+        super.setResolution(newResolution);
+        for (SubTile tile : tiles) {
+            tile.setResolution(newResolution);
+        }
+    }
+
+    private void refreshTileMetrics() {
+        for (SubTile tile : tiles) {
+            tile.beginTransaction();
+
+            Rect position = tile.getPosition();
+            float positionX = tile.x / tile.zoom;
+            float positionY = tile.y / tile.zoom;
+            float tileSizeWidth = tileSize.width / tile.zoom;
+            float tileSizeHeight = tileSize.height / tile.zoom;
+            position.set((int) positionX, (int) positionY, (int) (positionX + tileSizeWidth + 1), (int) (positionY + tileSizeHeight + 1));
+            tile.setPosition(position);
+
+            tile.endTransaction();
+        }
+    }
+
+    private RectF roundToTileSize(RectF input, FloatSize tileSize) {
+        float minX = ((int)(input.left / tileSize.width)) * tileSize.width;
+        float minY = ((int)(input.top / tileSize.height)) * tileSize.height;
+        float maxX = ((int)(input.right / tileSize.width) + 1) * tileSize.width;
+        float maxY = ((int)(input.bottom / tileSize.height) + 1) * tileSize.height;
+        return new RectF(minX, minY, maxX, maxY);
+    }
+
+    private RectF inflate(RectF rect, FloatSize inflateSize) {
+        RectF newRect = new RectF(rect);
+        newRect.left -= inflateSize.width;
+        newRect.left = newRect.left < 0.0f ? 0.0f : newRect.left;
+
+        newRect.top -= inflateSize.height;
+        newRect.top = newRect.top < 0.0f ? 0.0f : newRect.top;
+
+        newRect.right += inflateSize.width;
+        newRect.bottom += inflateSize.height;
+
+        return newRect;
+    }
+
+    public void reevaluateTiles(ImmutableViewportMetrics viewportMetrics) {
+        RectF newCurrentViewPort = inflate(roundToTileSize(viewportMetrics.getViewport(), tileSize), tileSize);
+
+        if (!currentViewport.equals(newCurrentViewPort)) {
+            Log.i(LOGTAG, "reevaluateTiles " + currentViewport + " " + newCurrentViewPort);
+            currentViewport = newCurrentViewPort;
+            clearMarkedTiles();
+            addNewTiles(viewportMetrics);
+            markTiles(viewportMetrics);
+        }
+    }
+
+    private void addNewTiles(ImmutableViewportMetrics viewportMetrics) {
+        for (float y = currentViewport.top; y < currentViewport.bottom; y += tileSize.height) {
+            if (y > viewportMetrics.getPageHeight()) {
+                continue;
+            }
+            for (float x = currentViewport.left; x < currentViewport.right; x += tileSize.width) {
+                if (x > viewportMetrics.getPageWidth()) {
+                    continue;
+                }
+                boolean contains = false;
+                for (SubTile tile : tiles) {
+                    if (tile.x == x && tile.y == y && tile.zoom == viewportMetrics.zoomFactor) {
+                        contains = true;
+                    }
+                }
+                if (!contains) {
+                    CairoImage image = tileProvider.createTile(x, y, tileSize, viewportMetrics.zoomFactor);
+                    SubTile tile = new SubTile(image, (int) x, (int) y, viewportMetrics.zoomFactor);
+                    tile.beginTransaction();
+                    tiles.add(tile);
+                }
+            }
+        }
+    }
+
+    private void clearMarkedTiles() {
+        List<SubTile> tilesToRemove = new ArrayList<SubTile>();
+        for (SubTile tile : tiles) {
+            if (tile.markedForRemoval) {
+                tile.destroy();
+                tilesToRemove.add(tile);
+            }
+        }
+        tiles.removeAll(tilesToRemove);
+    }
+
+    private void markTiles(ImmutableViewportMetrics viewportMetrics) {
+        for (SubTile tile : tiles) {
+            if (FloatUtils.fuzzyEquals(tile.zoom, viewportMetrics.zoomFactor)) {
+                RectF tileRect = new RectF(tile.x, tile.y, tile.x + tileSize.width, tile.y + tileSize.height);
+                if (!RectF.intersects(currentViewport, tileRect)) {
+                    tile.markForRemoval();
+                }
+            } else {
+                tile.markForRemoval();
+            }
+        }
+    }
+
+    public void clearAllTiles() {
+        tiles.clear();
+    }
+}
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index 9c3a893..9ae462b 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -62,7 +62,7 @@ public class GeckoLayerClient implements LayerView.Listener {
     private boolean mRecordDrawTimes;
     private DrawTimingQueue mDrawTimingQueue;
 
-    private MultiTileLayer mRootLayer;
+    private DynamicTileLayer mRootLayer;
 
     /* The viewport that Gecko is currently displaying. */
     private ImmutableViewportMetrics mGeckoViewport;
@@ -88,7 +88,7 @@ public class GeckoLayerClient implements LayerView.Listener {
 
         mLayerController = layerController;
 
-        mRootLayer = new MultiTileLayer();
+        mRootLayer = new DynamicTileLayer();
 
         view.setListener(this);
         layerController.setRoot(mRootLayer);
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/MultiTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/MultiTileLayer.java
deleted file mode 100644
index 7d1306e..0000000
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/MultiTileLayer.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/* -*- 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-2012
-* the Initial Developer. All Rights Reserved.
-*
-* Contributor(s):
-*   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 ***** */
-
-package org.mozilla.gecko.gfx;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Region;
-
-import org.libreoffice.TileProvider;
-import org.mozilla.gecko.util.FloatUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-public class MultiTileLayer extends Layer {
-    private static final String LOGTAG = "MultiTileLayer";
-
-    private static int TILE_SIZE = 256;
-    private final List<SubTile> mTiles = new CopyOnWriteArrayList<SubTile>();
-    private TileProvider tileProvider;
-    private RectF currentViewPort = new RectF();
-
-    public void invalidate() {
-        for (SubTile layer : mTiles) {
-            layer.invalidate();
-        }
-    }
-
-    private void validateTiles() {
-        // Set tile origins and resolution
-        Point origin = new Point();
-        refreshTileMetrics(origin, getResolution(), false);
-    }
-
-    @Override
-    protected void performUpdates(RenderContext context) {
-        super.performUpdates(context);
-
-        validateTiles();
-
-        // Iterate over the tiles and decide which ones we'll be drawing
-        int dirtyTiles = 0;
-        boolean screenUpdateDone = false;
-        SubTile firstDirtyTile = null;
-        for (SubTile layer : mTiles) {
-            // First do a non-texture update to make sure coordinates are
-            // up-to-date.
-            layer.performUpdates(context);
-
-            RectF layerBounds = layer.getBounds(context);
-
-            if (!RectF.intersects(layerBounds, context.viewport)) {
-                if (firstDirtyTile == null) {
-                    firstDirtyTile = layer;
-                }
-                dirtyTiles++;
-            } else {
-                // This tile intersects with the screen and is dirty,
-                // update it immediately.
-                screenUpdateDone = true;
-                layer.performUpdates(context);
-            }
-        }
-
-        // Now if no tiles that intersect with the screen were updated, update
-        // a single tile that doesn't (if there are any). This has the effect
-        // of spreading out non-critical texture upload over time, and smoothing
-        // upload-related hitches.
-        if (!screenUpdateDone && firstDirtyTile != null) {
-            firstDirtyTile.performUpdates(context);
-            dirtyTiles--;
-        }
-
-    }
-
-    private void refreshTileMetrics(Point origin, float resolution, boolean inTransaction) {
-        for (SubTile layer : mTiles) {
-            if (!inTransaction) {
-                layer.beginTransaction();
-            }
-
-            if (origin != null) {
-                Rect position = layer.getPosition();
-                float positionX = origin.x + (layer.x / layer.zoom);
-                float positionY = origin.y + (layer.y / layer.zoom);
-                float tileSize = TILE_SIZE / layer.zoom;
-                position.set((int) positionX, (int) positionY, (int) (positionX + tileSize + 1), (int) (positionY + tileSize + 1));
-                layer.setPosition(position);
-            }
-            if (resolution >= 0.0f) {
-                layer.setResolution(resolution);
-            }
-
-            if (!inTransaction) {
-                layer.endTransaction();
-            }
-        }
-    }
-
-    @Override
-    public void setResolution(float newResolution) {
-        super.setResolution(newResolution);
-        refreshTileMetrics(null, newResolution, true);
-    }
-
-    @Override
-    public void beginTransaction() {
-        super.beginTransaction();
-
-        for (SubTile layer : mTiles) {
-            layer.beginTransaction();
-        }
-    }
-
-    @Override
-    public void endTransaction() {
-        for (SubTile layer : mTiles) {
-            layer.endTransaction();
-        }
-        super.endTransaction();
-    }
-
-    private RectF roundToTileSize(RectF input, int tileSize) {
-        float minX = (Math.round(input.left) / tileSize) * tileSize;
-        float minY = (Math.round(input.top) / tileSize) * tileSize;
-        float maxX = ((Math.round(input.right) / tileSize) + 1) * tileSize;
-        float maxY = ((Math.round(input.bottom) / tileSize) + 1) * tileSize;
-        return new RectF(minX, minY, maxX, maxY);
-    }
-
-    private RectF inflate(RectF rect, float inflateSize) {
-        RectF newRect = new RectF(rect);
-        newRect.left -= inflateSize;
-        newRect.left = newRect.left < 0.0f ? 0.0f : newRect.left;
-
-        newRect.top -= inflateSize;
-        newRect.top = newRect.top < 0.0f ? 0.0f : newRect.top;
-
-        newRect.right += inflateSize;
-        newRect.bottom += inflateSize;
-
-        return newRect;
-    }
-
-    @Override
-    public void draw(RenderContext context) {
-        for (SubTile layer : mTiles) {
-            // Avoid work, only draw tiles that intersect with the viewport
-            RectF layerBounds = layer.getBounds(context);
-
-            if (RectF.intersects(layerBounds, context.viewport)) {
-                layer.draw(context);
-            }
-        }
-    }
-
-    @Override
-    public Region getValidRegion(RenderContext context) {
-        Region validRegion = new Region();
-        for (SubTile tile : mTiles) {
-            validRegion.op(tile.getValidRegion(context), Region.Op.UNION);
-        }
-
-        return validRegion;
-    }
-
-    public void setTileProvider(TileProvider tileProvider) {
-        this.tileProvider = tileProvider;
-    }
-
-    public void reevaluateTiles(ImmutableViewportMetrics viewportMetrics) {
-        RectF newCurrentViewPort = inflate(roundToTileSize(viewportMetrics.getViewport(), TILE_SIZE), TILE_SIZE);
-
-        if (currentViewPort != newCurrentViewPort) {
-            currentViewPort = newCurrentViewPort;
-            clearMarkedTiles();
-            addNewTiles(viewportMetrics);
-            markTiles(viewportMetrics);
-        }
-    }
-
-    private void clearMarkedTiles() {
-        List<SubTile> tilesToRemove = new ArrayList<SubTile>();
-        for(SubTile tile : mTiles) {
-            if (tile.markedForRemoval) {
-                tile.destroy();
-                tilesToRemove.add(tile);
-            }
-        }
-        mTiles.removeAll(tilesToRemove);
-    }
-
-    private void addNewTiles(ImmutableViewportMetrics viewportMetrics) {
-        for (float y = currentViewPort.top; y < currentViewPort.bottom; y += TILE_SIZE) {
-            if (y > viewportMetrics.getPageHeight()) {
-                continue;
-            }
-            for (float x = currentViewPort.left; x < currentViewPort.right; x += TILE_SIZE) {
-                if (x > viewportMetrics.getPageWidth()) {
-                    continue;
-                }
-                boolean contains = false;
-                for (SubTile tile : mTiles) {
-                    if (tile.x == x && tile.y == y && tile.zoom == viewportMetrics.zoomFactor) {
-                        contains = true;
-                    }

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list