From 124624785d45648a6cb21a9ae635d4f6b7b7baae Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Tue, 7 Aug 2012 03:04:39 +0200 Subject: [PATCH] - adding MapDatabase backend for our TileStache provider - fixing some renering bugs on nexus phone and some refactoring and cleanup --- AndroidManifest.xml | 17 +- .../activity_advanced_map_viewer.xml | 25 - res/menu/options_menu_pre_honeycomb.xml | 71 + res/values-de/strings.xml | 1 + res/values-fi/strings.xml | 1 + res/values-it/strings.xml | 1 + res/values/arrays.xml | 1 + res/values/strings.xml | 1 + .../{MapRenderer.java => IMapRenderer.java} | 10 +- src/org/mapsforge/android/MapView.java | 365 +++-- .../mapsforge/android/MapViewPosition.java | 13 +- .../android/glrenderer/LayerPool.java | 28 +- .../android/glrenderer/LineLayers.java | 8 +- ...atabaseRenderer.java => MapGenerator.java} | 189 +-- .../android/glrenderer/MapRenderer.java | 526 ++++--- .../android/glrenderer/PolygonLayers.java | 8 +- .../android/mapgenerator/IMapGenerator.java | 30 +- .../android/mapgenerator/JobParameters.java | 16 +- .../android/mapgenerator/JobQueue.java | 3 +- .../mapgenerator/MapDatabaseFactory.java | 23 +- ...atabaseInternal.java => MapDatabases.java} | 6 +- .../android/mapgenerator/MapGeneratorJob.java | 36 +- ...orFactory.java => MapRendererFactory.java} | 40 +- ...neratorInternal.java => MapRenderers.java} | 2 +- .../android/mapgenerator/MapWorker.java | 40 +- .../{JobTheme.java => Theme.java} | 2 +- .../rendertheme/ExternalRenderTheme.java | 4 +- .../rendertheme/InternalRenderTheme.java | 9 +- .../android/rendertheme/RenderTheme.java | 115 +- .../rendertheme/osmarender/osmarender.xml | 1392 ++++++++--------- ...atabaseRenderer.java => MapGenerator.java} | 149 +- .../android/swrenderer/MapRenderer.java | 126 +- .../android/swrenderer/WayDecorator.java | 4 +- src/org/mapsforge/android/utils/GlUtils.java | 24 +- .../android/utils/PausableThread.java | 8 + src/org/mapsforge/app/TileMap.java | 43 +- .../mapsforge/app/filepicker/FilePicker.java | 3 +- .../app/preferences/EditPreferences.java | 20 +- src/org/mapsforge/database/IMapDatabase.java | 4 +- .../mapsforge/database/json/MapDatabase.java | 41 +- .../database/mapfile/MapDatabase.java | 123 +- .../mapsforge/database/pbmap/MapDatabase.java | 513 ++++++ .../database/postgis/MapDatabase.java | 25 +- 43 files changed, 2287 insertions(+), 1779 deletions(-) delete mode 100644 res/layout-port/activity_advanced_map_viewer.xml create mode 100644 res/menu/options_menu_pre_honeycomb.xml rename src/org/mapsforge/android/{MapRenderer.java => IMapRenderer.java} (81%) rename src/org/mapsforge/android/glrenderer/{DatabaseRenderer.java => MapGenerator.java} (73%) rename src/org/mapsforge/android/mapgenerator/{MapDatabaseInternal.java => MapDatabases.java} (93%) rename src/org/mapsforge/android/mapgenerator/{MapGeneratorFactory.java => MapRendererFactory.java} (57%) rename src/org/mapsforge/android/mapgenerator/{MapGeneratorInternal.java => MapRenderers.java} (96%) rename src/org/mapsforge/android/mapgenerator/{JobTheme.java => Theme.java} (96%) rename src/org/mapsforge/android/swrenderer/{DatabaseRenderer.java => MapGenerator.java} (81%) create mode 100644 src/org/mapsforge/database/pbmap/MapDatabase.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 3596e557..a4905fcb 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -12,14 +12,15 @@ + android:targetSdkVersion="16" /> - - + android:label="@string/application_name" + android:theme="@style/Theme.TileMap" > + @@ -28,6 +29,6 @@ - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/res/layout-port/activity_advanced_map_viewer.xml b/res/layout-port/activity_advanced_map_viewer.xml deleted file mode 100644 index 47c2204a..00000000 --- a/res/layout-port/activity_advanced_map_viewer.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/res/menu/options_menu_pre_honeycomb.xml b/res/menu/options_menu_pre_honeycomb.xml new file mode 100644 index 00000000..bd8e33e0 --- /dev/null +++ b/res/menu/options_menu_pre_honeycomb.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 2a7f286e..d6678156 100755 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -3,6 +3,7 @@ Mapfile PostGIS + OpenScienceMap diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 1929f577..3d3ce7f4 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -3,6 +3,7 @@ Mapfile PostGIS + OpenScienceMap diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 312f0e2f..b5e05653 100755 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -3,6 +3,7 @@ Mapfile PostGIS + OpenScienceMap diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 04b7c6fe..f34e3ba5 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -3,6 +3,7 @@ MAP_READER POSTGIS_READER + PBMAP_READER POSTGIS_READER diff --git a/res/values/strings.xml b/res/values/strings.xml index 55e2ad76..1353acbe 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3,6 +3,7 @@ Mapfile PostGIS + OpenScienceMap diff --git a/src/org/mapsforge/android/MapRenderer.java b/src/org/mapsforge/android/IMapRenderer.java similarity index 81% rename from src/org/mapsforge/android/MapRenderer.java rename to src/org/mapsforge/android/IMapRenderer.java index d84e2933..b5249d32 100644 --- a/src/org/mapsforge/android/MapRenderer.java +++ b/src/org/mapsforge/android/IMapRenderer.java @@ -14,6 +14,7 @@ */ package org.mapsforge.android; +import org.mapsforge.android.mapgenerator.IMapGenerator; import org.mapsforge.android.mapgenerator.MapGeneratorJob; import android.opengl.GLSurfaceView; @@ -21,7 +22,7 @@ import android.opengl.GLSurfaceView; /** * */ -public interface MapRenderer extends GLSurfaceView.Renderer { +public interface IMapRenderer extends GLSurfaceView.Renderer { /** * @param mapGeneratorJob @@ -31,9 +32,8 @@ public interface MapRenderer extends GLSurfaceView.Renderer { public boolean passTile(MapGeneratorJob mapGeneratorJob); /** - * @return true when tile passed to renderer is processed false otherwise. - * used to lock overwriting resources passed with the tile - * (e.g. lock until bitmap is loaded to texture) + * @return true when tile passed to renderer is processed false otherwise. used to lock overwriting resources passed + * with the tile (e.g. lock until bitmap is loaded to texture) */ public boolean processedTile(); @@ -44,4 +44,6 @@ public interface MapRenderer extends GLSurfaceView.Renderer { * ... */ public void redrawTiles(boolean clear); + + public IMapGenerator createMapGenerator(); } diff --git a/src/org/mapsforge/android/MapView.java b/src/org/mapsforge/android/MapView.java index 28f8a36e..8703f23b 100644 --- a/src/org/mapsforge/android/MapView.java +++ b/src/org/mapsforge/android/MapView.java @@ -16,25 +16,35 @@ package org.mapsforge.android; import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +import javax.xml.parsers.ParserConfigurationException; import org.mapsforge.android.input.TouchHandler; import org.mapsforge.android.mapgenerator.IMapGenerator; import org.mapsforge.android.mapgenerator.JobParameters; import org.mapsforge.android.mapgenerator.JobQueue; -import org.mapsforge.android.mapgenerator.JobTheme; import org.mapsforge.android.mapgenerator.MapDatabaseFactory; -import org.mapsforge.android.mapgenerator.MapDatabaseInternal; -import org.mapsforge.android.mapgenerator.MapGeneratorFactory; -import org.mapsforge.android.mapgenerator.MapGeneratorInternal; +import org.mapsforge.android.mapgenerator.MapDatabases; +import org.mapsforge.android.mapgenerator.MapGeneratorJob; +import org.mapsforge.android.mapgenerator.MapRendererFactory; +import org.mapsforge.android.mapgenerator.MapRenderers; import org.mapsforge.android.mapgenerator.MapWorker; +import org.mapsforge.android.mapgenerator.Theme; import org.mapsforge.android.rendertheme.ExternalRenderTheme; import org.mapsforge.android.rendertheme.InternalRenderTheme; +import org.mapsforge.android.rendertheme.RenderTheme; +import org.mapsforge.android.rendertheme.RenderThemeHandler; import org.mapsforge.android.utils.GlConfigChooser; import org.mapsforge.core.GeoPoint; import org.mapsforge.core.MapPosition; import org.mapsforge.database.FileOpenResult; import org.mapsforge.database.IMapDatabase; +import org.mapsforge.database.MapFileInfo; import org.mapsforge.database.mapfile.MapDatabase; +import org.xml.sax.SAXException; import android.content.Context; import android.opengl.GLSurfaceView; @@ -49,8 +59,7 @@ import android.view.MotionEvent; *

* This implementation supports offline map rendering as well as downloading map images (tiles) over an Internet * connection. The operation mode of a MapView can be set in the constructor and changed at runtime with the - * {@link #setMapGeneratorInternal(IMapGenerator)} method. Some MapView parameters depend on the selected operation - * mode. + * {@link #setMapDatabase(MapDatabases)} method. Some MapView parameters depend on the selected operation mode. *

* In offline rendering mode a special database file is required which contains the map data. Map files can be stored in * any folder. The current map file is set by calling {@link #setMapFile(String)}. To retrieve the current @@ -67,12 +76,12 @@ public class MapView extends GLSurfaceView { public static final InternalRenderTheme DEFAULT_RENDER_THEME = InternalRenderTheme.OSMARENDER; private static final float DEFAULT_TEXT_SCALE = 1; + private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16); private final MapController mMapController; // private final MapMover mMapMover; // private final ZoomAnimator mZoomAnimator; - - private final MapScaleBar mMapScaleBar; + // private final MapScaleBar mMapScaleBar; private final MapViewPosition mMapViewPosition; private final MapZoomControls mMapZoomControls; @@ -80,10 +89,11 @@ public class MapView extends GLSurfaceView { private final TouchHandler mTouchEventHandler; private IMapDatabase mMapDatabase; - private IMapGenerator mMapGenerator; - private MapRenderer mMapRenderer; + private MapDatabases mMapDatabaseType; + private IMapRenderer mMapRenderer; private JobQueue mJobQueue; - private MapWorker mMapWorker; + private MapWorker mMapWorkers[]; + private int mNumMapWorkers = 6; private JobParameters mJobParameters; private DebugSettings mDebugSettings; private String mMapFile; @@ -95,9 +105,7 @@ public class MapView extends GLSurfaceView { * if the context object is not an instance of {@link MapActivity} . */ public MapView(Context context) { - this(context, null, - MapGeneratorFactory.createMapGenerator(MapGeneratorInternal.GL_RENDERER), - MapDatabaseFactory.createMapDatabase(MapDatabaseInternal.MAP_READER)); + this(context, null, MapRenderers.GL_RENDERER, MapDatabases.MAP_READER); } /** @@ -110,25 +118,12 @@ public class MapView extends GLSurfaceView { */ public MapView(Context context, AttributeSet attributeSet) { this(context, attributeSet, - MapGeneratorFactory.createMapGenerator(attributeSet), - MapDatabaseFactory.createMapDatabase(attributeSet)); - } - - /** - * @param context - * the enclosing MapActivity instance. - * @param mapGenerator - * the MapGenerator for this MapView. - * @throws IllegalArgumentException - * if the context object is not an instance of {@link MapActivity} . - */ - public MapView(Context context, IMapGenerator mapGenerator) { - this(context, null, mapGenerator, MapDatabaseFactory - .createMapDatabase(MapDatabaseInternal.MAP_READER)); + MapRendererFactory.getMapGenerator(attributeSet), + MapDatabaseFactory.getMapDatabase(attributeSet)); } private MapView(Context context, AttributeSet attributeSet, - IMapGenerator mapGenerator, IMapDatabase mapDatabase) { + MapRenderers mapGeneratorType, MapDatabases mapDatabaseType) { super(context, attributeSet); @@ -147,46 +142,63 @@ public class MapView extends GLSurfaceView { mJobParameters = new JobParameters(DEFAULT_RENDER_THEME, DEFAULT_TEXT_SCALE); mMapController = new MapController(this); - // mMapDatabase = MapDatabaseFactory.createMapDatabase(MapDatabaseInternal.POSTGIS_READER); - // mMapDatabase = MapDatabaseFactory.createMapDatabase(MapDatabaseInternal.JSON_READER); - mMapDatabase = mapDatabase; + mMapDatabaseType = mapDatabaseType; mMapViewPosition = new MapViewPosition(this); - mMapScaleBar = new MapScaleBar(this); + // mMapScaleBar = new MapScaleBar(this); mMapZoomControls = new MapZoomControls(mapActivity, this); mProjection = new MapViewProjection(this); mTouchEventHandler = new TouchHandler(mapActivity, this); mJobQueue = new JobQueue(this); - mMapWorker = new MapWorker(this); - mMapWorker.start(); + // mMapMover = new MapMover(this); // mMapMover.start(); // mZoomAnimator = new ZoomAnimator(this); // mZoomAnimator.start(); - setMapGeneratorInternal(mapGenerator); + mMapRenderer = MapRendererFactory.createMapRenderer(this, mapGeneratorType); + mMapWorkers = new MapWorker[mNumMapWorkers]; - GeoPoint startPoint = mMapGenerator.getStartPoint(); - if (startPoint != null) { - mMapViewPosition.setMapCenter(startPoint); + for (int i = 0; i < mNumMapWorkers; i++) { + IMapDatabase mapDatabase = MapDatabaseFactory + .createMapDatabase(mapDatabaseType); + + IMapGenerator mapGenerator = mMapRenderer.createMapGenerator(); + mapGenerator.setMapDatabase(mapDatabase); + + if (i == 0) { + mMapDatabase = mapDatabase; + initMapStartPosition(); + + // mapGenerator.setRendertheme(DEFAULT_RENDER_THEME); + } + mMapWorkers[i] = new MapWorker(i, this, mapGenerator, mMapRenderer); + mMapWorkers[i].start(); } - Byte startZoomLevel = mMapGenerator.getStartZoomLevel(); - if (startZoomLevel != null) { - mMapViewPosition.setZoomLevel(startZoomLevel.byteValue()); - } + setRenderTheme(InternalRenderTheme.OSMARENDER); mapActivity.registerMapView(this); setEGLConfigChooser(new GlConfigChooser()); setEGLContextClientVersion(2); - mMapRenderer = mMapGenerator.getMapRenderer(this); setRenderer(mMapRenderer); - setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - mMapWorker.setMapRenderer(mMapRenderer); + } + + private void initMapStartPosition() { + GeoPoint startPoint = getStartPoint(); + if (startPoint != null) { + mMapViewPosition.setMapCenter(startPoint); + } + + Byte startZoomLevel = getStartZoomLevel(); + if (startZoomLevel != null) { + mMapViewPosition.setZoomLevel(startZoomLevel.byteValue()); + } + } /** @@ -224,13 +236,6 @@ public class MapView extends GLSurfaceView { return mMapFile; } - /** - * @return the currently used MapGenerator (may be null). - */ - public IMapGenerator getMapGenerator() { - return mMapGenerator; - } - // /** // * @return the MapMover which is used by this MapView. // */ @@ -245,19 +250,19 @@ public class MapView extends GLSurfaceView { return mMapViewPosition; } - /** - * @return the scale bar which is used in this MapView. - */ - public MapScaleBar getMapScaleBar() { - return mMapScaleBar; - } + // /** + // * @return the scale bar which is used in this MapView. + // */ + // public MapScaleBar getMapScaleBar() { + // return mMapScaleBar; + // } - /** - * @return the zoom controls instance which is used in this MapView. - */ - public MapZoomControls getMapZoomControls() { - return mMapZoomControls; - } + // /** + // * @return the zoom controls instance which is used in this MapView. + // */ + // public MapZoomControls getMapZoomControls() { + // return mMapZoomControls; + // } /** * @return the currently used projection of the map. Do not keep this object for a longer time. @@ -362,37 +367,41 @@ public class MapView extends GLSurfaceView { // mZoomAnimator.pause(); // mMapMover.pause(); - mMapWorker.pause(); // mZoomAnimator.awaitPausing(); // mMapMover.awaitPausing(); - mMapWorker.awaitPausing(); // mZoomAnimator.proceed(); // mMapMover.stopMove(); // mMapMover.proceed(); - mMapWorker.proceed(); - mMapDatabase.closeFile(); + boolean initialized = false; - if (mapFile != null) - fileOpenResult = mMapDatabase.openFile(new File(mapFile)); - else - fileOpenResult = mMapDatabase.openFile(null); + mJobQueue.clear(); - if (fileOpenResult != null && fileOpenResult.isSuccess()) { - mMapFile = mapFile; + mapWorkersPause(); - GeoPoint startPoint = mMapGenerator.getStartPoint(); - if (startPoint != null) { - Log.d(TAG, "mapfile got startpoint"); - mMapViewPosition.setMapCenter(startPoint); + for (MapWorker mapWorker : mMapWorkers) { + + IMapGenerator mapGenerator = mapWorker.getMapGenerator(); + IMapDatabase mapDatabase = mapGenerator.getMapDatabase(); + + mapDatabase.closeFile(); + + if (mapFile != null) + fileOpenResult = mapDatabase.openFile(new File(mapFile)); + else + fileOpenResult = mapDatabase.openFile(null); + + if (fileOpenResult != null && fileOpenResult.isSuccess()) { + mMapFile = mapFile; + + if (!initialized) + initialized = true; } + } - Byte startZoomLevel = mMapGenerator.getStartZoomLevel(); - if (startZoomLevel != null) { - Log.d(TAG, "mapfile got start zoomlevel"); - mMapViewPosition.setZoomLevel(startZoomLevel.byteValue()); - } + mapWorkersProceed(); + if (initialized) { clearAndRedrawMapView(); Log.d(TAG, "mapfile set"); return true; @@ -404,76 +413,61 @@ public class MapView extends GLSurfaceView { return false; } - /** - * Sets the MapGenerator for this MapView. - * - * @param mapGenerator - * the new MapGenerator. - */ - public void setMapGenerator(IMapGenerator mapGenerator) { - - if (mMapGenerator != mapGenerator) { - setMapGeneratorInternal(mapGenerator); - - clearAndRedrawMapView(); + private GeoPoint getStartPoint() { + if (mMapDatabase != null && mMapDatabase.hasOpenFile()) { + MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo(); + if (mapFileInfo.startPosition != null) { + return mapFileInfo.startPosition; + } else if (mapFileInfo.mapCenter != null) { + return mapFileInfo.mapCenter; + } } + + return null; } - private void setMapGeneratorInternal(IMapGenerator mapGenerator) { - if (mapGenerator == null) { - throw new IllegalArgumentException("mapGenerator must not be null"); + private Byte getStartZoomLevel() { + if (mMapDatabase != null && mMapDatabase.hasOpenFile()) { + MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo(); + if (mapFileInfo.startZoomLevel != null) { + return mapFileInfo.startZoomLevel; + } } - mapGenerator.setMapDatabase(mMapDatabase); - - mMapGenerator = mapGenerator; - mMapWorker.setMapGenerator(mMapGenerator); - + return DEFAULT_START_ZOOM_LEVEL; } /** * Sets the MapDatabase for this MapView. * - * @param mapDatabase + * @param mapDatabaseType * the new MapDatabase. */ - public void setMapDatabase(IMapDatabase mapDatabase) { - Log.d(TAG, "setMapDatabase " + mapDatabase.getClass()); - if (mMapDatabase != mapDatabase) { - if (mMapDatabase != null) - mMapDatabase.closeFile(); + public void setMapDatabase(MapDatabases mapDatabaseType) { + IMapGenerator mapGenerator; - setMapDatabaseInternal(mapDatabase); + Log.d(TAG, "setMapDatabase " + mapDatabaseType.name()); - // clearAndRedrawMapView(); - } - } + if (mMapDatabaseType == mapDatabaseType) + return; - private void setMapDatabaseInternal(IMapDatabase mapDatabase) { - if (mapDatabase == null) { - throw new IllegalArgumentException("MapDatabase must not be null"); - } + mapWorkersPause(); - if (!mMapWorker.isPausing()) { - mMapWorker.pause(); - mMapWorker.awaitPausing(); + for (MapWorker mapWorker : mMapWorkers) { + mapGenerator = mapWorker.getMapGenerator(); + + mapGenerator.setMapDatabase(MapDatabaseFactory + .createMapDatabase(mapDatabaseType)); } mJobQueue.clear(); - mMapDatabase = mapDatabase; - mMapGenerator.setMapDatabase(mMapDatabase); - - Log.d(TAG, "setMapDatabaseInternal " + mapDatabase.getClass()); String mapFile = mMapFile; mMapFile = null; setMapFile(mapFile); - mMapWorker.proceed(); - - // mMapWorker.setMapDatabase(mMapDatabase); - + mapWorkersProceed(); } /** @@ -489,8 +483,7 @@ public class MapView extends GLSurfaceView { throw new IllegalArgumentException("render theme must not be null"); } - Log.d(TAG, "set rendertheme " + internalRenderTheme); - mJobParameters = new JobParameters(internalRenderTheme, mJobParameters.textScale); + setRenderTheme((Theme) internalRenderTheme); clearAndRedrawMapView(); } @@ -510,12 +503,40 @@ public class MapView extends GLSurfaceView { throw new IllegalArgumentException("render theme path must not be null"); } - JobTheme jobTheme = new ExternalRenderTheme(renderThemePath); - mJobParameters = new JobParameters(jobTheme, mJobParameters.textScale); + setRenderTheme(new ExternalRenderTheme(renderThemePath)); clearAndRedrawMapView(); } + private boolean setRenderTheme(Theme theme) { + + mapWorkersPause(); + + InputStream inputStream = null; + try { + inputStream = theme.getRenderThemeAsStream(); + RenderTheme t = RenderThemeHandler.getRenderTheme(inputStream); + mMapWorkers[0].getMapGenerator().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 { + mapWorkersProceed(); + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + Log.e(TAG, e.getMessage()); + } + } + return false; + } + /** * Sets the text scale for the map rendering. Has no effect in downloading mode. * @@ -523,7 +544,7 @@ public class MapView extends GLSurfaceView { * the new text scale for the map rendering. */ public void setTextScale(float textScale) { - mJobParameters = new JobParameters(mJobParameters.jobTheme, textScale); + mJobParameters = new JobParameters(mJobParameters.theme, textScale); clearAndRedrawMapView(); } @@ -583,28 +604,33 @@ public class MapView extends GLSurfaceView { @Override protected synchronized void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { - mMapWorker.pause(); - mMapWorker.awaitPausing(); - super.onSizeChanged(width, height, oldWidth, oldHeight); - mMapWorker.proceed(); - + for (MapWorker mapWorker : mMapWorkers) { + mapWorker.pause(); + mapWorker.awaitPausing(); + super.onSizeChanged(width, height, oldWidth, oldHeight); + mapWorker.proceed(); + } // redrawTiles(); } void destroy() { // mMapMover.interrupt(); - mMapWorker.interrupt(); // mZoomAnimator.interrupt(); - try { - mMapWorker.join(); - } catch (InterruptedException e) { - // restore the interrupted status - Thread.currentThread().interrupt(); + for (MapWorker mapWorker : mMapWorkers) { + mapWorker.interrupt(); + + try { + mapWorker.join(); + } catch (InterruptedException e) { + // restore the interrupted status + Thread.currentThread().interrupt(); + } + IMapDatabase mapDatabase = mapWorker.getMapGenerator().getMapDatabase(); + mapDatabase.closeFile(); } - mMapScaleBar.destroy(); - mMapDatabase.closeFile(); + // mMapScaleBar.destroy(); } @@ -612,8 +638,9 @@ public class MapView extends GLSurfaceView { * @return the maximum possible zoom level. */ byte getMaximumPossibleZoomLevel() { - return (byte) Math.min(mMapZoomControls.getZoomLevelMax(), - mMapGenerator.getZoomLevelMax()); + return (byte) 20; + // FIXME Math.min(mMapZoomControls.getZoomLevelMax(), + // mMapGenerator.getZoomLevelMax()); } /** @@ -639,7 +666,9 @@ public class MapView extends GLSurfaceView { @Override public void onPause() { super.onPause(); - mMapWorker.pause(); + for (MapWorker mapWorker : mMapWorkers) + mapWorker.pause(); + // mMapMover.pause(); // mZoomAnimator.pause(); } @@ -647,7 +676,9 @@ public class MapView extends GLSurfaceView { @Override public void onResume() { super.onResume(); - mMapWorker.proceed(); + for (MapWorker mapWorker : mMapWorkers) + mapWorker.proceed(); + // mMapMover.proceed(); // mZoomAnimator.proceed(); } @@ -706,9 +737,33 @@ public class MapView extends GLSurfaceView { } /** - * @return MapWorker + * add jobs and remember MapWorkers that stuff needs to be done + * + * @param jobs + * tile jobs */ - public MapWorker getMapWorker() { - return mMapWorker; + public void addJobs(ArrayList jobs) { + mJobQueue.setJobs(jobs); + + for (MapWorker m : mMapWorkers) { + synchronized (m) { + m.notify(); + } + } } + + private void mapWorkersPause() { + for (MapWorker mapWorker : mMapWorkers) { + if (!mapWorker.isPausing()) { + mapWorker.pause(); + mapWorker.awaitPausing(); + } + } + } + + private void mapWorkersProceed() { + for (MapWorker mapWorker : mMapWorkers) + mapWorker.proceed(); + } + } diff --git a/src/org/mapsforge/android/MapViewPosition.java b/src/org/mapsforge/android/MapViewPosition.java index 0bfae24a..e3e20562 100644 --- a/src/org/mapsforge/android/MapViewPosition.java +++ b/src/org/mapsforge/android/MapViewPosition.java @@ -26,6 +26,7 @@ import android.util.FloatMath; public class MapViewPosition { private static float MAX_SCALE = 2.0f; private static float MIN_SCALE = 1.0f; + private static int MAX_ZOOMLEVEL = 16; private double mLatitude; private double mLongitude; @@ -162,12 +163,14 @@ public class MapViewPosition { float s = mScale * scale; if (s >= MAX_SCALE) { - - byte z = (byte) FloatMath.sqrt(s); - if (z != 0 && mZoomLevel == 20) + if (s > 8) return; - mZoomLevel += z; - s *= 1.0f / (1 << z); + + if (mZoomLevel <= MAX_ZOOMLEVEL) { + byte z = (byte) FloatMath.sqrt(s); + mZoomLevel += z; + s *= 1.0f / (1 << z); + } } else if (s < MIN_SCALE) { byte z = (byte) FloatMath.sqrt(1 / s); if (z != 0 && mZoomLevel == 1) diff --git a/src/org/mapsforge/android/glrenderer/LayerPool.java b/src/org/mapsforge/android/glrenderer/LayerPool.java index 9621c0ee..21215a21 100644 --- a/src/org/mapsforge/android/glrenderer/LayerPool.java +++ b/src/org/mapsforge/android/glrenderer/LayerPool.java @@ -18,31 +18,33 @@ package org.mapsforge.android.glrenderer; import java.util.LinkedList; class LayerPool { - static private LinkedList pool; + static private LinkedList pool = null; static private int count; static void init() { - pool = new LinkedList(); - count = 0; + if (pool == null) { + pool = new LinkedList(); + count = 0; + } } static PoolItem get() { - if (count == 0) - return new PoolItem(); - - PoolItem it; synchronized (pool) { - count--; - it = pool.pop(); - it.used = 0; - } - return it; + if (count == 0) + return new PoolItem(); + + count--; + PoolItem it = pool.pop(); + it.used = 0; + return it; + } } static void add(LinkedList items) { - int size = items.size(); synchronized (pool) { + int size = items.size(); + while (count < 4096 && size-- > 0) { count++; pool.add(items.pop()); diff --git a/src/org/mapsforge/android/glrenderer/LineLayers.java b/src/org/mapsforge/android/glrenderer/LineLayers.java index d799f415..3299bb8d 100644 --- a/src/org/mapsforge/android/glrenderer/LineLayers.java +++ b/src/org/mapsforge/android/glrenderer/LineLayers.java @@ -61,7 +61,7 @@ class LineLayers { ByteOrder.nativeOrder()); fbuf = bbuf.asFloatBuffer(); } else { - fbuf.position(0); + fbuf.clear(); } int pos = 0; @@ -81,7 +81,7 @@ class LineLayers { l.pool = null; } - fbuf.position(0); + fbuf.flip(); // not needed for drawing layers = null; @@ -105,7 +105,7 @@ class LineLayers { ByteOrder.nativeOrder()); sbuf = bbuf.asShortBuffer(); } else { - sbuf.position(0); + sbuf.clear(); } int pos = 0; @@ -129,7 +129,7 @@ class LineLayers { l.pool = null; } - sbuf.position(0); + sbuf.flip(); // not needed for drawing layers = null; diff --git a/src/org/mapsforge/android/glrenderer/DatabaseRenderer.java b/src/org/mapsforge/android/glrenderer/MapGenerator.java similarity index 73% rename from src/org/mapsforge/android/glrenderer/DatabaseRenderer.java rename to src/org/mapsforge/android/glrenderer/MapGenerator.java index 1fd6c45b..64165fdb 100644 --- a/src/org/mapsforge/android/glrenderer/DatabaseRenderer.java +++ b/src/org/mapsforge/android/glrenderer/MapGenerator.java @@ -14,29 +14,19 @@ */ package org.mapsforge.android.glrenderer; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; - -import javax.xml.parsers.ParserConfigurationException; - -import org.mapsforge.android.MapView; import org.mapsforge.android.mapgenerator.IMapGenerator; -import org.mapsforge.android.mapgenerator.JobTheme; import org.mapsforge.android.mapgenerator.MapGeneratorJob; import org.mapsforge.android.rendertheme.IRenderCallback; import org.mapsforge.android.rendertheme.RenderTheme; -import org.mapsforge.android.rendertheme.RenderThemeHandler; import org.mapsforge.android.rendertheme.renderinstruction.Area; import org.mapsforge.android.rendertheme.renderinstruction.Line; -import org.mapsforge.core.GeoPoint; -import org.mapsforge.core.WebMercator; +import org.mapsforge.android.rendertheme.renderinstruction.RenderInstruction; +import org.mapsforge.core.MercatorProjection; import org.mapsforge.core.Tag; import org.mapsforge.core.Tile; +import org.mapsforge.core.WebMercator; import org.mapsforge.database.IMapDatabase; import org.mapsforge.database.IMapDatabaseCallback; -import org.mapsforge.database.MapFileInfo; -import org.xml.sax.SAXException; import android.graphics.Bitmap; import android.graphics.Color; @@ -46,33 +36,26 @@ import android.util.Log; /** * */ -public class DatabaseRenderer implements IMapGenerator, IRenderCallback, - IMapDatabaseCallback { - private static String TAG = DatabaseRenderer.class.getName(); +public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabaseCallback { + + private static String TAG = MapGenerator.class.getName(); - private static final byte ZOOM_MAX = 22; - private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16); private static final double PI180 = (Math.PI / 180) / 1000000.0; private static final double PIx4 = Math.PI * 4; private static final double STROKE_INCREASE = Math.sqrt(2); private static final byte STROKE_MIN_ZOOM_LEVEL = 12; private static final byte LAYERS = 11; + private static final double f900913 = 20037508.342789244; private static RenderTheme renderTheme; private IMapDatabase mMapDatabase; - private JobTheme mPreviousJobTheme; - // private float mPreviousTextScale; - private byte mPreviousZoomLevel; - private GLMapTile mCurrentTile; private float[] mWayNodes; private int[] mWays; - private ArrayList mCurrentLines; - private LineLayers mLineLayers; private PolygonLayers mPolyLayers; private MeshLayers mMeshLayers; @@ -81,14 +64,13 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, private int mLevels; private boolean useSphericalMercator = false; + private float mStrokeScale = 1.0f; /** * */ - public DatabaseRenderer() { + public MapGenerator() { Log.d(TAG, "init DatabaseRenderer"); - mCurrentLines = new ArrayList(); - LayerPool.init(); } @@ -107,7 +89,6 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, private boolean mProjected; private boolean mProjectedResult; private float mSimplify; - private static final double f900913 = 20037508.342789244; private boolean projectToTile(boolean area) { if (mProjected) @@ -136,6 +117,8 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, for (int pos = 0, outPos = 0, i = 0, m = mWays.length; i < m; i++) { int len = mWays[i]; + if (len == 0) + continue; int cnt = 0; float lat, lon, prevLon = 0, prevLat = 0; @@ -197,6 +180,8 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, private boolean firstMatch; private boolean prevClosed; + private RenderInstruction[] mRenderInstructions = null; + @Override public void renderWay(byte layer, Tag[] tags, float[] wayNodes, int[] wayLength, boolean changed) { @@ -220,17 +205,20 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, mSimplify = 0; } - mCurrentLines.clear(); mWayNodes = wayNodes; mWays = wayLength; if (!firstMatch && prevClosed == closed && !changed) { - DatabaseRenderer.renderTheme.matchWay(this, tags, - (byte) (mCurrentTile.zoomLevel + 0), - closed, false); + if (mRenderInstructions != null) { + for (int i = 0, n = mRenderInstructions.length; i < n; i++) + mRenderInstructions[i].renderWay(this, tags); + } + // MapGenerator.renderTheme.matchWay(this, tags, + // (byte) (mCurrentTile.zoomLevel + 0), + // closed, false); } else { prevClosed = closed; - DatabaseRenderer.renderTheme.matchWay(this, tags, + mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags, (byte) (mCurrentTile.zoomLevel + 0), closed, true); } @@ -273,9 +261,6 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, @Override public void renderWay(Line line) { - // if (prevClosed && !mProjected) - // return; - projectToTile(false); LineLayer outlineLayer = null; @@ -284,11 +269,12 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, float w = line.strokeWidth; - if (!line.fixed) - w *= mStrokeScale / 1.5f; - + if (!line.fixed) { + w *= mStrokeScale; + w *= mProjectionScaleFactor; + } if (line.outline != -1) { - Line outline = DatabaseRenderer.renderTheme.getOutline(line.outline); + Line outline = MapGenerator.renderTheme.getOutline(line.outline); if (outline != null) { outlineLayer = mLineLayers.getLayer(mDrawingLayer + outline.level, outline.color, true, false); @@ -363,33 +349,19 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, if (mMapDatabase == null) return false; + useSphericalMercator = WebMercator.NAME.equals(mMapDatabase.getMapProjection()); + mCurrentTile = (GLMapTile) mapGeneratorJob.tile; mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons; - // FIXME still chance of concurrency with maprenderer updateVisibleList ? if (mCurrentTile.isLoading || mCurrentTile.isDrawn) return false; mCurrentTile.isLoading = true; - JobTheme jobTheme = mapGeneratorJob.jobParameters.jobTheme; + mLevels = MapGenerator.renderTheme.getLevels(); - if (jobTheme != mPreviousJobTheme) { - if (!setRenderTheme(jobTheme)) { - mPreviousJobTheme = null; - return false; - } - - mPreviousJobTheme = jobTheme; - mPreviousZoomLevel = Byte.MIN_VALUE; - mLevels = DatabaseRenderer.renderTheme.getLevels(); - } - - byte zoomLevel = mCurrentTile.zoomLevel; - if (zoomLevel != mPreviousZoomLevel) { - setScaleStrokeWidth(zoomLevel); - mPreviousZoomLevel = zoomLevel; - } + setScaleStrokeWidth(mCurrentTile.zoomLevel); mLineLayers = new LineLayers(); mPolyLayers = new PolygonLayers(); @@ -399,81 +371,32 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, mCurrentTile.meshLayers = mMeshLayers; firstMatch = true; - mMapDatabase.executeQuery(mCurrentTile, this); - // Log.d(TAG, "loaded " + mCurrentTile); + mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection + .pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel) + * (Math.PI / 180))) / 1.5f; + mMapDatabase.executeQuery(mCurrentTile, this); if (mapGeneratorJob.debugSettings.mDrawTileFrames) { float[] coords = { 0, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, 0, 0, 0 }; LineLayer ll = mLineLayers.getLayer(Integer.MAX_VALUE, Color.BLACK, false, true); - ll.addLine(coords, 0, coords.length, 1.0f, false); + ll.addLine(coords, 0, coords.length, 2.0f, false); } mCurrentTile.newData = true; return true; } - @Override - public GeoPoint getStartPoint() { - useSphericalMercator = false; - - if (mMapDatabase != null && mMapDatabase.hasOpenFile()) { - MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo(); - - if (WebMercator.NAME.equals(mapFileInfo.projectionName)) { - Log.d(TAG, "using Spherical Mercator"); - - useSphericalMercator = true; - } - if (mapFileInfo.startPosition != null) { - return mapFileInfo.startPosition; - } else if (mapFileInfo.mapCenter != null) { - return mapFileInfo.mapCenter; - } - - } - return null; - } - - @Override - public Byte getStartZoomLevel() { - return DEFAULT_START_ZOOM_LEVEL; - } - - @Override - public byte getZoomLevelMax() { - return ZOOM_MAX; - } - - private static boolean setRenderTheme(JobTheme jobTheme) { - InputStream inputStream = null; - try { - inputStream = jobTheme.getRenderThemeAsStream(); - DatabaseRenderer.renderTheme = RenderThemeHandler.getRenderTheme(inputStream); - 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()); - } - } - return false; - } + private float mProjectionScaleFactor; private static byte getValidLayer(byte layer) { if (layer < 0) { return 0; + /** + * return instances of MapRenderer + */ } else if (layer >= LAYERS) { return LAYERS - 1; } else { @@ -481,9 +404,17 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, } } - @Override - public MapRenderer getMapRenderer(MapView mapView) { - return new MapRenderer(mapView); + /** + * Sets the scale stroke factor for the given zoom level. + * + * @param zoomLevel + * the zoom level for which the scale stroke factor should be set. + */ + private void setScaleStrokeWidth(byte zoomLevel) { + int zoomLevelDiff = Math.max(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0); + mStrokeScale = (float) Math.pow(STROKE_INCREASE, zoomLevelDiff); + if (mStrokeScale < 1) + mStrokeScale = 1; } @Override @@ -491,19 +422,13 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, mMapDatabase = mapDatabase; } - private static float mStrokeScale = 1.0f; + @Override + public IMapDatabase getMapDatabase() { + return mMapDatabase; + } - /** - * Sets the scale stroke factor for the given zoom level. - * - * @param zoomLevel - * the zoom level for which the scale stroke factor should be set. - */ - private static void setScaleStrokeWidth(byte zoomLevel) { - int zoomLevelDiff = Math.max(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0); - mStrokeScale = (float) Math.pow(STROKE_INCREASE, zoomLevelDiff); - if (mStrokeScale < 1) - mStrokeScale = 1; - // DatabaseRenderer.renderTheme.scaleStrokeWidth(mStrokeScale); + @Override + public void setRenderTheme(RenderTheme theme) { + MapGenerator.renderTheme = theme; } } diff --git a/src/org/mapsforge/android/glrenderer/MapRenderer.java b/src/org/mapsforge/android/glrenderer/MapRenderer.java index deb118d1..047af6dd 100644 --- a/src/org/mapsforge/android/glrenderer/MapRenderer.java +++ b/src/org/mapsforge/android/glrenderer/MapRenderer.java @@ -14,6 +14,57 @@ */ package org.mapsforge.android.glrenderer; +import static android.opengl.GLES20.GL_ARRAY_BUFFER; +import static android.opengl.GLES20.GL_BLEND; +import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; +import static android.opengl.GLES20.GL_DEPTH_TEST; +import static android.opengl.GLES20.GL_DITHER; +import static android.opengl.GLES20.GL_DYNAMIC_DRAW; +import static android.opengl.GLES20.GL_EQUAL; +import static android.opengl.GLES20.GL_EXTENSIONS; +import static android.opengl.GLES20.GL_FLOAT; +import static android.opengl.GLES20.GL_INVERT; +import static android.opengl.GLES20.GL_NEVER; +import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA; +import static android.opengl.GLES20.GL_SCISSOR_TEST; +import static android.opengl.GLES20.GL_SRC_ALPHA; +import static android.opengl.GLES20.GL_STENCIL_BUFFER_BIT; +import static android.opengl.GLES20.GL_STENCIL_TEST; +import static android.opengl.GLES20.GL_TRIANGLES; +import static android.opengl.GLES20.GL_TRIANGLE_FAN; +import static android.opengl.GLES20.GL_TRIANGLE_STRIP; +import static android.opengl.GLES20.GL_ZERO; +import static android.opengl.GLES20.glBindBuffer; +import static android.opengl.GLES20.glBlendFunc; +import static android.opengl.GLES20.glBufferData; +import static android.opengl.GLES20.glClear; +import static android.opengl.GLES20.glClearColor; +import static android.opengl.GLES20.glClearStencil; +import static android.opengl.GLES20.glColorMask; +import static android.opengl.GLES20.glDepthMask; +import static android.opengl.GLES20.glDisable; +import static android.opengl.GLES20.glDisableVertexAttribArray; +import static android.opengl.GLES20.glDrawArrays; +import static android.opengl.GLES20.glEnable; +import static android.opengl.GLES20.glEnableVertexAttribArray; +import static android.opengl.GLES20.glFinish; +import static android.opengl.GLES20.glGenBuffers; +import static android.opengl.GLES20.glGetAttribLocation; +import static android.opengl.GLES20.glGetString; +import static android.opengl.GLES20.glGetUniformLocation; +import static android.opengl.GLES20.glScissor; +import static android.opengl.GLES20.glStencilFunc; +import static android.opengl.GLES20.glStencilMask; +import static android.opengl.GLES20.glStencilOp; +import static android.opengl.GLES20.glUniform1f; +import static android.opengl.GLES20.glUniform2f; +import static android.opengl.GLES20.glUniform4f; +import static android.opengl.GLES20.glUniform4fv; +import static android.opengl.GLES20.glUniformMatrix4fv; +import static android.opengl.GLES20.glUseProgram; +import static android.opengl.GLES20.glVertexAttribPointer; +import static android.opengl.GLES20.glViewport; + import java.nio.FloatBuffer; import java.nio.ShortBuffer; import java.util.ArrayList; @@ -25,10 +76,9 @@ import javax.microedition.khronos.opengles.GL10; import org.mapsforge.android.DebugSettings; import org.mapsforge.android.MapView; -import org.mapsforge.android.mapgenerator.JobParameters; import org.mapsforge.android.mapgenerator.IMapGenerator; +import org.mapsforge.android.mapgenerator.JobParameters; import org.mapsforge.android.mapgenerator.MapGeneratorJob; -import org.mapsforge.android.mapgenerator.MapWorker; import org.mapsforge.android.mapgenerator.TileCacheKey; import org.mapsforge.android.mapgenerator.TileDistanceSort; import org.mapsforge.android.utils.GlConfigChooser; @@ -47,12 +97,15 @@ import android.util.Log; * TODO - use proxy child/parent tile nearer to current tile (currently it is always parent first) - use stencil instead * of scissor mask for rotation - draw up to two parents above current tile, maybe prefetch parent */ -public class MapRenderer implements org.mapsforge.android.MapRenderer { +public class MapRenderer implements org.mapsforge.android.IMapRenderer { private static final String TAG = "MapRenderer"; + private static final int MB = 1024 * 1024; + + private boolean mTriangulate = false; private static int CACHE_TILES_MAX = 400; private static int CACHE_TILES = CACHE_TILES_MAX; - private static final int LIMIT_BUFFERS = 32 * (1024 * 1024); + private static int LIMIT_BUFFERS = 20 * MB; private static final int OES_HALF_FLOAT = 0x8D61; private static final int FLOAT_BYTES = 4; @@ -64,8 +117,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { private static int STENCIL_BITS = 8; private final MapView mMapView; - private final MapWorker mMapWorker; - private final ArrayList mJobList; private final ArrayList mVBOs; private final TileCacheKey mTileCacheKey; @@ -88,9 +139,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { // current center tile private long mTileX, mTileY; - private FloatBuffer floatBuffer = null; - // private ByteBuffer byteBuffer = null; - private ShortBuffer shortBuffer = null; + private FloatBuffer floatBuffer[]; + private ShortBuffer shortBuffer[]; boolean useHalfFloat = false; @@ -147,7 +197,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { public MapRenderer(MapView mapView) { Log.d(TAG, "init MapRenderer"); mMapView = mapView; - mMapWorker = mapView.getMapWorker(); mDebugSettings = mapView.getDebugSettings(); mVBOs = new ArrayList(); @@ -316,7 +365,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { mJobList.clear(); mJobParameter = mMapView.getJobParameters(); - IMapGenerator mapGenerator = mMapView.getMapGenerator(); int tiles = 0; if (newTiles == null) return false; @@ -376,19 +424,19 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { newTiles.tiles[tiles++] = tile; if (!tile.isDrawn && !tile.newData && !tile.isLoading) { - MapGeneratorJob job = new MapGeneratorJob(tile, mapGenerator, - mJobParameter, mDebugSettings); + MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter, + mDebugSettings); mJobList.add(job); } // prefetch parent - if (tile.parent != null && !tile.parent.isDrawn && !tile.parent.newData - && !tile.parent.isLoading) { - MapGeneratorJob job = new MapGeneratorJob(tile.parent, mapGenerator, - mJobParameter, mDebugSettings); - if (!mJobList.contains(job)) - mJobList.add(job); - } + // if (tile.parent != null && !tile.parent.isDrawn && !tile.parent.newData + // && !tile.parent.isLoading) { + // MapGeneratorJob job = new MapGeneratorJob(tile.parent, mJobParameter, + // mDebugSettings); + // if (!mJobList.contains(job)) + // mJobList.add(job); + // } } } @@ -419,12 +467,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { limitCache(removes); - if (mJobList.size() > 0) { - mMapView.getJobQueue().setJobs(mJobList); - synchronized (mMapWorker) { - mMapWorker.notify(); - } - } + if (mJobList.size() > 0) + mMapView.addJobs(mJobList); return true; } @@ -513,7 +557,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { @Override public boolean passTile(MapGeneratorJob mapGeneratorJob) { - if (!timing) + if (!timing && mapGeneratorJob.tile.isVisible) mMapView.requestRender(); return true; } @@ -524,10 +568,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { boolean blend = false; // draw to framebuffer - GLES20.glColorMask(true, true, true, true); + glColorMask(true, true, true, true); // do not modify stencil buffer - GLES20.glStencilMask(0); + glStencilMask(0); for (int c = 0; c < count; c++) { PolygonLayer l = mFillPolys[c]; @@ -541,26 +585,26 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { alpha = 1.0f; if (!blend) { - GLES20.glEnable(GLES20.GL_BLEND); + glEnable(GL_BLEND); blend = true; } } else if (blend) { - GLES20.glDisable(GLES20.GL_BLEND); + glDisable(GL_BLEND); blend = false; } - GLES20.glUniform4f(gPolygonColorHandle, + glUniform4f(gPolygonColorHandle, l.colors[0], l.colors[1], l.colors[2], alpha); // set stencil buffer mask used to draw this layer - GLES20.glStencilFunc(GLES20.GL_EQUAL, 0xff, 1 << c); + glStencilFunc(GL_EQUAL, 0xff, 1 << c); // draw tile fill coordinates - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } if (blend) - GLES20.glDisable(GLES20.GL_BLEND); + glDisable(GL_BLEND); } private boolean drawPolygons(GLMapTile tile, int diff) { @@ -569,63 +613,68 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (tile.polygonLayers == null || tile.polygonLayers.array == null) return true; - GLES20.glScissor(tile.sx, tile.sy, tile.sw, tile.sh); + glScissor(tile.sx, tile.sy, tile.sw, tile.sh); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id); + if (mLastBoundVBO != tile.polygonVBO.id) { + mLastBoundVBO = tile.polygonVBO.id; + glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id); - if (useHalfFloat) { - GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2, - OES_HALF_FLOAT, false, 0, - POLYGON_VERTICES_DATA_POS_OFFSET); - } else { - GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2, - GLES20.GL_FLOAT, false, 0, - POLYGON_VERTICES_DATA_POS_OFFSET); + if (useHalfFloat) { + glVertexAttribPointer(gPolygonVertexPositionHandle, 2, + OES_HALF_FLOAT, false, 0, + POLYGON_VERTICES_DATA_POS_OFFSET); + } else { + glVertexAttribPointer(gPolygonVertexPositionHandle, 2, + GL_FLOAT, false, 0, + POLYGON_VERTICES_DATA_POS_OFFSET); + } + + // glBindBuffer(GL_ARRAY_BUFFER, 0); } - - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - setMatrix(tile, diff); - GLES20.glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0); + glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0); boolean firstPass = true; for (int i = 0, n = tile.polygonLayers.array.length; i < n; i++) { PolygonLayer l = tile.polygonLayers.array[i]; - if (cnt == 0) { - // disable drawing to framebuffer - GLES20.glColorMask(false, false, false, false); - - // never pass the test, i.e. always apply first stencil op (sfail) - GLES20.glStencilFunc(GLES20.GL_NEVER, 0, 0xff); - - if (firstPass) - firstPass = false; - else { - // clear stencilbuffer - GLES20.glStencilMask(0xFF); - GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT); - - // clear stencilbuffer (tile region) - // GLES20.glStencilOp(GLES20.GL_ZERO, GLES20.GL_ZERO, GLES20.GL_ZERO); - // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); - } - - // stencil op for stencil method polygon drawing - GLES20.glStencilOp(GLES20.GL_INVERT, GLES20.GL_INVERT, GLES20.GL_INVERT); - } - // fade out polygon layers (set in RederTheme) if (l.fadeLevel > 0 && l.fadeLevel > mDrawZ) continue; + if (cnt == 0) { + // disable drawing to framebuffer + glColorMask(false, false, false, false); + + // never pass the test, i.e. always apply first stencil op (sfail) + glStencilFunc(GL_NEVER, 0, 0xff); + + if (firstPass) + firstPass = false; + else { + // eeek, nexus! - cant do old-school polygons + // glFinish(); + + // clear stencilbuffer + glStencilMask(0xFF); + // glClear(GL_STENCIL_BUFFER_BIT); + + // clear stencilbuffer (tile region) + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + + // stencil op for stencil method polygon drawing + glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); + } + mFillPolys[cnt] = l; // set stencil mask to draw to - GLES20.glStencilMask(1 << cnt++); + glStencilMask(1 << cnt++); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, l.offset, l.verticesCnt); + glDrawArrays(GL_TRIANGLE_FAN, l.offset, l.verticesCnt); // draw up to 8 layers into stencil buffer if (cnt == STENCIL_BITS) { @@ -634,47 +683,54 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } } - if (cnt > 0) + if (cnt > 0) { fillPolygons(cnt); - + // eeek, nexus! - cant do old-school polygons + // glFinish(); + } return true; } + private int mLastBoundVBO; + private boolean drawTriangles(GLMapTile tile, int diff) { if (tile.meshLayers == null || tile.meshLayers.array == null) return true; - GLES20.glScissor(tile.sx, tile.sy, tile.sw, tile.sh); + glScissor(tile.sx, tile.sy, tile.sw, tile.sh); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id); + if (mLastBoundVBO != tile.polygonVBO.id) { + mLastBoundVBO = tile.polygonVBO.id; + glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id); - if (useHalfFloat) { - GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2, - OES_HALF_FLOAT, false, 0, - POLYGON_VERTICES_DATA_POS_OFFSET); - } else { - GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2, - GLES20.GL_FLOAT, false, 0, - POLYGON_VERTICES_DATA_POS_OFFSET); + if (useHalfFloat) { + glVertexAttribPointer(gPolygonVertexPositionHandle, 2, + OES_HALF_FLOAT, false, 0, + POLYGON_VERTICES_DATA_POS_OFFSET); + } else { + glVertexAttribPointer(gPolygonVertexPositionHandle, 2, + GL_FLOAT, false, 0, + POLYGON_VERTICES_DATA_POS_OFFSET); + } + + // glBindBuffer(GL_ARRAY_BUFFER, 0); } - - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - setMatrix(tile, diff); - GLES20.glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0); + glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0); MeshLayer[] layers = tile.meshLayers.array; for (int i = 0, n = layers.length; i < n; i++) { MeshLayer l = layers[i]; - GLES20.glUniform4fv(gPolygonColorHandle, 1, l.colors, 0); + glUniform4fv(gPolygonColorHandle, 1, l.colors, 0); - // GLES20.glUniform4f(gPolygonColorHandle, 1, 0, 0, 1); + // glUniform4f(gPolygonColorHandle, 1, 0, 0, 1); // System.out.println("draw: " + l.offset + " " + l.verticesCnt); - GLES20.glDrawArrays(GLES20.GL_TRIANGLES, l.offset, l.verticesCnt); + glDrawArrays(GL_TRIANGLES, l.offset, l.verticesCnt); } + return true; } @@ -684,30 +740,32 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (tile.lineLayers == null || tile.lineLayers.array == null) return false; - GLES20.glScissor(tile.sx, tile.sy, tile.sw, tile.sh); + glScissor(tile.sx, tile.sy, tile.sw, tile.sh); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.id); + if (mLastBoundVBO != tile.lineVBO.id) { + mLastBoundVBO = tile.lineVBO.id; + glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id); - if (useHalfFloat) { - GLES20.glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT, - false, 8, LINE_VERTICES_DATA_POS_OFFSET); + if (useHalfFloat) { + glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT, + false, 8, LINE_VERTICES_DATA_POS_OFFSET); - GLES20.glVertexAttribPointer(gLineTexturePositionHandle, 2, OES_HALF_FLOAT, - false, 8, LINE_VERTICES_DATA_TEX_OFFSET >> 1); - } else { - GLES20.glVertexAttribPointer(gLineVertexPositionHandle, 2, GLES20.GL_FLOAT, - false, 16, LINE_VERTICES_DATA_POS_OFFSET); + glVertexAttribPointer(gLineTexturePositionHandle, 2, OES_HALF_FLOAT, + false, 8, LINE_VERTICES_DATA_TEX_OFFSET >> 1); + } else { + glVertexAttribPointer(gLineVertexPositionHandle, 2, GL_FLOAT, + false, 16, LINE_VERTICES_DATA_POS_OFFSET); - GLES20.glVertexAttribPointer(gLineTexturePositionHandle, 2, GLES20.GL_FLOAT, - false, 16, LINE_VERTICES_DATA_TEX_OFFSET); + glVertexAttribPointer(gLineTexturePositionHandle, 2, GL_FLOAT, + false, 16, LINE_VERTICES_DATA_TEX_OFFSET); + } + // glBindBuffer(GL_ARRAY_BUFFER, 0); } - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - if (diff != 0) z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff); setMatrix(tile, diff); - GLES20.glUniformMatrix4fv(gLineMatrixHandle, 1, false, mMVPMatrix, 0); + glUniformMatrix4fv(gLineMatrixHandle, 1, false, mMVPMatrix, 0); LineLayer[] layers = tile.lineLayers.array; @@ -729,42 +787,37 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { drawFixed = l.isFixed; if (drawOutlines) { - GLES20.glUniform2f(gLineModeHandle, 0, wdiv); + glUniform2f(gLineModeHandle, 0, wdiv); } else if (!drawFixed) { - GLES20.glUniform2f(gLineModeHandle, 0, wdiv * 0.98f); + glUniform2f(gLineModeHandle, 0, wdiv * 0.98f); } } if (drawFixed) { if (l.width < 1.0) - GLES20.glUniform2f(gLineModeHandle, 0.4f, fdiv); + glUniform2f(gLineModeHandle, 0.4f, fdiv); else - GLES20.glUniform2f(gLineModeHandle, 0, fdiv); + glUniform2f(gLineModeHandle, 0, fdiv); } - GLES20.glUniform4fv(gLineColorHandle, 1, l.colors, 0); + glUniform4fv(gLineColorHandle, 1, l.colors, 0); if (drawOutlines) { for (int j = 0, m = l.outlines.size(); j < m; j++) { LineLayer o = l.outlines.get(j); if (mSimpleLines) - GLES20.glUniform1f(gLineWidthHandle, o.width); + glUniform1f(gLineWidthHandle, o.width); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt); + glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt); } } else { if (mSimpleLines) - GLES20.glUniform1f(gLineWidthHandle, l.width); + glUniform1f(gLineWidthHandle, l.width); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt); + glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt); } - // cnt += l.verticesCnt; } - // GLES20.glUniform2f(gLineModeHandle, 0, wdiv); - // float[] c = { 1, 0, 0, 1 }; - // GLES20.glUniform4fv(gLineColorHandle, 1, c, 0); - // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, cnt); return true; } @@ -940,47 +993,53 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } } - private boolean mTriangulate = false; - private int uploadCnt = 0; private boolean uploadTileData(GLMapTile tile) { - // not sure about this, but seems it fixes some flickering when - // multiple tiles are uploaded in one go. but if this is really - // the issue tiles should stay corrupted.. - if (uploadCnt++ > 0) - GLES20.glFinish(); + // double start = SystemClock.uptimeMillis(); + // use multiple buffers to avoid overwriting buffer while current data is uploaded + // (or rather the blocking which is required to avoid this) + if (uploadCnt >= 10) { + // mMapView.requestRender(); + // return false; + uploadCnt = 0; + glFinish(); + } + + // Upload line data to vertex buffer object if (tile.lineVBO == null) { - // Upload line data to vertex buffer object synchronized (mVBOs) { - if (mVBOs.size() < 2) + if (mVBOs.size() < 2) { + Log.d(TAG, "uploadTileData, no VBOs left"); return false; - + } tile.lineVBO = mVBOs.remove(mVBOs.size() - 1); tile.polygonVBO = mVBOs.remove(mVBOs.size() - 1); } } if (useHalfFloat) - shortBuffer = tile.lineLayers.compileLayerData(shortBuffer); + shortBuffer[uploadCnt * 2] = tile.lineLayers + .compileLayerData(shortBuffer[uploadCnt * 2]); else - floatBuffer = tile.lineLayers.compileLayerData(floatBuffer); + floatBuffer[uploadCnt * 2] = tile.lineLayers + .compileLayerData(floatBuffer[uploadCnt * 2]); if (tile.lineLayers.size > 0) { mBufferMemoryUsage -= tile.lineVBO.size; - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.id); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, GLES20.GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id); + // glBufferData(GL_ARRAY_BUFFER, 0, null, GL_DYNAMIC_DRAW); if (useHalfFloat) { tile.lineVBO.size = tile.lineLayers.size * SHORT_BYTES; - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.size, - shortBuffer, GLES20.GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size, + shortBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW); } else { tile.lineVBO.size = tile.lineLayers.size * FLOAT_BYTES; - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.lineVBO.size, - floatBuffer, GLES20.GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size, + floatBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW); } mBufferMemoryUsage += tile.lineVBO.size; @@ -991,26 +1050,28 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (!mTriangulate) { if (useHalfFloat) - shortBuffer = tile.polygonLayers.compileLayerData(shortBuffer); + shortBuffer[uploadCnt * 2 + 1] = tile.polygonLayers + .compileLayerData(shortBuffer[uploadCnt * 2 + 1]); else - floatBuffer = tile.polygonLayers.compileLayerData(floatBuffer); + floatBuffer[uploadCnt * 2 + 1] = tile.polygonLayers + .compileLayerData(floatBuffer[uploadCnt * 2 + 1]); // Upload polygon data to vertex buffer object if (tile.polygonLayers.size > 0) { mBufferMemoryUsage -= tile.polygonVBO.size; - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, - GLES20.GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id); + // glBufferData(GL_ARRAY_BUFFER, 0, null, + // GL_DYNAMIC_DRAW); if (useHalfFloat) { tile.polygonVBO.size = tile.polygonLayers.size * SHORT_BYTES; - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, - shortBuffer, GLES20.GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size, + shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW); } else { tile.polygonVBO.size = tile.polygonLayers.size * FLOAT_BYTES; - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, - floatBuffer, GLES20.GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size, + floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW); } mBufferMemoryUsage += tile.polygonVBO.size; @@ -1020,26 +1081,28 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } else { if (useHalfFloat) - shortBuffer = tile.meshLayers.compileLayerData(shortBuffer); + shortBuffer[uploadCnt * 2 + 1] = tile.meshLayers + .compileLayerData(shortBuffer[uploadCnt * 2 + 1]); else - floatBuffer = tile.meshLayers.compileLayerData(floatBuffer); + floatBuffer[uploadCnt * 2 + 1] = tile.meshLayers + .compileLayerData(floatBuffer[uploadCnt * 2 + 1]); // Upload triangle data to vertex buffer object if (tile.meshLayers.size > 0) { mBufferMemoryUsage -= tile.polygonVBO.size; - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, - GLES20.GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id); + // glBufferData(GL_ARRAY_BUFFER, 0, null, + // GL_DYNAMIC_DRAW); if (useHalfFloat) { tile.polygonVBO.size = tile.meshLayers.size * SHORT_BYTES; - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, - shortBuffer, GLES20.GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size, + shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW); } else { tile.polygonVBO.size = tile.meshLayers.size * FLOAT_BYTES; - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, - floatBuffer, GLES20.GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size, + floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW); } mBufferMemoryUsage += tile.polygonVBO.size; @@ -1050,6 +1113,13 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { tile.newData = false; tile.isDrawn = true; tile.isLoading = false; + // double compile = SystemClock.uptimeMillis(); + // glFinish(); + // double now = SystemClock.uptimeMillis(); + // Log.d(TAG, tile + " - upload took: " + (now - start) + " " + // + (mBufferMemoryUsage / 1024) + "kb"); + + uploadCnt++; return true; } @@ -1066,10 +1136,9 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (timing) start = SystemClock.uptimeMillis(); - GLES20.glStencilMask(0xFF); - GLES20.glDisable(GLES20.GL_SCISSOR_TEST); - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT); - // GLES20.glFlush(); + glStencilMask(0xFF); + glDisable(GL_SCISSOR_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // long endTime = SystemClock.uptimeMillis(); // long dt = endTime - startTime; @@ -1100,22 +1169,21 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { GLMapTile[] tiles = curTiles.tiles; if (mBufferMemoryUsage > LIMIT_BUFFERS) { - Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / (1024 * 1024) - + "MB"); + Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB"); synchronized (mVBOs) { for (VertexBufferObject vbo : mVBOs) { if (vbo.size == 0) continue; mBufferMemoryUsage -= vbo.size; - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, - GLES20.GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, vbo.id); + glBufferData(GL_ARRAY_BUFFER, 0, null, + GL_DYNAMIC_DRAW); vbo.size = 0; } - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); } - Log.d(TAG, " > " + mBufferMemoryUsage / (1024 * 1024) + "MB"); + Log.d(TAG, " > " + mBufferMemoryUsage / MB + "MB"); if (CACHE_TILES > 50) CACHE_TILES -= 50; @@ -1124,6 +1192,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } uploadCnt = 0; + mLastBoundVBO = -1; // check visible tiles, set tile clip scissors, upload new vertex data for (int i = 0; i < tileCnt; i++) { @@ -1134,11 +1203,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (tile.newData) { uploadTileData(tile); - - if (timing) - Log.d(TAG, "buffer upload took: " - + (SystemClock.uptimeMillis() - start)); - continue; } @@ -1158,23 +1222,25 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } } } - // GLES20.glFinish(); - GlUtils.checkGlError("upload"); + + if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage) + && LIMIT_BUFFERS > MB) + LIMIT_BUFFERS -= MB; if (timing) clear_time = (SystemClock.uptimeMillis() - start); - GLES20.glEnable(GLES20.GL_SCISSOR_TEST); + glEnable(GL_SCISSOR_TEST); - GLES20.glUseProgram(gPolygonProgram); - // GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle); + glUseProgram(gPolygonProgram); + glEnableVertexAttribArray(gPolygonVertexPositionHandle); if (!mTriangulate) { - GLES20.glDisable(GLES20.GL_BLEND); + glDisable(GL_BLEND); // Draw Polygons - GLES20.glEnable(GLES20.GL_STENCIL_TEST); + glEnable(GL_STENCIL_TEST); - // GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle); + // glEnableVertexAttribArray(gPolygonVertexPositionHandle); for (int i = 0; i < tileCnt; i++) { if (tiles[i].isVisible) { @@ -1186,8 +1252,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { drawProxyPolygons(tile); } } - GlUtils.checkGlError("polygons"); - GLES20.glDisable(GLES20.GL_STENCIL_TEST); + // GlUtils.checkGlError("polygons"); + glDisable(GL_STENCIL_TEST); } else { // Draw Triangles for (int i = 0; i < tileCnt; i++) { @@ -1200,23 +1266,22 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { drawProxyTriangles(tile); } } - GlUtils.checkGlError("triangles"); + // GlUtils.checkGlError("triangles"); } - // required on GalaxyII, Android 2.3.3 - // GLES20.glDisableVertexAttribArray(gPolygonVertexPositionHandle); + // required on GalaxyII, Android 2.3.3 (cant just VAA enable once...) + glDisableVertexAttribArray(gPolygonVertexPositionHandle); if (timing) { - GLES20.glFinish(); + glFinish(); poly_time = (SystemClock.uptimeMillis() - start); } - GLES20.glFlush(); // Draw lines - GLES20.glEnable(GLES20.GL_BLEND); - GLES20.glUseProgram(gLineProgram); + glEnable(GL_BLEND); + glUseProgram(gLineProgram); - // GLES20.glEnableVertexAttribArray(gLineVertexPositionHandle); - // GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle); + glEnableVertexAttribArray(gLineVertexPositionHandle); + glEnableVertexAttribArray(gLineTexturePositionHandle); for (int i = 0; i < tileCnt; i++) { if (tiles[i].isVisible) { @@ -1230,14 +1295,13 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } if (timing) { - GLES20.glFinish(); + glFinish(); Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " " + clear_time + " " + poly_time); } - // GLES20.glDisableVertexAttribArray(gLineVertexPositionHandle); - // GLES20.glDisableVertexAttribArray(gLineTexturePositionHandle); - GlUtils.checkGlError("lines"); - GLES20.glFinish(); + glDisableVertexAttribArray(gLineVertexPositionHandle); + glDisableVertexAttribArray(gLineTexturePositionHandle); + // GlUtils.checkGlError("lines"); } private int[] mVboIds; @@ -1261,7 +1325,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { mHeight = height; mAspect = (float) height / width; - GLES20.glViewport(0, 0, width, height); + glViewport(0, 0, width, height); int tiles = (mWidth / Tile.TILE_SIZE + 4) * (mHeight / Tile.TILE_SIZE + 4); curTiles = new TilesData(tiles); @@ -1271,7 +1335,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { // Set up vertex buffer objects int numVBO = (CACHE_TILES + tiles) * 2; mVboIds = new int[numVBO]; - GLES20.glGenBuffers(numVBO, mVboIds, 0); + glGenBuffers(numVBO, mVboIds, 0); for (int i = 0; i < numVBO; i++) mVBOs.add(new VertexBufferObject(mVboIds[i])); @@ -1302,21 +1366,25 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } } - String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS); + String ext = glGetString(GL_EXTENSIONS); - if (ext.indexOf("GL_OES_vertex_half_float") >= 0) + if (ext.indexOf("GL_OES_vertex_half_float") >= 0) { useHalfFloat = true; - + shortBuffer = new ShortBuffer[20]; + } + else { + floatBuffer = new FloatBuffer[20]; + } Log.d(TAG, "Extensions: " + ext); - gLineMatrixHandle = GLES20.glGetUniformLocation(gLineProgram, "u_center"); - gLineModeHandle = GLES20.glGetUniformLocation(gLineProgram, "u_mode"); - gLineColorHandle = GLES20.glGetUniformLocation(gLineProgram, "u_color"); + gLineMatrixHandle = glGetUniformLocation(gLineProgram, "u_center"); + gLineModeHandle = glGetUniformLocation(gLineProgram, "u_mode"); + gLineColorHandle = glGetUniformLocation(gLineProgram, "u_color"); gLineVertexPositionHandle = GLES20 .glGetAttribLocation(gLineProgram, "a_position"); - gLineTexturePositionHandle = GLES20.glGetAttribLocation(gLineProgram, "a_st"); + gLineTexturePositionHandle = glGetAttribLocation(gLineProgram, "a_st"); if (mSimpleLines) - gLineWidthHandle = GLES20.glGetUniformLocation(gLineProgram, "u_width"); + gLineWidthHandle = glGetUniformLocation(gLineProgram, "u_width"); // Set up the program for rendering polygons gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader, @@ -1325,31 +1393,39 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { Log.e(TAG, "Could not create polygon program."); return; } - gPolygonMatrixHandle = GLES20.glGetUniformLocation(gPolygonProgram, "u_center"); - gPolygonVertexPositionHandle = GLES20.glGetAttribLocation(gPolygonProgram, + gPolygonMatrixHandle = glGetUniformLocation(gPolygonProgram, "u_center"); + gPolygonVertexPositionHandle = glGetAttribLocation(gPolygonProgram, "a_position"); - gPolygonColorHandle = GLES20.glGetUniformLocation(gPolygonProgram, "u_color"); + gPolygonColorHandle = glGetUniformLocation(gPolygonProgram, "u_color"); - GLES20.glUseProgram(gPolygonProgram); - GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle); + // glUseProgram(gPolygonProgram); + // glEnableVertexAttribArray(gPolygonVertexPositionHandle); + // + // glUseProgram(gLineProgram); + // glEnableVertexAttribArray(gLineVertexPositionHandle); + // glEnableVertexAttribArray(gLineTexturePositionHandle); - GLES20.glUseProgram(gLineProgram); - GLES20.glEnableVertexAttribArray(gLineVertexPositionHandle); - GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); - - GLES20.glDisable(GLES20.GL_DEPTH_TEST); - GLES20.glDepthMask(false); - GLES20.glDisable(GLES20.GL_DITHER); - GLES20.glClearColor(0.98f, 0.98f, 0.97f, 1.0f); - GLES20.glClearStencil(0); - - // GLES20.glFrontFace(GLES20.GL_CCW); + glDisable(GL_DEPTH_TEST); + glDepthMask(false); + glDisable(GL_DITHER); + glClearColor(0.98f, 0.98f, 0.97f, 1.0f); + glClearStencil(0); } @Override public boolean processedTile() { return true; } + + public IMapGenerator getMapGenerator() { + return new MapGenerator(); + } + + @Override + public IMapGenerator createMapGenerator() { + return new MapGenerator(); + + } } diff --git a/src/org/mapsforge/android/glrenderer/PolygonLayers.java b/src/org/mapsforge/android/glrenderer/PolygonLayers.java index 66ae641c..ebb35401 100644 --- a/src/org/mapsforge/android/glrenderer/PolygonLayers.java +++ b/src/org/mapsforge/android/glrenderer/PolygonLayers.java @@ -75,7 +75,7 @@ class PolygonLayers { // Log.d("GLMap", "allocate buffer " + size); fbuf = bbuf.asFloatBuffer(); } else { - fbuf.position(0); + fbuf.clear(); } fbuf.put(mFillCoords, 0, 8); @@ -95,7 +95,7 @@ class PolygonLayers { l.pool = null; } - fbuf.position(0); + fbuf.flip(); // not needed for drawing layers = null; @@ -121,7 +121,7 @@ class PolygonLayers { ByteOrder.nativeOrder()); sbuf = bbuf.asShortBuffer(); } else { - sbuf.position(0); + sbuf.clear(); } short[] data = new short[PoolItem.SIZE]; @@ -157,7 +157,7 @@ class PolygonLayers { l.pool = null; } - sbuf.position(0); + sbuf.flip(); // not needed for drawing layers = null; diff --git a/src/org/mapsforge/android/mapgenerator/IMapGenerator.java b/src/org/mapsforge/android/mapgenerator/IMapGenerator.java index 9134e312..344c1d11 100644 --- a/src/org/mapsforge/android/mapgenerator/IMapGenerator.java +++ b/src/org/mapsforge/android/mapgenerator/IMapGenerator.java @@ -14,9 +14,7 @@ */ package org.mapsforge.android.mapgenerator; -import org.mapsforge.android.MapRenderer; -import org.mapsforge.android.MapView; -import org.mapsforge.core.GeoPoint; +import org.mapsforge.android.rendertheme.RenderTheme; import org.mapsforge.database.IMapDatabase; /** @@ -37,31 +35,13 @@ public interface IMapGenerator { */ boolean executeJob(MapGeneratorJob mapGeneratorJob); - /** - * @return the start point of this MapGenerator (may be null). - */ - GeoPoint getStartPoint(); - - /** - * @return the start zoom level of this MapGenerator (may be null). - */ - Byte getStartZoomLevel(); - - /** - * @return the maximum zoom level that this MapGenerator supports. - */ - byte getZoomLevelMax(); - - /** - * @param mapView - * the MapView - * @return GLSurfaceView Renderer - */ - MapRenderer getMapRenderer(MapView mapView); - /** * @param mapDatabase * the MapDatabase from which the map data will be read. */ void setMapDatabase(IMapDatabase mapDatabase); + + IMapDatabase getMapDatabase(); + + void setRenderTheme(RenderTheme theme); } diff --git a/src/org/mapsforge/android/mapgenerator/JobParameters.java b/src/org/mapsforge/android/mapgenerator/JobParameters.java index 3e95b469..b9be2257 100644 --- a/src/org/mapsforge/android/mapgenerator/JobParameters.java +++ b/src/org/mapsforge/android/mapgenerator/JobParameters.java @@ -22,7 +22,7 @@ public class JobParameters { /** * The render theme which should be used. */ - public final JobTheme jobTheme; + public final Theme theme; /** * The text scale factor which should applied to the render theme. @@ -32,13 +32,13 @@ public class JobParameters { private final int mHashCodeValue; /** - * @param jobTheme + * @param theme * render theme which should be used. * @param textScale * the text scale factor which should applied to the render theme. */ - public JobParameters(JobTheme jobTheme, float textScale) { - this.jobTheme = jobTheme; + public JobParameters(Theme theme, float textScale) { + this.theme = theme; this.textScale = textScale; mHashCodeValue = calculateHashCode(); } @@ -52,11 +52,11 @@ public class JobParameters { return false; } JobParameters other = (JobParameters) obj; - if (jobTheme == null) { - if (other.jobTheme != null) { + if (theme == null) { + if (other.theme != null) { return false; } - } else if (!jobTheme.equals(other.jobTheme)) { + } else if (!theme.equals(other.theme)) { return false; } if (Float.floatToIntBits(textScale) != Float.floatToIntBits(other.textScale)) { @@ -75,7 +75,7 @@ public class JobParameters { */ private int calculateHashCode() { int result = 7; - result = 31 * result + ((jobTheme == null) ? 0 : jobTheme.hashCode()); + result = 31 * result + ((theme == null) ? 0 : theme.hashCode()); result = 31 * result + Float.floatToIntBits(textScale); return result; } diff --git a/src/org/mapsforge/android/mapgenerator/JobQueue.java b/src/org/mapsforge/android/mapgenerator/JobQueue.java index 9b4db9d8..a2445204 100644 --- a/src/org/mapsforge/android/mapgenerator/JobQueue.java +++ b/src/org/mapsforge/android/mapgenerator/JobQueue.java @@ -103,7 +103,8 @@ public class JobQueue { * Schedules all jobs in this queue. */ private void schedule() { - PriorityQueue tempJobQueue = new PriorityQueue(INITIAL_CAPACITY); + PriorityQueue tempJobQueue = new PriorityQueue( + INITIAL_CAPACITY); TileScheduler.time = SystemClock.uptimeMillis(); TileScheduler.mapPosition = mMapView.getMapPosition().getMapPosition(); diff --git a/src/org/mapsforge/android/mapgenerator/MapDatabaseFactory.java b/src/org/mapsforge/android/mapgenerator/MapDatabaseFactory.java index 41f581d6..12bed3b1 100644 --- a/src/org/mapsforge/android/mapgenerator/MapDatabaseFactory.java +++ b/src/org/mapsforge/android/mapgenerator/MapDatabaseFactory.java @@ -37,29 +37,40 @@ public final class MapDatabaseFactory { return new org.mapsforge.database.postgis.MapDatabase(); } - MapDatabaseInternal mapDatabaseInternal = MapDatabaseInternal - .valueOf(mapDatabaseName); + MapDatabases mapDatabaseInternal = MapDatabases.valueOf(mapDatabaseName); return MapDatabaseFactory.createMapDatabase(mapDatabaseInternal); } + public static MapDatabases getMapDatabase(AttributeSet attributeSet) { + String mapDatabaseName = attributeSet.getAttributeValue(null, + MAP_DATABASE_ATTRIBUTE_NAME); + if (mapDatabaseName == null) { + return MapDatabases.POSTGIS_READER; + } + + return MapDatabases.valueOf(mapDatabaseName); + } + /** - * @param mapDatabaseInternal + * @param mapDatabase * the internal MapDatabase implementation. * @return a new MapGenerator instance. */ - public static IMapDatabase createMapDatabase(MapDatabaseInternal mapDatabaseInternal) { - switch (mapDatabaseInternal) { + public static IMapDatabase createMapDatabase(MapDatabases mapDatabase) { + switch (mapDatabase) { case MAP_READER: return new org.mapsforge.database.mapfile.MapDatabase(); case JSON_READER: return new org.mapsforge.database.json.MapDatabase(); case POSTGIS_READER: return new org.mapsforge.database.postgis.MapDatabase(); + case PBMAP_READER: + return new org.mapsforge.database.pbmap.MapDatabase(); } - throw new IllegalArgumentException("unknown enum value: " + mapDatabaseInternal); + throw new IllegalArgumentException("unknown enum value: " + mapDatabase); } private MapDatabaseFactory() { diff --git a/src/org/mapsforge/android/mapgenerator/MapDatabaseInternal.java b/src/org/mapsforge/android/mapgenerator/MapDatabases.java similarity index 93% rename from src/org/mapsforge/android/mapgenerator/MapDatabaseInternal.java rename to src/org/mapsforge/android/mapgenerator/MapDatabases.java index da134d68..370f0347 100644 --- a/src/org/mapsforge/android/mapgenerator/MapDatabaseInternal.java +++ b/src/org/mapsforge/android/mapgenerator/MapDatabases.java @@ -17,7 +17,7 @@ package org.mapsforge.android.mapgenerator; /** * MapDatabase Implementations */ -public enum MapDatabaseInternal { +public enum MapDatabases { /** * ... */ @@ -33,4 +33,8 @@ public enum MapDatabaseInternal { */ POSTGIS_READER, + /** + * ... + */ + PBMAP_READER, } diff --git a/src/org/mapsforge/android/mapgenerator/MapGeneratorJob.java b/src/org/mapsforge/android/mapgenerator/MapGeneratorJob.java index 476d3b1d..bab438b9 100644 --- a/src/org/mapsforge/android/mapgenerator/MapGeneratorJob.java +++ b/src/org/mapsforge/android/mapgenerator/MapGeneratorJob.java @@ -37,7 +37,7 @@ public class MapGeneratorJob implements Comparable, Serializabl /** * The rendering parameters for this job. */ - public final JobParameters jobParameters; + // public final JobParameters jobParameters; /** * The tile which should be generated. @@ -45,7 +45,6 @@ public class MapGeneratorJob implements Comparable, Serializabl public final MapTile tile; private transient int mHashCodeValue; - private final IMapGenerator mMapGenerator; private transient double mPriority; /** @@ -90,18 +89,15 @@ public class MapGeneratorJob implements Comparable, Serializabl * * @param _tile * the tile which should be generated. - * @param mapGenerator - * the MapGenerator for this job. * @param _jobParameters * the rendering parameters for this job. * @param _debugSettings * the debug settings for this job. */ - public MapGeneratorJob(MapTile _tile, IMapGenerator mapGenerator, - JobParameters _jobParameters, DebugSettings _debugSettings) { + public MapGeneratorJob(MapTile _tile, JobParameters _jobParameters, + DebugSettings _debugSettings) { tile = _tile; - mMapGenerator = mapGenerator; - jobParameters = _jobParameters; + // jobParameters = _jobParameters; debugSettings = _debugSettings; calculateTransientValues(); } @@ -133,16 +129,14 @@ public class MapGeneratorJob implements Comparable, Serializabl } else if (!debugSettings.equals(other.debugSettings)) { return false; } - if (jobParameters == null) { - if (other.jobParameters != null) { - return false; - } - } else if (!jobParameters.equals(other.jobParameters)) { - return false; - } - if (mMapGenerator != other.mMapGenerator) { - return false; - } + // if (jobParameters == null) { + // if (other.jobParameters != null) { + // return false; + // } + // } else if (!jobParameters.equals(other.jobParameters)) { + // return false; + // } + if (tile == null) { if (other.tile != null) { return false; @@ -164,8 +158,7 @@ public class MapGeneratorJob implements Comparable, Serializabl private int calculateHashCode() { int result = 1; result = 31 * result + ((debugSettings == null) ? 0 : debugSettings.hashCode()); - result = 31 * result + ((jobParameters == null) ? 0 : jobParameters.hashCode()); - result = 31 * result + ((mMapGenerator == null) ? 0 : mMapGenerator.hashCode()); + // result = 31 * result + ((jobParameters == null) ? 0 : jobParameters.hashCode()); result = 31 * result + ((tile == null) ? 0 : tile.hashCode()); return result; } @@ -177,7 +170,8 @@ public class MapGeneratorJob implements Comparable, Serializabl mHashCodeValue = calculateHashCode(); } - private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { + private void readObject(ObjectInputStream objectInputStream) throws IOException, + ClassNotFoundException { objectInputStream.defaultReadObject(); calculateTransientValues(); } diff --git a/src/org/mapsforge/android/mapgenerator/MapGeneratorFactory.java b/src/org/mapsforge/android/mapgenerator/MapRendererFactory.java similarity index 57% rename from src/org/mapsforge/android/mapgenerator/MapGeneratorFactory.java rename to src/org/mapsforge/android/mapgenerator/MapRendererFactory.java index a80d9465..5b20ca60 100644 --- a/src/org/mapsforge/android/mapgenerator/MapGeneratorFactory.java +++ b/src/org/mapsforge/android/mapgenerator/MapRendererFactory.java @@ -14,46 +14,66 @@ */ package org.mapsforge.android.mapgenerator; +import org.mapsforge.android.IMapRenderer; +import org.mapsforge.android.MapView; + import android.util.AttributeSet; /** * A factory for the internal MapGenerator implementations. */ -public final class MapGeneratorFactory { +public final class MapRendererFactory { private static final String MAP_GENERATOR_ATTRIBUTE_NAME = "mapGenerator"; /** + * @param mapView + * ... * @param attributeSet * A collection of attributes which includes the desired MapGenerator. * @return a new MapGenerator instance. */ - public static IMapGenerator createMapGenerator(AttributeSet attributeSet) { - String mapGeneratorName = attributeSet.getAttributeValue(null, MAP_GENERATOR_ATTRIBUTE_NAME); + public static IMapRenderer createMapRenderer(MapView mapView, + AttributeSet attributeSet) { + String mapGeneratorName = attributeSet.getAttributeValue(null, + MAP_GENERATOR_ATTRIBUTE_NAME); if (mapGeneratorName == null) { - return new org.mapsforge.android.glrenderer.DatabaseRenderer(); + return new org.mapsforge.android.glrenderer.MapRenderer(mapView); } - MapGeneratorInternal mapGeneratorInternal = MapGeneratorInternal.valueOf(mapGeneratorName); - return MapGeneratorFactory.createMapGenerator(mapGeneratorInternal); + MapRenderers mapGeneratorInternal = MapRenderers.valueOf(mapGeneratorName); + return MapRendererFactory.createMapRenderer(mapView, mapGeneratorInternal); + } + + public static MapRenderers getMapGenerator(AttributeSet attributeSet) { + String mapGeneratorName = attributeSet.getAttributeValue(null, + MAP_GENERATOR_ATTRIBUTE_NAME); + if (mapGeneratorName == null) { + return MapRenderers.GL_RENDERER; + } + + return MapRenderers.valueOf(mapGeneratorName); } /** + * @param mapView + * ... * @param mapGeneratorInternal * the internal MapGenerator implementation. * @return a new MapGenerator instance. */ - public static IMapGenerator createMapGenerator(MapGeneratorInternal mapGeneratorInternal) { + public static IMapRenderer createMapRenderer(MapView mapView, + MapRenderers mapGeneratorInternal) { switch (mapGeneratorInternal) { case SW_RENDERER: - return new org.mapsforge.android.swrenderer.DatabaseRenderer(); + return new org.mapsforge.android.swrenderer.MapRenderer(mapView); case GL_RENDERER: - return new org.mapsforge.android.glrenderer.DatabaseRenderer(); + return new org.mapsforge.android.glrenderer.MapRenderer(mapView); } throw new IllegalArgumentException("unknown enum value: " + mapGeneratorInternal); } - private MapGeneratorFactory() { + private MapRendererFactory() { throw new IllegalStateException(); } } diff --git a/src/org/mapsforge/android/mapgenerator/MapGeneratorInternal.java b/src/org/mapsforge/android/mapgenerator/MapRenderers.java similarity index 96% rename from src/org/mapsforge/android/mapgenerator/MapGeneratorInternal.java rename to src/org/mapsforge/android/mapgenerator/MapRenderers.java index cab28c0e..fcf36dc2 100644 --- a/src/org/mapsforge/android/mapgenerator/MapGeneratorInternal.java +++ b/src/org/mapsforge/android/mapgenerator/MapRenderers.java @@ -17,7 +17,7 @@ package org.mapsforge.android.mapgenerator; /** * Enumeration of all internal MapGenerator implementations. */ -public enum MapGeneratorInternal { +public enum MapRenderers { /** * texture renderer. */ diff --git a/src/org/mapsforge/android/mapgenerator/MapWorker.java b/src/org/mapsforge/android/mapgenerator/MapWorker.java index 1e9cdb77..dcf1409b 100644 --- a/src/org/mapsforge/android/mapgenerator/MapWorker.java +++ b/src/org/mapsforge/android/mapgenerator/MapWorker.java @@ -14,7 +14,7 @@ */ package org.mapsforge.android.mapgenerator; -import org.mapsforge.android.MapRenderer; +import org.mapsforge.android.IMapRenderer; import org.mapsforge.android.MapView; import org.mapsforge.android.utils.PausableThread; @@ -23,35 +23,33 @@ import org.mapsforge.android.utils.PausableThread; * thread. */ public class MapWorker extends PausableThread { - private static final String THREAD_NAME = "MapWorker"; - + private final String THREAD_NAME; private final JobQueue mJobQueue; - private IMapGenerator mMapGenerator; - private MapRenderer mMapRenderer; + private final IMapGenerator mMapGenerator; + private final IMapRenderer mMapRenderer; /** + * @param id + * thread id * @param mapView * the MapView for which this MapWorker generates map tiles. + * @param mapGenerator + * ... + * @param mapRenderer + * ... */ - public MapWorker(MapView mapView) { + public MapWorker(int id, MapView mapView, IMapGenerator mapGenerator, + IMapRenderer mapRenderer) { super(); mJobQueue = mapView.getJobQueue(); - } - - /** - * @param mapGenerator - * the MapGenerator which this MapWorker should use. - */ - public void setMapGenerator(IMapGenerator mapGenerator) { mMapGenerator = mapGenerator; + mMapRenderer = mapRenderer; + + THREAD_NAME = "MapWorker" + id; } - /** - * @param mapRenderer - * the MapRenderer - */ - public void setMapRenderer(MapRenderer mapRenderer) { - mMapRenderer = mapRenderer; + public IMapGenerator getMapGenerator() { + return mMapGenerator; } @Override @@ -65,6 +63,7 @@ public class MapWorker extends PausableThread { if (mMapGenerator == null || mapGeneratorJob == null) return; + // Log.d(THREAD_NAME, "processing: " + mapGeneratorJob.tile); boolean success = mMapGenerator.executeJob(mapGeneratorJob); @@ -80,7 +79,8 @@ public class MapWorker extends PausableThread { @Override protected int getThreadPriority() { - return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 2; + // return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 2; + return Thread.MIN_PRIORITY; } @Override diff --git a/src/org/mapsforge/android/mapgenerator/JobTheme.java b/src/org/mapsforge/android/mapgenerator/Theme.java similarity index 96% rename from src/org/mapsforge/android/mapgenerator/JobTheme.java rename to src/org/mapsforge/android/mapgenerator/Theme.java index b1913c54..41eb4816 100644 --- a/src/org/mapsforge/android/mapgenerator/JobTheme.java +++ b/src/org/mapsforge/android/mapgenerator/Theme.java @@ -21,7 +21,7 @@ import java.io.Serializable; /** * A JobTheme defines the render theme which is used for a {@link MapGeneratorJob}. */ -public interface JobTheme extends Serializable { +public interface Theme extends Serializable { /** * @return an InputStream to read the render theme data from. * @throws FileNotFoundException diff --git a/src/org/mapsforge/android/rendertheme/ExternalRenderTheme.java b/src/org/mapsforge/android/rendertheme/ExternalRenderTheme.java index 0b2aab15..6fee1a04 100644 --- a/src/org/mapsforge/android/rendertheme/ExternalRenderTheme.java +++ b/src/org/mapsforge/android/rendertheme/ExternalRenderTheme.java @@ -21,12 +21,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; -import org.mapsforge.android.mapgenerator.JobTheme; +import org.mapsforge.android.mapgenerator.Theme; /** * An ExternalRenderTheme allows for customizing the rendering style of the map via an XML file. */ -public class ExternalRenderTheme implements JobTheme { +public class ExternalRenderTheme implements Theme { private static final long serialVersionUID = 1L; private final long mFileModificationDate; diff --git a/src/org/mapsforge/android/rendertheme/InternalRenderTheme.java b/src/org/mapsforge/android/rendertheme/InternalRenderTheme.java index 23b523d5..af245c0f 100644 --- a/src/org/mapsforge/android/rendertheme/InternalRenderTheme.java +++ b/src/org/mapsforge/android/rendertheme/InternalRenderTheme.java @@ -16,12 +16,12 @@ package org.mapsforge.android.rendertheme; import java.io.InputStream; -import org.mapsforge.android.mapgenerator.JobTheme; +import org.mapsforge.android.mapgenerator.Theme; /** * Enumeration of all internal rendering themes. */ -public enum InternalRenderTheme implements JobTheme { +public enum InternalRenderTheme implements Theme { /** * A rendering theme similar to the OpenStreetMap Osmarender style. * @@ -37,6 +37,9 @@ public enum InternalRenderTheme implements JobTheme { @Override public InputStream getRenderThemeAsStream() { - return Thread.currentThread().getClass().getResourceAsStream(mPath); + // getResourceAsStream(mPath); + return InternalRenderTheme.class.getResourceAsStream(mPath); + // return Thread.currentThread().getClass().getResourceAsStream(mPath); + } } diff --git a/src/org/mapsforge/android/rendertheme/RenderTheme.java b/src/org/mapsforge/android/rendertheme/RenderTheme.java index c8d9b7fe..74b7b39d 100644 --- a/src/org/mapsforge/android/rendertheme/RenderTheme.java +++ b/src/org/mapsforge/android/rendertheme/RenderTheme.java @@ -87,10 +87,6 @@ public class RenderTheme { private final LRUCache mMatchingCacheWay; private final LRUCache mMatchingCacheArea; - // private List mMatchingListWay; - // private List mMatchingListArea; - // private List mMatchingListNode; - RenderTheme(int mapBackground, float baseStrokeWidth, float baseTextSize) { mMapBackground = mapBackground; mBaseStrokeWidth = baseStrokeWidth; @@ -198,7 +194,7 @@ public class RenderTheme { } } - private RenderInstruction[] mRenderInstructions = null; + // private RenderInstruction[] mRenderInstructions = null; /** * Matches a way with the given parameters against this RenderTheme. @@ -213,23 +209,26 @@ public class RenderTheme { * way is Closed * @param changed * ... + * @return currently processed render instructions */ - public void matchWay(IRenderCallback renderCallback, Tag[] tags, byte zoomLevel, + public synchronized RenderInstruction[] matchWay(IRenderCallback renderCallback, + Tag[] tags, + byte zoomLevel, boolean closed, boolean changed) { RenderInstruction[] renderInstructions = null; LRUCache matchingCache; MatchingCacheKey matchingCacheKey; - if (!changed) { - renderInstructions = mRenderInstructions; - - if (renderInstructions != null) { - for (int i = 0, n = renderInstructions.length; i < n; i++) - renderInstructions[i].renderWay(renderCallback, tags); - } - return; - } + // if (!changed) { + // renderInstructions = mRenderInstructions; + // + // if (renderInstructions != null) { + // for (int i = 0, n = renderInstructions.length; i < n; i++) + // renderInstructions[i].renderWay(renderCallback, tags); + // } + // return; + // } if (closed) { matchingCache = mMatchingCacheArea; @@ -267,90 +266,8 @@ public class RenderTheme { matchingCache.put(matchingCacheKey, renderInstructions); } - mRenderInstructions = renderInstructions; - - // if (matchingList != null) { - // for (int i = 0, n = matchingList.size(); i < n; ++i) { - // matchingList.get(i).renderWay(renderCallback, tags); - // } - // } - // return renderInstructions; - - // if (closed) { - // mMatchingListArea = matchingList; - // } else { - // mMatchingListWay = matchingList; - // } - - // if (mCompareKey.set(tags, zoomLevel, closed)) { - // // Log.d("mapsforge", "SAME AS BAFORE!!!" + tags); - // for (int i = 0, n = mInstructionList.length; i < n; ++i) { - // mInstructionList[i].renderWay(renderCallback, tags); - // } - // return; - // } - // - // SparseArray matchingList = mMatchingCache.get(mCompareKey); - // - // if (matchingList != null) { - // mInstructionList = matchingList.get(zoomLevel); - // if (mInstructionList != null) { - // // cache hit - // // Log.d("mapsforge", "CCACHE HIT !!!" + tags); - // for (int i = 0, n = mInstructionList.length; i < n; ++i) { - // mInstructionList[i].renderWay(renderCallback, tags); - // } - // - // return; - // } - // } - // // Log.d("mapsforge", "CACHE MISS !!!" + tags); - // // cache miss - // ArrayList instructionList = new ArrayList(); - // - // for (int i = 0, n = mRulesList.size(); i < n; ++i) { - // mRulesList.get(i).matchWay(renderCallback, mCompareKey.getTags(), zoomLevel, closed, instructionList); - // } - // - // boolean found = false; - // int size = instructionList.size(); - // - // if (matchingList == null) { - // matchingList = new SparseArray(25); - // MatchingCacheKey matchingCacheKey = new MatchingCacheKey(mCompareKey); - // mMatchingCache.put(matchingCacheKey, matchingList); - // } else { - // // check if another zoomLevel uses the same instructionList - // for (int i = 0, n = matchingList.size(); i < n; i++) { - // int key = matchingList.keyAt(i); - // - // RenderInstruction[] list2 = matchingList.get(key); - // if (list2.length != size) - // continue; - // - // int j = 0; - // while (j < size && (list2[j] == instructionList.get(j))) - // j++; - // - // if (j == size) { - // instructionList.clear(); - // mInstructionList = list2; - // found = true; - // break; - // } - // } - // } - // - // if (!found) { - // mInstructionList = new RenderInstruction[size]; - // for (int i = 0; i < size; i++) - // mInstructionList[i] = instructionList.get(i); - // } - // - // for (int i = 0, n = mInstructionList.length; i < n; ++i) - // mInstructionList[i].renderWay(renderCallback, tags); - // - // matchingList.put(zoomLevel, mInstructionList); + // mRenderInstructions = renderInstructions; + return renderInstructions; } void addRule(Rule rule) { diff --git a/src/org/mapsforge/android/rendertheme/osmarender/osmarender.xml b/src/org/mapsforge/android/rendertheme/osmarender/osmarender.xml index 0b0a5f4f..12c70405 100644 --- a/src/org/mapsforge/android/rendertheme/osmarender/osmarender.xml +++ b/src/org/mapsforge/android/rendertheme/osmarender/osmarender.xml @@ -1,700 +1,700 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://mapsforge.org/renderTheme ../renderTheme.xsd" + version="1" map-background="#f0f0f0"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/org/mapsforge/android/swrenderer/DatabaseRenderer.java b/src/org/mapsforge/android/swrenderer/MapGenerator.java similarity index 81% rename from src/org/mapsforge/android/swrenderer/DatabaseRenderer.java rename to src/org/mapsforge/android/swrenderer/MapGenerator.java index bcf5bb46..8c7f2568 100644 --- a/src/org/mapsforge/android/swrenderer/DatabaseRenderer.java +++ b/src/org/mapsforge/android/swrenderer/MapGenerator.java @@ -14,77 +14,39 @@ */ package org.mapsforge.android.swrenderer; -import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; -import javax.xml.parsers.ParserConfigurationException; - -import org.mapsforge.android.MapView; import org.mapsforge.android.mapgenerator.IMapGenerator; -import org.mapsforge.android.mapgenerator.JobTheme; import org.mapsforge.android.mapgenerator.MapGeneratorJob; +import org.mapsforge.android.mapgenerator.Theme; import org.mapsforge.android.rendertheme.IRenderCallback; import org.mapsforge.android.rendertheme.RenderTheme; -import org.mapsforge.android.rendertheme.RenderThemeHandler; import org.mapsforge.android.rendertheme.renderinstruction.Area; import org.mapsforge.android.rendertheme.renderinstruction.Line; -import org.mapsforge.core.GeoPoint; import org.mapsforge.core.Tag; import org.mapsforge.core.Tile; import org.mapsforge.database.IMapDatabase; import org.mapsforge.database.IMapDatabaseCallback; -import org.mapsforge.database.MapFileInfo; import org.mapsforge.database.mapfile.MapDatabase; -import org.xml.sax.SAXException; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Paint; import android.util.FloatMath; -import android.util.Log; /** * A DatabaseRenderer renders map tiles by reading from a {@link MapDatabase}. */ -public class DatabaseRenderer implements IMapGenerator, IRenderCallback, +public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabaseCallback { - private static String TAG = DatabaseRenderer.class.getName(); - private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 12); + // private static String TAG = MapGenerator.class.getName(); private static final byte LAYERS = 11; private static final Paint PAINT_WATER_TILE_HIGHTLIGHT = new Paint( Paint.ANTI_ALIAS_FLAG); private static final double STROKE_INCREASE = 1.5; private static final byte STROKE_MIN_ZOOM_LEVEL = 12; - private static final byte ZOOM_MAX = 22; - - // private static MapRenderer mMapRenderer; - - private static RenderTheme getRenderTheme(JobTheme jobTheme) { - InputStream inputStream = null; - try { - inputStream = jobTheme.getRenderThemeAsStream(); - return RenderThemeHandler.getRenderTheme(inputStream); - } 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()); - } - } - return null; - } - private static byte getValidLayer(byte layer) { if (layer < 0) { return 0; @@ -103,7 +65,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, private List mNodes; private float mPoiX; private float mPoiY; - private JobTheme mPreviousJobTheme; + private Theme mPreviousJobTheme; private float mPreviousTextScale; private byte mPreviousZoomLevel; private static RenderTheme renderTheme; @@ -138,7 +100,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, /** * Constructs a new DatabaseRenderer. */ - public DatabaseRenderer() { + public MapGenerator() { mCanvasRasterer = new CanvasRasterer(); mLabelPlacement = new LabelPlacement(); @@ -161,8 +123,8 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, @Override public void cleanup() { mTileBitmap.recycle(); - if (DatabaseRenderer.renderTheme != null) { - DatabaseRenderer.renderTheme.destroy(); + if (MapGenerator.renderTheme != null) { + MapGenerator.renderTheme.destroy(); } } @@ -189,30 +151,30 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, // mTileHeight = mLat1 - mLat2; mScale = mapGeneratorJob.getScale(); - JobTheme jobTheme = mapGeneratorJob.jobParameters.jobTheme; - if (!jobTheme.equals(mPreviousJobTheme)) { - if (DatabaseRenderer.renderTheme == null) - DatabaseRenderer.renderTheme = getRenderTheme(jobTheme); - if (DatabaseRenderer.renderTheme == null) { - mPreviousJobTheme = null; - return false; - } - createWayLists(); - mPreviousJobTheme = jobTheme; - mPreviousZoomLevel = Byte.MIN_VALUE; - } - - byte zoomLevel = mCurrentTile.zoomLevel; - if (zoomLevel != mPreviousZoomLevel) { - setScaleStrokeWidth(zoomLevel); - mPreviousZoomLevel = zoomLevel; - } - - float textScale = mapGeneratorJob.jobParameters.textScale; - if (textScale != mPreviousTextScale) { - DatabaseRenderer.renderTheme.scaleTextSize(textScale); - mPreviousTextScale = textScale; - } + // Theme theme = mapGeneratorJob.jobParameters.theme; + // if (!theme.equals(mPreviousJobTheme)) { + // // if (MapGenerator.renderTheme == null) + // // MapGenerator.renderTheme = getRenderTheme(theme); + // // if (MapGenerator.renderTheme == null) { + // // mPreviousJobTheme = null; + // // return false; + // // } + // createWayLists(); + // mPreviousJobTheme = theme; + // mPreviousZoomLevel = Byte.MIN_VALUE; + // } + // + // byte zoomLevel = mCurrentTile.zoomLevel; + // if (zoomLevel != mPreviousZoomLevel) { + // setScaleStrokeWidth(zoomLevel); + // mPreviousZoomLevel = zoomLevel; + // } + // + // float textScale = mapGeneratorJob.jobParameters.textScale; + // if (textScale != mPreviousTextScale) { + // MapGenerator.renderTheme.scaleTextSize(textScale); + // mPreviousTextScale = textScale; + // } if (mMapDatabase != null) { mMapDatabase.executeQuery(mCurrentTile, this); @@ -230,7 +192,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, // FIXME mCoords = mMapDatabase.getCoordinates(); mCanvasRasterer.setCanvasBitmap(mTileBitmap, mScale); - mCanvasRasterer.fill(DatabaseRenderer.renderTheme.getMapBackground()); + mCanvasRasterer.fill(MapGenerator.renderTheme.getMapBackground()); mCanvasRasterer.drawWays(mCoords, mWays); mCanvasRasterer.drawSymbols(mWaySymbols); mCanvasRasterer.drawSymbols(mPointSymbols); @@ -255,37 +217,6 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, return true; } - @Override - public GeoPoint getStartPoint() { - if (mMapDatabase != null && mMapDatabase.hasOpenFile()) { - MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo(); - if (mapFileInfo.startPosition != null) { - return mapFileInfo.startPosition; - } else if (mapFileInfo.mapCenter != null) { - return mapFileInfo.mapCenter; - } - } - - return null; - } - - @Override - public Byte getStartZoomLevel() { - if (mMapDatabase != null && mMapDatabase.hasOpenFile()) { - MapFileInfo mapFileInfo = mMapDatabase.getMapFileInfo(); - if (mapFileInfo.startZoomLevel != null) { - return mapFileInfo.startZoomLevel; - } - } - - return DEFAULT_START_ZOOM_LEVEL; - } - - @Override - public byte getZoomLevelMax() { - return ZOOM_MAX; - } - @Override public void renderAreaCaption(String textKey, float verticalOffset, Paint paint, Paint stroke) { @@ -314,7 +245,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, mDrawingLayer = mWays[getValidLayer(layer)]; mPoiX = scaleLongitude(longitude); mPoiY = scaleLatitude(latitude); - DatabaseRenderer.renderTheme.matchNode(this, tags, mCurrentTile.zoomLevel); + MapGenerator.renderTheme.matchNode(this, tags, mCurrentTile.zoomLevel); } @Override @@ -539,7 +470,7 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, } private void createWayLists() { - int levels = DatabaseRenderer.renderTheme.getLevels(); + int levels = MapGenerator.renderTheme.getLevels(); for (byte i = LAYERS - 1; i >= 0; --i) { mWays[i] = new LayerContainer(levels); } @@ -581,12 +512,18 @@ public class DatabaseRenderer implements IMapGenerator, IRenderCallback, */ private static void setScaleStrokeWidth(byte zoomLevel) { int zoomLevelDiff = Math.max(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0); - DatabaseRenderer.renderTheme.scaleStrokeWidth((float) Math.pow(STROKE_INCREASE, + MapGenerator.renderTheme.scaleStrokeWidth((float) Math.pow(STROKE_INCREASE, zoomLevelDiff)); } @Override - public MapRenderer getMapRenderer(MapView mapView) { - return new MapRenderer(mapView); + public IMapDatabase getMapDatabase() { + return mMapDatabase; + } + + @Override + public void setRenderTheme(RenderTheme theme) { + // TODO Auto-generated method stub + } } diff --git a/src/org/mapsforge/android/swrenderer/MapRenderer.java b/src/org/mapsforge/android/swrenderer/MapRenderer.java index 92b84d8d..0a9e4890 100644 --- a/src/org/mapsforge/android/swrenderer/MapRenderer.java +++ b/src/org/mapsforge/android/swrenderer/MapRenderer.java @@ -28,10 +28,9 @@ import javax.microedition.khronos.opengles.GL10; import org.mapsforge.android.DebugSettings; import org.mapsforge.android.MapView; -import org.mapsforge.android.mapgenerator.JobParameters; import org.mapsforge.android.mapgenerator.IMapGenerator; +import org.mapsforge.android.mapgenerator.JobParameters; import org.mapsforge.android.mapgenerator.MapGeneratorJob; -import org.mapsforge.android.mapgenerator.MapWorker; import org.mapsforge.android.mapgenerator.TileCacheKey; import org.mapsforge.android.mapgenerator.TileDistanceSort; import org.mapsforge.android.utils.GlUtils; @@ -46,7 +45,7 @@ import android.opengl.Matrix; /** * */ -public class MapRenderer implements org.mapsforge.android.MapRenderer { +public class MapRenderer implements org.mapsforge.android.IMapRenderer { // private static String TAG = "MapRenderer"; private static final int FLOAT_SIZE_BYTES = 4; @@ -72,7 +71,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { private ArrayList mJobList; ArrayList mTextures; - MapWorker mMapWorker; MapView mMapView; GLMapTile[] currentTiles; @@ -97,7 +95,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { */ public MapRenderer(MapView mapView) { mMapView = mapView; - mMapWorker = mapView.getMapWorker(); mDebugSettings = mapView.getDebugSettings(); mMapScale = 1; @@ -133,7 +130,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (diff != 0) { float z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff); - t.distance = (long) (Math.abs((t.tileX) * z - x) + Math.abs((t.tileY) * z - y)); + t.distance = (long) (Math.abs((t.tileX) * z - x) + Math.abs((t.tileY) * z + - y)); t.distance *= 2 * diff * diff; } else { t.distance = (Math.abs(t.tileX - x) + Math.abs(t.tileY - y)); @@ -160,7 +158,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } if (t.hasTexture()) { synchronized (mTextures) { - mTextures.add(new Integer(t.getTexture())); + mTextures.add(Integer.valueOf(t.getTexture())); } } } @@ -184,7 +182,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { mJobList.clear(); - IMapGenerator mapGenerator = mMapView.getMapGenerator(); + // IMapGenerator mapGenerator = mMapView.getMapGenerator(); + int tiles = 0; for (long tileY = tileTop - 1; tileY <= tileBottom + 1; tileY++) { for (long tileX = tileLeft - 1; tileX <= tileRight + 1; tileX++) { @@ -216,13 +215,14 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (!tile.isDrawn || (tile.getScale() != scale)) { tile.isLoading = true; // approximation for TileScheduler - if (tileY < tileTop || tileY > tileBottom || tileX < tileLeft || tileX > tileRight) + if (tileY < tileTop || tileY > tileBottom || tileX < tileLeft + || tileX > tileRight) tile.isVisible = false; else tile.isVisible = true; - MapGeneratorJob job = new MapGeneratorJob(tile, mapGenerator, - mJobParameter, mDebugSettings); + MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter, + mDebugSettings); job.setScale(scale); mJobList.add(job); } @@ -243,10 +243,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } if (mJobList.size() > 0) { - mMapView.getJobQueue().setJobs(mJobList); - synchronized (mMapWorker) { - mMapWorker.notify(); - } + mMapView.addJobs(mJobList); } return true; @@ -262,10 +259,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { mMapPosition = mMapView.getMapPosition().getMapPosition(); - long x = (long) MercatorProjection.longitudeToPixelX(mMapPosition.geoPoint.getLongitude(), + long x = (long) MercatorProjection.longitudeToPixelX( + mMapPosition.geoPoint.getLongitude(), mMapPosition.zoomLevel); long y = (long) MercatorProjection - .latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), mMapPosition.zoomLevel); + .latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), + mMapPosition.zoomLevel); long tileX = MercatorProjection.pixelXToTileX(x, mMapPosition.zoomLevel); long tileY = MercatorProjection.pixelYToTileY(y, mMapPosition.zoomLevel); @@ -345,7 +344,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { z = 1.0f / (1 << -diff); } drawX = MercatorProjection - .longitudeToPixelX(mMapPosition.geoPoint.getLongitude(), tile.zoomLevel); + .longitudeToPixelX(mMapPosition.geoPoint.getLongitude(), + tile.zoomLevel); drawY = MercatorProjection .latitudeToPixelY(mMapPosition.geoPoint.getLatitude(), tile.zoomLevel); @@ -377,7 +377,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { Matrix.setIdentityM(mMatrix, 0); // map tile GL coordinates to screen coordinates - Matrix.scaleM(mMatrix, 0, 2.0f * (tileSize * z) / mWidth, 2.0f * (tileSize * z) / mHeight, 1); + Matrix.scaleM(mMatrix, 0, 2.0f * (tileSize * z) / mWidth, 2.0f * (tileSize * z) + / mHeight, 1); // scale tile Matrix.scaleM(mMatrix, 0, mapScale / z, mapScale / z, 1); @@ -396,7 +397,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { @Override public void onDrawFrame(GL10 glUnused) { - boolean loadedTexture = false; + // boolean loadedTexture = false; GLES20.glDisable(GLES20.GL_SCISSOR_TEST); GLES20.glClearColor(0.95f, 0.95f, 0.94f, 1.0f); // GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); @@ -437,14 +438,16 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (tile.getTexture() >= 0) { // reuse tile texture GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.getTexture()); - GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mMapGeneratorJob.getBitmap()); + GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, + mMapGeneratorJob.getBitmap()); } else if (mTextures.size() > 0) { // reuse texture from previous tiles Integer texture; texture = mTextures.remove(mTextures.size() - 1); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.intValue()); - GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mMapGeneratorJob.getBitmap()); + GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, + mMapGeneratorJob.getBitmap()); tile.setTexture(texture.intValue()); } else { // create texture @@ -457,7 +460,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { mMapGeneratorJob = null; processedTile = true; - loadedTexture = true; + // loadedTexture = true; } int tileSize = (int) (Tile.TILE_SIZE * mMapScale); int hWidth = mWidth >> 1; @@ -491,11 +494,12 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } } } - if (loadedTexture) { - synchronized (mMapWorker) { - mMapWorker.notify(); - } - } + // FIXME + // if (loadedTexture) { + // synchronized (mMapWorker) { + // mMapWorker.notify(); + // } + // } } @Override @@ -579,65 +583,9 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { public boolean processedTile() { return processedTile; } + + @Override + public IMapGenerator createMapGenerator() { + return new MapGenerator(); + } } - -// private void limitCache(long top, long bottom, long left, long right, byte zoom, int remove) { -// int cnt = 0; -// TileCacheKey[] keys = new TileCacheKey[remove]; -// -// for (Entry e : mTiles.entrySet()) { -// GLMapTile t = e.getValue(); -// if (t.zoomLevel == zoom && t.tileX >= left && t.tileX <= right && -// t.tileY >= top && t.tileY <= bottom) -// continue; -// -// if (t.zoomLevel + 1 == zoom) { -// boolean found = false; -// for (int i = 0; i < 4; i++) { -// GLMapTile c = t.child[i]; -// if (c != null && !c.hasTexture() && c.tileX >= left && c.tileX <= right && -// c.tileY >= top && c.tileY <= bottom) { -// found = true; -// break; -// } -// } -// if (found) -// continue; -// } -// if (t.zoomLevel - 1 == zoom) { -// GLMapTile p = t.parent; -// if (p != null && !p.hasTexture() && p.tileX >= left && p.tileX <= right && -// p.tileY >= top && p.tileY <= bottom) { -// continue; -// } -// } -// -// keys[cnt++] = e.getKey(); -// -// if (cnt == remove) -// break; -// } -// -// for (TileCacheKey key : keys) { -// GLMapTile t = mTiles.remove(key); -// if (t == null) -// continue; -// -// for (int i = 0; i < 4; i++) { -// if (t.child[i] != null) -// t.child[i].parent = null; -// } -// if (t.parent != null) { -// for (int i = 0; i < 4; i++) { -// if (t.parent.child[i] == t) -// t.parent.child[i] = null; -// } -// } -// if (t.hasTexture()) { -// synchronized (mTextures) { -// mTextures.add(new Integer(t.getTexture())); -// } -// } -// } -// } - diff --git a/src/org/mapsforge/android/swrenderer/WayDecorator.java b/src/org/mapsforge/android/swrenderer/WayDecorator.java index 1fe0cb8d..875c195e 100644 --- a/src/org/mapsforge/android/swrenderer/WayDecorator.java +++ b/src/org/mapsforge/android/swrenderer/WayDecorator.java @@ -99,7 +99,7 @@ final class WayDecorator { } } - static void renderText(DatabaseRenderer databaseRenderer, Paint paint, Paint outline, + static void renderText(MapGenerator mapGenerator, Paint paint, Paint outline, float[] coordinates, WayDataContainer wayDataContainer, List wayNames) { @@ -185,7 +185,7 @@ final class WayDecorator { if (wayNameWidth < 0) { if (text == null) { - text = databaseRenderer.getWayName(); + text = mapGenerator.getWayName(); if (text == null) text = "blub"; } diff --git a/src/org/mapsforge/android/utils/GlUtils.java b/src/org/mapsforge/android/utils/GlUtils.java index 45e8d50b..4bccfeb0 100644 --- a/src/org/mapsforge/android/utils/GlUtils.java +++ b/src/org/mapsforge/android/utils/GlUtils.java @@ -40,13 +40,17 @@ public class GlUtils { GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID); - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); + GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, + GLES20.GL_LINEAR); - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); + GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, + GLES20.GL_LINEAR); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, + GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, + GLES20.GL_CLAMP_TO_EDGE); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); @@ -125,4 +129,16 @@ public class GlUtils { // throw new RuntimeException(op + ": glError " + error); } } + + public static boolean checkGlOutOfMemory(String op) { + int error; + boolean oom = false; + while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { + Log.e(TAG, op + ": glError " + error); + // throw new RuntimeException(op + ": glError " + error); + if (error == 1285) + oom = true; + } + return oom; + } } diff --git a/src/org/mapsforge/android/utils/PausableThread.java b/src/org/mapsforge/android/utils/PausableThread.java index 780bde36..b1d7e0e8 100644 --- a/src/org/mapsforge/android/utils/PausableThread.java +++ b/src/org/mapsforge/android/utils/PausableThread.java @@ -37,6 +37,14 @@ public abstract class PausableThread extends Thread { } } + @Override + public void interrupt() { + // first acquire the monitor which is used to call wait() + synchronized (this) { + super.interrupt(); + } + } + /** * @return true if this thread is currently pausing, false otherwise. */ diff --git a/src/org/mapsforge/app/TileMap.java b/src/org/mapsforge/app/TileMap.java index c4cf3853..c4a6e400 100755 --- a/src/org/mapsforge/app/TileMap.java +++ b/src/org/mapsforge/app/TileMap.java @@ -9,8 +9,7 @@ import org.mapsforge.android.DebugSettings; import org.mapsforge.android.MapActivity; import org.mapsforge.android.MapController; import org.mapsforge.android.MapView; -import org.mapsforge.android.mapgenerator.MapDatabaseFactory; -import org.mapsforge.android.mapgenerator.MapDatabaseInternal; +import org.mapsforge.android.mapgenerator.MapDatabases; import org.mapsforge.android.rendertheme.InternalRenderTheme; import org.mapsforge.android.utils.AndroidUtils; import org.mapsforge.app.filefilter.FilterByFileExtension; @@ -20,7 +19,6 @@ import org.mapsforge.app.filepicker.FilePicker; import org.mapsforge.app.preferences.EditPreferences; import org.mapsforge.core.BoundingBox; import org.mapsforge.core.GeoPoint; -import org.mapsforge.database.IMapDatabase; import org.mapsforge.database.MapFileInfo; import android.annotation.TargetApi; @@ -74,7 +72,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL private static final int SELECT_MAP_FILE = 0; private static final int SELECT_RENDER_THEME_FILE = 1; private LocationManager mLocationManager; - private MapDatabaseInternal mMapDatabaseInternal; + private MapDatabases mMapDatabase; private MyLocationListener mMyLocationListener; private boolean mShowMyLocation; private boolean mSnapToLocation; @@ -88,8 +86,11 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.options_menu, menu); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) + getMenuInflater().inflate(R.menu.options_menu, menu); + else + getMenuInflater().inflate(R.menu.options_menu_pre_honeycomb, menu); mMenu = menu; return true; } @@ -434,7 +435,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL editText.setText(Double.toString(mapCenter.getLongitude())); SeekBar zoomlevel = (SeekBar) dialog.findViewById(R.id.zoomLevel); - zoomlevel.setMax(mMapView.getMapGenerator().getZoomLevelMax()); + zoomlevel.setMax(20); // FIXME mMapView.getMapGenerator().getZoomLevelMax()); zoomlevel.setProgress(mMapView.getMapPosition().getZoomLevel()); final TextView textView = (TextView) dialog.findViewById(R.id.zoomlevelValue); @@ -532,25 +533,31 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL if (preferences.contains("mapDatabase")) { String name = preferences.getString("mapDatabase", - MapDatabaseInternal.POSTGIS_READER.name()); + MapDatabases.POSTGIS_READER.name()); - MapDatabaseInternal mapDatabaseInternalNew; + MapDatabases mapDatabaseNew; try { - mapDatabaseInternalNew = MapDatabaseInternal.valueOf(name); + mapDatabaseNew = MapDatabases.valueOf(name); } catch (IllegalArgumentException e) { - mapDatabaseInternalNew = MapDatabaseInternal.POSTGIS_READER; + mapDatabaseNew = MapDatabases.POSTGIS_READER; } - // mapDatabaseInternalNew = MapDatabaseInternal.JSON_READER; - Log.d("VectorTileMap", "set map database " + mapDatabaseInternalNew); + // mapDatabaseInternalNew = MapDatabaseInternal.PBMAP_READER; + Log.d("VectorTileMap", "set map database " + mapDatabaseNew); - if (mapDatabaseInternalNew != mMapDatabaseInternal) { - IMapDatabase mapDatabase = MapDatabaseFactory - .createMapDatabase(mapDatabaseInternalNew); - mMapView.setMapDatabase(mapDatabase); - mMapDatabaseInternal = mapDatabaseInternalNew; + if (mapDatabaseNew != mMapDatabase) { + mMapView.setMapDatabase(mapDatabaseNew); + mMapDatabase = mapDatabaseNew; } + + // if (mapDatabaseNew != mMapDatabase) { + // IMapDatabase mapDatabase = MapDatabaseFactory + // .createMapDatabase(mapDatabaseNew); + // + // mMapView.setMapDatabase(mapDatabase); + // mMapDatabase = mapDatabaseNew; + // } } try { @@ -586,7 +593,7 @@ public class TileMap extends MapActivity { // implements ActionBar.OnNavigationL mMapView.setDebugSettings(debugSettings); - if (mMapDatabaseInternal == MapDatabaseInternal.MAP_READER) { + if (mMapDatabase == MapDatabases.MAP_READER) { if (mMapView.getMapFile() == null) startMapFilePicker(); } else { diff --git a/src/org/mapsforge/app/filepicker/FilePicker.java b/src/org/mapsforge/app/filepicker/FilePicker.java index bb556fd0..7c997da5 100755 --- a/src/org/mapsforge/app/filepicker/FilePicker.java +++ b/src/org/mapsforge/app/filepicker/FilePicker.java @@ -226,7 +226,8 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe @Override protected void onResume() { super.onResume(); - getActionBar().hide(); + // getActionBar().hide(); + // check if the full screen mode should be activated // if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen", false)) { // getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); diff --git a/src/org/mapsforge/app/preferences/EditPreferences.java b/src/org/mapsforge/app/preferences/EditPreferences.java index a1dbdabc..4b919aa8 100644 --- a/src/org/mapsforge/app/preferences/EditPreferences.java +++ b/src/org/mapsforge/app/preferences/EditPreferences.java @@ -18,8 +18,6 @@ import org.mapsforge.app.R; import android.os.Bundle; import android.preference.PreferenceActivity; -import android.preference.PreferenceManager; -import android.view.WindowManager; /** * Activity to edit the application preferences. @@ -34,16 +32,16 @@ public class EditPreferences extends PreferenceActivity { @Override protected void onResume() { super.onResume(); - getActionBar().hide(); + // getActionBar().hide(); // check if the full screen mode should be activated - if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen", - false)) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - } else { - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - } + // if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fullscreen", + // false)) { + // getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + // getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + // } else { + // getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + // getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + // } } } diff --git a/src/org/mapsforge/database/IMapDatabase.java b/src/org/mapsforge/database/IMapDatabase.java index 91dd43d9..be92c261 100644 --- a/src/org/mapsforge/database/IMapDatabase.java +++ b/src/org/mapsforge/database/IMapDatabase.java @@ -62,6 +62,8 @@ public interface IMapDatabase { */ public abstract FileOpenResult openFile(File mapFile); + public abstract String getMapProjection(); + /** * @param position * .... @@ -69,4 +71,4 @@ public interface IMapDatabase { */ public abstract String readString(int position); -} \ No newline at end of file +} diff --git a/src/org/mapsforge/database/json/MapDatabase.java b/src/org/mapsforge/database/json/MapDatabase.java index ec93b2e9..054ea32c 100644 --- a/src/org/mapsforge/database/json/MapDatabase.java +++ b/src/org/mapsforge/database/json/MapDatabase.java @@ -31,13 +31,14 @@ import org.mapsforge.database.MapFileInfo; */ public class MapDatabase implements IMapDatabase { + private final static String PROJECTION = "Mercator"; private float[] mCoords = new float[20]; - private int[] mIndex = new int[1]; + private int[] mIndex = new int[2]; // private Tag[] mTags = { new Tag("boundary", "administrative"), new Tag("admin_level", "2") }; - private Tag[] mTags = { new Tag("building", "yes") }; + private Tag[] mTags = { new Tag("natural", "water") }; private final MapFileInfo mMapInfo = new MapFileInfo(new BoundingBox(-180, -90, 180, 90), - new Byte((byte) 0), null, "Mercator", 0, 0, 0, "de", "yo!", "by me"); + new Byte((byte) 0), null, PROJECTION, 0, 0, 0, "de", "yo!", "by me"); private boolean mOpenFile = false; @@ -95,10 +96,10 @@ public class MapDatabase implements IMapDatabase { // // mIndex[0] = 10; - lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 80, tile.zoomLevel) * 1000000; - lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 80, tile.zoomLevel) * 1000000; - lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 80, tile.zoomLevel) * 1000000; - lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 80, tile.zoomLevel) * 1000000; + lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 139, tile.zoomLevel) * 1000000; + lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 139, tile.zoomLevel) * 1000000; + lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 139, tile.zoomLevel) * 1000000; + lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 139, tile.zoomLevel) * 1000000; mCoords[0] = lon1; mCoords[1] = lat1; @@ -117,9 +118,35 @@ public class MapDatabase implements IMapDatabase { mIndex[0] = 10; + lon1 = (float) MercatorProjection.pixelXToLongitude(cx - 119, tile.zoomLevel) * 1000000; + lon2 = (float) MercatorProjection.pixelXToLongitude(cx + 119, tile.zoomLevel) * 1000000; + lat1 = (float) MercatorProjection.pixelYToLatitude(cy - 119, tile.zoomLevel) * 1000000; + lat2 = (float) MercatorProjection.pixelYToLatitude(cy + 119, tile.zoomLevel) * 1000000; + + mCoords[10] = lon1; + mCoords[11] = lat1; + + mCoords[12] = lon2; + mCoords[13] = lat1; + + mCoords[14] = lon2; + mCoords[15] = lat2; + + mCoords[16] = lon1; + mCoords[17] = lat2; + + mCoords[18] = lon1; + mCoords[19] = lat1; + + mIndex[1] = 10; mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true); } + @Override + public String getMapProjection() { + return PROJECTION; + } + @Override public MapFileInfo getMapFileInfo() { return mMapInfo; diff --git a/src/org/mapsforge/database/mapfile/MapDatabase.java b/src/org/mapsforge/database/mapfile/MapDatabase.java index 0c39d473..fd3ca7a7 100644 --- a/src/org/mapsforge/database/mapfile/MapDatabase.java +++ b/src/org/mapsforge/database/mapfile/MapDatabase.java @@ -177,11 +177,13 @@ public class MapDatabase implements IMapDatabase { */ private static final int WAY_NUMBER_OF_TAGS_BITMASK = 0x0f; - private IndexCache mDatabaseIndexCache; + private static IndexCache sDatabaseIndexCache; + private static MapFileHeader sMapFileHeader; + private static int instances = 0; + private long mFileSize; private boolean mDebugFile; private RandomAccessFile mInputFile; - private MapFileHeader mMapFileHeader; private ReadBuffer mReadBuffer; private String mSignatureBlock; private String mSignaturePoi; @@ -193,31 +195,6 @@ public class MapDatabase implements IMapDatabase { private float[] mWayNodes = new float[100000]; private int mWayNodePosition; - /* - * (non-Javadoc) - * @see org.mapsforge.map.reader.IMapDatabase#closeFile() - */ - @Override - public void closeFile() { - try { - mMapFileHeader = null; - - if (mDatabaseIndexCache != null) { - mDatabaseIndexCache.destroy(); - mDatabaseIndexCache = null; - } - - if (mInputFile != null) { - mInputFile.close(); - mInputFile = null; - } - - mReadBuffer = null; - } catch (IOException e) { - LOG.log(Level.SEVERE, null, e); - } - } - private int minLat, minLon; /* @@ -227,7 +204,7 @@ public class MapDatabase implements IMapDatabase { */ @Override public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) { - if (mMapFileHeader == null) + if (sMapFileHeader == null) return; if (mIntBuffer == null) @@ -235,29 +212,13 @@ public class MapDatabase implements IMapDatabase { mWayNodePosition = 0; - // if (tile.zoomLevel < 10) { - // // reduce small nodes with distance smaller min pixel - // int min = 1; - // long cx = tile.getPixelX() + (Tile.TILE_SIZE >> 1); - // long cy = tile.getPixelY() + (Tile.TILE_SIZE >> 1); - // double l1 = MercatorProjection.pixelXToLongitude(cx, tile.zoomLevel); - // double l2 = MercatorProjection.pixelXToLongitude(cx + min, tile.zoomLevel); - // minLon = (int) Math.abs((l1 * 1000000.0) - (l2 * 1000000.0)); - // l1 = MercatorProjection.pixelYToLatitude(cy, tile.zoomLevel); - // l2 = MercatorProjection.pixelYToLatitude(cy + min, tile.zoomLevel); - // minLat = (int) Math.abs((l1 * 1000000.0) - (l2 * 1000000.0)); - // } else { - minLat = 0; - minLon = 0; - // } - try { - prepareExecution(); + // prepareExecution(); QueryParameters queryParameters = new QueryParameters(); - queryParameters.queryZoomLevel = mMapFileHeader + queryParameters.queryZoomLevel = sMapFileHeader .getQueryZoomLevel(tile.zoomLevel); // get and check the sub-file for the query zoom level - SubFileParameter subFileParameter = mMapFileHeader + SubFileParameter subFileParameter = sMapFileHeader .getSubFileParameter(queryParameters.queryZoomLevel); if (subFileParameter == null) { LOG.warning("no sub-file for zoom level: " @@ -279,10 +240,15 @@ public class MapDatabase implements IMapDatabase { */ @Override public MapFileInfo getMapFileInfo() { - if (mMapFileHeader == null) { + if (sMapFileHeader == null) { throw new IllegalStateException("no map file is currently opened"); } - return mMapFileHeader.getMapFileInfo(); + return sMapFileHeader.getMapFileInfo(); + } + + @Override + public String getMapProjection() { + return getMapFileInfo().projectionName; } /* @@ -300,6 +266,7 @@ public class MapDatabase implements IMapDatabase { */ @Override public FileOpenResult openFile(File mapFile) { + try { if (mapFile == null) { // throw new IllegalArgumentException("mapFile must not be null"); @@ -323,14 +290,23 @@ public class MapDatabase implements IMapDatabase { mFileSize = mInputFile.length(); mReadBuffer = new ReadBuffer(mInputFile); - mMapFileHeader = new MapFileHeader(); - FileOpenResult fileOpenResult = mMapFileHeader.readHeader(mReadBuffer, + if (instances > 0) { + instances++; + return FileOpenResult.SUCCESS; + } + + sMapFileHeader = new MapFileHeader(); + FileOpenResult fileOpenResult = sMapFileHeader.readHeader(mReadBuffer, mFileSize); if (!fileOpenResult.isSuccess()) { closeFile(); return fileOpenResult; } + prepareExecution(); + + instances++; + return FileOpenResult.SUCCESS; } catch (IOException e) { LOG.log(Level.SEVERE, null, e); @@ -340,6 +316,37 @@ public class MapDatabase implements IMapDatabase { } } + /* + * (non-Javadoc) + * @see org.mapsforge.map.reader.IMapDatabase#closeFile() + */ + @Override + public void closeFile() { + instances--; + if (instances > 0) { + mReadBuffer = null; + return; + } + + try { + sMapFileHeader = null; + + if (sDatabaseIndexCache != null) { + sDatabaseIndexCache.destroy(); + sDatabaseIndexCache = null; + } + + if (mInputFile != null) { + mInputFile.close(); + mInputFile = null; + } + + mReadBuffer = null; + } catch (IOException e) { + LOG.log(Level.SEVERE, null, e); + } + } + /** * Logs the debug signatures of the current way and block. */ @@ -351,8 +358,8 @@ public class MapDatabase implements IMapDatabase { } private void prepareExecution() { - if (mDatabaseIndexCache == null) { - mDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE); + if (sDatabaseIndexCache == null) { + sDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE); } } @@ -436,7 +443,7 @@ public class MapDatabase implements IMapDatabase { long blockNumber = row * subFileParameter.blocksWidth + column; // get the current index entry - long currentBlockIndexEntry = mDatabaseIndexCache.getIndexEntry( + long currentBlockIndexEntry = sDatabaseIndexCache.getIndexEntry( subFileParameter, blockNumber); // check if the current query would still return a water tile @@ -462,7 +469,7 @@ public class MapDatabase implements IMapDatabase { nextBlockPointer = subFileParameter.subFileSize; } else { // get and check the next block pointer - nextBlockPointer = mDatabaseIndexCache.getIndexEntry( + nextBlockPointer = sDatabaseIndexCache.getIndexEntry( subFileParameter, blockNumber + 1) & BITMASK_INDEX_OFFSET; if (nextBlockPointer < 1 @@ -559,7 +566,7 @@ public class MapDatabase implements IMapDatabase { * @return true if the POIs could be processed successfully, false otherwise. */ private boolean processPOIs(IMapDatabaseCallback mapDatabaseCallback, int numberOfPois) { - Tag[] poiTags = mMapFileHeader.getMapFileInfo().poiTags; + Tag[] poiTags = sMapFileHeader.getMapFileInfo().poiTags; Tag[] tags = null; for (int elementCounter = numberOfPois; elementCounter != 0; --elementCounter) { @@ -778,7 +785,7 @@ public class MapDatabase implements IMapDatabase { int numberOfWays) { Tag[] tags = null; - Tag[] wayTags = mMapFileHeader.getMapFileInfo().wayTags; + Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags; int[] textPos = new int[3]; // float[] labelPosition; boolean skippedWays = false; @@ -957,7 +964,7 @@ public class MapDatabase implements IMapDatabase { || cumulatedNumberOfWays > MAXIMUM_ZOOM_TABLE_OBJECTS) { LOG.warning("invalid cumulated number of ways in row " + row + ' ' + cumulatedNumberOfWays); - if (mMapFileHeader.getMapFileInfo().debugFile) { + if (sMapFileHeader.getMapFileInfo().debugFile) { LOG.warning(DEBUG_SIGNATURE_BLOCK + mSignatureBlock); } return null; diff --git a/src/org/mapsforge/database/pbmap/MapDatabase.java b/src/org/mapsforge/database/pbmap/MapDatabase.java new file mode 100644 index 00000000..4f594b26 --- /dev/null +++ b/src/org/mapsforge/database/pbmap/MapDatabase.java @@ -0,0 +1,513 @@ +/* + * Copyright 2012 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.mapsforge.database.pbmap; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.zip.GZIPInputStream; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.message.BasicHeader; +import org.mapsforge.core.BoundingBox; +import org.mapsforge.core.GeoPoint; +import org.mapsforge.core.Tag; +import org.mapsforge.core.Tile; +import org.mapsforge.core.WebMercator; +import org.mapsforge.database.FileOpenResult; +import org.mapsforge.database.IMapDatabase; +import org.mapsforge.database.IMapDatabaseCallback; +import org.mapsforge.database.MapFileInfo; + +import android.net.http.AndroidHttpClient; +import android.util.Log; + +/** + * + * + */ +public class MapDatabase implements IMapDatabase { + private static final String TAG = "MapDatabase"; + + private static final MapFileInfo mMapInfo = + new MapFileInfo(new BoundingBox(-180, -90, 180, 90), + new Byte((byte) 14), new GeoPoint(53.11, 8.85), + WebMercator.NAME, 0, 0, 0, "de", "comment", "author"); + + private boolean mOpenFile = false; + + // private static final String URL = "http://city.informatik.uni-bremen.de:8020/test/%d/%d/%d.osmtile"; + private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/test/%d/%d/%d.osmtile"; + private static final Header encodingHeader = + new BasicHeader("Accept-Encoding", "gzip"); + + private static volatile HashMap tagHash = new HashMap(100); + + private Tag[] curTags = new Tag[1000]; + private int mCurTagCnt; + + private AndroidHttpClient mClient; + private IMapDatabaseCallback mMapGenerator; + private float mScaleFactor; + + @Override + public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) { + + String url = String.format(URL, Integer.valueOf(tile.zoomLevel), + Long.valueOf(tile.tileX), Long.valueOf(tile.tileY)); + + HttpGet getRequest = new HttpGet(url); + getRequest.addHeader(encodingHeader); + mMapGenerator = mapDatabaseCallback; + mCurTagCnt = 0; + // using variable coordinate scalefactor to take advantage of + // variable byte encoded integers + mScaleFactor = 1 / 100f; + if (tile.zoomLevel < 12) + mScaleFactor = (float) Math.pow(2, (12 - tile.zoomLevel)) / 100f; + + try { + HttpResponse response = mClient.execute(getRequest); + final int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + Log.d(TAG, "Http response " + statusCode); + return; + } + + final HttpEntity entity = response.getEntity(); + if (entity == null) { + Log.d(TAG, "Somethings wrong? - no entity " + statusCode); + return; + } + + InputStream is = null; + GZIPInputStream zis = null; + try { + + is = entity.getContent(); + zis = new GZIPInputStream(is); + + decode(zis); + + } finally { + if (zis != null) + zis.close(); + if (is != null) + is.close(); + entity.consumeContent(); + } + } catch (Exception ex) { + getRequest.abort(); + ex.printStackTrace(); + } + } + + @Override + public String getMapProjection() { + return WebMercator.NAME; + } + + @Override + public MapFileInfo getMapFileInfo() { + return mMapInfo; + } + + @Override + public boolean hasOpenFile() { + return mOpenFile; + } + + @Override + public FileOpenResult openFile(File mapFile) { + mOpenFile = true; + mClient = AndroidHttpClient.newInstance("Android"); + return new FileOpenResult(); + } + + @Override + public void closeFile() { + mOpenFile = false; + if (mClient != null) + mClient.close(); + } + + @Override + public String readString(int position) { + return null; + } + + private static final int BUFFER_SIZE = 32768; + private final byte[] buffer = new byte[BUFFER_SIZE]; + private int bufferPos; + private int bufferSize; + private InputStream inputStream; + + private static final int TAG_TILE_TAGS = 1; + private static final int TAG_TILE_WAYS = 2; + private static final int TAG_TILE_NODES = 3; + private static final int TAG_WAY_TAGS = 1; + private static final int TAG_WAY_INDEX = 2; + private static final int TAG_WAY_COORDS = 3; + // private static final int TAG_NODE_TAGS = 1; + // private static final int TAG_NODE_COORDS = 2; + + private int bytesRead; + + private boolean decode(InputStream is) throws IOException { + inputStream = is; + bytesRead = 0; + bufferSize = 0; + bufferPos = 0; + while (true) { + // read tag and wire type + int val = decodeVarint32(); + if (val == 0) { + // Log.d(TAG, "EOF, all good"); + return true; + } + int tag = (val >> 3); + // int wireType = (val & 7); + // Log.d(TAG, "tile " + tag + " " + wireType); + + switch (tag) { + case TAG_TILE_TAGS: + decodeTileTags(); + break; + + case TAG_TILE_WAYS: + decodeTileWays(); + break; + + case TAG_TILE_NODES: + decodeTileNodes(); + break; + + default: + Log.d(TAG, "invalid type for tile: " + tag); + return false; + } + } + } + + private boolean decodeTileTags() throws IOException { + String tagString = decodeString(); + + Tag tag = tagHash.get(tagString); + if (tag == null) { + tag = new Tag(tagString); + tagHash.put(tagString, tag); + } + curTags[mCurTagCnt++] = tag; + + // Log.d(TAG, "tag:" + tag); + return true; + } + + private boolean decodeTileWays() throws IOException { + int bytes = decodeVarint32(); + + int end = bytesRead + bytes; + int indexCnt = 0; + int tagCnt = 0; + int coordCnt = 0; + while (bytesRead < end) { + // read tag and wire type + + int val = decodeVarint32(); + if (val == 0) + break; + + int tag = (val >> 3); + // int wireType = val & 7; + + // Log.d(TAG, "way " + tag + " " + wireType + " bytes:" + bytes); + + switch (tag) { + case TAG_WAY_TAGS: + tagCnt = decodeWayTags(); + break; + + case TAG_WAY_INDEX: + indexCnt = decodeWayIndices(); + break; + + case TAG_WAY_COORDS: + coordCnt = decodeWayCoordinates(); + break; + + default: + Log.d(TAG, "invalid type for way: " + tag); + } + } + + if (indexCnt == 0 || tagCnt == 0) + return false; + + int[] index = new int[indexCnt]; + + int sum = 0; + for (int i = 0; i < indexCnt; i++) { + index[i] = tmpIndices[i] * 2; + sum += index[i]; + } + + Tag[] tags = new Tag[tagCnt]; + for (int i = 0; i < tagCnt; i++) + tags[i] = curTags[tmpTags[i]]; + + float[] coords = tmpCoords; + int pos = 0; + + if (coordCnt != sum) { + Log.d(TAG, "way length is wrong " + coordCnt + " " + sum); + return false; + } + + float z = mScaleFactor; + for (int j = 0, m = indexCnt; j < m; j++) { + float lastX = 0; + float lastY = 0; + + for (int n = index[j] + pos; pos < n; pos += 2) { + lastX = coords[pos] = (coords[pos] * z) + lastX; + lastY = coords[pos + 1] = (coords[pos + 1] * z) + lastY; + } + + } + + mMapGenerator.renderWay((byte) 0, tags, coords, index, true); + return true; + } + + private boolean decodeTileNodes() throws IOException { + int bytes = decodeVarint32(); + Log.d(TAG, "way nodes " + bytes); + return true; + } + + private int MAX_WAY_COORDS = 32768; + private int MAX_WAY_INDICES = 1000; + private int[] tmpTags = new int[32]; + private int[] tmpIndices = new int[MAX_WAY_INDICES]; + private float[] tmpCoords = new float[MAX_WAY_COORDS]; + + // private boolean ensureBufferSize(int size) throws IOException { + // if (size > (bufferSize - bufferPos)) + // readBuffer(size - (bufferSize - bufferPos)); + // + // return true; + // } + + private int decodeWayTags() throws IOException { + int bytes = decodeVarint32(); + // Log.d(TAG, "way tags: " + bytes); + + int cnt = 0; + int end = bytesRead + bytes; + + while (bytesRead < end) + tmpTags[cnt++] = decodeVarint32(); + + return cnt; + } + + private int decodeWayIndices() throws IOException { + int bytes = decodeVarint32(); + // Log.d(TAG, "way indices: " + bytes); + + int cnt = 0; + int end = bytesRead + bytes; + + while (bytesRead < end) { + int val = decodeVarint32(); + if (cnt >= MAX_WAY_INDICES) { + + MAX_WAY_INDICES += 128; + Log.d(TAG, "increase indices array " + MAX_WAY_INDICES); + int[] tmp = new int[MAX_WAY_INDICES]; + System.arraycopy(tmpIndices, 0, tmp, 0, cnt); + tmpIndices = tmp; + } + + tmpIndices[cnt++] = val; + + } + return cnt; + } + + private int decodeWayCoordinates() throws IOException { + int bytes = decodeVarint32(); + + int cnt = 0; + int end = bytesRead + bytes; + + while (bytesRead < end) { + int val = decodeZigZag32(decodeVarint32()); + if (cnt >= MAX_WAY_COORDS) { + MAX_WAY_COORDS += 128; + Log.d(TAG, "increase coords array " + MAX_WAY_COORDS); + float[] tmp = new float[MAX_WAY_COORDS]; + System.arraycopy(tmpCoords, 0, tmp, 0, cnt); + tmpCoords = tmp; + } + tmpCoords[cnt++] = val; + } + return cnt; + } + + private void readBuffer() throws IOException { + + int len = inputStream.read(buffer, 0, BUFFER_SIZE); + if (len < 0) { + buffer[bufferPos] = 0; + // Log.d(TAG, " nothing to read... pos " + bufferPos + ", size " + // + bufferSize + ", read " + bytesRead); + return; + } + bufferSize = len; + bufferPos = 0; + + // Log.d(TAG, "pos " + bufferPos + ", size " + bufferSize + ", read " + // + bytesRead); + } + + private void readBuffer(int size) throws IOException { + if (size < (bufferSize - bufferPos)) + return; + + if (size > BUFFER_SIZE) { + Log.d(TAG, "EEEK too large"); + // FIXME throw exception, but frankly better sanitize tile data on compilation + // this only happen with Strings larger than 32kb + return; + } + + if ((size - bufferSize) + bufferPos > BUFFER_SIZE) { + // copy bytes left to read from buffer to the beginning of buffer + System.arraycopy(buffer, bufferPos, buffer, 0, bufferSize - bufferPos); + bufferPos = 0; + } + + while ((bufferSize - bufferPos) < size) { + // read until requested size is available in buffer + int len = inputStream.read(buffer, bufferSize, BUFFER_SIZE - bufferSize); + if (len < 0) { + buffer[bufferSize - 1] = 0; // FIXME is this needed? + break; + } + bufferSize += len; + } + + // Log.d(TAG, "needed " + size + " pos " + bufferPos + ", size " + // + bufferSize + // + ", read " + bytesRead); + } + + /* All code below is taken from or based on Google's Protocol Buffers implementation: */ + + // Protocol Buffers - Google's data interchange format + // Copyright 2008 Google Inc. All rights reserved. + // http://code.google.com/p/protobuf/ + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions are + // met: + // + // * Redistributions of source code must retain the above copyright + // notice, this list of conditions and the following disclaimer. + // * Redistributions in binary form must reproduce the above + // copyright notice, this list of conditions and the following disclaimer + // in the documentation and/or other materials provided with the + // distribution. + // * Neither the name of Google Inc. nor the names of its + // contributors may be used to endorse or promote products derived from + // this software without specific prior written permission. + // + // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + private byte readRawByte() throws IOException { + if (bufferPos == bufferSize) { + readBuffer(); + } + bytesRead++; + return buffer[bufferPos++]; + } + + private int decodeVarint32() throws IOException { + byte tmp = readRawByte(); + if (tmp >= 0) { + return tmp; + } + int result = tmp & 0x7f; + if ((tmp = readRawByte()) >= 0) { + return result | tmp << 7; + } + result |= (tmp & 0x7f) << 7; + if ((tmp = readRawByte()) >= 0) { + return result | tmp << 14; + } + result |= (tmp & 0x7f) << 14; + if ((tmp = readRawByte()) >= 0) { + return result | tmp << 21; + } + result |= (tmp & 0x7f) << 21; + result |= (tmp = readRawByte()) << 28; + + if (tmp < 0) { + // Discard upper 32 bits. + for (int i = 0; i < 5; i++) { + if (readRawByte() >= 0) { + return result; + } + } + Log.d(TAG, "EEK malformedVarint"); + // FIXME throw some poo + } + + return result; + } + + private String decodeString() throws IOException { + final int size = decodeVarint32(); + + readBuffer(size); + + final String result = new String(buffer, bufferPos, size, "UTF-8"); + bufferPos += size; + bytesRead += size; + return result; + + } + + public static int decodeZigZag32(final int n) { + return (n >>> 1) ^ -(n & 1); + } + +} diff --git a/src/org/mapsforge/database/postgis/MapDatabase.java b/src/org/mapsforge/database/postgis/MapDatabase.java index 1f0c2f25..7444167c 100644 --- a/src/org/mapsforge/database/postgis/MapDatabase.java +++ b/src/org/mapsforge/database/postgis/MapDatabase.java @@ -26,9 +26,9 @@ import java.util.Properties; import org.mapsforge.core.BoundingBox; import org.mapsforge.core.GeoPoint; -import org.mapsforge.core.WebMercator; import org.mapsforge.core.Tag; import org.mapsforge.core.Tile; +import org.mapsforge.core.WebMercator; import org.mapsforge.database.FileOpenResult; import org.mapsforge.database.IMapDatabase; import org.mapsforge.database.IMapDatabaseCallback; @@ -40,7 +40,7 @@ import org.postgresql.PGConnection; * */ public class MapDatabase implements IMapDatabase { - private static final String QUERY = "SELECT * FROM __get_tile(?,?,?)"; + private static final String QUERY = "SELECT tags, geom FROM __get_tile(?,?,?)"; private final float mScale = 1; // 1000000.0f; @@ -55,16 +55,13 @@ public class MapDatabase implements IMapDatabase { new MapFileInfo(new BoundingBox(-180, -85, 180, 85), new Byte((byte) 14), new GeoPoint(53.11, 8.85), WebMercator.NAME, - 0, 0, 0, "de", "yo!", "hannes"); - // new MapFileInfo(new BoundingBox(-180, -90, 180, 90), - // new Byte((byte) 0), null, "Mercator", - // 0, 0, 0, "de", "yo!", "by me"); + 0, 0, 0, "de", "comment", "author"); private boolean mOpenFile = false; private Connection connection = null; - private static HashMap, Tag> tagHash = new HashMap, Tag>( - 100); + private static volatile HashMap, Tag> tagHash = + new HashMap, Tag>(100); private PreparedStatement prepQuery = null; private boolean connect() { @@ -123,7 +120,6 @@ public class MapDatabase implements IMapDatabase { byte[] b = null; PGHStore h = null; - // long id; try { while (r != null && r.next()) { @@ -131,9 +127,7 @@ public class MapDatabase implements IMapDatabase { mCoordPos = 0; try { - // id = r.getLong(1); - - Object obj = r.getObject(2); + Object obj = r.getObject(1); h = null; if (obj instanceof PGHStore) @@ -141,7 +135,7 @@ public class MapDatabase implements IMapDatabase { else continue; - b = r.getBytes(3); + b = r.getBytes(2); } catch (SQLException e) { e.printStackTrace(); @@ -184,6 +178,11 @@ public class MapDatabase implements IMapDatabase { } } + @Override + public String getMapProjection() { + return WebMercator.NAME; + } + @Override public MapFileInfo getMapFileInfo() { return mMapInfo;