summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.com>2014-10-01 13:51:00 +0200
committerTomaž Vajngerl <tomaz.vajngerl@collabora.com>2014-10-04 17:49:38 +0200
commit7afb0e2491ac47021412529e3330f3924991d234 (patch)
treecc65d19cb1434b9b98e988a24c2af3cf25dec7b4 /android
parentce77933dbe278f59afb7e6a74c3b160b1d33b6df (diff)
android: replace MultiTileLayer with new & simpler DynamicTileLayer
Change-Id: Idec2246975a65f8ce664642a4ef49415e20ca187
Diffstat (limited to 'android')
-rw-r--r--android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DynamicTileLayer.java197
-rw-r--r--android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java4
-rw-r--r--android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/MultiTileLayer.java273
3 files changed, 199 insertions, 275 deletions
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 000000000000..03da4bfe4ad7
--- /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 9c3a893d48df..9ae462b68b40 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 7d1306e76416..000000000000
--- 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@gmail.com>
-* Arkady Blyakher <rkadyb@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;
- }
- }
- if (!contains) {
- CairoImage image = tileProvider.createTile(x, y, new FloatSize(TILE_SIZE, TILE_SIZE), viewportMetrics.zoomFactor);
- SubTile tile = new SubTile(image, (int)x, (int)y, viewportMetrics.zoomFactor);
- tile.beginTransaction();
- mTiles.add(tile);
- }
- }
- }
- }
-
- private void markTiles(ImmutableViewportMetrics viewportMetrics) {
- for (SubTile tile : mTiles) {
- if (FloatUtils.fuzzyEquals(tile.zoom, viewportMetrics.zoomFactor)) {
- RectF tileRect = new RectF(tile.x, tile.y, tile.x + TILE_SIZE, tile.y + TILE_SIZE);
- if (!RectF.intersects(currentViewPort, tileRect)) {
- tile.markForRemoval();
- }
- } else {
- tile.markForRemoval();
- }
- }
- }
-
- public void clearAllTiles() {
- mTiles.clear();
- }
-}
-