diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1353acbe..264fa792 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -88,7 +88,8 @@
Show the scale of the map
Tile coordinates
Show coordinates on tiles
- Tile boundaries
+ Draw unmatched ways
+ Tile boundaries
Draw tile boundaries
Disable Polygon rendering
Highlight tiles which have the water flag set
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index e633f96c..2dad5457 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -32,8 +32,8 @@
android:key="showFpsCounter" /> -->
-
+
diff --git a/src/org/mapsforge/android/DebugSettings.java b/src/org/mapsforge/android/DebugSettings.java
index faa04aab..729e5c1c 100644
--- a/src/org/mapsforge/android/DebugSettings.java
+++ b/src/org/mapsforge/android/DebugSettings.java
@@ -29,13 +29,13 @@ public class DebugSettings {
*/
public final boolean mDrawTileFrames;
+ public final boolean mDrawUnmatchted;
+
/**
* True if highlighting of water tiles is enabled, false otherwise.
*/
public final boolean mDisablePolygons;
- private final int mHashCodeValue;
-
/**
* @param drawTileCoordinates
* if drawing of tile coordinates is enabled.
@@ -43,49 +43,14 @@ public class DebugSettings {
* if drawing of tile frames is enabled.
* @param disablePolygons
* if highlighting of water tiles is enabled.
+ * @param drawUnmatched
+ * ...
*/
public DebugSettings(boolean drawTileCoordinates, boolean drawTileFrames,
- boolean disablePolygons) {
+ boolean disablePolygons, boolean drawUnmatched) {
mDrawTileCoordinates = drawTileCoordinates;
mDrawTileFrames = drawTileFrames;
+ mDrawUnmatchted = drawUnmatched;
mDisablePolygons = disablePolygons;
- mHashCodeValue = calculateHashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof DebugSettings)) {
- return false;
- }
- DebugSettings other = (DebugSettings) obj;
- if (mDrawTileCoordinates != other.mDrawTileCoordinates) {
- return false;
- }
- if (mDrawTileFrames != other.mDrawTileFrames) {
- return false;
- }
- if (mDisablePolygons != other.mDisablePolygons) {
- return false;
- }
- return true;
- }
-
- @Override
- public int hashCode() {
- return mHashCodeValue;
- }
-
- /**
- * @return the hash code of this object.
- */
- private int calculateHashCode() {
- int result = 1;
- result = 31 * result + (mDrawTileCoordinates ? 1231 : 1237);
- result = 31 * result + (mDrawTileFrames ? 1231 : 1237);
- result = 31 * result + (mDisablePolygons ? 1231 : 1237);
- return result;
}
}
diff --git a/src/org/mapsforge/android/MapView.java b/src/org/mapsforge/android/MapView.java
index 8f6fcf84..ef5b1b62 100644
--- a/src/org/mapsforge/android/MapView.java
+++ b/src/org/mapsforge/android/MapView.java
@@ -40,6 +40,7 @@ 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.core.Tile;
import org.mapsforge.database.FileOpenResult;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.MapFileInfo;
@@ -93,9 +94,9 @@ public class MapView extends GLSurfaceView {
private IMapRenderer mMapRenderer;
private JobQueue mJobQueue;
private MapWorker mMapWorkers[];
- private int mNumMapWorkers = 4;
+ private int mNumMapWorkers = 6;
private JobParameters mJobParameters;
- private DebugSettings mDebugSettings;
+ public DebugSettings debugSettings;
private String mMapFile;
/**
@@ -122,6 +123,8 @@ public class MapView extends GLSurfaceView {
MapDatabaseFactory.getMapDatabase(attributeSet));
}
+ private boolean mDebugDatabase = false;
+
private MapView(Context context, AttributeSet attributeSet,
MapRenderers mapGeneratorType, MapDatabases mapDatabaseType) {
@@ -131,13 +134,17 @@ public class MapView extends GLSurfaceView {
throw new IllegalArgumentException(
"context is not an instance of MapActivity");
}
+ Log.d(TAG, "create MapView: " + mapDatabaseType.name());
- setWillNotDraw(true);
- setWillNotCacheDrawing(true);
+ // TODO make this dpi dependent
+ Tile.TILE_SIZE = 400;
+
+ // setWillNotDraw(true);
+ // setWillNotCacheDrawing(true);
MapActivity mapActivity = (MapActivity) context;
- mDebugSettings = new DebugSettings(false, false, false);
+ debugSettings = new DebugSettings(false, false, false, false);
mJobParameters = new JobParameters(DEFAULT_RENDER_THEME, DEFAULT_TEXT_SCALE);
mMapController = new MapController(this);
@@ -161,8 +168,14 @@ public class MapView extends GLSurfaceView {
mMapWorkers = new MapWorker[mNumMapWorkers];
for (int i = 0; i < mNumMapWorkers; i++) {
- IMapDatabase mapDatabase = MapDatabaseFactory
- .createMapDatabase(mapDatabaseType);
+ IMapDatabase mapDatabase;
+ if (mDebugDatabase) {
+ mapDatabase = MapDatabaseFactory
+ .createMapDatabase(MapDatabases.JSON_READER);
+
+ } else {
+ mapDatabase = MapDatabaseFactory.createMapDatabase(mapDatabaseType);
+ }
IMapGenerator mapGenerator = mMapRenderer.createMapGenerator();
mapGenerator.setMapDatabase(mapDatabase);
@@ -170,8 +183,6 @@ public class MapView extends GLSurfaceView {
if (i == 0) {
mMapDatabase = mapDatabase;
initMapStartPosition();
-
- // mapGenerator.setRendertheme(DEFAULT_RENDER_THEME);
}
mMapWorkers[i] = new MapWorker(i, this, mapGenerator, mMapRenderer);
mMapWorkers[i].start();
@@ -179,13 +190,13 @@ public class MapView extends GLSurfaceView {
setRenderTheme(InternalRenderTheme.OSMARENDER);
- mapActivity.registerMapView(this);
-
setEGLConfigChooser(new GlConfigChooser());
setEGLContextClientVersion(2);
setRenderer(mMapRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+
+ mapActivity.registerMapView(this);
}
private void initMapStartPosition() {
@@ -212,7 +223,7 @@ public class MapView extends GLSurfaceView {
* @return the debug settings which are used in this MapView.
*/
public DebugSettings getDebugSettings() {
- return mDebugSettings;
+ return debugSettings;
}
/**
@@ -302,14 +313,14 @@ public class MapView extends GLSurfaceView {
* Calculates all necessary tiles and adds jobs accordingly.
*/
public void redrawTiles() {
- if (getWidth() > 0 && getHeight() > 0)
+ if (getWidth() <= 0 || getHeight() <= 0)
return;
mMapRenderer.redrawTiles(false);
}
- void clearAndRedrawMapView() {
- if (getWidth() > 0 && getHeight() > 0)
+ private void clearAndRedrawMapView() {
+ if (getWidth() <= 0 || getHeight() <= 0)
return;
mMapRenderer.redrawTiles(true);
@@ -343,7 +354,7 @@ public class MapView extends GLSurfaceView {
* the new DebugSettings for this MapView.
*/
public void setDebugSettings(DebugSettings debugSettings) {
- mDebugSettings = debugSettings;
+ this.debugSettings = debugSettings;
clearAndRedrawMapView();
}
@@ -377,7 +388,7 @@ public class MapView extends GLSurfaceView {
mJobQueue.clear();
- mapWorkersPause();
+ mapWorkersPause(true);
for (MapWorker mapWorker : mMapWorkers) {
@@ -445,6 +456,9 @@ public class MapView extends GLSurfaceView {
*/
public void setMapDatabase(MapDatabases mapDatabaseType) {
+ if (mDebugDatabase)
+ return;
+
IMapGenerator mapGenerator;
Log.d(TAG, "setMapDatabase " + mapDatabaseType.name());
@@ -452,7 +466,9 @@ public class MapView extends GLSurfaceView {
if (mMapDatabaseType == mapDatabaseType)
return;
- mapWorkersPause();
+ mMapDatabaseType = mapDatabaseType;
+
+ mapWorkersPause(true);
for (MapWorker mapWorker : mMapWorkers) {
mapGenerator = mapWorker.getMapGenerator();
@@ -468,6 +484,8 @@ public class MapView extends GLSurfaceView {
setMapFile(mapFile);
mapWorkersProceed();
+
+ Log.d(TAG, ">>>");
}
/**
@@ -510,7 +528,7 @@ public class MapView extends GLSurfaceView {
private boolean setRenderTheme(Theme theme) {
- mapWorkersPause();
+ mapWorkersPause(true);
InputStream inputStream = null;
try {
@@ -607,7 +625,7 @@ public class MapView extends GLSurfaceView {
int oldHeight) {
mJobQueue.clear();
- mapWorkersPause();
+ mapWorkersPause(true);
super.onSizeChanged(width, height, oldWidth, oldHeight);
@@ -668,8 +686,7 @@ public class MapView extends GLSurfaceView {
@Override
public void onPause() {
super.onPause();
- for (MapWorker mapWorker : mMapWorkers)
- mapWorker.pause();
+ mapWorkersPause(false);
// mMapMover.pause();
// mZoomAnimator.pause();
@@ -678,8 +695,7 @@ public class MapView extends GLSurfaceView {
@Override
public void onResume() {
super.onResume();
- for (MapWorker mapWorker : mMapWorkers)
- mapWorker.proceed();
+ mapWorkersProceed();
// mMapMover.proceed();
// mZoomAnimator.proceed();
@@ -747,21 +763,24 @@ public class MapView extends GLSurfaceView {
public void addJobs(ArrayList jobs) {
mJobQueue.setJobs(jobs);
- for (MapWorker m : mMapWorkers) {
+ for (int i = 0; i < mNumMapWorkers; i++) {
+ MapWorker m = mMapWorkers[i];
synchronized (m) {
m.notify();
}
}
}
- private void mapWorkersPause() {
+ private void mapWorkersPause(boolean wait) {
for (MapWorker mapWorker : mMapWorkers) {
if (!mapWorker.isPausing())
mapWorker.pause();
}
- for (MapWorker mapWorker : mMapWorkers) {
- if (!mapWorker.isPausing())
- mapWorker.awaitPausing();
+ if (wait) {
+ for (MapWorker mapWorker : mMapWorkers) {
+ if (!mapWorker.isPausing())
+ mapWorker.awaitPausing();
+ }
}
}
diff --git a/src/org/mapsforge/android/glrenderer/GLMapTile.java b/src/org/mapsforge/android/glrenderer/GLMapTile.java
index f8837803..9abc5783 100644
--- a/src/org/mapsforge/android/glrenderer/GLMapTile.java
+++ b/src/org/mapsforge/android/glrenderer/GLMapTile.java
@@ -14,6 +14,8 @@
*/
package org.mapsforge.android.glrenderer;
+import java.util.ArrayList;
+
import org.mapsforge.android.mapgenerator.MapTile;
import org.mapsforge.core.Tile;
@@ -21,10 +23,12 @@ class GLMapTile extends MapTile {
VertexBufferObject lineVBO;
VertexBufferObject polygonVBO;
+ TextTexture texture;
- LineLayers lineLayers;
- PolygonLayers polygonLayers;
- // MeshLayers meshLayers;
+ LineLayer lineLayers;
+ PolygonLayer polygonLayers;
+
+ ArrayList labels;
boolean newData;
boolean loading;
diff --git a/src/org/mapsforge/android/glrenderer/Layer.java b/src/org/mapsforge/android/glrenderer/Layer.java
index e7d3de3b..ca93b35e 100644
--- a/src/org/mapsforge/android/glrenderer/Layer.java
+++ b/src/org/mapsforge/android/glrenderer/Layer.java
@@ -14,35 +14,27 @@
*/
package org.mapsforge.android.glrenderer;
-import java.util.LinkedList;
-
class Layer {
- LinkedList pool;
+ PoolItem pool;
+
protected PoolItem curItem;
int verticesCnt;
int offset;
final int layer;
- // final int color;
- final float[] colors;
- Layer(int l, int color) {
+ Layer(int l) {
layer = l;
verticesCnt = 0;
-
- colors = new float[4];
-
- colors[0] = (color >> 16 & 0xff) / 255.0f;
- colors[1] = (color >> 8 & 0xff) / 255.0f;
- colors[2] = (color >> 0 & 0xff) / 255.0f;
- colors[3] = (color >> 24 & 0xff) / 255.0f;
}
float[] getNextPoolItem() {
curItem.used = PoolItem.SIZE;
- curItem = LayerPool.get();
- pool.add(curItem);
+
+ curItem.next = VertexPool.get();
+ curItem = curItem.next;
+
return curItem.vertices;
}
}
diff --git a/src/org/mapsforge/android/glrenderer/LineLayer.java b/src/org/mapsforge/android/glrenderer/LineLayer.java
index 085a3e95..f8524ddc 100644
--- a/src/org/mapsforge/android/glrenderer/LineLayer.java
+++ b/src/org/mapsforge/android/glrenderer/LineLayer.java
@@ -14,34 +14,39 @@
*/
package org.mapsforge.android.glrenderer;
-import java.util.ArrayList;
-import java.util.LinkedList;
-
+import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.core.Tile;
+import android.util.FloatMath;
+
class LineLayer extends Layer {
- ArrayList outlines;
- boolean isOutline;
- boolean isFixed;
+ Line line;
+
+ LineLayer next;
+ LineLayer outlines;
+
float width;
+ boolean isOutline;
- LineLayer(int layer, int color, boolean outline, boolean fixed) {
- super(layer, color);
- isOutline = outline;
- isFixed = fixed;
- if (outline) {
- outlines = new ArrayList();
- } else {
- curItem = LayerPool.get();
+ LineLayer(int layer, Line line, boolean outline) {
+ super(layer);
- pool = new LinkedList();
- pool.add(curItem);
+ this.line = line;
+ this.isOutline = outline;
+
+ if (!outline) {
+ curItem = VertexPool.get();
+ pool = curItem;
}
}
void addOutline(LineLayer link) {
- if (!outlines.contains(link))
- outlines.add(link);
+ for (LineLayer l = outlines; l != null; l = l.outlines)
+ if (link == l)
+ return;
+
+ link.outlines = outlines;
+ outlines = link;
}
/*
@@ -49,7 +54,7 @@ class LineLayer extends Layer {
*/
void addLine(float[] pointArray, int pos, int length, float w, boolean capRound) {
float x, y, nextX, nextY, prevX, prevY, ux, uy, vx, vy, wx, wy;
- double a;
+ float a;
int pointPos = pos;
boolean rounded = capRound;
width = w;
@@ -59,10 +64,12 @@ class LineLayer extends Layer {
// amount of vertices used
verticesCnt += length + (rounded ? 6 : 2);
+ int MAX = PoolItem.SIZE;
+
float[] curVertices = curItem.vertices;
int vertexPos = curItem.used;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -77,7 +84,7 @@ class LineLayer extends Layer {
vx = nextX - x;
vy = nextY - y;
- a = Math.sqrt(vx * vx + vy * vy);
+ a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
@@ -103,7 +110,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 1.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -113,7 +120,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 1.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -123,7 +130,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 1.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -134,7 +141,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -161,7 +168,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -171,7 +178,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -195,14 +202,14 @@ class LineLayer extends Layer {
// Unit vector pointing back to previous node
vx = prevX - x;
vy = prevY - y;
- a = Math.sqrt(vx * vx + vy * vy);
+ a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
// Unit vector pointing forward to next node
wx = nextX - x;
wy = nextY - y;
- a = Math.sqrt(wx * wx + wy * wy);
+ a = FloatMath.sqrt(wx * wx + wy * wy);
wx = (float) (wx / a);
wy = (float) (wy / a);
@@ -242,7 +249,7 @@ class LineLayer extends Layer {
uxw = ux * w;
uyw = uy * w;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -252,7 +259,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -271,7 +278,7 @@ class LineLayer extends Layer {
vx = prevX - x;
vy = prevY - y;
- a = Math.sqrt(vx * vx + vy * vy);
+ a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
@@ -288,11 +295,16 @@ class LineLayer extends Layer {
outside = (x <= 0 || x >= Tile.TILE_SIZE || y <= 0 || y >= Tile.TILE_SIZE)
&& (x - vxw <= 0 || x - vxw >= Tile.TILE_SIZE || y - vyw <= 0 || y - vyw >= Tile.TILE_SIZE);
- if (vertexPos == PoolItem.SIZE) {
- curItem.used = vertexPos;
- curItem = LayerPool.get();
- pool.add(curItem);
- curVertices = curItem.vertices;
+ // if (vertexPos == MAX) {
+ // curItem.used = vertexPos;
+ // curItem = LayerPool.get();
+ // pool.add(curItem);
+ // curVertices = curItem.vertices;
+ // vertexPos = 0;
+ // }
+
+ if (vertexPos == MAX) {
+ curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -302,7 +314,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -312,7 +324,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -323,7 +335,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = -1.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -334,7 +346,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = -1.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -358,7 +370,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
@@ -369,7 +381,7 @@ class LineLayer extends Layer {
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
- if (vertexPos == PoolItem.SIZE) {
+ if (vertexPos == MAX) {
curVertices = getNextPoolItem();
vertexPos = 0;
}
diff --git a/src/org/mapsforge/android/glrenderer/LineLayers.java b/src/org/mapsforge/android/glrenderer/LineLayers.java
index 3299bb8d..97ebd51a 100644
--- a/src/org/mapsforge/android/glrenderer/LineLayers.java
+++ b/src/org/mapsforge/android/glrenderer/LineLayers.java
@@ -19,42 +19,17 @@ import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
-import android.util.SparseArray;
-
class LineLayers {
private static int NUM_VERTEX_FLOATS = 4;
- private SparseArray layers;
-
- LineLayer[] array = null;
- int size = 0;
-
- LineLayers() {
- layers = new SparseArray(10);
- }
-
- LineLayer getLayer(int layer, int color, boolean outline, boolean fixed) {
- LineLayer l = layers.get(layer);
- if (l != null) {
- return l;
- }
-
- l = new LineLayer(layer, color, outline, fixed);
- layers.put(layer, l);
-
- return l;
- }
-
- FloatBuffer compileLayerData(FloatBuffer buf) {
+ static FloatBuffer compileLayerData(LineLayer layers, FloatBuffer buf) {
FloatBuffer fbuf = buf;
+ int size = 0;
- array = new LineLayer[layers.size()];
+ for (LineLayer l = layers; l != null; l = l.next)
+ size += l.verticesCnt;
- for (int i = 0, n = layers.size(); i < n; i++) {
- LineLayer l = layers.valueAt(i);
- array[i] = l;
- size += l.verticesCnt * NUM_VERTEX_FLOATS;
- }
+ size *= NUM_VERTEX_FLOATS;
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
@@ -65,40 +40,42 @@ class LineLayers {
}
int pos = 0;
- for (int i = 0, n = array.length; i < n; i++) {
- LineLayer l = array[i];
+ PoolItem last = null, items = null;
+
+ for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline)
continue;
- for (PoolItem item : l.pool) {
+ for (PoolItem item = l.pool; item != null; item = item.next) {
fbuf.put(item.vertices, 0, item.used);
+ last = item;
}
-
l.offset = pos;
pos += l.verticesCnt;
- LayerPool.add(l.pool);
+ if (last != null) {
+ last.next = items;
+ items = l.pool;
+ }
+
l.pool = null;
}
- fbuf.flip();
+ VertexPool.add(items);
- // not needed for drawing
- layers = null;
+ fbuf.flip();
return fbuf;
}
- ShortBuffer compileLayerData(ShortBuffer buf) {
+ static ShortBuffer compileLayerData(LineLayer layers, ShortBuffer buf) {
+ int size = 0;
ShortBuffer sbuf = buf;
- array = new LineLayer[layers.size()];
+ for (LineLayer l = layers; l != null; l = l.next)
+ size += l.verticesCnt;
- for (int i = 0, n = layers.size(); i < n; i++) {
- LineLayer l = layers.valueAt(i);
- array[i] = l;
- size += l.verticesCnt * NUM_VERTEX_FLOATS;
- }
+ size *= NUM_VERTEX_FLOATS;
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order(
@@ -111,29 +88,40 @@ class LineLayers {
short[] data = new short[PoolItem.SIZE];
- for (int i = 0, n = array.length; i < n; i++) {
- LineLayer l = array[i];
+ PoolItem last = null, items = null;
+
+ for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline)
continue;
- for (int k = 0, m = l.pool.size(); k < m; k++) {
- PoolItem item = l.pool.get(k);
+ for (PoolItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used);
+ last = item;
}
l.offset = pos;
pos += l.verticesCnt;
- LayerPool.add(l.pool);
+ if (last != null) {
+ last.next = items;
+ items = l.pool;
+ }
+
l.pool = null;
}
- sbuf.flip();
+ VertexPool.add(items);
- // not needed for drawing
- layers = null;
+ sbuf.flip();
return sbuf;
}
+
+ static void clear(LineLayer layer) {
+ for (LineLayer l = layer; l != null; l = l.next) {
+ if (l.pool != null)
+ VertexPool.add(l.pool);
+ }
+ }
}
diff --git a/src/org/mapsforge/android/glrenderer/MapGenerator.java b/src/org/mapsforge/android/glrenderer/MapGenerator.java
index 4ed8a11b..35e756e6 100644
--- a/src/org/mapsforge/android/glrenderer/MapGenerator.java
+++ b/src/org/mapsforge/android/glrenderer/MapGenerator.java
@@ -14,11 +14,14 @@
*/
package org.mapsforge.android.glrenderer;
+import java.util.ArrayList;
+
import org.mapsforge.android.mapgenerator.IMapGenerator;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.rendertheme.IRenderCallback;
import org.mapsforge.android.rendertheme.RenderTheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
+import org.mapsforge.android.rendertheme.renderinstruction.Caption;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.android.rendertheme.renderinstruction.RenderInstruction;
import org.mapsforge.core.MercatorProjection;
@@ -27,9 +30,9 @@ import org.mapsforge.core.Tile;
import org.mapsforge.core.WebMercator;
import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback;
+import org.mapsforge.database.QueryResult;
import android.graphics.Bitmap;
-import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
@@ -54,11 +57,14 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
private GLMapTile mCurrentTile;
private float[] mWayNodes;
- private int[] mWays;
+ private short[] mWays;
- private LineLayers mLineLayers;
- private PolygonLayers mPolyLayers;
- // private MeshLayers mMeshLayers;
+ private LineLayer mLineLayers;
+ private PolygonLayer mPolyLayers;
+ private LineLayer mCurLineLayer;
+ private PolygonLayer mCurPolyLayer;
+
+ private ArrayList mLabels;
private int mDrawingLayer;
private int mLevels;
@@ -71,13 +77,60 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
*/
public MapGenerator() {
Log.d(TAG, "init DatabaseRenderer");
- LayerPool.init();
+ VertexPool.init();
+ }
+
+ private float mPoiX = 256;
+ private float mPoiY = 256;
+
+ private Tag mTagEmptyName = new Tag("name", "");
+ private Tag mTagName;
+
+ private void filterTags(Tag[] tags) {
+ for (int i = 0; i < tags.length; i++) {
+ // Log.d(TAG, "check tag: " + tags[i]);
+ if (tags[i].key == mTagEmptyName.key && tags[i].value != null) {
+ mTagName = tags[i];
+ tags[i] = mTagEmptyName;
+ }
+ }
}
@Override
- public void renderPointOfInterest(byte layer, int latitude, int longitude, Tag[] tags) {
- // TODO Auto-generated method stub
+ public void renderPointOfInterest(byte layer, float latitude, float longitude,
+ Tag[] tags) {
+ mTagName = null;
+
+ long x = mCurrentTile.x;
+ long y = mCurrentTile.y;
+ long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
+
+ double divx, divy;
+ long dx = (x - (z >> 1));
+ long dy = (y - (z >> 1));
+
+ if (useSphericalMercator) {
+ divx = f900913 / (z >> 1);
+ divy = f900913 / (z >> 1);
+ mPoiX = (float) (longitude / divx - dx);
+ mPoiY = (float) (latitude / divy + dy);
+ } else {
+ divx = 180000000.0 / (z >> 1);
+ divy = z / PIx4;
+ mPoiX = (float) (longitude / divx - dx);
+ double sinLat = Math.sin(latitude * PI180);
+ mPoiY = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
+ if (mPoiX < -10 || mPoiX > Tile.TILE_SIZE + 10 || mPoiY < -10
+ || mPoiY > Tile.TILE_SIZE + 10)
+ return;
+ }
+
+ // remove tags that should not be cached in Rendertheme
+ filterTags(tags);
+ // Log.d(TAG, "renderPointOfInterest: " + mTagName);
+
+ MapGenerator.renderTheme.matchNode(this, tags, mCurrentTile.zoomLevel);
}
@Override
@@ -94,7 +147,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (mProjected)
return mProjectedResult;
- float minx = Float.MAX_VALUE, miny = Float.MAX_VALUE, maxx = Float.MIN_VALUE, maxy = Float.MIN_VALUE;
+ // float minx = Float.MAX_VALUE, miny = Float.MAX_VALUE, maxx = Float.MIN_VALUE, maxy = Float.MIN_VALUE;
float[] coords = mWayNodes;
@@ -133,16 +186,16 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
lat = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
}
- if (area && i == 0) {
- if (lon < minx)
- minx = lon;
- if (lon > maxx)
- maxx = lon;
- if (lat < miny)
- miny = lat;
- if (lat > maxy)
- maxy = lat;
- }
+ // if (area && i == 0) {
+ // if (lon < minx)
+ // minx = lon;
+ // if (lon > maxx)
+ // maxx = lon;
+ // if (lat < miny)
+ // miny = lat;
+ // if (lat > maxy)
+ // maxy = lat;
+ // }
if (cnt != 0) {
// drop small distance intermediate nodes
@@ -161,38 +214,44 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
cnt += 2;
}
- if (area) {
- // Log.d(TAG, "area:" + (maxx - minx) * (maxy - miny));
- if ((maxx - minx) * (maxy - miny) < 2000 / mCurrentTile.zoomLevel) {
- mProjected = true;
- mProjectedResult = false;
- return false;
- }
- }
+ // if (area) {
+ // // Log.d(TAG, "area:" + (maxx - minx) * (maxy - miny));
+ // if ((maxx - minx) * (maxy - miny) < 2000 / mCurrentTile.zoomLevel) {
+ // mProjected = true;
+ // mProjectedResult = false;
+ // return false;
+ // }
+ // }
- mWays[i] = cnt;
+ mWays[i] = (short) cnt;
}
mProjected = true;
mProjectedResult = true;
return true;
}
- private boolean firstMatch;
- private boolean prevClosed;
+ // private boolean firstMatch;
+ // private boolean prevClosed;
private RenderInstruction[] mRenderInstructions = null;
+ private final String TAG_WATER = "water".intern();
+
@Override
- public void renderWay(byte layer, Tag[] tags, float[] wayNodes, int[] wayLength,
+ public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
boolean changed) {
+ // Log.d(TAG, "render way: " + layer);
+ mTagName = null;
+
mProjected = false;
mDrawingLayer = getValidLayer(layer) * mLevels;
- int len = wayLength[0];
- boolean closed = (wayNodes[0] == wayNodes[len - 2] &&
- wayNodes[1] == wayNodes[len - 1]);
+ // int len = wayLength[0];
+ // boolean closed = (wayNodes[0] == wayNodes[len - 2] &&
+ // wayNodes[1] == wayNodes[len - 1]);
+ boolean closed = changed;
mSimplify = 0.5f;
if (closed) {
@@ -201,36 +260,76 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
else
mSimplify = 0.2f;
- if (tags.length == 1 && "water".equals(tags[0].value))
+ if (tags.length == 1 && TAG_WATER == (tags[0].value))
mSimplify = 0;
}
mWayNodes = wayNodes;
mWays = wayLength;
- if (!firstMatch && prevClosed == closed && !changed) {
- 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);
+ // if (mRenderInstructions != null) {
+ // for (int i = 0, n = mRenderInstructions.length; i < n; i++)
+ // mRenderInstructions[i].renderWay(this, tags);
+ // }
+
+ // prevClosed = closed;
+ mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
+ (byte) (mCurrentTile.zoomLevel + 0),
+ closed, true);
+
+ if (mRenderInstructions == null && mDebugDrawUnmatched)
+ debugUnmatched(closed, tags);
+
+ // firstMatch = false;
+ }
+
+ private void debugUnmatched(boolean closed, Tag[] tags) {
+
+ Log.d(TAG, "way not matched: " + tags[0] + " "
+ + (tags.length > 1 ? tags[1] : "") + " " + closed);
+
+ mTagName = new Tag("name", tags[0].key + ":" + tags[0].value, false);
+
+ if (closed) {
+ mRenderInstructions = MapGenerator.renderTheme.matchWay(this, debugTagArea,
+ (byte) 0, true, true);
} else {
- prevClosed = closed;
- mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
- (byte) (mCurrentTile.zoomLevel + 0),
- closed, true);
+ mRenderInstructions = MapGenerator.renderTheme.matchWay(this, debugTagWay,
+ (byte) 0, true, true);
}
- firstMatch = false;
}
@Override
- public void renderAreaCaption(String caption, float verticalOffset, Paint paint,
- Paint stroke) {
- // TODO Auto-generated method stub
+ public void renderAreaCaption(Caption caption) {
+ // Log.d(TAG, "renderAreaCaption: " + mTagName);
+ if (mTagName == null)
+ return;
+
+ if (caption.textKey == mTagEmptyName.key) {
+ if (mLabels == null)
+ mLabels = new ArrayList();
+ mLabels.add(new TextItem(mWayNodes[0], mWayNodes[1], mTagName.value, caption));
+ }
+
+ // if (caption.textKey == mTagEmptyName.key)
+ // mLabels.add(new TextItem(mPoiX, mPoiY, mTagName.value, caption));
+ }
+
+ @Override
+ public void renderPointOfInterestCaption(Caption caption) {
+ // Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY + " "
+ // + mTagName);
+
+ if (mTagName == null)
+ return;
+
+ if (caption.textKey == mTagEmptyName.key) {
+ if (mLabels == null)
+ mLabels = new ArrayList();
+ mLabels.add(new TextItem(mPoiX, mPoiY, mTagName.value, caption));
+ }
}
@Override
@@ -239,13 +338,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
}
- @Override
- public void renderPointOfInterestCaption(String caption, float verticalOffset,
- Paint paint, Paint stroke) {
- // TODO Auto-generated method stub
-
- }
-
@Override
public void renderPointOfInterestCircle(float radius, Paint fill, int level) {
// TODO Auto-generated method stub
@@ -260,12 +352,60 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
@Override
public void renderWay(Line line) {
-
projectToTile(false);
LineLayer outlineLayer = null;
- LineLayer l = mLineLayers.getLayer(mDrawingLayer + line.level, line.color, false,
- line.fixed);
+ LineLayer lineLayer = null;
+
+ int numLayer = mDrawingLayer + line.level;
+
+ // LineLayer l = mLineLayers;
+ //
+ // for (; l != null; l = l.next)
+ // if (l.next == null || l.next.layer > numLayer)
+ // break;
+ //
+ // if (l == null || l == mLineLayers) {
+ // // insert at start
+ // lineLayer = new LineLayer(numLayer, line, false);
+ // lineLayer.next = mLineLayers;
+ // mLineLayers = lineLayer;
+ // } else if (l.layer == numLayer) {
+ // lineLayer = l;
+ // } else {
+ // // insert between current and next layer
+ // lineLayer = new LineLayer(numLayer, line, false);
+ // lineLayer.next = l.next;
+ // l.next = lineLayer;
+ // }
+
+ // FIXME simplify this...
+ if (mCurLineLayer != null && mCurLineLayer.layer == numLayer) {
+ lineLayer = mCurLineLayer;
+ } else if (mLineLayers == null || mLineLayers.layer > numLayer) {
+ // insert new layer at start
+ lineLayer = new LineLayer(numLayer, line, false);
+ lineLayer.next = mLineLayers;
+ mLineLayers = lineLayer;
+ } else {
+ for (LineLayer l = mLineLayers; l != null; l = l.next) {
+ if (l.layer == numLayer) {
+ lineLayer = l;
+ break;
+ }
+ if (l.next == null || l.next.layer > numLayer) {
+ lineLayer = new LineLayer(numLayer, line, false);
+ // insert new layer between current and next layer
+ lineLayer.next = l.next;
+ l.next = lineLayer;
+ }
+ }
+ }
+
+ if (lineLayer == null)
+ return;
+
+ mCurLineLayer = lineLayer;
float w = line.strokeWidth;
@@ -273,13 +413,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
w *= mStrokeScale;
w *= mProjectionScaleFactor;
}
- if (line.outline != -1) {
- Line outline = MapGenerator.renderTheme.getOutline(line.outline);
- if (outline != null) {
- outlineLayer = mLineLayers.getLayer(mDrawingLayer + outline.level,
- outline.color, true, false);
- outlineLayer.addOutline(l);
- }
+ else {
+ w *= 1.2; // TODO make this dependent on dpi
}
for (int i = 0, pos = 0, n = mWays.length; i < n; i++) {
@@ -287,10 +422,44 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
// need at least two points
if (length >= 4)
- l.addLine(mWayNodes, pos, length, w, line.round);
+ lineLayer.addLine(mWayNodes, pos, length, w, line.round);
pos += length;
}
+
+ if (line.outline < 0)
+ return;
+
+ Line outline = MapGenerator.renderTheme.getOutline(line.outline);
+
+ if (outline == null)
+ return;
+
+ numLayer = mDrawingLayer + outline.level;
+
+ if (mLineLayers == null || mLineLayers.layer > numLayer) {
+ // insert new layer at start
+ outlineLayer = new LineLayer(numLayer, outline, true);
+ outlineLayer.next = mLineLayers;
+ mLineLayers = outlineLayer;
+ } else {
+ for (LineLayer l = mLineLayers; l != null; l = l.next) {
+ if (l.layer == numLayer) {
+ outlineLayer = l;
+ break;
+ }
+ if (l.next == null || l.next.layer > numLayer) {
+ outlineLayer = new LineLayer(numLayer, outline, true);
+ // insert new layer between current and next layer
+ outlineLayer.next = l.next;
+ l.next = outlineLayer;
+ }
+ }
+ }
+
+ if (outlineLayer != null)
+ outlineLayer.addOutline(lineLayer);
+
}
@Override
@@ -302,17 +471,41 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (!projectToTile(false))
return;
- PolygonLayer l = mPolyLayers.getLayer(mDrawingLayer + area.level, area.color,
- area.fade);
+ int numLayer = mDrawingLayer + area.level;
+ PolygonLayer layer = null;
- // MeshLayer l = mMeshLayers.getLayer(mDrawingLayer + area.level, area.color,
- // area.fade);
+ if (mCurPolyLayer != null && mCurPolyLayer.layer == numLayer) {
+ layer = mCurPolyLayer;
+ } else if (mPolyLayers == null || mPolyLayers.layer > numLayer) {
+ // insert new layer at start
+ layer = new PolygonLayer(numLayer, area);
+ layer.next = mPolyLayers;
+ mPolyLayers = layer;
+ } else {
+ for (PolygonLayer l = mPolyLayers; l != null; l = l.next) {
+ if (l.layer >= numLayer) {
+ layer = l;
+ break;
+ }
+
+ if (l.next == null || l.next.layer > numLayer) {
+ layer = new PolygonLayer(numLayer, area);
+ // insert new layer between current and next layer
+ layer.next = l.next;
+ l.next = layer;
+ }
+ }
+ }
+ if (layer == null)
+ return;
+
+ mCurPolyLayer = layer;
for (int i = 0, pos = 0, n = mWays.length; i < n; i++) {
int length = mWays[i];
// need at least three points
if (length >= 6)
- l.addPolygon(mWayNodes, pos, length);
+ layer.addPolygon(mWayNodes, pos, length);
pos += length;
}
@@ -338,10 +531,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
}
private boolean mDebugDrawPolygons;
+ boolean mDebugDrawUnmatched;
@Override
public boolean executeJob(MapGeneratorJob mapGeneratorJob) {
- // Log.d(TAG, "load " + mCurrentTile);
if (!(mapGeneratorJob.tile instanceof GLMapTile))
return false;
@@ -353,7 +546,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurrentTile = (GLMapTile) mapGeneratorJob.tile;
mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons;
-
+ mDebugDrawUnmatched = mapGeneratorJob.debugSettings.mDrawUnmatchted;
if (mCurrentTile.isLoading || mCurrentTile.isDrawn)
return false;
@@ -363,32 +556,49 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
setScaleStrokeWidth(mCurrentTile.zoomLevel);
- mLineLayers = new LineLayers();
- mPolyLayers = new PolygonLayers();
- // mMeshLayers = new MeshLayers();
- mCurrentTile.lineLayers = mLineLayers;
- mCurrentTile.polygonLayers = mPolyLayers;
- // mCurrentTile.meshLayers = mMeshLayers;
+ mLineLayers = null;
+ mPolyLayers = null;
+ mLabels = null;
- firstMatch = true;
+ // firstMatch = true;
mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection
.pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel)
- * (Math.PI / 180))) / 1.5f;
- mMapDatabase.executeQuery(mCurrentTile, this);
+ * (Math.PI / 180))); // / 1.5f;
+
+ if (mMapDatabase.executeQuery(mCurrentTile, this) != QueryResult.SUCCESS) {
+ LineLayers.clear(mLineLayers);
+ PolygonLayers.clear(mPolyLayers);
+ mLineLayers = null;
+ mPolyLayers = null;
+ mCurrentTile.isLoading = false;
+ return false;
+ }
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.5f, false);
+ mTagName = new Tag("name", mCurrentTile.toString(), false);
+ mPoiX = 10;
+ mPoiY = 10;
+ MapGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0);
+ // 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, -1);
+ // ll.addLine(coords, 0, coords.length, 1.5f, false);
}
+ mCurrentTile.lineLayers = mLineLayers;
+ mCurrentTile.polygonLayers = mPolyLayers;
+ mCurrentTile.labels = mLabels;
+ mCurPolyLayer = null;
+ mCurLineLayer = null;
mCurrentTile.newData = true;
return true;
}
+ private Tag[] debugTagWay = { new Tag("debug", "way") };
+ private Tag[] debugTagArea = { new Tag("debug", "area") };
+
private float mProjectionScaleFactor;
private static byte getValidLayer(byte layer) {
@@ -431,4 +641,13 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
public void setRenderTheme(RenderTheme theme) {
MapGenerator.renderTheme = theme;
}
+
+ @Override
+ public boolean checkWay(Tag[] tags, boolean closed) {
+
+ mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
+ (byte) (mCurrentTile.zoomLevel + 0), closed, false);
+
+ return mRenderInstructions != null;
+ }
}
diff --git a/src/org/mapsforge/android/glrenderer/MapRenderer.java b/src/org/mapsforge/android/glrenderer/MapRenderer.java
index f7c0988c..da15fb87 100644
--- a/src/org/mapsforge/android/glrenderer/MapRenderer.java
+++ b/src/org/mapsforge/android/glrenderer/MapRenderer.java
@@ -25,6 +25,7 @@ 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;
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;
@@ -80,6 +81,7 @@ import org.mapsforge.android.mapgenerator.JobParameters;
import org.mapsforge.android.mapgenerator.MapGeneratorJob;
import org.mapsforge.android.mapgenerator.TileCacheKey;
import org.mapsforge.android.mapgenerator.TileDistanceSort;
+import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.android.utils.GlConfigChooser;
import org.mapsforge.android.utils.GlUtils;
import org.mapsforge.core.MapPosition;
@@ -102,7 +104,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// private boolean mTriangulate = false;
- private static int CACHE_TILES_MAX = 400;
+ private static int CACHE_TILES_MAX = 250;
private static int CACHE_TILES = CACHE_TILES_MAX;
private static int LIMIT_BUFFERS = 20 * MB;
@@ -127,28 +129,29 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private JobParameters mJobParameter;
private MapPosition mMapPosition, mPrevMapPosition;
- private int mWidth, mHeight;
- private float mAspect;
+ private static int mWidth, mHeight;
+ private static float mAspect;
// draw position is updated from current position in onDrawFrame
// keeping the position consistent while drawing
- private double mDrawX, mDrawY, mDrawZ, mCurX, mCurY, mCurZ;
- private float mDrawScale, mCurScale;
+ private static double mDrawX, mDrawY, mDrawZ, mCurX, mCurY, mCurZ;
+ private static float mDrawScale, mCurScale;
// current center tile
- private long mTileX, mTileY;
+ private static long mTileX, mTileY;
- private FloatBuffer floatBuffer[];
- private ShortBuffer shortBuffer[];
+ private static int rotateBuffers = 2;
+ private static FloatBuffer floatBuffer[];
+ private static ShortBuffer shortBuffer[];
- boolean useHalfFloat = false;
+ static boolean useHalfFloat = false;
// bytes currently loaded in VBOs
- private int mBufferMemoryUsage;
+ private static int mBufferMemoryUsage;
// flag set by updateVisibleList when current visible tiles changed.
// used in onDrawFrame to nextTiles to curTiles
- private boolean mUpdateTiles;
+ private static boolean mUpdateTiles;
class TilesData {
int cnt = 0;
@@ -159,30 +162,30 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
- private float[] mMVPMatrix = new float[16];
+ private static float[] mMVPMatrix = new float[16];
// private float[] mMMatrix = new float[16];
// private float[] mRMatrix = new float[16];
// newTiles is set in updateVisibleList and synchronized swapped
// with nextTiles on main thread.
// nextTiles is swapped with curTiles in onDrawFrame in GL thread.
- private TilesData newTiles, nextTiles, curTiles;
+ private static TilesData newTiles, nextTiles, curTiles;
private boolean mInitial;
// shader handles
- private int gLineProgram;
- private int gLineVertexPositionHandle;
- private int gLineTexturePositionHandle;
- private int gLineColorHandle;
- private int gLineMatrixHandle;
- private int gLineModeHandle;
- private int gLineWidthHandle;
+ private static int lineProgram;
+ private static int hLineVertexPosition;
+ private static int hLineTexturePosition;
+ private static int hLineColor;
+ private static int hLineMatrix;
+ private static int hLineMode;
+ private static int hLineWidth;
- private int gPolygonProgram;
- private int gPolygonVertexPositionHandle;
- private int gPolygonMatrixHandle;
- private int gPolygonColorHandle;
+ private static int polygonProgram;
+ private static int hPolygonVertexPosition;
+ private static int hPolygonMatrix;
+ private static int hPolygonColor;
/**
*
@@ -261,7 +264,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLMapTile t = mTileList.remove(j);
if (t.isActive) {
- // Log.d(TAG, "EEEK removing active tile");
+ Log.d(TAG, "EEEK removing active tile");
mTileList.add(t);
continue;
}
@@ -441,18 +444,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
updateTileDistances();
- // scramble tile draw order, might help to make draw calls independent... just a guess :)
+ // scramble tile draw order: might help to make gl
+ // pipelines more independent... just a guess :)
for (int i = 1; i < tiles / 2; i += 2) {
GLMapTile tmp = newTiles.tiles[i];
newTiles.tiles[i] = newTiles.tiles[tiles - i];
newTiles.tiles[tiles - i] = tmp;
}
- int removes = mTiles.size() - CACHE_TILES;
-
- if (removes > 0)
- Collections.sort(mTileList, mTileDistanceSort);
-
// pass new tile list to glThread
synchronized (this) {
for (int i = 0; i < nextTiles.cnt; i++)
@@ -472,7 +471,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mUpdateTiles = true;
}
- limitCache(removes);
+ int removes = mTiles.size() - CACHE_TILES;
+
+ if (removes > 0) {
+ Collections.sort(mTileList, mTileDistanceSort);
+ limitCache(removes);
+ }
if (mJobList.size() > 0)
mMapView.addJobs(mJobList);
@@ -593,7 +597,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
float alpha = 1.0f;
- if (l.fadeLevel >= mDrawZ) {
+ if (l.area.fade >= mDrawZ) {
alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha;
if (alpha > 1.0f)
@@ -608,8 +612,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
blend = false;
}
- glUniform4f(gPolygonColorHandle,
- l.colors[0], l.colors[1], l.colors[2], alpha);
+ glUniform4f(hPolygonColor,
+ l.area.color[0], l.area.color[1], l.area.color[2], alpha);
// set stencil buffer mask used to draw this layer
glStencilFunc(GL_EQUAL, 0xff, 1 << c);
@@ -625,7 +629,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private boolean drawPolygons(GLMapTile tile, int diff) {
int cnt = 0;
- if (tile.polygonLayers == null || tile.polygonLayers.array == null)
+ if (tile.polygonLayers == null)
return true;
glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
@@ -635,27 +639,23 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
if (useHalfFloat) {
- glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
+ glVertexAttribPointer(hPolygonVertexPosition, 2,
OES_HALF_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
} else {
- glVertexAttribPointer(gPolygonVertexPositionHandle, 2,
+ glVertexAttribPointer(hPolygonVertexPosition, 2,
GL_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
}
-
- // glBindBuffer(GL_ARRAY_BUFFER, 0);
}
setMatrix(tile, diff);
- glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0);
+ glUniformMatrix4fv(hPolygonMatrix, 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];
-
+ for (PolygonLayer l = tile.polygonLayers; l != null; l = l.next) {
// fade out polygon layers (set in RederTheme)
- if (l.fadeLevel > 0 && l.fadeLevel > mDrawZ)
+ if (l.area.fade > 0 && l.area.fade > mDrawZ)
continue;
if (cnt == 0) {
@@ -668,8 +668,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (firstPass)
firstPass = false;
else {
- // eeek, nexus! - cant do old-school polygons
- // glFinish();
+ GLES20.glFlush();
// clear stencilbuffer
glStencilMask(0xFF);
@@ -703,56 +702,16 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// eeek, nexus! - cant do old-school polygons
// glFinish();
}
+ GLES20.glFlush();
return true;
}
- private int mLastBoundVBO;
-
- // private boolean drawTriangles(GLMapTile tile, int diff) {
- //
- // if (tile.meshLayers == null || tile.meshLayers.array == null)
- // return true;
- //
- // glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
- //
- // if (mLastBoundVBO != tile.polygonVBO.id) {
- // mLastBoundVBO = tile.polygonVBO.id;
- // glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
- //
- // 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);
- // }
- // setMatrix(tile, diff);
- // 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];
- // glUniform4fv(gPolygonColorHandle, 1, l.colors, 0);
- //
- // // glUniform4f(gPolygonColorHandle, 1, 0, 0, 1);
- //
- // // System.out.println("draw: " + l.offset + " " + l.verticesCnt);
- // glDrawArrays(GL_TRIANGLES, l.offset, l.verticesCnt);
- // }
- //
- // return true;
- // }
+ private static int mLastBoundVBO;
private boolean drawLines(GLMapTile tile, int diff) {
float z = 1;
- if (tile.lineLayers == null || tile.lineLayers.array == null)
+ if (tile.lineLayers == null)
return false;
glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
@@ -762,27 +721,24 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
if (useHalfFloat) {
- glVertexAttribPointer(gLineVertexPositionHandle, 2, OES_HALF_FLOAT,
+ glVertexAttribPointer(hLineVertexPosition, 2, OES_HALF_FLOAT,
false, 8, LINE_VERTICES_DATA_POS_OFFSET);
- glVertexAttribPointer(gLineTexturePositionHandle, 2, OES_HALF_FLOAT,
+ glVertexAttribPointer(hLineTexturePosition, 2, OES_HALF_FLOAT,
false, 8, LINE_VERTICES_DATA_TEX_OFFSET >> 1);
} else {
- glVertexAttribPointer(gLineVertexPositionHandle, 2, GL_FLOAT,
+ glVertexAttribPointer(hLineVertexPosition, 2, GL_FLOAT,
false, 16, LINE_VERTICES_DATA_POS_OFFSET);
- glVertexAttribPointer(gLineTexturePositionHandle, 2, GL_FLOAT,
+ glVertexAttribPointer(hLineTexturePosition, 2, GL_FLOAT,
false, 16, LINE_VERTICES_DATA_TEX_OFFSET);
}
- // glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (diff != 0)
z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff);
setMatrix(tile, diff);
- glUniformMatrix4fv(gLineMatrixHandle, 1, false, mMVPMatrix, 0);
-
- LineLayer[] layers = tile.lineLayers.array;
+ glUniformMatrix4fv(hLineMatrix, 1, false, mMVPMatrix, 0);
boolean drawOutlines = false;
boolean drawFixed = false;
@@ -792,52 +748,67 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// linear scale for fixed lines
float fdiv = 0.9f / (mDrawScale / z);
- // int cnt = 0;
- for (int i = 0, n = layers.length; i < n; i++) {
- LineLayer l = layers[i];
+ boolean first = true;
+
+ for (LineLayer l = tile.lineLayers; l != null; l = l.next) {
+ Line line = l.line;
+ if (line.fade > 0 && line.fade > mDrawZ)
+ continue;
// set line width and mode
- if ((i == 0) || (l.isOutline != drawOutlines) || (l.isFixed != drawFixed)) {
+ if (first || (l.isOutline != drawOutlines)
+ || (line.fixed != drawFixed)) {
+ first = false;
drawOutlines = l.isOutline;
- drawFixed = l.isFixed;
+ drawFixed = line.fixed;
if (drawOutlines) {
- glUniform2f(gLineModeHandle, 0, wdiv);
+ glUniform2f(hLineMode, 0, wdiv);
} else if (!drawFixed) {
- glUniform2f(gLineModeHandle, 0, wdiv * 0.98f);
+ glUniform2f(hLineMode, 0, wdiv * 0.98f);
}
}
if (drawFixed) {
if (l.width < 1.0)
- glUniform2f(gLineModeHandle, 0.4f, fdiv);
+ glUniform2f(hLineMode, 0.4f, fdiv);
else
- glUniform2f(gLineModeHandle, 0, fdiv);
+ glUniform2f(hLineMode, 0, fdiv);
+ }
+
+ if (line.fade >= mDrawZ) {
+ float alpha = 1.0f;
+
+ alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha;
+ if (alpha > 1.0f)
+ alpha = 1.0f;
+ glUniform4f(hLineColor,
+ line.color[0], line.color[1], line.color[2], alpha);
+ } else {
+ glUniform4fv(hLineColor, 1, line.color, 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);
+ for (LineLayer o = l.outlines; o != null; o = o.outlines) {
if (mSimpleLines)
- glUniform1f(gLineWidthHandle, o.width);
+ glUniform1f(hLineWidth, o.width);
glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
}
}
else {
if (mSimpleLines)
- glUniform1f(gLineWidthHandle, l.width);
+ glUniform1f(hLineWidth, l.width);
glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
}
}
-
+ GLES20.glFlush();
return true;
}
- private void setMatrix(GLMapTile tile, int diff) {
+ private static void setMatrix(GLMapTile tile, int diff) {
float x, y, scale;
float z = 1;
@@ -858,7 +829,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mMVPMatrix[5] = (scale);
}
- private boolean setTileScissor(GLMapTile tile, float div) {
+ private static boolean setTileScissor(GLMapTile tile, float div) {
double dx, dy, scale;
@@ -916,12 +887,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private int uploadCnt = 0;
private boolean uploadTileData(GLMapTile tile) {
+ ShortBuffer sbuf = null;
+ FloatBuffer fbuf = null;
// 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) {
+ // use multiple buffers to avoid overwriting buffer while current
+ // data is uploaded (or rather the blocking which is required to avoid this)
+ if (uploadCnt >= rotateBuffers) {
// mMapView.requestRender();
// return false;
uploadCnt = 0;
@@ -939,27 +912,34 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
tile.polygonVBO = mVBOs.remove(mVBOs.size() - 1);
}
}
- if (useHalfFloat)
- shortBuffer[uploadCnt * 2] = tile.lineLayers
- .compileLayerData(shortBuffer[uploadCnt * 2]);
- else
- floatBuffer[uploadCnt * 2] = tile.lineLayers
- .compileLayerData(floatBuffer[uploadCnt * 2]);
+ int size = 0;
- if (tile.lineLayers.size > 0) {
+ if (useHalfFloat) {
+ sbuf = LineLayers.compileLayerData(tile.lineLayers,
+ shortBuffer[uploadCnt * 2]);
+ size = sbuf.remaining();
+ shortBuffer[uploadCnt * 2] = sbuf;
+ } else {
+ fbuf = LineLayers.compileLayerData(tile.lineLayers,
+ floatBuffer[uploadCnt * 2]);
+ size = fbuf.remaining();
+ floatBuffer[uploadCnt * 2] = fbuf;
+ }
+
+ if (size > 0) {
mBufferMemoryUsage -= tile.lineVBO.size;
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;
+ tile.lineVBO.size = size * SHORT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
- shortBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW);
+ sbuf, GL_DYNAMIC_DRAW);
} else {
- tile.lineVBO.size = tile.lineLayers.size * FLOAT_BYTES;
+ tile.lineVBO.size = size * FLOAT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
- floatBuffer[uploadCnt * 2], GL_DYNAMIC_DRAW);
+ fbuf, GL_DYNAMIC_DRAW);
}
mBufferMemoryUsage += tile.lineVBO.size;
@@ -968,16 +948,19 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
tile.lineLayers = null;
}
- // if (!mTriangulate) {
- if (useHalfFloat)
- shortBuffer[uploadCnt * 2 + 1] = tile.polygonLayers
- .compileLayerData(shortBuffer[uploadCnt * 2 + 1]);
- else
- floatBuffer[uploadCnt * 2 + 1] = tile.polygonLayers
- .compileLayerData(floatBuffer[uploadCnt * 2 + 1]);
-
+ if (useHalfFloat) {
+ sbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
+ shortBuffer[uploadCnt * 2 + 1]);
+ size = sbuf.remaining();
+ shortBuffer[uploadCnt * 2 + 1] = sbuf;
+ } else {
+ fbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
+ floatBuffer[uploadCnt * 2 + 1]);
+ size = fbuf.remaining();
+ floatBuffer[uploadCnt * 2 + 1] = fbuf;
+ }
// Upload polygon data to vertex buffer object
- if (tile.polygonLayers.size > 0) {
+ if (size > 0) {
mBufferMemoryUsage -= tile.polygonVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
@@ -985,54 +968,24 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// GL_DYNAMIC_DRAW);
if (useHalfFloat) {
- tile.polygonVBO.size = tile.polygonLayers.size * SHORT_BYTES;
+ tile.polygonVBO.size = size * SHORT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
- shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
+ sbuf, GL_DYNAMIC_DRAW);
} else {
- tile.polygonVBO.size = tile.polygonLayers.size * FLOAT_BYTES;
+ tile.polygonVBO.size = size * FLOAT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
- floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
+ fbuf, GL_DYNAMIC_DRAW);
}
mBufferMemoryUsage += tile.polygonVBO.size;
} else {
tile.polygonLayers = null;
}
- // }
- // else {
- // if (useHalfFloat)
- // shortBuffer[uploadCnt * 2 + 1] = tile.meshLayers
- // .compileLayerData(shortBuffer[uploadCnt * 2 + 1]);
- // else
- // 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;
- //
- // 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;
- // glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
- // shortBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
- // } else {
- // tile.polygonVBO.size = tile.meshLayers.size * FLOAT_BYTES;
- // glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
- // floatBuffer[uploadCnt * 2 + 1], GL_DYNAMIC_DRAW);
- // }
- // mBufferMemoryUsage += tile.polygonVBO.size;
- //
- // } else {
- // tile.meshLayers = null;
- // }
- // }
+
tile.newData = false;
tile.isDrawn = true;
tile.isLoading = false;
+
// double compile = SystemClock.uptimeMillis();
// glFinish();
// double now = SystemClock.uptimeMillis();
@@ -1044,8 +997,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
return true;
}
- // private long startTime = SystemClock.uptimeMillis();
-
@Override
public void onDrawFrame(GL10 glUnused) {
long start = 0, poly_time = 0, clear_time = 0;
@@ -1057,20 +1008,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
start = SystemClock.uptimeMillis();
glStencilMask(0xFF);
- glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- // long endTime = SystemClock.uptimeMillis();
- // long dt = endTime - startTime;
- // if (dt < 33)
- // try {
- // Thread.sleep(33 - dt);
- // } catch (InterruptedException e) {
- // Log.d(TAG, "interrupt");
- // return;
- // }
- // startTime = SystemClock.uptimeMillis();
-
synchronized (this) {
mDrawX = mCurX;
mDrawY = mCurY;
@@ -1114,13 +1053,20 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
uploadCnt = 0;
mLastBoundVBO = -1;
+ int updateTextures = 0;
+
// check visible tiles, set tile clip scissors, upload new vertex data
+
for (int i = 0; i < tileCnt; i++) {
GLMapTile tile = tiles[i];
if (!setTileScissor(tile, 1))
continue;
+ if (tile.texture == null && tile.labels != null &&
+ mTextRenderer.drawToTexture(tile))
+ updateTextures++;
+
if (tile.newData) {
uploadTileData(tile);
continue;
@@ -1143,25 +1089,25 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
- if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage)
- && LIMIT_BUFFERS > MB)
- LIMIT_BUFFERS -= MB;
+ if (updateTextures > 0)
+ mTextRenderer.compileTextures();
+
+ // if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage)
+ // && LIMIT_BUFFERS > MB)
+ // LIMIT_BUFFERS -= MB;
if (timing)
clear_time = (SystemClock.uptimeMillis() - start);
glEnable(GL_SCISSOR_TEST);
- glUseProgram(gPolygonProgram);
- glEnableVertexAttribArray(gPolygonVertexPositionHandle);
+ glUseProgram(polygonProgram);
+ glEnableVertexAttribArray(hPolygonVertexPosition);
- // if (!mTriangulate) {
glDisable(GL_BLEND);
// Draw Polygons
glEnable(GL_STENCIL_TEST);
- // glEnableVertexAttribArray(gPolygonVertexPositionHandle);
-
for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible) {
GLMapTile tile = tiles[i];
@@ -1172,24 +1118,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
drawProxyPolygons(tile);
}
}
- // GlUtils.checkGlError("polygons");
+
glDisable(GL_STENCIL_TEST);
- // } else {
- // // Draw Triangles
- // for (int i = 0; i < tileCnt; i++) {
- // if (tiles[i].isVisible) {
- // GLMapTile tile = tiles[i];
- //
- // if (tile.isDrawn)
- // drawTriangles(tile, 0);
- // else
- // drawProxyTriangles(tile);
- // }
- // }
- // // GlUtils.checkGlError("triangles");
- // }
+
// required on GalaxyII, Android 2.3.3 (cant just VAA enable once...)
- glDisableVertexAttribArray(gPolygonVertexPositionHandle);
+ glDisableVertexAttribArray(hPolygonVertexPosition);
if (timing) {
glFinish();
@@ -1198,10 +1131,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// Draw lines
glEnable(GL_BLEND);
- glUseProgram(gLineProgram);
+ glUseProgram(lineProgram);
- glEnableVertexAttribArray(gLineVertexPositionHandle);
- glEnableVertexAttribArray(gLineTexturePositionHandle);
+ glEnableVertexAttribArray(hLineVertexPosition);
+ glEnableVertexAttribArray(hLineTexturePosition);
for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible) {
@@ -1214,20 +1147,37 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
+ glDisableVertexAttribArray(hLineVertexPosition);
+ glDisableVertexAttribArray(hLineTexturePosition);
+
+ glDisable(GL_SCISSOR_TEST);
+
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ mTextRenderer.beginDraw();
+ for (int i = 0; i < tileCnt; i++) {
+ if (!tiles[i].isVisible || tiles[i].texture == null)
+ continue;
+
+ setMatrix(tiles[i], 0);
+
+ mTextRenderer.drawTile(tiles[i], mMVPMatrix);
+ }
+ mTextRenderer.endDraw();
+
if (timing) {
glFinish();
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " "
+ clear_time + " " + poly_time);
}
- glDisableVertexAttribArray(gLineVertexPositionHandle);
- glDisableVertexAttribArray(gLineTexturePositionHandle);
- // GlUtils.checkGlError("lines");
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- private int[] mVboIds;
+ private static TextRenderer mTextRenderer;
@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
+ GlUtils.checkGlError("onSurfaceChanged");
+
mVBOs.clear();
mTiles.clear();
mTileList.clear();
@@ -1246,20 +1196,27 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mAspect = (float) height / width;
glViewport(0, 0, width, height);
+ GlUtils.checkGlError("glViewport");
- int tiles = (mWidth / Tile.TILE_SIZE + 4) * (mHeight / Tile.TILE_SIZE + 4);
- curTiles = new TilesData(tiles);
- newTiles = new TilesData(tiles);
- nextTiles = new TilesData(tiles);
+ int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
+ * (mHeight / (Tile.TILE_SIZE / 2) + 2);
+
+ curTiles = new TilesData(numTiles);
+ newTiles = new TilesData(numTiles);
+ nextTiles = new TilesData(numTiles);
// Set up vertex buffer objects
- int numVBO = (CACHE_TILES + tiles) * 2;
- mVboIds = new int[numVBO];
+ int numVBO = (CACHE_TILES + numTiles) * 2;
+ int[] mVboIds = new int[numVBO];
glGenBuffers(numVBO, mVboIds, 0);
+ GlUtils.checkGlError("glGenBuffers");
for (int i = 0; i < numVBO; i++)
mVBOs.add(new VertexBufferObject(mVboIds[i]));
+ // Set up textures
+ mTextRenderer = new TextRenderer(numTiles * 2);
+
mDebugSettings = mMapView.getDebugSettings();
mJobParameter = mMapView.getJobParameters();
@@ -1273,14 +1230,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set up the program for rendering lines
- gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
+ lineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShader);
- if (gLineProgram == 0) {
+ if (lineProgram == 0) {
mSimpleLines = true;
Log.e(TAG, "trying simple line program.");
- gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
+ lineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShaderSimple);
- if (gLineProgram == 0) {
+ if (lineProgram == 0) {
Log.e(TAG, "Could not create line program.");
return;
}
@@ -1290,48 +1247,51 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (ext.indexOf("GL_OES_vertex_half_float") >= 0) {
useHalfFloat = true;
- shortBuffer = new ShortBuffer[20];
+ shortBuffer = new ShortBuffer[rotateBuffers * 2];
}
else {
- floatBuffer = new FloatBuffer[20];
+ floatBuffer = new FloatBuffer[rotateBuffers * 2];
}
Log.d(TAG, "Extensions: " + ext);
- gLineMatrixHandle = glGetUniformLocation(gLineProgram, "u_center");
- gLineModeHandle = glGetUniformLocation(gLineProgram, "u_mode");
- gLineColorHandle = glGetUniformLocation(gLineProgram, "u_color");
- gLineVertexPositionHandle = GLES20
- .glGetAttribLocation(gLineProgram, "a_position");
- gLineTexturePositionHandle = glGetAttribLocation(gLineProgram, "a_st");
+ hLineMatrix = glGetUniformLocation(lineProgram, "u_center");
+ hLineMode = glGetUniformLocation(lineProgram, "u_mode");
+ hLineColor = glGetUniformLocation(lineProgram, "u_color");
+ hLineVertexPosition = GLES20.glGetAttribLocation(lineProgram, "a_position");
+ hLineTexturePosition = glGetAttribLocation(lineProgram, "a_st");
if (mSimpleLines)
- gLineWidthHandle = glGetUniformLocation(gLineProgram, "u_width");
+ hLineWidth = glGetUniformLocation(lineProgram, "u_width");
// Set up the program for rendering polygons
- gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader,
+ polygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader,
Shaders.gPolygonFragmentShader);
- if (gPolygonProgram == 0) {
+ if (polygonProgram == 0) {
Log.e(TAG, "Could not create polygon program.");
return;
}
- gPolygonMatrixHandle = glGetUniformLocation(gPolygonProgram, "u_center");
- gPolygonVertexPositionHandle = glGetAttribLocation(gPolygonProgram,
- "a_position");
- gPolygonColorHandle = glGetUniformLocation(gPolygonProgram, "u_color");
+ hPolygonMatrix = glGetUniformLocation(polygonProgram, "u_center");
+ hPolygonVertexPosition = glGetAttribLocation(polygonProgram, "a_position");
+ hPolygonColor = glGetUniformLocation(polygonProgram, "u_color");
- // glUseProgram(gPolygonProgram);
- // glEnableVertexAttribArray(gPolygonVertexPositionHandle);
+ // glUseProgram(polygonProgram);
+ // glEnableVertexAttribArray(hPolygonVertexPosition);
//
- // glUseProgram(gLineProgram);
- // glEnableVertexAttribArray(gLineVertexPositionHandle);
- // glEnableVertexAttribArray(gLineTexturePositionHandle);
+ // glUseProgram(lineProgram);
+ // glEnableVertexAttribArray(hLineVertexPosition);
+ // glEnableVertexAttribArray(hLineTexturePosition);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ // glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
glDisable(GL_DITHER);
glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
glClearStencil(0);
+
+ GlUtils.checkGlError("onSurfaceCreated");
+
}
private void drawProxyLines(GLMapTile tile) {
@@ -1397,38 +1357,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
- // private void drawProxyTriangles(GLMapTile tile) {
- // if (tile.parent != null && tile.parent.isDrawn) {
- // tile.parent.sx = tile.sx;
- // tile.parent.sy = tile.sy;
- // tile.parent.sw = tile.sw;
- // tile.parent.sh = tile.sh;
- // drawTriangles(tile.parent, -1);
- // } else {
- // int drawn = 0;
- //
- // for (int i = 0; i < 4; i++) {
- // GLMapTile c = tile.child[i];
- //
- // if (c != null && c.isDrawn && setTileScissor(c, 2)) {
- // drawTriangles(c, 1);
- // drawn++;
- // }
- // }
- //
- // if (drawn < 4 && tile.parent != null) {
- // GLMapTile p = tile.parent.parent;
- // if (p != null && p.isDrawn) {
- // p.sx = tile.sx;
- // p.sy = tile.sy;
- // p.sw = tile.sw;
- // p.sh = tile.sh;
- // drawTriangles(p, -2);
- // }
- // }
- // }
- // }
-
@Override
public boolean processedTile() {
return true;
diff --git a/src/org/mapsforge/android/glrenderer/PolygonLayer.java b/src/org/mapsforge/android/glrenderer/PolygonLayer.java
index d8890fb3..bb8025d8 100644
--- a/src/org/mapsforge/android/glrenderer/PolygonLayer.java
+++ b/src/org/mapsforge/android/glrenderer/PolygonLayer.java
@@ -14,21 +14,21 @@
*/
package org.mapsforge.android.glrenderer;
-import java.util.LinkedList;
+import org.mapsforge.android.rendertheme.renderinstruction.Area;
class PolygonLayer extends Layer {
- int fadeLevel;
+ PolygonLayer next;
+ Area area;
private boolean first = true;
private float originX;
private float originY;
- PolygonLayer(int layer, int color, int fade) {
- super(layer, color);
- fadeLevel = fade;
- curItem = LayerPool.get();
- pool = new LinkedList();
- pool.add(curItem);
+ PolygonLayer(int layer, Area area) {
+ super(layer);
+ this.area = area;
+ curItem = VertexPool.get();
+ pool = curItem;
}
void addPolygon(float[] points, int pos, int length) {
diff --git a/src/org/mapsforge/android/glrenderer/PolygonLayers.java b/src/org/mapsforge/android/glrenderer/PolygonLayers.java
index ebb35401..98de333c 100644
--- a/src/org/mapsforge/android/glrenderer/PolygonLayers.java
+++ b/src/org/mapsforge/android/glrenderer/PolygonLayers.java
@@ -22,50 +22,20 @@ import java.nio.ShortBuffer;
import org.mapsforge.android.utils.FastMath;
import org.mapsforge.core.Tile;
-import android.util.SparseArray;
-
class PolygonLayers {
private static final int NUM_VERTEX_FLOATS = 2;
- private static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1,
+ static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1,
Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, -2,
-2, Tile.TILE_SIZE + 1, -2 };
private static short[] mByteFillCoords = null;
- private SparseArray layers;
-
- PolygonLayer[] array = null;
- int size;
-
- PolygonLayers() {
- layers = new SparseArray(10);
- size = 4;
- }
-
- PolygonLayer getLayer(int layer, int color, int fade) {
- PolygonLayer l = layers.get(layer);
- if (l != null) {
- // if (color == l.color)
- return l;
-
- // return getLayer(layer + 1, color, fade);
- }
-
- l = new PolygonLayer(layer, color, fade);
- layers.put(layer, l);
- return l;
- }
-
- FloatBuffer compileLayerData(FloatBuffer buf) {
+ static FloatBuffer compileLayerData(PolygonLayer layers, FloatBuffer buf) {
FloatBuffer fbuf = buf;
+ int size = 4;
- array = new PolygonLayer[layers.size()];
-
- for (int i = 0, n = layers.size(); i < n; i++) {
- PolygonLayer l = layers.valueAt(i);
- array[i] = l;
+ for (PolygonLayer l = layers; l != null; l = l.next)
size += l.verticesCnt;
- }
size *= NUM_VERTEX_FLOATS;
@@ -81,38 +51,40 @@ class PolygonLayers {
fbuf.put(mFillCoords, 0, 8);
int pos = 4;
- for (int i = 0, n = array.length; i < n; i++) {
- PolygonLayer l = array[i];
+ PoolItem last = null, items = null;
- for (PoolItem item : l.pool) {
+ for (PolygonLayer l = layers; l != null; l = l.next) {
+
+ for (PoolItem item = l.pool; item != null; item = item.next) {
fbuf.put(item.vertices, 0, item.used);
+ last = item;
}
-
l.offset = pos;
pos += l.verticesCnt;
- LayerPool.add(l.pool);
+ if (last != null) {
+ last.next = items;
+ items = l.pool;
+ }
+
l.pool = null;
}
- fbuf.flip();
+ VertexPool.add(items);
- // not needed for drawing
- layers = null;
+ fbuf.flip();
return fbuf;
}
- ShortBuffer compileLayerData(ShortBuffer buf) {
+ static final short[] tmpItem = new short[PoolItem.SIZE];
+
+ static ShortBuffer compileLayerData(PolygonLayer layers, ShortBuffer buf) {
ShortBuffer sbuf = buf;
+ int size = 4;
- array = new PolygonLayer[layers.size()];
-
- for (int i = 0, n = layers.size(); i < n; i++) {
- PolygonLayer l = layers.valueAt(i);
- array[i] = l;
+ for (PolygonLayer l = layers; l != null; l = l.next)
size += l.verticesCnt;
- }
size *= NUM_VERTEX_FLOATS;
@@ -124,7 +96,7 @@ class PolygonLayers {
sbuf.clear();
}
- short[] data = new short[PoolItem.SIZE];
+ short[] data = tmpItem;
if (mByteFillCoords == null) {
mByteFillCoords = new short[8];
@@ -141,27 +113,38 @@ class PolygonLayers {
sbuf.put(mByteFillCoords, 0, 8);
int pos = 4;
- for (int i = 0, n = array.length; i < n; i++) {
- PolygonLayer l = array[i];
+ PoolItem last = null, items = null;
- for (int k = 0, m = l.pool.size(); k < m; k++) {
- PoolItem item = l.pool.get(k);
+ for (PolygonLayer l = layers; l != null; l = l.next) {
+
+ for (PoolItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used);
+ last = item;
}
l.offset = pos;
pos += l.verticesCnt;
- LayerPool.add(l.pool);
+ if (last != null) {
+ last.next = items;
+ items = l.pool;
+ }
+
l.pool = null;
}
- sbuf.flip();
+ VertexPool.add(items);
- // not needed for drawing
- layers = null;
+ sbuf.flip();
return sbuf;
}
+
+ static void clear(PolygonLayer layers) {
+ for (PolygonLayer l = layers; l != null; l = l.next) {
+ if (l.pool != null)
+ VertexPool.add(l.pool);
+ }
+ }
}
diff --git a/src/org/mapsforge/android/glrenderer/PoolItem.java b/src/org/mapsforge/android/glrenderer/PoolItem.java
index 2f92db25..1be769c1 100644
--- a/src/org/mapsforge/android/glrenderer/PoolItem.java
+++ b/src/org/mapsforge/android/glrenderer/PoolItem.java
@@ -24,13 +24,14 @@ import java.nio.IntBuffer;
class PoolItem {
final float[] vertices;
int used;
+ PoolItem next;
PoolItem() {
vertices = new float[SIZE];
used = 0;
}
- static int SIZE = 256;
+ static int SIZE = 128;
private static final float FLOAT_HALF_PREC = 5.96046E-8f;
private static final float FLOAT_HALF_MAX = 65504f;
diff --git a/src/org/mapsforge/android/glrenderer/Shaders.java b/src/org/mapsforge/android/glrenderer/Shaders.java
index 1e9696f5..f4e30903 100644
--- a/src/org/mapsforge/android/glrenderer/Shaders.java
+++ b/src/org/mapsforge/android/glrenderer/Shaders.java
@@ -23,6 +23,8 @@ class Shaders {
+ "attribute vec2 a_st;"
+ "varying vec2 v_st;"
+ "void main() {"
+ // + " gl_Position = u_center * vec4(a_position.x, a_position.y, 0.0, 1.0);"
+ // + " v_st = a_position.zw;"
+ " gl_Position = u_center * a_position;"
+ " v_st = a_st;"
+ "}";
diff --git a/src/org/mapsforge/android/glrenderer/TextItem.java b/src/org/mapsforge/android/glrenderer/TextItem.java
new file mode 100644
index 00000000..ee129cc9
--- /dev/null
+++ b/src/org/mapsforge/android/glrenderer/TextItem.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * 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.android.glrenderer;
+
+import org.mapsforge.android.rendertheme.renderinstruction.Caption;
+
+public class TextItem {
+ TextItem next;
+
+ final float x, y;
+ final String text;
+ final Caption caption;
+ final float width;
+
+ public TextItem(float x, float y, String text, Caption caption) {
+ this.x = x;
+ this.y = y;
+ this.text = text;
+ this.caption = caption;
+ this.width = caption.paint.measureText(text);
+ }
+
+}
diff --git a/src/org/mapsforge/android/glrenderer/TextLayer.java b/src/org/mapsforge/android/glrenderer/TextLayer.java
new file mode 100644
index 00000000..a833b601
--- /dev/null
+++ b/src/org/mapsforge/android/glrenderer/TextLayer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * 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.android.glrenderer;
+
+import java.util.ArrayList;
+
+import org.mapsforge.android.rendertheme.renderinstruction.Caption;
+
+public class TextLayer {
+ public ArrayList labels;
+
+ void addLabel(float x, float y, String text, Caption caption) {
+
+ }
+
+}
diff --git a/src/org/mapsforge/android/glrenderer/TextRenderer.java b/src/org/mapsforge/android/glrenderer/TextRenderer.java
new file mode 100644
index 00000000..e339cf7a
--- /dev/null
+++ b/src/org/mapsforge/android/glrenderer/TextRenderer.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * 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.android.glrenderer;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import org.mapsforge.android.utils.GlUtils;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.opengl.GLES20;
+import android.opengl.GLUtils;
+import android.util.Log;
+
+public class TextRenderer {
+ private final static int TEXTURE_WIDTH = 512;
+ private final static int TEXTURE_HEIGHT = 256;
+
+ final static int MAX_LABELS = 30;
+
+ private final Bitmap mBitmap;
+ private final Canvas mCanvas;
+ private int mFontPadX = 1;
+ private int mFontPadY = 1;
+ private int mBitmapFormat;
+ private int mBitmapType;
+ private ByteBuffer mByteBuffer;
+ private FloatBuffer mFloatBuffer;
+ private TextTexture[] mTextures;
+
+ private int mIndicesVBO;
+ private int mVerticesVBO;
+
+ final static int INDICES_PER_SPRITE = 6; // Indices Per Sprite
+ final static int VERTICES_PER_SPRITE = 4; // Vertices Per Sprite
+ final static int FLOATS_PER_VERTICE = 4;
+
+ private static int mTextProgram;
+ static int mTextUVPMatrixLocation;
+ static int mTextVertexLocation;
+ static int mTextTextureCoordLocation;
+ static int mTextUColorLocation;
+
+ static Paint mPaint = new Paint(Color.BLACK);
+
+ boolean debug = false;
+ float[] debugVertices = {
+
+ 0, 0,
+ 0, 1,
+
+ 0, TEXTURE_HEIGHT - 1,
+ 0, 0,
+
+ TEXTURE_WIDTH - 1, 0,
+ 1, 1,
+
+ TEXTURE_WIDTH - 1, TEXTURE_HEIGHT - 1,
+ 1, 0,
+
+ };
+
+ TextRenderer(int numTextures) {
+ mBitmap = Bitmap
+ .createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
+ mCanvas = new Canvas(mBitmap);
+
+ mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
+ mBitmapType = GLUtils.getType(mBitmap);
+
+ mTextProgram = GlUtils.createProgram(textVertexShader, textFragmentShader);
+
+ mTextUVPMatrixLocation = GLES20.glGetUniformLocation(mTextProgram, "mvp");
+ mTextUColorLocation = GLES20.glGetUniformLocation(mTextProgram, "col");
+ mTextVertexLocation = GLES20.glGetAttribLocation(mTextProgram, "vertex");
+ mTextTextureCoordLocation = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
+
+ // mVertexBuffer = new float[];
+ int bufferSize = numTextures
+ * MAX_LABELS * VERTICES_PER_SPRITE
+ * FLOATS_PER_VERTICE * (Float.SIZE / 8);
+
+ mByteBuffer = ByteBuffer.allocateDirect(bufferSize)
+ .order(ByteOrder.nativeOrder());
+
+ mFloatBuffer = mByteBuffer.asFloatBuffer();
+
+ int[] textureIds = new int[numTextures];
+ TextTexture[] textures = new TextTexture[numTextures];
+ GLES20.glGenTextures(numTextures, textureIds, 0);
+
+ for (int i = 0; i < numTextures; i++) {
+ // setup filters for texture
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[i]);
+
+ 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_WRAP_S,
+ GLES20.GL_CLAMP_TO_EDGE); // Set U Wrapping
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
+ GLES20.GL_CLAMP_TO_EDGE); // Set V Wrapping
+
+ // load the generated bitmap onto the texture
+ // GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBitmap, 0);
+ GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBitmapFormat, mBitmap,
+ mBitmapType, 0);
+
+ textures[i] = new TextTexture(textureIds[i]);
+ }
+ GlUtils.checkGlError("init textures");
+
+ mTextures = textures;
+
+ // Setup triangle indices
+ short[] indices = new short[MAX_LABELS * INDICES_PER_SPRITE];
+ int len = indices.length;
+ short j = 0;
+ for (int i = 0; i < len; i += INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE) {
+ indices[i + 0] = (short) (j + 0);
+ indices[i + 1] = (short) (j + 1);
+ indices[i + 2] = (short) (j + 2);
+ indices[i + 3] = (short) (j + 2);
+ indices[i + 4] = (short) (j + 3);
+ indices[i + 5] = (short) (j + 0);
+ }
+
+ ShortBuffer tmpIndices = mByteBuffer.asShortBuffer();
+
+ tmpIndices.put(indices, 0, len);
+ tmpIndices.flip();
+
+ int[] mVboIds = new int[2];
+ GLES20.glGenBuffers(2, mVboIds, 0);
+
+ GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mVboIds[0]);
+ GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, len * (Short.SIZE / 8),
+ tmpIndices,
+ GLES20.GL_STATIC_DRAW);
+ GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ mIndicesVBO = mVboIds[0];
+ mVerticesVBO = mVboIds[1];
+ }
+
+ boolean drawToTexture(GLMapTile tile) {
+ TextTexture tex = null;
+
+ if (tile.labels.size() == 0)
+ return false;
+
+ for (int i = 0; i < mTextures.length; i++) {
+ tex = mTextures[i];
+ if (tex.tile == null)
+ break;
+ if (!tex.tile.isActive)
+ break;
+
+ tex = null;
+ }
+
+ if (tex == null) {
+ Log.d(TAG, "no textures left");
+ return false;
+ }
+ if (tex.tile != null)
+ tex.tile.texture = null;
+
+ // if (debug)
+ // mBitmap.eraseColor(0xaa0000aa);
+ // else
+ mBitmap.eraseColor(Color.TRANSPARENT);
+
+ int pos = 0;
+ float[] buf = tex.vertices;
+
+ float xx = mFontPadX;
+ float yy = 0;
+ float width, height;
+
+ float y = 0;
+ float x = 0;
+
+ int max = tile.labels.size();
+ if (max > MAX_LABELS)
+ max = MAX_LABELS;
+
+ if (debug) {
+ mCanvas.drawLine(debugVertices[0], debugVertices[1], debugVertices[4],
+ debugVertices[5], mPaint);
+ mCanvas.drawLine(debugVertices[0], debugVertices[1], debugVertices[8],
+ debugVertices[9], mPaint);
+
+ mCanvas.drawLine(debugVertices[12], debugVertices[13], debugVertices[4],
+ debugVertices[5], mPaint);
+ mCanvas.drawLine(debugVertices[12], debugVertices[13], debugVertices[8],
+ debugVertices[9], mPaint);
+ }
+ int advanceY = 0;
+ // int advanceX = 0;
+ for (int i = 0; i < max; i++) {
+ TextItem t = tile.labels.get(i);
+
+ height = (int) (t.caption.fontHeight) + 2 * mFontPadY;
+ width = t.width + 2 * mFontPadX;
+
+ if (height > advanceY)
+ advanceY = (int) height;
+
+ if (xx + width > TEXTURE_WIDTH) {
+ xx = mFontPadX;
+ y += advanceY;
+ advanceY = (int) height;
+ }
+
+ yy = y + (height - 1) - t.caption.fontDescent - mFontPadY;
+
+ if (t.caption.stroke != null)
+ mCanvas.drawText(t.text, xx + t.width / 2, yy, t.caption.stroke);
+
+ mCanvas.drawText(t.text, xx + t.width / 2, yy, t.caption.paint);
+
+ // Log.d(TAG, "draw: " + t.text + " at:" + (xx + t.width / 2) + " " + yy + " w:"
+ // + t.width + " " + cellHeight);
+
+ if (width > TEXTURE_WIDTH)
+ width = TEXTURE_WIDTH;
+
+ float halfWidth = width / 2.0f;
+ float halfHeight = height / 2.0f;
+ float x1 = t.x - halfWidth;
+ float y1 = t.y - halfHeight;
+ float x2 = t.x + halfWidth;
+ float y2 = t.y + halfHeight;
+
+ float u1 = xx / TEXTURE_WIDTH;
+ float v1 = y / TEXTURE_HEIGHT;
+ float u2 = u1 + (width / TEXTURE_WIDTH);
+ float v2 = v1 + (height / TEXTURE_HEIGHT);
+
+ buf[pos++] = x1;
+ buf[pos++] = y1;
+ buf[pos++] = u1;
+ buf[pos++] = v2;
+
+ buf[pos++] = x2;
+ buf[pos++] = y1;
+ buf[pos++] = u2;
+ buf[pos++] = v2;
+
+ buf[pos++] = x2;
+ buf[pos++] = y2;
+ buf[pos++] = u2;
+ buf[pos++] = v1;
+
+ buf[pos++] = x1;
+ buf[pos++] = y2;
+ buf[pos++] = u1;
+ buf[pos++] = v1;
+
+ // yy += cellHeight;
+ // x += width;
+
+ xx += width;
+
+ // y += cellHeight;
+ if (y > TEXTURE_HEIGHT) {
+ Log.d(TAG, "reached max labels");
+ break;
+ }
+ }
+
+ tex.length = pos;
+ tile.texture = tex;
+ tex.tile = tile;
+ // GlUtils.checkGlError("0");
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.id);
+ // GlUtils.checkGlError("1");
+ GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap, mBitmapFormat,
+ mBitmapType);
+ // GlUtils.checkGlError("2");
+
+ return true;
+ }
+
+ private static String TAG = "TextRenderer";
+
+ void compileTextures() {
+ int offset = 0;
+ TextTexture tex;
+
+ GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
+
+ mFloatBuffer.clear();
+
+ for (int i = 0; i < mTextures.length; i++) {
+ tex = mTextures[i];
+ if (tex.tile == null || !tex.tile.isActive)
+ continue;
+
+ mFloatBuffer.put(tex.vertices, 0, tex.length);
+ tex.offset = offset;
+ offset += tex.length;
+ }
+
+ mFloatBuffer.flip();
+ // Log.d(TAG, "compileTextures" + mFloatBuffer.remaining() + " " + offset);
+
+ // TODO use sub-bufferdata function
+ GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, offset * (Float.SIZE / 8),
+ mFloatBuffer, GLES20.GL_DYNAMIC_DRAW);
+ }
+
+ void beginDraw() {
+ GLES20.glUseProgram(mTextProgram);
+
+ GLES20.glEnableVertexAttribArray(mTextTextureCoordLocation);
+ GLES20.glEnableVertexAttribArray(mTextVertexLocation);
+
+ if (debug) {
+ GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+ mFloatBuffer.clear();
+ mFloatBuffer.put(debugVertices, 0, 16);
+ mFloatBuffer.flip();
+ GLES20.glVertexAttribPointer(mTextVertexLocation, 2,
+ GLES20.GL_FLOAT, false, 16, mFloatBuffer);
+ mFloatBuffer.position(2);
+ GLES20.glVertexAttribPointer(mTextTextureCoordLocation, 2,
+ GLES20.GL_FLOAT, false, 16, mFloatBuffer);
+ } else {
+ GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
+ GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
+ }
+ }
+
+ void endDraw() {
+
+ GLES20.glDisableVertexAttribArray(mTextTextureCoordLocation);
+ GLES20.glDisableVertexAttribArray(mTextVertexLocation);
+ }
+
+ void drawTile(GLMapTile tile, float[] matrix) {
+
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.texture.id);
+ GlUtils.checkGlError("bind");
+
+ GLES20.glUniformMatrix4fv(mTextUVPMatrixLocation, 1, false, matrix, 0);
+ GlUtils.checkGlError("matrix");
+
+ if (debug) {
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+ } else {
+
+ GLES20.glVertexAttribPointer(mTextVertexLocation, 2,
+ GLES20.GL_FLOAT, false, 16, tile.texture.offset * 4);
+
+ GLES20.glVertexAttribPointer(mTextTextureCoordLocation, 2,
+ GLES20.GL_FLOAT, false, 16, tile.texture.offset * 4 + 8);
+
+ GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 16) *
+ INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
+
+ }
+
+ }
+
+ private static String textVertexShader = ""
+ + "precision highp float; "
+ + "attribute vec4 vertex;"
+ + "attribute vec2 tex_coord;"
+ + "uniform mat4 mvp;"
+ + "varying vec2 tex_c;"
+ + "void main() {"
+ + " gl_Position = mvp * vertex;"
+ + " tex_c = tex_coord;"
+ + "}";
+
+ private static String textFragmentShader = ""
+ + "precision highp float;"
+ + "uniform sampler2D tex;"
+ + "uniform vec4 col;"
+ + "varying vec2 tex_c;"
+ + "void main() {"
+ + " gl_FragColor = texture2D(tex, tex_c);"
+ + "}";
+
+}
diff --git a/src/org/mapsforge/android/glrenderer/TextTexture.java b/src/org/mapsforge/android/glrenderer/TextTexture.java
new file mode 100644
index 00000000..2ef358e3
--- /dev/null
+++ b/src/org/mapsforge/android/glrenderer/TextTexture.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * 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.android.glrenderer;
+
+public class TextTexture {
+
+ final float[] vertices;
+ final int id;
+ int length;
+ int offset;
+ GLMapTile tile;
+
+ String[] text;
+
+ TextTexture(int textureID) {
+ vertices = new float[TextRenderer.MAX_LABELS * 16];
+ id = textureID;
+ }
+
+}
diff --git a/src/org/mapsforge/android/glrenderer/LayerPool.java b/src/org/mapsforge/android/glrenderer/VertexPool.java
similarity index 53%
rename from src/org/mapsforge/android/glrenderer/LayerPool.java
rename to src/org/mapsforge/android/glrenderer/VertexPool.java
index 21215a21..63200b8f 100644
--- a/src/org/mapsforge/android/glrenderer/LayerPool.java
+++ b/src/org/mapsforge/android/glrenderer/VertexPool.java
@@ -15,40 +15,62 @@
package org.mapsforge.android.glrenderer;
-import java.util.LinkedList;
+import android.annotation.SuppressLint;
-class LayerPool {
- static private LinkedList pool = null;
- static private int count;
+class VertexPool {
+ private static final int POOL_LIMIT = 8192;
+
+ @SuppressLint("UseValueOf")
+ private static final Boolean lock = new Boolean(true);
+
+ static private PoolItem pool = null;
+ static private int count = 0;
static void init() {
- if (pool == null) {
- pool = new LinkedList();
- count = 0;
- }
}
static PoolItem get() {
- synchronized (pool) {
+ synchronized (lock) {
if (count == 0)
return new PoolItem();
count--;
- PoolItem it = pool.pop();
+
+ PoolItem it = pool;
+ pool = pool.next;
it.used = 0;
+ it.next = null;
return it;
}
}
- static void add(LinkedList items) {
- synchronized (pool) {
- int size = items.size();
+ static void add(PoolItem items) {
+ if (items == null)
+ return;
- while (count < 4096 && size-- > 0) {
+ synchronized (lock) {
+ PoolItem last = items;
+
+ // limit pool items
+ while (count < POOL_LIMIT) {
+ if (last.next == null) {
+ break;
+ }
+ last = last.next;
count++;
- pool.add(items.pop());
}
+
+ // clear references
+ PoolItem tmp2, tmp = last.next;
+ while (tmp != null) {
+ tmp2 = tmp;
+ tmp = tmp.next;
+ tmp2.next = null;
+ }
+
+ last.next = pool;
+ pool = items;
}
}
}
diff --git a/src/org/mapsforge/android/input/TouchHandler.java b/src/org/mapsforge/android/input/TouchHandler.java
index 21d8a265..75602a6a 100644
--- a/src/org/mapsforge/android/input/TouchHandler.java
+++ b/src/org/mapsforge/android/input/TouchHandler.java
@@ -19,6 +19,7 @@ import org.mapsforge.core.Tile;
import android.content.Context;
import android.os.CountDownTimer;
+import android.os.SystemClock;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
@@ -59,7 +60,8 @@ public class TouchHandler {
mMapView = mapView;
mMapMoveDelta = viewConfiguration.getScaledTouchSlop();
mActivePointerId = INVALID_POINTER_ID;
- mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener(mMapView));
+ mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener(
+ mMapView));
mGestureDetector = new GestureDetector(new MapGestureDetector(mMapView));
}
@@ -90,7 +92,8 @@ public class TouchHandler {
boolean scaling = mScaleGestureDetector.isInProgress();
if (!scaling && !mMoveThresholdReached) {
- if (Math.abs(moveX) > 3 * mMapMoveDelta || Math.abs(moveY) > 3 * mMapMoveDelta) {
+ if (Math.abs(moveX) > 3 * mMapMoveDelta
+ || Math.abs(moveY) > 3 * mMapMoveDelta) {
// the map movement threshold has been reached
// longPressDetector.pressStop();
mMoveThresholdReached = true;
@@ -179,15 +182,19 @@ public class TouchHandler {
return true;
}
+ private long lastRun = 0;
+
/**
* @param motionEvent
* ...
* @return ...
*/
public boolean handleMotionEvent(MotionEvent motionEvent) {
+
// workaround for a bug in the ScaleGestureDetector, see Android issue
// #12976
- if (motionEvent.getAction() != MotionEvent.ACTION_MOVE || motionEvent.getPointerCount() > 1) {
+ if (motionEvent.getAction() != MotionEvent.ACTION_MOVE
+ || motionEvent.getPointerCount() > 1) {
mScaleGestureDetector.onTouchEvent(motionEvent);
}
@@ -197,23 +204,44 @@ public class TouchHandler {
// // return true;
// }
int action = getAction(motionEvent);
-
+ boolean ret = false;
if (action == MotionEvent.ACTION_DOWN) {
- return onActionDown(motionEvent);
+ ret = onActionDown(motionEvent);
} else if (action == MotionEvent.ACTION_MOVE) {
- return onActionMove(motionEvent);
+ ret = onActionMove(motionEvent);
} else if (action == MotionEvent.ACTION_UP) {
- return onActionUp(motionEvent);
+ ret = onActionUp(motionEvent);
} else if (action == MotionEvent.ACTION_CANCEL) {
- return onActionCancel();
+ ret = onActionCancel();
// } else if (action == MotionEvent.ACTION_POINTER_DOWN) {
// return onActionPointerDown(motionEvent);
} else if (action == MotionEvent.ACTION_POINTER_UP) {
- return onActionPointerUp(motionEvent);
+ ret = onActionPointerUp(motionEvent);
}
+ // if (ret) {
+ // Log.d("", "" + );
+ //
+ // // try {
+ // //
+ // // Thread.sleep(10);
+ // // } catch (InterruptedException e) {
+ // // // TODO Auto-generated catch block
+ // // // e.printStackTrace();
+ // // }
+ //
+ // }
+ if (ret) {
+ // throttle input
+ long diff = SystemClock.uptimeMillis() - lastRun;
+ if (diff < 16) {
+ // Log.d("", "" + diff);
+ SystemClock.sleep(16 - diff);
+ }
+ lastRun = SystemClock.uptimeMillis();
+ }
// the event was not handled
- return false;
+ return ret;
}
class MapGestureDetector extends SimpleOnGestureListener {
@@ -254,7 +282,8 @@ public class TouchHandler {
}
@Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
+ float velocityY) {
int w = Tile.TILE_SIZE * 20;
int h = Tile.TILE_SIZE * 20;
mPrevX = 0;
@@ -265,7 +294,8 @@ public class TouchHandler {
mTimer = null;
}
- mScroller.fling(0, 0, Math.round(velocityX) / 2, Math.round(velocityY) / 2, -w, w, -h, h);
+ mScroller.fling(0, 0, Math.round(velocityX) / 2, Math.round(velocityY) / 2,
+ -w, w, -h, h);
// animate for two seconds
mTimer = new CountDownTimer(2000, 20) {
@Override
diff --git a/src/org/mapsforge/android/rendertheme/IRenderCallback.java b/src/org/mapsforge/android/rendertheme/IRenderCallback.java
index 19980f5f..bbaff643 100644
--- a/src/org/mapsforge/android/rendertheme/IRenderCallback.java
+++ b/src/org/mapsforge/android/rendertheme/IRenderCallback.java
@@ -15,6 +15,7 @@
package org.mapsforge.android.rendertheme;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
+import org.mapsforge.android.rendertheme.renderinstruction.Caption;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import android.graphics.Bitmap;
@@ -37,14 +38,8 @@ public interface IRenderCallback {
*
* @param caption
* the text to be rendered.
- * @param verticalOffset
- * the vertical offset of the caption.
- * @param paint
- * the paint to be used for rendering the text.
- * @param stroke
- * an optional paint for the text casing (may be null).
*/
- void renderAreaCaption(String caption, float verticalOffset, Paint paint, Paint stroke);
+ void renderAreaCaption(Caption caption);
/**
* Renders an area symbol with the given bitmap.
@@ -59,14 +54,8 @@ public interface IRenderCallback {
*
* @param caption
* the text to be rendered.
- * @param verticalOffset
- * the vertical offset of the caption.
- * @param paint
- * the paint to be used for rendering the text.
- * @param stroke
- * an optional paint for the text casing (may be null).
*/
- void renderPointOfInterestCaption(String caption, float verticalOffset, Paint paint, Paint stroke);
+ void renderPointOfInterestCaption(Caption caption);
/**
* Renders a point of interest circle with the given parameters.
diff --git a/src/org/mapsforge/android/rendertheme/RenderTheme.java b/src/org/mapsforge/android/rendertheme/RenderTheme.java
index 74b7b39d..8324d31f 100644
--- a/src/org/mapsforge/android/rendertheme/RenderTheme.java
+++ b/src/org/mapsforge/android/rendertheme/RenderTheme.java
@@ -140,7 +140,7 @@ public class RenderTheme {
public void matchNode(IRenderCallback renderCallback, Tag[] tags, byte zoomLevel) {
// List matchingList = matchingListNode;
// MatchingCacheKey matchingCacheKey = matchingCacheKeyNode;
- //
+
// if (!changed) {
// if (matchingList != null) {
// for (int i = 0, n = matchingList.size(); i < n; ++i) {
@@ -158,11 +158,13 @@ public class RenderTheme {
// matchingList.get(i).renderNode(renderCallback, tags);
// }
// } else {
- // // cache miss
+
+ // cache miss
// matchingList = new ArrayList();
- // for (int i = 0, n = mRulesList.size(); i < n; ++i) {
- // mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel, matchingList);
- // }
+ for (int i = 0, n = mRulesList.size(); i < n; ++i) {
+ mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel);
+ // , matchingList
+ }
// matchingCacheNodes.put(matchingCacheKey, matchingList);
// }
//
@@ -214,7 +216,7 @@ public class RenderTheme {
public synchronized RenderInstruction[] matchWay(IRenderCallback renderCallback,
Tag[] tags,
byte zoomLevel,
- boolean closed, boolean changed) {
+ boolean closed, boolean render) {
RenderInstruction[] renderInstructions = null;
LRUCache matchingCache;
@@ -240,12 +242,6 @@ public class RenderTheme {
boolean found = matchingCache.containsKey(matchingCacheKey);
if (found) {
renderInstructions = matchingCache.get(matchingCacheKey);
-
- if (renderInstructions != null) {
- for (int i = 0, n = renderInstructions.length; i < n; i++)
- renderInstructions[i].renderWay(renderCallback, tags);
-
- }
} else {
// cache miss
int c = (closed ? Closed.YES : Closed.NO);
@@ -259,13 +255,17 @@ public class RenderTheme {
renderInstructions = new RenderInstruction[matchingList.size()];
for (int i = 0, n = matchingList.size(); i < n; ++i) {
RenderInstruction renderInstruction = matchingList.get(i);
- renderInstruction.renderWay(renderCallback, tags);
+
renderInstructions[i] = renderInstruction;
}
}
matchingCache.put(matchingCacheKey, renderInstructions);
}
+ if (render && renderInstructions != null) {
+ for (int i = 0, n = renderInstructions.length; i < n; i++)
+ renderInstructions[i].renderWay(renderCallback, tags);
+ }
// mRenderInstructions = renderInstructions;
return renderInstructions;
}
diff --git a/src/org/mapsforge/android/rendertheme/osmarender/osmarender.xml b/src/org/mapsforge/android/rendertheme/osmarender/osmarender.xml
index 12c70405..8f837911 100644
--- a/src/org/mapsforge/android/rendertheme/osmarender/osmarender.xml
+++ b/src/org/mapsforge/android/rendertheme/osmarender/osmarender.xml
@@ -5,29 +5,36 @@
version="1" map-background="#f0f0f0">
-
+
-
+
+
+
+
+
-
+
+
+
+
+
-
-
-
+
+
+
-
+
-
+
+
-
-
@@ -99,15 +106,16 @@
+
-
+
-
-
+
+
+
+
+
+
+
@@ -132,19 +145,35 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -181,7 +210,7 @@
-
+
@@ -190,14 +219,23 @@
-
+
+ >
+
+
+
-
+
-
+
+
+
+
+
-
+
-
@@ -346,6 +384,8 @@
-->
+
+
@@ -371,30 +411,30 @@
-
+
-
+
-
+
-
+
-
+
+ fixed="true" fade="5"/>
-
+
@@ -403,11 +443,11 @@
-
-
+
@@ -426,7 +466,7 @@
-
+
@@ -434,10 +474,10 @@
-
+
-
+
@@ -558,11 +598,11 @@
-
+
-
+
@@ -579,6 +619,12 @@
+
+
+
+
+
@@ -634,6 +680,15 @@
+
+
+
+
+
+
+
+
+
@@ -642,6 +697,10 @@
+
+
+
+