- adding MapDatabase backend for our TileStache provider

- fixing some renering bugs on nexus phone
and some refactoring and cleanup
This commit is contained in:
Hannes Janetzek
2012-08-07 03:04:39 +02:00
parent c5c952bf14
commit 124624785d
43 changed files with 2287 additions and 1779 deletions

View File

@@ -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<PointTextContainer> 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
}
}

View File

@@ -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<MapGeneratorJob> mJobList;
ArrayList<Integer> 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<TileCacheKey, GLMapTile> 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()));
// }
// }
// }
// }

View File

@@ -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<WayTextContainer> 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";
}