From 676b994f2da607fda71d4f9a25998ae508fed860 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Tue, 23 Apr 2013 01:13:21 +0200 Subject: [PATCH] refactoring of TileLayer, some more --- src/org/oscim/core/MapElement.java | 4 +- src/org/oscim/database/IMapDatabase.java | 14 +- .../oscim/database/IMapDatabaseCallback.java | 2 +- src/org/oscim/layers/tile/ITileGenerator.java | 26 -- src/org/oscim/layers/tile/MapTile.java | 6 +- src/org/oscim/layers/tile/MapTileLayer.java | 231 +++++++++++++++ ...{TileGenerator.java => MapTileLoader.java} | 18 +- src/org/oscim/layers/tile/TestTileLayer.java | 79 ++++++ .../oscim/layers/tile/TileDistanceSort.java | 15 +- .../layers/tile/TileGeneratorExample.java | 54 ---- src/org/oscim/layers/tile/TileLayer.java | 267 +++--------------- .../tile/{MapWorker.java => TileLoader.java} | 40 +-- src/org/oscim/layers/tile/TileManager.java | 14 +- .../oscim/renderer/layer/LineRenderer.java | 4 +- src/org/oscim/view/MapView.java | 13 +- 15 files changed, 409 insertions(+), 378 deletions(-) delete mode 100644 src/org/oscim/layers/tile/ITileGenerator.java create mode 100644 src/org/oscim/layers/tile/MapTileLayer.java rename src/org/oscim/layers/tile/{TileGenerator.java => MapTileLoader.java} (95%) create mode 100644 src/org/oscim/layers/tile/TestTileLayer.java delete mode 100644 src/org/oscim/layers/tile/TileGeneratorExample.java rename src/org/oscim/layers/tile/{MapWorker.java => TileLoader.java} (75%) diff --git a/src/org/oscim/core/MapElement.java b/src/org/oscim/core/MapElement.java index 7a726120..56494ec9 100644 --- a/src/org/oscim/core/MapElement.java +++ b/src/org/oscim/core/MapElement.java @@ -15,8 +15,8 @@ package org.oscim.core; /** - * MapElement is created by MapDatabase(s) and passed to TileGenerator - * via IMapDatabaseCallback.renderElement() TileGenerator processes the + * MapElement is created by MapDatabase(s) and passed to MapTileLoader + * via IMapDatabaseCallback.renderElement() MapTileLoader processes the * data into MapTile.layers. * ----- * This is really just a buffer object that belongs to MapDatabase, so diff --git a/src/org/oscim/database/IMapDatabase.java b/src/org/oscim/database/IMapDatabase.java index d5e44b3d..ee1664ff 100644 --- a/src/org/oscim/database/IMapDatabase.java +++ b/src/org/oscim/database/IMapDatabase.java @@ -32,7 +32,7 @@ public interface IMapDatabase { * the callback which handles the extracted map elements. * @return true if successful */ - public abstract QueryResult executeQuery(MapTile tile, + abstract QueryResult executeQuery(MapTile tile, IMapDatabaseCallback mapDatabaseCallback); /** @@ -40,12 +40,12 @@ public interface IMapDatabase { * @throws IllegalStateException * if no map is currently opened. */ - public abstract MapInfo getMapInfo(); + abstract MapInfo getMapInfo(); /** * @return true if a map database is currently opened, false otherwise. */ - public abstract boolean isOpen(); + abstract boolean isOpen(); /** * Opens MapDatabase @@ -54,21 +54,21 @@ public interface IMapDatabase { * the options. * @return a OpenResult containing an error message in case of a failure. */ - public abstract OpenResult open(MapOptions options); + abstract OpenResult open(MapOptions options); /** * Closes the map file and destroys all internal caches. Has no effect if no * map file is currently opened. Should also force to close Socket so that * thread cannot hang in socket.read */ - public abstract void close(); + abstract void close(); - public abstract String getMapProjection(); + abstract String getMapProjection(); /** * Cancel loading */ - public abstract void cancel(); + abstract void cancel(); public static enum QueryResult { SUCCESS, diff --git a/src/org/oscim/database/IMapDatabaseCallback.java b/src/org/oscim/database/IMapDatabaseCallback.java index baa46032..4f0b879b 100644 --- a/src/org/oscim/database/IMapDatabaseCallback.java +++ b/src/org/oscim/database/IMapDatabaseCallback.java @@ -18,7 +18,7 @@ import org.oscim.core.MapElement; /** - * MapDatabase callbacks (implemented by TileGenerator) + * MapDatabase callbacks (implemented by MapTileLoader) * ____ * NOTE: All parameters passed belong to the caller! i.e. dont hold * references to any arrays after callback function returns. diff --git a/src/org/oscim/layers/tile/ITileGenerator.java b/src/org/oscim/layers/tile/ITileGenerator.java deleted file mode 100644 index 2f273a72..00000000 --- a/src/org/oscim/layers/tile/ITileGenerator.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2013 Hannes Janetzek - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.layers.tile; - -public interface ITileGenerator { - - /** - * Load data for 'tile' and file tile.layers for rendering. - * (executed on MapWorker threads) - */ - public abstract boolean executeJob(MapTile tile); - - public abstract void cleanup(); -} diff --git a/src/org/oscim/layers/tile/MapTile.java b/src/org/oscim/layers/tile/MapTile.java index 6a606d7a..1bc85d1d 100644 --- a/src/org/oscim/layers/tile/MapTile.java +++ b/src/org/oscim/layers/tile/MapTile.java @@ -21,7 +21,7 @@ import org.oscim.utils.quadtree.QuadTree; /** * Extends Tile class to hold state and data for concurrent use in - * TileManager (Main Thread), TileGenerator (MapWorker Thread) and + * TileManager (Main Thread), TileLoader (Worker Threads) and * Rendering (GL Thread). */ public final class MapTile extends Tile { @@ -30,7 +30,7 @@ public final class MapTile extends Tile { /** * STATE_LOADING means the tile is about to be loaded / loading. - * it belongs to MapWorker/TileGenerator thread. + * it belongs to TileLoader thread. */ public final static int STATE_LOADING = 1 << 0; @@ -66,7 +66,7 @@ public final class MapTile extends Tile { public float distance; /** - * Tile data set by TileGenerator. + * Tile data set by TileLoader. */ public TextItem labels; public Layers layers; diff --git a/src/org/oscim/layers/tile/MapTileLayer.java b/src/org/oscim/layers/tile/MapTileLayer.java new file mode 100644 index 00000000..6fd115f3 --- /dev/null +++ b/src/org/oscim/layers/tile/MapTileLayer.java @@ -0,0 +1,231 @@ +/* + * Copyright 2013 Hannes Janetzek + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.layers.tile; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; + +import org.oscim.core.GeoPoint; +import org.oscim.core.MapPosition; +import org.oscim.database.IMapDatabase; +import org.oscim.database.IMapDatabase.OpenResult; +import org.oscim.database.MapDatabaseFactory; +import org.oscim.database.MapDatabases; +import org.oscim.database.MapInfo; +import org.oscim.database.MapOptions; +import org.oscim.renderer.GLRenderer; +import org.oscim.theme.ExternalRenderTheme; +import org.oscim.theme.IRenderTheme; +import org.oscim.theme.InternalRenderTheme; +import org.oscim.theme.RenderThemeHandler; +import org.oscim.theme.Theme; +import org.oscim.view.MapView; +import org.xml.sax.SAXException; + +import android.util.Log; + +public class MapTileLayer extends TileLayer { + private final static String TAG = MapTileLayer.class.getName(); + + public MapTileLayer(MapView mapView) { + super(mapView, new TileLoader.Factory(){ + @Override + public MapTileLoader create(JobQueue q, TileManager tm) { + return new MapTileLoader(q, tm); + }}); + } + + private MapOptions mMapOptions; + private IMapDatabase mMapDatabase; + private String mRenderTheme; + + /** + * Sets the MapDatabase for this MapView. + * + * @param options + * the new MapDatabase options. + * @return true if MapDatabase changed + */ + public boolean setMapDatabase(MapOptions options) { + Log.i(TAG, "setMapDatabase: " + options.db.name()); + + if (mMapOptions != null && mMapOptions.equals(options)) + return true; + + pauseLoaders(true); + + mJobQueue.clear(); + mMapOptions = options; + + mMapDatabase = null; + + for (int i = 0; i < mNumTileLoader; i++) { + IMapDatabase mapDatabase = MapDatabaseFactory + .createMapDatabase(options.db); + + OpenResult result = mapDatabase.open(options); + + if (result != OpenResult.SUCCESS) { + Log.d(TAG, "failed open db: " + result.getErrorMessage()); + } + + mTileLoader.get(i).setMapDatabase(mapDatabase); + + // TODO this could be done in a cleaner way.. + if (mMapDatabase == null) + mMapDatabase = mapDatabase; + } + + if (options.db == MapDatabases.OSCIMAP_READER || + options.db == MapDatabases.MAP_READER || + options.db == MapDatabases.TEST_READER) + MapView.enableClosePolygons = true; + else + MapView.enableClosePolygons = false; + + clearMap(); + + resumeLoaders(); + + return true; + } + + public Map getMapOptions() { + return mMapOptions; + } + + public MapPosition getMapFileCenter() { + if (mMapDatabase == null) + return null; + + MapInfo mapInfo = mMapDatabase.getMapInfo(); + if (mapInfo == null) + return null; + + GeoPoint startPos = mapInfo.startPosition; + + if (startPos == null) + startPos = mapInfo.mapCenter; + + if (startPos == null) + startPos = new GeoPoint(0, 0); + + MapPosition mapPosition = new MapPosition(); + mapPosition.setPosition(startPos); + + if (mapInfo.startZoomLevel == null) + mapPosition.setZoomLevel(12); + else + mapPosition.setZoomLevel((mapInfo.startZoomLevel).byteValue()); + + return mapPosition; + } + + public String getRenderTheme() { + return mRenderTheme; + } + + /** + * Sets the internal theme which is used for rendering the map. + * + * @param internalRenderTheme + * the internal rendering theme. + * @return ... + * @throws IllegalArgumentException + * if the supplied internalRenderTheme is null. + */ + public boolean setRenderTheme(InternalRenderTheme internalRenderTheme) { + if (internalRenderTheme == null) { + throw new IllegalArgumentException("render theme must not be null"); + } + + if (internalRenderTheme.name() == mRenderTheme) + return true; + + boolean ret = setRenderTheme((Theme) internalRenderTheme); + if (ret) { + mRenderTheme = internalRenderTheme.name(); + } + + clearMap(); + + return ret; + } + + /** + * Sets the theme file which is used for rendering the map. + * + * @param renderThemePath + * the path to the XML file which defines the rendering theme. + * @throws IllegalArgumentException + * if the supplied internalRenderTheme is null. + * @throws FileNotFoundException + * if the supplied file does not exist, is a directory or cannot + * be read. + */ + public void setRenderTheme(String renderThemePath) throws FileNotFoundException { + if (renderThemePath == null) { + throw new IllegalArgumentException("render theme path must not be null"); + } + + boolean ret = setRenderTheme(new ExternalRenderTheme(renderThemePath)); + if (ret) { + mRenderTheme = renderThemePath; + } + + clearMap(); + } + + private boolean setRenderTheme(Theme theme) { + + pauseLoaders(true); + + InputStream inputStream = null; + try { + inputStream = theme.getRenderThemeAsStream(); + IRenderTheme t = RenderThemeHandler.getRenderTheme(inputStream); + t.scaleTextSize(1 + (MapView.dpi / 240 - 1) * 0.5f); + + // FIXME !!! + GLRenderer.setRenderTheme(t); + + for (MapTileLoader g : mTileLoader) + g.setRenderTheme(t); + + return true; + } catch (ParserConfigurationException e) { + Log.e(TAG, e.getMessage()); + } catch (SAXException e) { + Log.e(TAG, e.getMessage()); + } catch (IOException e) { + Log.e(TAG, e.getMessage()); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + Log.e(TAG, e.getMessage()); + } + resumeLoaders(); + } + return false; + } + +} diff --git a/src/org/oscim/layers/tile/TileGenerator.java b/src/org/oscim/layers/tile/MapTileLoader.java similarity index 95% rename from src/org/oscim/layers/tile/TileGenerator.java rename to src/org/oscim/layers/tile/MapTileLoader.java index bd942a8a..3846f297 100644 --- a/src/org/oscim/layers/tile/TileGenerator.java +++ b/src/org/oscim/layers/tile/MapTileLoader.java @@ -50,17 +50,17 @@ import android.util.Log; /** * @note - * 1. The MapWorkers call TileGenerator.execute() to load a tile. + * 1. The MapWorkers call MapTileLoader.execute() to load a tile. * 2. The tile data will be loaded from current MapDatabase * 3. MapDatabase calls the IMapDatabaseCallback functions - * implemented by TileGenerator for WAY and POI items. + * implemented by MapTileLoader for WAY and POI items. * 4. these callbacks then call RenderTheme to get the matching style. * 5. RenderTheme calls IRenderCallback functions with style information * 6. Styled items become added to MapTile.layers... roughly */ -public class TileGenerator extends MapWorker implements IRenderCallback, IMapDatabaseCallback, ITileGenerator { +public class MapTileLoader extends TileLoader implements IRenderCallback, IMapDatabaseCallback { - private static final String TAG = TileGenerator.class.getName(); + private static final String TAG = MapTileLoader.class.getName(); private static final double STROKE_INCREASE = Math.sqrt(2.2); private static final byte LAYERS = 11; @@ -83,7 +83,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat private IRenderTheme renderTheme; private int renderLevels; - // current MapDatabase used by this TileGenerator + // current MapDatabase used by this MapTileLoader private IMapDatabase mMapDatabase; // currently processed tile @@ -117,8 +117,8 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat /** */ - public TileGenerator(int id, JobQueue jobQueue, TileManager tileManager) { - super(id, jobQueue, tileManager); + public MapTileLoader(JobQueue jobQueue, TileManager tileManager) { + super(jobQueue, tileManager); mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE, true); @@ -140,7 +140,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat } /* (non-Javadoc) - * @see org.oscim.layers.tile.ITileGenerator#cleanup() + * @see org.oscim.layers.tile.TileLoader#cleanup() */ @Override public void cleanup() { @@ -148,7 +148,7 @@ public class TileGenerator extends MapWorker implements IRenderCallback, IMapDat } /* (non-Javadoc) - * @see org.oscim.layers.tile.ITileGenerator#executeJob(org.oscim.layers.tile.MapTile) + * @see org.oscim.layers.tile.TileLoader#executeJob(org.oscim.layers.tile.MapTile) */ @Override public boolean executeJob(MapTile mapTile) { diff --git a/src/org/oscim/layers/tile/TestTileLayer.java b/src/org/oscim/layers/tile/TestTileLayer.java new file mode 100644 index 00000000..6d9904b9 --- /dev/null +++ b/src/org/oscim/layers/tile/TestTileLayer.java @@ -0,0 +1,79 @@ +/* + * Copyright 2013 Hannes Janetzek + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.layers.tile; + +import org.oscim.core.GeometryBuffer; +import org.oscim.core.Tile; +import org.oscim.graphics.Color; +import org.oscim.graphics.Paint.Cap; +import org.oscim.layers.tile.TestTileLayer.TestTileLoader; +import org.oscim.renderer.layer.Layers; +import org.oscim.renderer.layer.LineLayer; +import org.oscim.theme.renderinstruction.Line; +import org.oscim.view.MapView; + +import android.util.Log; + +public class TestTileLayer extends TileLayer { + final static String TAG = TestTileLayer.class.getName(); + + public TestTileLayer(MapView mapView) { + // create an TileLayer instance using TestTileLoader as TileLoader + super(mapView, new TileLoader.Factory(){ + @Override + public TestTileLoader create(JobQueue q, TileManager tm) { + return new TestTileLoader(q, tm); + }}); + } + + static class TestTileLoader extends TileLoader { + public TestTileLoader(JobQueue jobQueue, TileManager tileManager) { + super(jobQueue, tileManager); + } + + GeometryBuffer mGeom = new GeometryBuffer(128, 16); + Line mLineStyle = new Line(Color.BLUE, 2f, Cap.ROUND); + + @Override + public boolean executeJob(MapTile tile) { + Log.d(TAG, "load tile " + tile); + tile.layers = new Layers(); + + LineLayer ll = tile.layers.getLineLayer(0); + ll.line = mLineStyle; + ll.width = 2; + + int m = 20; + int s = Tile.SIZE - m * 2; + GeometryBuffer g = mGeom; + + g.clear(); + g.startLine(); + g.addPoint(m, m); + g.addPoint(m, s); + g.addPoint(s, s); + g.addPoint(s, m); + g.addPoint(m, m); + + ll.addLine(g); + + return true; + } + + @Override + public void cleanup() { + } + } +} diff --git a/src/org/oscim/layers/tile/TileDistanceSort.java b/src/org/oscim/layers/tile/TileDistanceSort.java index b0f75563..18282b8d 100644 --- a/src/org/oscim/layers/tile/TileDistanceSort.java +++ b/src/org/oscim/layers/tile/TileDistanceSort.java @@ -51,13 +51,11 @@ public class TileDistanceSort { return 0; } - private static void binarySort(MapTile[] a, int lo, int hi, int start) - { + private static void binarySort(MapTile[] a, int lo, int hi, int start) { assert ((lo <= start) && (start <= hi)); if (start == lo) ++start; - for (; start < hi; ++start) - { + for (; start < hi; ++start) { MapTile pivot = a[start]; int left = lo; @@ -98,8 +96,7 @@ public class TileDistanceSort { } } - private static int countRunAndMakeAscending(MapTile[] a, int lo, int hi) - { + private static int countRunAndMakeAscending(MapTile[] a, int lo, int hi) { assert (lo < hi); int runHi = lo + 1; if (runHi == hi) { @@ -118,8 +115,7 @@ public class TileDistanceSort { return (runHi - lo); } - private static void reverseRange(MapTile[] a, int lo, int hi) - { + private static void reverseRange(MapTile[] a, int lo, int hi) { --hi; while (lo < hi) { MapTile t = a[lo]; @@ -127,4 +123,7 @@ public class TileDistanceSort { a[(hi--)] = t; } } + + private TileDistanceSort() { + } } diff --git a/src/org/oscim/layers/tile/TileGeneratorExample.java b/src/org/oscim/layers/tile/TileGeneratorExample.java deleted file mode 100644 index 5827665b..00000000 --- a/src/org/oscim/layers/tile/TileGeneratorExample.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2013 Hannes Janetzek - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.layers.tile; - -import org.oscim.core.GeometryBuffer; -import org.oscim.core.Tile; -import org.oscim.graphics.Color; -import org.oscim.graphics.Paint.Cap; -import org.oscim.renderer.layer.LineLayer; -import org.oscim.theme.renderinstruction.Line; - - -public class TileGeneratorExample implements ITileGenerator { - GeometryBuffer mGeom = new GeometryBuffer(128, 16); - Line mLineStyle = new Line(Color.BLUE, 2f, Cap.ROUND); - - @Override - public boolean executeJob(MapTile tile) { - LineLayer ll = tile.layers.getLineLayer(0); - ll.line = mLineStyle; - ll.width = 2; - - int m = 20; - int s = Tile.SIZE - m * 2; - GeometryBuffer g = mGeom; - - g.clear(); - g.startPolygon(); - g.addPoint(m, m); - g.addPoint(m, s); - g.addPoint(s, s); - g.addPoint(s, m); - - ll.addLine(g); - - return true; - } - - @Override - public void cleanup() { - } -} diff --git a/src/org/oscim/layers/tile/TileLayer.java b/src/org/oscim/layers/tile/TileLayer.java index 4a8ad059..9e89cb05 100644 --- a/src/org/oscim/layers/tile/TileLayer.java +++ b/src/org/oscim/layers/tile/TileLayer.java @@ -14,58 +14,43 @@ */ package org.oscim.layers.tile; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; +import java.util.ArrayList; -import javax.xml.parsers.ParserConfigurationException; - -import org.oscim.core.GeoPoint; import org.oscim.core.MapPosition; -import org.oscim.database.IMapDatabase; -import org.oscim.database.IMapDatabase.OpenResult; -import org.oscim.database.MapDatabaseFactory; -import org.oscim.database.MapDatabases; -import org.oscim.database.MapInfo; -import org.oscim.database.MapOptions; import org.oscim.layers.Layer; -import org.oscim.renderer.GLRenderer; -import org.oscim.theme.ExternalRenderTheme; -import org.oscim.theme.IRenderTheme; -import org.oscim.theme.InternalRenderTheme; -import org.oscim.theme.RenderThemeHandler; -import org.oscim.theme.Theme; import org.oscim.view.MapView; -import org.xml.sax.SAXException; -import android.util.Log; - -public class TileLayer extends Layer { - private final static String TAG = TileLayer.class.getName(); +public class TileLayer extends Layer { + //private final static String TAG = TileLayer.class.getName(); private boolean mClearMap = true; - private final TileManager mTileManager; + protected final TileManager mTileManager; - private final JobQueue mJobQueue; + protected final JobQueue mJobQueue; - private final int mNumTileWorker = 4; - private final TileGenerator mTileWorker[]; + protected final int mNumTileLoader = 4; + protected final ArrayList mTileLoader; - public TileLayer(MapView mapView) { + public TileLayer(MapView mapView, TileLoader.Factory factory) { super(mapView); + + // TileManager responsible for adding visible tiles + // to load queue and managing in-memory tile cache. mTileManager = new TileManager(mapView, this); + mJobQueue = new JobQueue(); - mTileWorker = new TileGenerator[mNumTileWorker]; - TileGenerator.setDebugSettings(mapView.getDebugSettings()); - - for (int i = 0; i < mNumTileWorker; i++) { - mTileWorker[i] = new TileGenerator(i, mJobQueue, mTileManager); - mTileWorker[i].start(); + // Instantiate TileLoader threads + mTileLoader = new ArrayList(); + for (int i = 0; i < mNumTileLoader; i++) { + T tileGenerator = factory.create(mJobQueue, mTileManager); + mTileLoader.add(tileGenerator); + tileGenerator.start(); } + // RenderLayer is working in GL Thread and actually + // drawing loaded tiles to screen. mLayer = new TileRenderLayer(mapView, mTileManager); } @@ -80,7 +65,6 @@ public class TileLayer extends Layer { mTileManager.init(mMapView.getWidth(), mMapView.getHeight()); mClearMap = false; changed = true; - Log.d(TAG, "init TileManager ----- "); } if (changed) mTileManager.update(mapPosition); @@ -91,7 +75,7 @@ public class TileLayer extends Layer { mTileManager.destroy(); - for (TileGenerator tileWorker : mTileWorker) { + for (T tileWorker : mTileLoader) { tileWorker.pause(); tileWorker.interrupt(); @@ -107,192 +91,11 @@ public class TileLayer extends Layer { } } - private void clearMap() { + protected void clearMap() { // clear tile and overlay data before next draw mClearMap = true; } - private MapOptions mMapOptions; - private IMapDatabase mMapDatabase; - private String mRenderTheme; - - /** - * Sets the MapDatabase for this MapView. - * - * @param options - * the new MapDatabase options. - * @return true if MapDatabase changed - */ - public boolean setMapDatabase(MapOptions options) { - Log.i(TAG, "setMapDatabase: " + options.db.name()); - - if (mMapOptions != null && mMapOptions.equals(options)) - return true; - - tileWorkersPause(true); - - mJobQueue.clear(); - mMapOptions = options; - - mMapDatabase = null; - - for (int i = 0; i < mNumTileWorker; i++) { - //TileGenerator tileWorker = mTileWorker[i]; - - IMapDatabase mapDatabase = MapDatabaseFactory - .createMapDatabase(options.db); - - OpenResult result = mapDatabase.open(options); - - if (result != OpenResult.SUCCESS) { - Log.d(TAG, "failed open db: " + result.getErrorMessage()); - } - - mTileWorker[i].setMapDatabase(mapDatabase); - - //TileGenerator tileGenerator = tileWorker.getTileGenerator(); - //tileGenerator.setMapDatabase(mapDatabase); - - // TODO this could be done in a cleaner way.. - if (mMapDatabase == null) - mMapDatabase = mapDatabase; - } - - if (options.db == MapDatabases.OSCIMAP_READER || - options.db == MapDatabases.MAP_READER || - options.db == MapDatabases.TEST_READER) - MapView.enableClosePolygons = true; - else - MapView.enableClosePolygons = false; - - clearMap(); - - tileWorkersProceed(); - - return true; - } - - public Map getMapOptions() { - return mMapOptions; - } - - public MapPosition getMapFileCenter() { - if (mMapDatabase == null) - return null; - - MapInfo mapInfo = mMapDatabase.getMapInfo(); - if (mapInfo == null) - return null; - - GeoPoint startPos = mapInfo.startPosition; - - if (startPos == null) - startPos = mapInfo.mapCenter; - - if (startPos == null) - startPos = new GeoPoint(0, 0); - - MapPosition mapPosition = new MapPosition(); - mapPosition.setPosition(startPos); - - if (mapInfo.startZoomLevel == null) - mapPosition.setZoomLevel(12); - else - mapPosition.setZoomLevel((mapInfo.startZoomLevel).byteValue()); - - return mapPosition; - } - - public String getRenderTheme() { - return mRenderTheme; - } - - /** - * Sets the internal theme which is used for rendering the map. - * - * @param internalRenderTheme - * the internal rendering theme. - * @return ... - * @throws IllegalArgumentException - * if the supplied internalRenderTheme is null. - */ - public boolean setRenderTheme(InternalRenderTheme internalRenderTheme) { - if (internalRenderTheme == null) { - throw new IllegalArgumentException("render theme must not be null"); - } - - if (internalRenderTheme.name() == mRenderTheme) - return true; - - boolean ret = setRenderTheme((Theme) internalRenderTheme); - if (ret) { - mRenderTheme = internalRenderTheme.name(); - } - - clearMap(); - - return ret; - } - - /** - * Sets the theme file which is used for rendering the map. - * - * @param renderThemePath - * the path to the XML file which defines the rendering theme. - * @throws IllegalArgumentException - * if the supplied internalRenderTheme is null. - * @throws FileNotFoundException - * if the supplied file does not exist, is a directory or cannot - * be read. - */ - public void setRenderTheme(String renderThemePath) throws FileNotFoundException { - if (renderThemePath == null) { - throw new IllegalArgumentException("render theme path must not be null"); - } - - boolean ret = setRenderTheme(new ExternalRenderTheme(renderThemePath)); - if (ret) { - mRenderTheme = renderThemePath; - } - - clearMap(); - } - - private boolean setRenderTheme(Theme theme) { - - tileWorkersPause(true); - - InputStream inputStream = null; - try { - inputStream = theme.getRenderThemeAsStream(); - IRenderTheme t = RenderThemeHandler.getRenderTheme(inputStream); - t.scaleTextSize(1 + (MapView.dpi / 240 - 1) * 0.5f); - - // FIXME !!! - GLRenderer.setRenderTheme(t); - - for (TileGenerator g : mTileWorker) - g.setRenderTheme(t); - - return true; - } catch (ParserConfigurationException e) { - Log.e(TAG, e.getMessage()); - } catch (SAXException e) { - Log.e(TAG, e.getMessage()); - } catch (IOException e) { - Log.e(TAG, e.getMessage()); - } finally { - try { - if (inputStream != null) { - inputStream.close(); - } - } catch (IOException e) { - Log.e(TAG, e.getMessage()); - } - tileWorkersProceed(); - } - return false; - } /** * add jobs and remember TileGenerators that stuff needs to be done @@ -300,36 +103,36 @@ public class TileLayer extends Layer { * @param jobs * tile jobs */ - public void addJobs(MapTile[] jobs) { + public void setJobs(MapTile[] jobs) { if (jobs == null) { mJobQueue.clear(); return; } mJobQueue.setJobs(jobs); - for (int i = 0; i < mNumTileWorker; i++) { - TileGenerator m = mTileWorker[i]; + for (int i = 0; i < mNumTileLoader; i++) { + T m = mTileLoader.get(i); synchronized (m) { m.notify(); } } } - private void tileWorkersPause(boolean wait) { - for (TileGenerator tileWorker : mTileWorker) { - if (!tileWorker.isPausing()) - tileWorker.pause(); + protected void pauseLoaders(boolean wait) { + for (T loader : mTileLoader) { + if (!loader.isPausing()) + loader.pause(); } if (wait) { - for (TileGenerator tileWorker : mTileWorker) { - if (!tileWorker.isPausing()) - tileWorker.awaitPausing(); + for (T loader : mTileLoader) { + if (!loader.isPausing()) + loader.awaitPausing(); } } } - private void tileWorkersProceed() { - for (TileGenerator tileWorker : mTileWorker) - tileWorker.proceed(); + protected void resumeLoaders() { + for (T loader : mTileLoader) + loader.proceed(); } } diff --git a/src/org/oscim/layers/tile/MapWorker.java b/src/org/oscim/layers/tile/TileLoader.java similarity index 75% rename from src/org/oscim/layers/tile/MapWorker.java rename to src/org/oscim/layers/tile/TileLoader.java index 7a459e76..667df3da 100644 --- a/src/org/oscim/layers/tile/MapWorker.java +++ b/src/org/oscim/layers/tile/TileLoader.java @@ -1,6 +1,5 @@ /* - * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2013 Hannes Hannes Janetzek + * Copyright 2013 Hannes Janetzek * * This program is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free Software @@ -17,32 +16,34 @@ package org.oscim.layers.tile; import org.oscim.utils.PausableThread; -/** - * A MapWorker uses a {@link TileGenerator} to generate map tiles. It runs in a - * separate thread to avoid blocking the UI thread. - */ -public abstract class MapWorker extends PausableThread { +public abstract class TileLoader extends PausableThread { + private static int id; + + public interface Factory{ + T create(JobQueue jobQueue, TileManager tileManager); + } + private final String THREAD_NAME; private final JobQueue mJobQueue; private final TileManager mTileManager; - /** - * @param id - * thread id - * @param jobQueue - * ... - * @param tileManager - * ... - */ - public MapWorker(int id, JobQueue jobQueue, TileManager tileManager) { - + public TileLoader(JobQueue jobQueue, TileManager tileManager) { super(); mJobQueue = jobQueue; mTileManager = tileManager; - - THREAD_NAME = "MapWorker" + id; + THREAD_NAME = "TileLoader" + (id++); } + public abstract void cleanup(); + + /** + * Load data for 'tile' and file tile.layers for rendering. + * (executed on MapWorker threads) + */ + + protected abstract boolean executeJob(MapTile tile); + + @Override protected void doWork() { MapTile tile = mJobQueue.poll(); @@ -63,7 +64,6 @@ public abstract class MapWorker extends PausableThread { } } - protected abstract boolean executeJob(MapTile tile); @Override protected String getThreadName() { diff --git a/src/org/oscim/layers/tile/TileManager.java b/src/org/oscim/layers/tile/TileManager.java index 1337bfad..0f165163 100644 --- a/src/org/oscim/layers/tile/TileManager.java +++ b/src/org/oscim/layers/tile/TileManager.java @@ -114,9 +114,9 @@ public class TileManager { }; private final float[] mBoxCoords = new float[8]; - private final TileLayer mTileLayer; + private final TileLayer mTileLayer; - public TileManager(MapView mapView, TileLayer tileLayer) { + public TileManager(MapView mapView, TileLayer tileLayer) { mMapView = mapView; mTileLayer = tileLayer; @@ -197,7 +197,7 @@ public class TileManager { // start with old jobs while new jobs are calculated, which // should increase the chance that they are free when new // jobs come in. - mTileLayer.addJobs(null); + mTileLayer.setJobs(null); // load some tiles more than currently visible (* 0.75) double scale = pos.scale * 0.9f; @@ -260,7 +260,7 @@ public class TileManager { updateTileDistances(jobs, jobs.length, pos); // sets tiles to state == LOADING - mTileLayer.addJobs(jobs); + mTileLayer.setJobs(jobs); mJobs.clear(); /* limit cache items */ @@ -527,7 +527,7 @@ public class TileManager { } else if (t.state == STATE_LOADING) { // NOTE: when set loading to false the tile could be // added to load queue again while still processed in - // TileGenerator => need tile.cancel flag. + // MapTileLoader => need tile.cancel flag. // t.isLoading = false; Log.d(TAG, "limitCache: cancel loading " + t + " " + t.distance); } else { @@ -560,7 +560,7 @@ public class TileManager { } /** - * called from MapWorker Thread when tile is loaded by TileGenerator + * called from MapWorker Thread when tile is loaded by MapTileLoader * * @param tile * Tile ready for upload to GL @@ -570,7 +570,7 @@ public class TileManager { if (tile.state != STATE_LOADING) { // - should rather be STATE_FAILED - // no one should be able to use this tile now, TileGenerator passed + // no one should be able to use this tile now, MapTileLoader passed // it, GL-Thread does nothing until newdata is set. //Log.d(TAG, "passTile: failed loading " + tile); return true; diff --git a/src/org/oscim/renderer/layer/LineRenderer.java b/src/org/oscim/renderer/layer/LineRenderer.java index e33a9990..813286b5 100644 --- a/src/org/oscim/renderer/layer/LineRenderer.java +++ b/src/org/oscim/renderer/layer/LineRenderer.java @@ -24,8 +24,8 @@ import static android.opengl.GLES20.glVertexAttribPointer; import org.oscim.core.MapPosition; import org.oscim.renderer.GLRenderer; -import org.oscim.renderer.GLState; import org.oscim.renderer.GLRenderer.Matrices; +import org.oscim.renderer.GLState; import org.oscim.theme.renderinstruction.Line; import org.oscim.utils.GlUtils; @@ -153,8 +153,6 @@ public final class LineRenderer { glUniform1f(uLineMode, lineMode); boolean blur = false; - // dont increase scale when max is reached - //boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL; Layer l = curLayer; for (; l != null && l.type == Layer.LINE; l = l.next) { diff --git a/src/org/oscim/view/MapView.java b/src/org/oscim/view/MapView.java index 7daf0711..141eafac 100644 --- a/src/org/oscim/view/MapView.java +++ b/src/org/oscim/view/MapView.java @@ -23,8 +23,8 @@ import org.oscim.core.MapPosition; import org.oscim.core.Tile; import org.oscim.database.MapOptions; import org.oscim.layers.Layer; -import org.oscim.layers.tile.TileGenerator; -import org.oscim.layers.tile.TileLayer; +import org.oscim.layers.tile.MapTileLayer; +import org.oscim.layers.tile.MapTileLoader; import org.oscim.overlay.BuildingOverlay; import org.oscim.overlay.LabelingOverlay; import org.oscim.overlay.Overlay; @@ -121,7 +121,7 @@ public class MapView extends RelativeLayout { mDebugSettings = new DebugSettings(); // FIXME - TileGenerator.setDebugSettings(mDebugSettings); + MapTileLoader.setDebugSettings(mDebugSettings); mapActivity.registerMapView(this); @@ -134,8 +134,8 @@ public class MapView extends RelativeLayout { redrawMap(false); } - public TileLayer setBaseMap(MapOptions options) { - TileLayer baseLayer = new TileLayer(this); + public MapTileLayer setBaseMap(MapOptions options) { + MapTileLayer baseLayer = new MapTileLayer(this); baseLayer.setMapDatabase(options); @@ -266,7 +266,7 @@ public class MapView extends RelativeLayout { */ public void setDebugSettings(DebugSettings debugSettings) { mDebugSettings = debugSettings; - TileGenerator.setDebugSettings(debugSettings); + MapTileLoader.setDebugSettings(debugSettings); } /** @@ -351,4 +351,5 @@ public class MapView extends RelativeLayout { public boolean getRotationEnabled() { return mRotationEnabled; } + }