add MapView.clearMap() -> clear all previous map state in Layers on next onUpate

- now labels are cleared properly when the or mapdb changes.
- getTileSet now requires a TileSet instance as input
This commit is contained in:
Hannes Janetzek 2013-05-07 16:09:01 +02:00
parent 6bb5cd3f68
commit 82a3a880ac
14 changed files with 215 additions and 154 deletions

View File

@ -18,7 +18,7 @@ import org.oscim.core.MapPosition;
import org.oscim.renderer.RenderLayer; import org.oscim.renderer.RenderLayer;
import org.oscim.view.MapView; import org.oscim.view.MapView;
public class Layer { public abstract class Layer {
public Layer(MapView mapView) { public Layer(MapView mapView) {
mMapView = mapView; mMapView = mapView;
} }
@ -45,7 +45,6 @@ public class Layer {
return mEnabled; return mEnabled;
} }
/** /**
* Called before each frame render request (on main thread). * Called before each frame render request (on main thread).
* *
@ -53,12 +52,15 @@ public class Layer {
* current MapPosition * current MapPosition
* @param changed * @param changed
* true when MapPosition has changed since last call * true when MapPosition has changed since last call
* @param clear
* Clear all resources that depend on previous map state. Most
* importantly all resources from previous GL context (hold by
* RenderLayer)
*/ */
public void onUpdate(MapPosition mapPosition, boolean changed) { public void onUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
} }
/** /**
* Override to perform clean up of resources before shutdown. By default * Override to perform clean up of resources before shutdown. By default
* does nothing. * does nothing.
@ -69,6 +71,5 @@ public class Layer {
public void destroy() { public void destroy() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
} }

View File

@ -70,7 +70,7 @@ public class BuildingOverlay extends Overlay {
private boolean mActive = false; private boolean mActive = false;
@Override @Override
public void onUpdate(MapPosition mapPosition, boolean changed) { public void onUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
boolean show = mapPosition.scale >= (1 << MIN_ZOOM); boolean show = mapPosition.scale >= (1 << MIN_ZOOM);
if (show && mActive) if (show && mActive)

View File

@ -14,6 +14,7 @@
*/ */
package org.oscim.layers.overlay; package org.oscim.layers.overlay;
import org.oscim.core.MapPosition;
import org.oscim.layers.tile.TileRenderLayer; import org.oscim.layers.tile.TileRenderLayer;
import org.oscim.renderer.layers.TextRenderLayer; import org.oscim.renderer.layers.TextRenderLayer;
import org.oscim.view.MapView; import org.oscim.view.MapView;
@ -34,6 +35,12 @@ public class LabelingOverlay extends Overlay {
mLayer = mTextLayer; mLayer = mTextLayer;
} }
@Override
public void onUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
if (clear)
mTextLayer.clearLabels();
}
private int multi; private int multi;
@Override @Override

View File

@ -95,7 +95,7 @@ public class MapScaleBar extends Layer {
} }
@Override @Override
public void onUpdate(MapPosition mapPosition, boolean changed) { public void onUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
double latitude = MercatorProjection.toLatitude(mapPosition.y); double latitude = MercatorProjection.toLatitude(mapPosition.y);
if (!mRedrawNeeded) { if (!mRedrawNeeded) {

View File

@ -24,9 +24,8 @@ public abstract class TileLayer<T extends TileLoader> extends Layer {
//private final static String TAG = TileLayer.class.getName(); //private final static String TAG = TileLayer.class.getName();
private final static int MAX_ZOOMLEVEL = 17; private final static int MAX_ZOOMLEVEL = 17;
private boolean mClearMap = true;
protected final TileManager mTileManager; protected final TileManager mTileManager;
protected final TileRenderLayer mRenderLayer;
protected final int mNumTileLoader = 4; protected final int mNumTileLoader = 4;
protected final ArrayList<T> mTileLoader; protected final ArrayList<T> mTileLoader;
@ -52,7 +51,7 @@ public abstract class TileLayer<T extends TileLoader> extends Layer {
// RenderLayer is working in GL Thread and actually // RenderLayer is working in GL Thread and actually
// drawing loaded tiles to screen. // drawing loaded tiles to screen.
mLayer = new TileRenderLayer(mapView, mTileManager); mLayer = mRenderLayer = new TileRenderLayer(mapView, mTileManager);
} }
abstract protected T createLoader(TileManager tm); abstract protected T createLoader(TileManager tm);
@ -62,11 +61,11 @@ public abstract class TileLayer<T extends TileLoader> extends Layer {
} }
@Override @Override
public void onUpdate(MapPosition mapPosition, boolean changed) { public void onUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
if (mClearMap) { if (clear) {
mRenderLayer.clearTiles();
mTileManager.init(mMapView.getWidth(), mMapView.getHeight()); mTileManager.init(mMapView.getWidth(), mMapView.getHeight());
mClearMap = false;
changed = true; changed = true;
} }
if (changed) if (changed)
@ -75,11 +74,7 @@ public abstract class TileLayer<T extends TileLoader> extends Layer {
@Override @Override
public void destroy() { public void destroy() {
mTileManager.destroy();
for (T tileWorker : mTileLoader) { for (T tileWorker : mTileLoader) {
tileWorker.pause(); tileWorker.pause();
tileWorker.interrupt(); tileWorker.interrupt();
tileWorker.cleanup(); tileWorker.cleanup();
@ -91,11 +86,7 @@ public abstract class TileLayer<T extends TileLoader> extends Layer {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }
} mTileManager.destroy();
protected void clearMap() {
// clear tile and overlay data before next draw
mClearMap = true;
} }
void notifyLoaders() { void notifyLoaders() {

View File

@ -68,7 +68,8 @@ public class TileManager {
// current end position in mTiles // current end position in mTiles
private int mTilesSize; private int mTilesSize;
// counter for tiles with new data not uploaded to GL // counter for tiles with new data not
// yet uploaded to GL
private volatile int mTilesForUpload; private volatile int mTilesForUpload;
// new tile jobs for MapWorkers // new tile jobs for MapWorkers
@ -80,12 +81,13 @@ public class TileManager {
// lock for TileSets while updating MapTile locks // lock for TileSets while updating MapTile locks
private final Object mTilelock = new Object(); private final Object mTilelock = new Object();
// need to keep track of TileSets to clear on reset... // need to keep track of TileSets to clear on reset.
private final ArrayList<TileSet> mTileSets = new ArrayList<TileSet>(4); //private final ArrayList<TileSet> mTileSets = new ArrayList<TileSet>(4);
private TileSet mCurrentTiles; private TileSet mCurrentTiles;
/* package */TileSet mNewTiles; /* package */TileSet mNewTiles;
// job queue filled in TileManager and polled by TileLoaders
final JobQueue jobQueue; final JobQueue jobQueue;
private final QuadTreeIndex<MapTile> mIndex = new QuadTreeIndex<MapTile>() { private final QuadTreeIndex<MapTile> mIndex = new QuadTreeIndex<MapTile>() {
@ -139,7 +141,7 @@ public class TileManager {
// ... free static pools // ... free static pools
} }
public synchronized void init(int width, int height) { public void init(int width, int height) {
// sync with GLRender thread // sync with GLRender thread
// ... and labeling thread? // ... and labeling thread?
@ -150,29 +152,24 @@ public class TileManager {
for (int i = 0; i < mTilesSize; i++) for (int i = 0; i < mTilesSize; i++)
clearTile(mTiles[i]); clearTile(mTiles[i]);
} }
//else {
// FIXME any of this still needed?
// mInitialized is set when surface changed // mInitialized is set when surface changed
// and VBOs might be lost // and VBOs might be lost
// VertexPool.init(); // VertexPool.init();
//}
// clear cache index // clear cache index
//QuadTree.init(); // QuadTree.init();
// clear references to cached MapTiles // clear references to cached MapTiles
Arrays.fill(mTiles, null); Arrays.fill(mTiles, null);
mTilesSize = 0; mTilesSize = 0;
mTilesCount = 0; mTilesCount = 0;
// clear all references to previous tiles
for (TileSet td : mTileSets) {
Arrays.fill(td.tiles, null);
td.cnt = 0;
}
// set up TileSet large enough to hold current tiles // set up TileSet large enough to hold current tiles
int num = Math.max(width, height); int num = Math.max(width, height);
int size = Tile.SIZE >> 1; int size = Tile.SIZE >> 1;
int numTiles = (num * num) / (size * size) * 4; int numTiles = (num * num) / (size * size) * 4;
mNewTiles = new TileSet(numTiles); mNewTiles = new TileSet(numTiles);
mCurrentTiles = new TileSet(numTiles); mCurrentTiles = new TileSet(numTiles);
Log.d(TAG, "max tiles: " + numTiles); Log.d(TAG, "max tiles: " + numTiles);
@ -278,7 +275,7 @@ public class TileManager {
limitCache(pos, remove); limitCache(pos, remove);
} }
/** only used in setmapDatabase -- deprecate?*/ /** only used in setmapDatabase -- deprecate? */
public void clearJobs() { public void clearJobs() {
jobQueue.clear(); jobQueue.clear();
} }
@ -288,13 +285,19 @@ public class TileManager {
* Tiles remain locked in cache until the set is unlocked by either passing * Tiles remain locked in cache until the set is unlocked by either passing
* it again to this function or to releaseTiles. If passed TileSet is null * it again to this function or to releaseTiles. If passed TileSet is null
* it will be allocated. * it will be allocated.
*
* @param tileSet to be updated
* @return true if TileSet has changed
*/ */
public TileSet getActiveTiles(TileSet td) { public boolean getActiveTiles(TileSet tileSet) {
if (mCurrentTiles == null) if (mCurrentTiles == null)
return td; return false;
if (td != null && td.serial == mUpdateSerial) if (tileSet == null)
return td; return false;
if (tileSet.serial == mUpdateSerial)
return false;
// dont flip new/currentTiles while copying // dont flip new/currentTiles while copying
synchronized (mTilelock) { synchronized (mTilelock) {
@ -306,26 +309,24 @@ public class TileManager {
newTiles[i].lock(); newTiles[i].lock();
MapTile[] nextTiles; MapTile[] nextTiles;
nextTiles = tileSet.tiles;
if (td == null) {
td = new TileSet(newTiles.length);
mTileSets.add(td);
}
nextTiles = td.tiles;
// unlock previously active tiles // unlock previously active tiles
for (int i = 0, n = td.cnt; i < n; i++) for (int i = 0, n = tileSet.cnt; i < n; i++)
nextTiles[i].unlock(); nextTiles[i].unlock();
if (nextTiles.length != mCurrentTiles.tiles.length) {
tileSet.tiles = nextTiles = new MapTile[mCurrentTiles.tiles.length];
}
// copy newTiles to nextTiles // copy newTiles to nextTiles
System.arraycopy(newTiles, 0, nextTiles, 0, cnt); System.arraycopy(newTiles, 0, nextTiles, 0, cnt);
td.serial = mUpdateSerial; tileSet.serial = mUpdateSerial;
td.cnt = cnt; tileSet.cnt = cnt;
} }
return td; return true;
} }
// /** // /**
@ -392,8 +393,9 @@ public class TileManager {
if (mTilesSize == mTiles.length) { if (mTilesSize == mTiles.length) {
if (mTilesSize > mTilesCount) { if (mTilesSize > mTilesCount) {
//Log.d(TAG, "repack: " + mTiles.length + " / " + mTilesCount);
TileDistanceSort.sort(mTiles, 0, mTilesSize); TileDistanceSort.sort(mTiles, 0, mTilesSize);
// sorting also repacks the 'sparse' filled array
// so end of mTiles is at mTilesCount now
mTilesSize = mTilesCount; mTilesSize = mTilesCount;
} }
@ -551,10 +553,10 @@ public class TileManager {
* called from MapWorker Thread when tile is loaded by MapTileLoader * called from MapWorker Thread when tile is loaded by MapTileLoader
* *
* @param tile * @param tile
* Tile ready for upload to GL * Tile ready for upload in TileRenderLayer
* @return ... caller does not care * @return caller does not care
*/ */
public synchronized boolean passTile(MapTile tile) { public boolean passTile(MapTile tile) {
if (tile.state != STATE_LOADING) { if (tile.state != STATE_LOADING) {
// - should rather be STATE_FAILED // - should rather be STATE_FAILED
@ -565,6 +567,8 @@ public class TileManager {
} }
tile.state = STATE_NEW_DATA; tile.state = STATE_NEW_DATA;
// is volatile
mTilesForUpload++; mTilesForUpload++;
// locked means the tile is visible or referenced by // locked means the tile is visible or referenced by

View File

@ -48,24 +48,15 @@ public class TileRenderLayer extends RenderLayer {
mMapPosition.copy(pos); mMapPosition.copy(pos);
int serial = 0; boolean tilesChanged;
if (mDrawTiles != null)
serial = mDrawTiles.getSerial();
synchronized (tilelock) { synchronized (tilelock) {
// get current tiles to draw // get current tiles to draw
mDrawTiles = mTileManager.getActiveTiles(mDrawTiles); tilesChanged = mTileManager.getActiveTiles(mDrawTiles);
} }
if (mDrawTiles == null || mDrawTiles.cnt == 0) if (mDrawTiles.cnt == 0)
return; return;
boolean tilesChanged = false;
// check if tiles have changed.
if (serial != mDrawTiles.getSerial())
tilesChanged = true;
int tileCnt = mDrawTiles.cnt; int tileCnt = mDrawTiles.cnt;
MapTile[] tiles = mDrawTiles.tiles; MapTile[] tiles = mDrawTiles.tiles;
@ -90,6 +81,14 @@ public class TileRenderLayer extends RenderLayer {
} }
public void clearTiles() {
// Clear all references to MapTiles as all current
// tiles will also be removed from TileManager.
GLRenderer.drawlock.lock();
mDrawTiles = new TileSet();
GLRenderer.drawlock.unlock();
}
/** compile tile layer data and upload to VBOs */ /** compile tile layer data and upload to VBOs */
private static int compileTileLayers(MapTile[] tiles, int tileCnt) { private static int compileTileLayers(MapTile[] tiles, int tileCnt) {
int uploadCnt = 0; int uploadCnt = 0;
@ -189,10 +188,22 @@ public class TileRenderLayer extends RenderLayer {
} }
} }
// get a TileSet of currently visible tiles /**
public TileSet getVisibleTiles(TileSet td) { * Update tileSet with currently visible tiles
if (mDrawTiles == null) * get a TileSet of currently visible tiles
return td; */
public boolean getVisibleTiles(TileSet tileSet) {
if (tileSet == null)
return false;
if (mDrawTiles == null) {
releaseTiles(tileSet);
return false;
}
// same tiles as before
if (tileSet.serial == mDrawTiles.serial)
return false;
// ensure tiles keep visible state // ensure tiles keep visible state
synchronized (tilelock) { synchronized (tilelock) {
@ -200,24 +211,26 @@ public class TileRenderLayer extends RenderLayer {
MapTile[] newTiles = mDrawTiles.tiles; MapTile[] newTiles = mDrawTiles.tiles;
int cnt = mDrawTiles.cnt; int cnt = mDrawTiles.cnt;
if (td == null)
td = new TileSet(newTiles.length);
// unlock previous tiles // unlock previous tiles
for (int i = 0; i < td.cnt; i++) for (int i = 0; i < tileSet.cnt; i++)
td.tiles[i].unlock(); tileSet.tiles[i].unlock();
// ensure same size
if (tileSet.tiles.length != mDrawTiles.tiles.length) {
tileSet.tiles = new MapTile[mDrawTiles.tiles.length];
}
// lock tiles to not be removed from cache // lock tiles to not be removed from cache
td.cnt = 0; tileSet.cnt = 0;
for (int i = 0; i < cnt; i++) { for (int i = 0; i < cnt; i++) {
MapTile t = newTiles[i]; MapTile t = newTiles[i];
if (t.isVisible && t.state == STATE_READY) { if (t.isVisible && t.state == STATE_READY) {
t.lock(); t.lock();
td.tiles[td.cnt++] = t; tileSet.tiles[tileSet.cnt++] = t;
} }
} }
} }
return td; return true;
} }
public void releaseTiles(TileSet td) { public void releaseTiles(TileSet td) {
@ -236,7 +249,7 @@ public class TileRenderLayer extends RenderLayer {
// happens rarely, unless you live on Fidschi // happens rarely, unless you live on Fidschi
/* package */int mNumTileHolder; /* package */int mNumTileHolder;
/* package */TileSet mDrawTiles; /* package */TileSet mDrawTiles = new TileSet();
// scanline fill class used to check tile visibility // scanline fill class used to check tile visibility
private final ScanBox mScanBox = new ScanBox() { private final ScanBox mScanBox = new ScanBox() {
@ -301,4 +314,5 @@ public class TileRenderLayer extends RenderLayer {
} }
} }
}; };
} }

View File

@ -14,9 +14,9 @@
*/ */
package org.oscim.layers.tile; package org.oscim.layers.tile;
import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
/** /**
* use with TileManager.getActiveTiles(TileSet) to get the current tiles. tiles * use with TileManager.getActiveTiles(TileSet) to get the current tiles. tiles
* are locked to not be modifed until getActiveTiles passes them back on a * are locked to not be modifed until getActiveTiles passes them back on a
@ -28,18 +28,19 @@ public final class TileSet {
int serial; int serial;
public int getSerial(){ public int getSerial() {
return serial; return serial;
} }
TileSet() { public TileSet() {
tiles = new MapTile[1];
} }
public TileSet(int numTiles) { public TileSet(int numTiles) {
tiles = new MapTile[numTiles]; tiles = new MapTile[numTiles];
} }
public MapTile getTile(int x, int y){ public MapTile getTile(int x, int y) {
for (int i = 0; i < cnt; i++) for (int i = 0; i < cnt; i++)
if (tiles[i].tileX == x && tiles[i].tileY == y) if (tiles[i].tileX == x && tiles[i].tileY == y)
return tiles[i]; return tiles[i];
@ -47,6 +48,11 @@ public final class TileSet {
return null; return null;
} }
public void clear() {
Arrays.fill(tiles, null);
cnt = 0;
}
public static Comparator<MapTile> coordComparator = new CoordComparator(); public static Comparator<MapTile> coordComparator = new CoordComparator();
public static class CoordComparator implements Comparator<MapTile> { public static class CoordComparator implements Comparator<MapTile> {

View File

@ -104,7 +104,7 @@ public class MapTileLayer extends TileLayer<MapTileLoader> {
else else
MapView.enableClosePolygons = false; MapView.enableClosePolygons = false;
clearMap(); mMapView.clearMap();
resumeLoaders(); resumeLoaders();
@ -168,7 +168,7 @@ public class MapTileLayer extends TileLayer<MapTileLoader> {
mRenderTheme = internalRenderTheme.name(); mRenderTheme = internalRenderTheme.name();
} }
clearMap(); mMapView.clearMap();
return ret; return ret;
} }
@ -194,7 +194,7 @@ public class MapTileLayer extends TileLayer<MapTileLoader> {
mRenderTheme = renderThemePath; mRenderTheme = renderThemePath;
} }
clearMap(); mMapView.clearMap();
} }
private boolean setRenderTheme(Theme theme) { private boolean setRenderTheme(Theme theme) {

View File

@ -41,6 +41,7 @@ public class ExtrusionRenderLayer extends RenderLayer {
public ExtrusionRenderLayer(MapView mapView, org.oscim.layers.tile.TileRenderLayer tileRenderLayer) { public ExtrusionRenderLayer(MapView mapView, org.oscim.layers.tile.TileRenderLayer tileRenderLayer) {
super(mapView); super(mapView);
mTileLayer = tileRenderLayer; mTileLayer = tileRenderLayer;
mTileSet = new TileSet();
} }
private static int[] shaderProgram = new int[2]; private static int[] shaderProgram = new int[2];
@ -56,7 +57,7 @@ public class ExtrusionRenderLayer extends RenderLayer {
// FIXME sum up size used while filling layer only up to: // FIXME sum up size used while filling layer only up to:
//public int mBufferSize = 65536; //public int mBufferSize = 65536;
private TileSet mTileSet; private final TileSet mTileSet;
private MapTile[] mTiles; private MapTile[] mTiles;
private int mTileCnt; private int mTileCnt;
@ -85,18 +86,15 @@ public class ExtrusionRenderLayer extends RenderLayer {
} }
} }
int ready = 0;
mTileSet = mTileLayer.getVisibleTiles(mTileSet);
if (mTileSet == null)
return;
MapTile[] tiles = mTileSet.tiles;
// FIXME just release tiles in this case
if (mAlpha == 0 || pos.zoomLevel < 16) { if (mAlpha == 0 || pos.zoomLevel < 16) {
isReady = false; isReady = false;
return; return;
} }
int ready = 0;
mTileLayer.getVisibleTiles(mTileSet);
MapTile[] tiles = mTileSet.tiles;
// keep a list of tiles available for rendering // keep a list of tiles available for rendering
if (mTiles == null || mTiles.length < mTileSet.cnt * 4) if (mTiles == null || mTiles.length < mTileSet.cnt * 4)
mTiles = new MapTile[mTileSet.cnt * 4]; mTiles = new MapTile[mTileSet.cnt * 4];
@ -104,9 +102,6 @@ public class ExtrusionRenderLayer extends RenderLayer {
ExtrusionLayer el; ExtrusionLayer el;
if (pos.zoomLevel >= 17) { if (pos.zoomLevel >= 17) {
for (int i = 0; i < mTileSet.cnt; i++) { for (int i = 0; i < mTileSet.cnt; i++) {
if (!tiles[i].isVisible)
continue;
el = getLayer(tiles[i]); el = getLayer(tiles[i]);
if (el == null) if (el == null)
continue; continue;
@ -123,12 +118,9 @@ public class ExtrusionRenderLayer extends RenderLayer {
mTiles[ready++] = tiles[i]; mTiles[ready++] = tiles[i];
} }
} else if (pos.zoomLevel == 16) { } else if (pos.zoomLevel == 16) {
// check if proxy children are ready
for (int i = 0; i < mTileSet.cnt; i++) { for (int i = 0; i < mTileSet.cnt; i++) {
if (!tiles[i].isVisible)
continue;
MapTile t = tiles[i]; MapTile t = tiles[i];
for (byte j = 0; j < 4; j++) { for (byte j = 0; j < 4; j++) {
if ((t.proxies & (1 << j)) != 0) { if ((t.proxies & (1 << j)) != 0) {
MapTile c = t.rel.get(j); MapTile c = t.rel.get(j);

View File

@ -57,6 +57,7 @@ import org.oscim.view.MapViewPosition;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Log;
public class TextRenderLayer extends BasicRenderLayer { public class TextRenderLayer extends BasicRenderLayer {
private final static String TAG = TextRenderLayer.class.getName(); private final static String TAG = TextRenderLayer.class.getName();
@ -64,7 +65,7 @@ public class TextRenderLayer extends BasicRenderLayer {
private final static float MIN_WAY_DIST = 3; private final static float MIN_WAY_DIST = 3;
private final MapViewPosition mMapViewPosition; private final MapViewPosition mMapViewPosition;
private TileSet mTileSet; private final TileSet mTileSet;
private final LabelThread mThread; private final LabelThread mThread;
private MapPosition mTmpPos; private MapPosition mTmpPos;
@ -170,15 +171,18 @@ public class TextRenderLayer extends BasicRenderLayer {
@Override @Override
protected void doWork() { protected void doWork() {
SystemClock.sleep(250); SystemClock.sleep(250);
if (!mRun) if (!mRun)
return; return;
mRun = false; synchronized (this) {
if (updateLabels()) { if (updateLabels()) {
mMapView.render(); mRun = false;
} else { mMapView.render();
mRun = true; } else {
mRun = true;
}
} }
} }
@ -202,8 +206,10 @@ public class TextRenderLayer extends BasicRenderLayer {
mMapViewPosition = mapView.getMapViewPosition(); mMapViewPosition = mapView.getMapViewPosition();
mTileLayer = baseLayer; mTileLayer = baseLayer;
mTileSet = new TileSet();
layers.textureLayers = new TextLayer(); layers.textureLayers = new TextLayer();
mTmpLayer = new TextLayer(); mTmpLayer = new TextLayer();
//mActiveTiles = new HashMap<MapTile, LabelTile>(); //mActiveTiles = new HashMap<MapTile, LabelTile>();
mTmpPos = new MapPosition(); mTmpPos = new MapPosition();
mThread = new LabelThread(); mThread = new LabelThread();
@ -348,9 +354,7 @@ public class TextRenderLayer extends BasicRenderLayer {
return false; return false;
// get current tiles // get current tiles
mTileSet = mTileLayer.getVisibleTiles(mTileSet); mTileLayer.getVisibleTiles(mTileSet);
if (mTileSet == null)
return false;
if (mTileSet.cnt == 0) if (mTileSet.cnt == 0)
return false; return false;
@ -613,10 +617,10 @@ public class TextRenderLayer extends BasicRenderLayer {
mTileLayer.releaseTiles(mTileSet); mTileLayer.releaseTiles(mTileSet);
// pass new labels for rendering // pass new labels for rendering
synchronized (this) { //synchronized (this) {
mNextLayer = tl; mNextLayer = tl;
mDebugLayer = dbg; mDebugLayer = dbg;
} //}
return true; return true;
} }
@ -774,4 +778,14 @@ public class TextRenderLayer extends BasicRenderLayer {
// mRun = false; // mRun = false;
// } // }
} }
public void clearLabels() {
Log.d(TAG, "clearLabels");
synchronized (mThread) {
mRun = false;
mPool.releaseAll(mPrevLabels);
mPrevLabels = null;
mTileSet.clear();
}
}
} }

View File

@ -37,6 +37,22 @@ public abstract class Pool<T extends Inlist<T>> {
pool = item; pool = item;
} }
public void releaseAll(T item) {
if (item == null)
return;
while (item != null) {
T next = item.next;
clearItem(item);
item.next = pool;
pool = item;
item = next;
}
}
// remove 'item' from 'list' and add back to pool // remove 'item' from 'list' and add back to pool
public T release(T list, T item) { public T release(T list, T item) {
if (item == null) if (item == null)
@ -44,7 +60,6 @@ public abstract class Pool<T extends Inlist<T>> {
clearItem(item); clearItem(item);
if (item == list) { if (item == list) {
T ret = item.next; T ret = item.next;

View File

@ -95,6 +95,24 @@ public class LayerManager extends AbstractList<Layer> implements OnGestureListen
o.onDetach(); o.onDetach();
} }
public void onUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
if (mDirtyLayers)
updateLayers();
for (Layer l : mLayers)
l.onUpdate(mapPosition, changed, clear);
}
public void destroy() {
if (mDirtyLayers)
updateLayers();
for (Layer l : mLayers) {
l.destroy();
}
}
Layer[] mLayers; Layer[] mLayers;
InputLayer[] mInputLayer; InputLayer[] mInputLayer;
@ -371,22 +389,7 @@ public class LayerManager extends AbstractList<Layer> implements OnGestureListen
return false; return false;
} }
public void onUpdate(MapPosition mapPosition, boolean changed) {
if (mDirtyLayers)
updateLayers();
for (Layer l : mLayers)
l.onUpdate(mapPosition, changed);
}
public void destroy() {
if (mDirtyLayers)
updateLayers();
for (Layer l : mLayers) {
l.destroy();
}
}
// /** // /**
// * Gets the optional TilesLayer class. // * Gets the optional TilesLayer class.

View File

@ -66,6 +66,7 @@ public class MapView extends RelativeLayout {
private int mWidth; private int mWidth;
private int mHeight; private int mHeight;
private boolean mInitialized;
// FIXME: keep until old pbmap reader is removed // FIXME: keep until old pbmap reader is removed
public static boolean enableClosePolygons = false; public static boolean enableClosePolygons = false;
@ -133,6 +134,7 @@ public class MapView extends RelativeLayout {
addView(mGLView, params); addView(mGLView, params);
clearMap();
redrawMap(false); redrawMap(false);
} }
@ -147,7 +149,7 @@ public class MapView extends RelativeLayout {
mRotationEnabled = true; mRotationEnabled = true;
//mLayerManager.add(new GenericOverlay(this, new GridOverlay(this))); //mLayerManager.add(new GenericOverlay(this, new GridRenderLayer(this)));
mLayerManager.add(new BuildingOverlay(this, baseLayer.getTileLayer())); mLayerManager.add(new BuildingOverlay(this, baseLayer.getTileLayer()));
mLayerManager.add(new LabelingOverlay(this, baseLayer.getTileLayer())); mLayerManager.add(new LabelingOverlay(this, baseLayer.getTileLayer()));
@ -161,8 +163,6 @@ public class MapView extends RelativeLayout {
public MapTileLayer setBaseMap(BitmapTileLayer tileLayer) { public MapTileLayer setBaseMap(BitmapTileLayer tileLayer) {
mLayerManager.add(0, new MapEventLayer(this)); mLayerManager.add(0, new MapEventLayer(this));
mLayerManager.add(1, tileLayer); mLayerManager.add(1, tileLayer);
//mRotationEnabled = true;
return null; return null;
} }
@ -170,6 +170,11 @@ public class MapView extends RelativeLayout {
mLayerManager.destroy(); mLayerManager.destroy();
} }
public void onStop() {
Log.d(TAG, "onStop");
//mLayerManager.destroy();
}
private boolean mPausing = false; private boolean mPausing = false;
void onPause() { void onPause() {
@ -181,18 +186,12 @@ public class MapView extends RelativeLayout {
} }
void onResume() { void onResume() {
if (this.mCompassEnabled) if (this.mCompassEnabled)
mCompass.enable(); mCompass.enable();
mPausing = false; mPausing = false;
} }
public void onStop() {
Log.d(TAG, "onStop");
//mLayerManager.destroy();
}
@Override @Override
public boolean onTouchEvent(MotionEvent motionEvent) { public boolean onTouchEvent(MotionEvent motionEvent) {
@ -212,11 +211,13 @@ public class MapView extends RelativeLayout {
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
if (width != 0 && height != 0) mInitialized = (mWidth > 0 && mWidth > 0);
if (mInitialized)
mMapViewPosition.setViewport(width, height); mMapViewPosition.setViewport(width, height);
} }
boolean mWaitRedraw; /* private */boolean mWaitRedraw;
private final Runnable mRedrawRequest = new Runnable() { private final Runnable mRedrawRequest = new Runnable() {
@Override @Override
@ -229,49 +230,62 @@ public class MapView extends RelativeLayout {
/** /**
* Request to redraw the map when a global state like position, * Request to redraw the map when a global state like position,
* datasource or theme has changed. This will trigger a call * datasource or theme has changed. This will trigger a call
* to onUpdate() to all Layers. * to onUpdate() for all Layers.
* *
* @param requestRender * @param requestRender
* also request to draw a frame * also request to draw a frame
*/ */
public void redrawMap(boolean requestRender) { public void redrawMap(boolean requestRender) {
if (requestRender) { if (requestRender && !mClearMap && !mPausing && mInitialized)
if (!(mPausing || mWidth == 0 || mHeight == 0)) mGLView.requestRender();
mGLView.requestRender();
}
if (!mWaitRedraw) { if (!mWaitRedraw) {
mWaitRedraw = true; mWaitRedraw = true;
post(mRedrawRequest); post(mRedrawRequest);
} }
} }
private boolean mClearMap;
public void clearMap(){
mClearMap = true;
}
/** /**
* Request to render a frame. Use this for animations. * Request to render a frame. Use this for animations.
*/ */
public void render() { public void render() {
mGLView.requestRender(); if (mClearMap)
redrawMap(false);
else
mGLView.requestRender();
} }
/** /**
* Calculates all necessary tiles and adds jobs accordingly. * Update all Layers on Main thread.
* *
* @param forceRedraw TODO * @param forceRedraw also render frame
* FIXME (does nothing atm)
*/ */
void redrawMapInternal(boolean forceRedraw) { void redrawMapInternal(boolean forceRedraw) {
boolean changed = false; boolean changed = forceRedraw;
if (mPausing || mWidth == 0 || mHeight == 0) if (mPausing || !mInitialized)
return; return;
if (forceRedraw) { if (forceRedraw && !mClearMap)
mGLView.requestRender(); mGLView.requestRender();
changed = true;
}
// get the current MapPosition // get the current MapPosition
changed |= mMapViewPosition.getMapPosition(mMapPosition); changed |= mMapViewPosition.getMapPosition(mMapPosition);
mLayerManager.onUpdate(mMapPosition, changed); mLayerManager.onUpdate(mMapPosition, changed, mClearMap);
// delay redraw until all layers had the chance to clear
// their state.
if (mClearMap){
mGLView.requestRender();
mClearMap =false;
}
} }
/** /**