started work on labeling

This commit is contained in:
Hannes Janetzek
2012-08-17 04:38:16 +02:00
parent 331aa6bf68
commit 7f573f0ac4
39 changed files with 2839 additions and 907 deletions

View File

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

View File

@@ -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<MapGeneratorJob> 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();
}
}
}

View File

@@ -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<TextItem> labels;
boolean newData;
boolean loading;

View File

@@ -14,35 +14,27 @@
*/
package org.mapsforge.android.glrenderer;
import java.util.LinkedList;
class Layer {
LinkedList<PoolItem> 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;
}
}

View File

@@ -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<LineLayer> 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<LineLayer>();
} else {
curItem = LayerPool.get();
LineLayer(int layer, Line line, boolean outline) {
super(layer);
pool = new LinkedList<PoolItem>();
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;
}

View File

@@ -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<LineLayer> layers;
LineLayer[] array = null;
int size = 0;
LineLayers() {
layers = new SparseArray<LineLayer>(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);
}
}
}

View File

@@ -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<TextItem> 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<TextItem>();
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<TextItem>();
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;
}
}

View File

@@ -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;

View File

@@ -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<PoolItem>();
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) {

View File

@@ -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<PolygonLayer> layers;
PolygonLayer[] array = null;
int size;
PolygonLayers() {
layers = new SparseArray<PolygonLayer>(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);
}
}
}

View File

@@ -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;

View File

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

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
import java.util.ArrayList;
import org.mapsforge.android.rendertheme.renderinstruction.Caption;
public class TextLayer {
public ArrayList<TextItem> labels;
void addLabel(float x, float y, String text, Caption caption) {
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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);"
+ "}";
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@@ -15,40 +15,62 @@
package org.mapsforge.android.glrenderer;
import java.util.LinkedList;
import android.annotation.SuppressLint;
class LayerPool {
static private LinkedList<PoolItem> 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<PoolItem>();
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<PoolItem> 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;
}
}
}

View File

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

View File

@@ -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.

View File

@@ -140,7 +140,7 @@ public class RenderTheme {
public void matchNode(IRenderCallback renderCallback, Tag[] tags, byte zoomLevel) {
// List<RenderInstruction> 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<RenderInstruction>();
// 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<MatchingCacheKey, RenderInstruction[]> 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;
}

View File

@@ -5,29 +5,36 @@
version="1" map-background="#f0f0f0">
<!-- ways -->
<rule e="way" k="*" v="*">
<rule e="way" k="*" v="*" >
<!-- landuse -->
<rule e="way" k="natural" v="grassland|scrub" zoom-min="9">
<area fill="#ebf2d2" fade="10" />
</rule>
<!-- landuse base -->
<rule e="way" k="landuse" v="*">
<rule e="way" k="*" v="farmland|farm">
<rule e="way" k="*" v="military">
<area fill="#dddddd"/>
<line stroke="#666666" stroke-width="1.5" fixed="true"/>
</rule>
<rule e="way" k="*" v="farmland|farm|orchard|vine_yard|greenhouse_horticulture|plant_nursery">
<area fill="#fff8bf" fade="10" />
</rule>
<rule e="way" k="landuse" v="grass">
<area fill="#deecb9" fade="10" />
<!-- Steinbruch, Schotter-, Kies-, Sand- und Tongrube -->
<rule e="way" k="*" v="quarry">
<area fill="#ddddcc" fade="10" />
</rule>
<rule e="way" k="*" v="residential|farmyard|retail|commercial">
<area fill="#efefeb" fade="10" />
</rule>
<!-- <rule e="way" k="landuse" v="industrial|brownfield|railway"> <area
fill="#bcaacd" stroke="#e4e4e4" stroke-width="0.2" /> -->
<rule e="way" k="*" v="industrial|railway"> <area
fill="#e8e3e4" stroke="#e4e4e4" stroke-width="0.2" fade="10" />
</rule>
<!--<rule e="way" k="landuse" v="construction|greenfield"> <area fill="#a47c41"
stroke="#e4e4e4" stroke-width="0.2" /> </rule> -->
<!-- <rule e="way" k="landuse" v="garages"> <area fill="#d6d6e4" /> </rule> -->
</rule>
<rule e="way" k="outline" v="*">
@@ -99,15 +106,16 @@
</rule>
</rule>
</rule>
<!-- landuse -->
<rule e="way" k="landuse" v="*" >
<rule e="way" k="landuse" v="*" zoom-min="10">
<!-- <rule e="way" k="*" v="landfill|quarry"> <area fill="#e9dd72" stroke="#556b2f"
stroke-width="0.2" /> </rule> -->
<rule e="way" k="*" v="cemetery">
<area fill="#d7e6b0" />
</rule>
<rule e="way" k="*" v="meadow|scrub">
<area fill="#deecb9" />
<rule e="way" k="*" v="meadow">
<area fill="#ebf2d2" fade="10"/>
</rule>
<!-- <rule e="way" k="*" v="village_green|recreation_ground">
@@ -122,7 +130,12 @@
</rule>
<rule e="way" k="leisure|landuse" v="allotments|village_green|recreation_ground|garden|golf_course|dog_park" zoom-min="12">
<!-- garden -->
<rule e="way" k="leisure" v="golf_course|dog_park" zoom-min="12">
<area fill="#e7f7c1" fade="12" />
</rule>
<rule e="way" k="landuse" v="allotments|village_green|recreation_ground" zoom-min="12">
<area fill="#e7f7c1" fade="12" />
</rule>
@@ -132,19 +145,35 @@
<area fill="#d7e6b0" fade="12" />
</rule>
</rule>
<rule e="way" k="natural|landuse" v="forest|wood" zoom-min="9">
<!-- <area fill="#BCCBB0" fade="10" /> -->
<!-- <rule e="way" k="*" v="*" zoom-max="11"> -->
<area fill="#d3dec8" fade="9" />
<!-- </rule> -->
<!-- <rule e="way" k="*" v="*" zoom-min="12">
<area fill="#cde2bc" fade="12" />
</rule> -->
<!-- <area fill="#87a670" fade="10" /> -->
<rule e="way" k="natural|" v="*">
<rule e="way" k="*" v="wood">
<rule e="way" k="*" v="*" zoom-max="12">
<area fill="#ebefe5" fade="7" />
</rule>
<rule e="way" k="*" v="*" zoom-min="11">
<area fill="#d3dec8" fade="12" />
</rule>
</rule>
</rule>
<rule e="way" k="landuse" v="*">
<rule e="way" k="*" v="forest">
<rule e="way" k="*" v="*" zoom-max="12">
<area fill="#ebefe5" fade="7" />
</rule>
<rule e="way" k="*" v="*" zoom-min="11">
<area fill="#d3dec8" fade="12" />
</rule>
</rule>
</rule>
<!-- keep grass above forest:wood and leisure:park! -->
<rule e="way" k="landuse" v="grass">
<area fill="#ebf2d2" fade="10" />
</rule>
<!-- amenity -->
<rule e="way" k="amenity" v="*">
@@ -181,7 +210,7 @@
<rule e="way" k="*" zoom-min="12" v="heath">
<area fill="#ffffc0" fade="12" />
</rule>
<rule e="way" k="*" v="marsh|wetland">
<rule e="way" k="*" v="marsh|wetland|mud">
<area fill="#deecb9" fade="12" />
</rule>
</rule>
@@ -190,14 +219,23 @@
<!-- leisure -->
<rule e="way" k="leisure" v="*" zoom-min="13">
<!-- playground| -->
<rule e="way" k="*" v="stadium" zoom-min="14">>
<line stroke="#c9c3c1" stroke-width="0.6" fixed="true" stroke-linecap="butt" />
<area fill="#e9e6e3" fade="15" />
</rule>
<!-- sollte unter playing field sein -->
<rule e="way" k="*" zoom_min="14" v="sports_centre|water_park">
<rule e="way" k="*" zoom-min="14" v="sports_centre|water_park">
<area fill="#daefdb" fade="12" />
</rule>
<rule e="way" k="*" v="*" zoom-min="15">
<rule e="way" k="*" v="*" zoom-min="14">
<rule e="way" k="*" v="playground|miniature_golf">
<area fill="#f4f4de" />
<line stroke="#fbdbc8" stroke-width="0.6" fixed="true"
stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="playing_fields|pitch">
<area fill="#f4f4de" />
<line stroke="#dbdbc8" stroke-width="0.6" fixed="true"
@@ -235,10 +273,10 @@
<line stroke="#b4cbdc" stroke-width="0.275" stroke-linecap="butt" />
</rule>
<rule e="way" k="waterway" v="river" zoom-min="12">
<line stroke="#b4cbdc" stroke-width="1.0" stroke-linecap="butt" />
<line stroke="#b4cbdc" stroke-width="1.3" stroke-linecap="butt" />
</rule>
<rule e="way" k="waterway" v="river" zoom-max="11">
<line stroke="#b4cbdc" stroke-width="1.0" stroke-linecap="butt"
<line stroke="#b4cbdc" stroke-width="1.3" stroke-linecap="butt"
fixed="true" />
</rule>
<rule e="way" k="waterway" v="riverbank|dock">
@@ -346,6 +384,8 @@
</rule> -->
</rule>
<rule e="way" k="outline" v="*">
<rule e="way" k="*" v="1">
<outline stroke="#909090" />
@@ -371,30 +411,30 @@
<rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
<!-- <line stroke="#eeee4a" stroke-width="1.8" stroke-linecap="butt"
fixed="true" /> -->
<line stroke="#f2df6d" stroke-width="1.9" stroke-linecap="butt"
fixed="true" />
<line stroke="#f2df6d" stroke-width="1.8" stroke-linecap="butt"
fixed="true" fade="9"/>
</rule>
<rule e="way" k="*" v="trunk_link|motorway_link" zoom-min="8">
<line stroke="#fed6a3" stroke-width="2.0" stroke-linecap="butt"
fixed="true" />
<line stroke="#fed6a3" stroke-width="1.8" stroke-linecap="butt"
fixed="true" fade="8"/>
</rule>
<rule e="way" k="*" v="primary" zoom-min="6">
<rule e="way" k="*" v="primary" zoom-min="5">
<!-- <line stroke="#eeee4a" stroke-width="1.4" stroke-linecap="butt"
fixed="true" /> -->
<line stroke="#f2df6d" stroke-width="2.0" stroke-linecap="butt"
fixed="true" />
<line stroke="#f2df6d" stroke-width="1.8" stroke-linecap="butt"
fixed="true" fade="5"/>
</rule>
<rule e="way" k="*" v="trunk" zoom-min="7">
<rule e="way" k="*" v="trunk" zoom-min="5">
<line stroke="#fed6a3" stroke-width="2.0" stroke-linecap="butt"
fixed="true" />
fixed="true" fade="5"/>
</rule>
<rule e="way" k="*" v="motorway">
<line stroke="#eec693" stroke-width="2.4" stroke-linecap="butt"
fixed="true" />
<line stroke="#eec693" stroke-width="2.2" stroke-linecap="butt"
fixed="true" fade="4"/>
</rule>
</rule>
@@ -403,11 +443,11 @@
<rule e="way" k="*" v="*" zoom-min="15">
<rule e="way" k="*" v="steps">
<line stroke="#f1f0f4" stroke-width="0.35" outline="2"
<line stroke="#f1f0f4" stroke-width="0.25" outline="2"
stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="track|footway|path|cycleway" zoom-min="16">
<line stroke="#c1bcb6" stroke-width="0.30" stroke-linecap="butt" />
<line stroke="#c1bcb6" stroke-width="0.20" stroke-linecap="butt" />
</rule>
</rule>
@@ -426,7 +466,7 @@
</rule>
<rule e="way" k="*" v="construction">
<line stroke="#d0d0d0" stroke-width="1.3" outline="1" />
<line stroke="#d0d0d0" stroke-width="1.2" outline="1" />
</rule>
</rule>
@@ -434,10 +474,10 @@
<rule e="way" k="*" v="residential|road|unclassified|living_street">
<rule e="way" k="bridge" v="yes|true">
<line stroke="#ffffff" stroke-width="1.3" outline="2" stroke-linecap="butt" />
<line stroke="#ffffff" stroke-width="1.2" outline="2" stroke-linecap="butt" />
</rule>
<rule e="way" k="bridge" v="~|no|false">
<line stroke="#ffffff" stroke-width="1.3" outline="1" />
<line stroke="#ffffff" stroke-width="1.2" outline="1" />
</rule>
</rule>
@@ -558,11 +598,11 @@
</rule>
<!-- railway casings and cores -->
<rule e="way" k="railway" v="tram">
<rule e="way" k="railway" v="tram" zoom-min="14">
<line stroke="#8c8f8c" stroke-width="0.8" fixed="true" />
</rule>
<rule e="way" k="railway" v="light_rail|subway|narrow_gauge">
<rule e="way" k="railway" v="light_rail|subway|narrow_gauge" zoom-min="14">
<line stroke="#a0a0a0" stroke-width="0.8" stroke-linecap="butt"
fixed="true" />
@@ -579,6 +619,12 @@
<line stroke="#bbbbcc" stroke-width="0.6" stroke-linecap="butt"
fixed="true" />
</rule>
<!-- whatever railway:spur means ... -->
<rule e="way" k="railway" v="disused|spur|abandoned|preserved" >
<line stroke="#cccccc" stroke-width="0.6" stroke-linecap="butt"
fixed="true" />
</rule>
</rule>
</rule>
@@ -634,6 +680,15 @@
<caption k="name" font-style="bold" font-size="10" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
<rule e="way" k="debug" v="area">
<line stroke="#ff0000" stroke-width="1.2" fixed="true" stroke-linecap="butt" />
<area fill="#880000ff"/>
<caption k="name" font-size="15" fill="#ffffff" stroke="#000000" stroke-width="2.0"/>
</rule>
<rule e="way" k="debug" v="way">
<line stroke="#00ffff" stroke-width="1.5" fixed="true" stroke-linecap="butt" />
<caption k="name" font-size="15" fill="#ffffff" stroke="#000000" stroke-width="2.0"/>
</rule>
</rule>
<rule e="node" k="*" v="*">
@@ -642,6 +697,10 @@
<circle r="1.5" fill="#909090" />
</rule>
<rule e="node" k="debug" v="*" >
<caption k="name" font-size="12" fill="#0000ff" />
</rule>
<!-- highway -->
<!-- <rule e="node" k="highway" v="*"> <rule e="node" k="highway" v="turning_circle">
@@ -671,12 +730,12 @@
<caption k="name" font-style="bold" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
<rule e="node" k="*" v="city" zoom-max="14">
<caption k="name" font-style="bold" font-size="25" fill="#000000"
<rule e="node" k="*" v="city">
<caption k="name" font-style="bold" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
<rule e="node" k="*" v="country" zoom-max="6">
<caption k="name" font-style="bold" font-size="25" fill="#000000"
<rule e="node" k="*" v="country" zoom-max="7">
<caption k="name" font-size="20" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
</rule>

View File

@@ -42,7 +42,8 @@ public final class Area implements RenderInstruction {
* @throws IOException
* if an I/O error occurs while reading a resource.
*/
public static Area create(String elementName, Attributes attributes, int level) throws IOException {
public static Area create(String elementName, Attributes attributes, int level)
throws IOException {
String src = null;
int fill = Color.BLACK;
int stroke = Color.TRANSPARENT;
@@ -73,7 +74,8 @@ public final class Area implements RenderInstruction {
private static void validate(float strokeWidth) {
if (strokeWidth < 0) {
throw new IllegalArgumentException("stroke-width must not be negative: " + strokeWidth);
throw new IllegalArgumentException("stroke-width must not be negative: "
+ strokeWidth);
}
}
@@ -96,22 +98,24 @@ public final class Area implements RenderInstruction {
/**
*
*/
public final int color;
public final float color[];
/**
*
*/
public final int fade;
private Area(String src, int fill, int stroke, float strokeWidth, int fade, int level) throws IOException {
private Area(String src, int fill, int stroke, float strokeWidth, int fade, int level)
throws IOException {
super();
Shader shader = BitmapUtils.createBitmapShader(src);
if (fill == Color.TRANSPARENT) {
paintFill = null;
} else {
paintFill = new Paint(Paint.ANTI_ALIAS_FLAG);
paintFill.setShader(shader);
if (src != null) {
Shader shader = BitmapUtils.createBitmapShader(src);
paintFill.setShader(shader);
}
paintFill.setStyle(Style.FILL);
paintFill.setColor(fill);
paintFill.setStrokeCap(Cap.ROUND);
@@ -125,7 +129,12 @@ public final class Area implements RenderInstruction {
paintOutline.setColor(stroke);
paintOutline.setStrokeCap(Cap.ROUND);
}
color = fill;
color = new float[4];
color[0] = (fill >> 16 & 0xff) / 255.0f;
color[1] = (fill >> 8 & 0xff) / 255.0f;
color[2] = (fill >> 0 & 0xff) / 255.0f;
color[3] = (fill >> 24 & 0xff) / 255.0f;
this.strokeWidth = strokeWidth;
this.fade = fade;
this.level = level;

View File

@@ -24,8 +24,10 @@ import org.xml.sax.Attributes;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Typeface;
import android.util.FloatMath;
/**
* Represents a text label on the map.
@@ -78,41 +80,54 @@ public final class Caption implements RenderInstruction {
return new Caption(textKey, dy, typeface, fontSize, fill, stroke, strokeWidth);
}
private static void validate(String elementName, String textKey, float fontSize, float strokeWidth) {
private static void validate(String elementName, String textKey, float fontSize,
float strokeWidth) {
if (textKey == null) {
throw new IllegalArgumentException("missing attribute k for element: " + elementName);
throw new IllegalArgumentException("missing attribute k for element: "
+ elementName);
} else if (fontSize < 0) {
throw new IllegalArgumentException("font-size must not be negative: " + fontSize);
throw new IllegalArgumentException("font-size must not be negative: "
+ fontSize);
} else if (strokeWidth < 0) {
throw new IllegalArgumentException("stroke-width must not be negative: " + strokeWidth);
throw new IllegalArgumentException("stroke-width must not be negative: "
+ strokeWidth);
}
}
private final float mDy;
private final float mFontSize;
private final Paint mPaint;
private final Paint mStroke;
private final String mTextKey;
public final float dy;
public float fontSize;
public final Paint paint;
public final Paint stroke;
public final String textKey;
public final float fontHeight;
public final float fontDescent;
private Caption(String textKey, float dy, Typeface typeface, float fontSize, int fill, int stroke, float strokeWidth) {
private Caption(String textKey, float dy, Typeface typeface, float fontSize,
int fillColor, int strokeColor, float strokeWidth) {
super();
mTextKey = textKey;
mDy = dy;
this.textKey = textKey.intern();
this.dy = dy;
this.fontSize = fontSize;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextAlign(Align.LEFT);
mPaint.setTypeface(typeface);
mPaint.setColor(fill);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextAlign(Align.CENTER);
paint.setTypeface(typeface);
paint.setColor(fillColor);
mStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
mStroke.setStyle(Style.STROKE);
mStroke.setTextAlign(Align.LEFT);
mStroke.setTypeface(typeface);
mStroke.setColor(stroke);
mStroke.setStrokeWidth(strokeWidth);
stroke = new Paint(Paint.ANTI_ALIAS_FLAG);
stroke.setStyle(Style.STROKE);
stroke.setTextAlign(Align.CENTER);
stroke.setTypeface(typeface);
stroke.setColor(strokeColor);
stroke.setStrokeWidth(strokeWidth);
mFontSize = fontSize;
paint.setTextSize(fontSize);
stroke.setTextSize(fontSize);
FontMetrics fm = paint.getFontMetrics();
fontHeight = FloatMath.ceil(Math.abs(fm.bottom) + Math.abs(fm.top));
fontDescent = FloatMath.ceil(Math.abs(fm.descent));
}
@Override
@@ -122,12 +137,12 @@ public final class Caption implements RenderInstruction {
@Override
public void renderNode(IRenderCallback renderCallback, Tag[] tags) {
renderCallback.renderPointOfInterestCaption(mTextKey, mDy, mPaint, mStroke);
renderCallback.renderPointOfInterestCaption(this);
}
@Override
public void renderWay(IRenderCallback renderCallback, Tag[] tags) {
renderCallback.renderAreaCaption(mTextKey, mDy, mPaint, mStroke);
renderCallback.renderAreaCaption(this);
}
@Override
@@ -137,7 +152,7 @@ public final class Caption implements RenderInstruction {
@Override
public void scaleTextSize(float scaleFactor) {
mPaint.setTextSize(mFontSize * scaleFactor);
mStroke.setTextSize(mFontSize * scaleFactor);
paint.setTextSize(fontSize * scaleFactor);
stroke.setTextSize(fontSize * scaleFactor);
}
}

View File

@@ -55,7 +55,7 @@ public final class Line implements RenderInstruction {
float[] strokeDasharray = null;
Cap strokeLinecap = Cap.ROUND;
int outline = -1;
// int fade = -1;
int fade = -1;
boolean fixed = false;
for (int i = 0; i < attributes.getLength(); ++i) {
@@ -75,7 +75,7 @@ public final class Line implements RenderInstruction {
} else if ("outline".equals(name)) {
outline = Integer.parseInt(value);
} else if ("fade".equals(name)) {
// fade = Integer.parseInt(value);
fade = Integer.parseInt(value);
} else if ("fixed".equals(name)) {
fixed = Boolean.parseBoolean(value);
} else {
@@ -85,7 +85,7 @@ public final class Line implements RenderInstruction {
validate(strokeWidth);
return new Line(src, stroke, strokeWidth, strokeDasharray, strokeLinecap, level,
outline, fixed);
outline, fixed, fade);
}
private static void validate(float strokeWidth) {
@@ -123,7 +123,7 @@ public final class Line implements RenderInstruction {
/**
*
*/
public final int color;
public final float color[];
/**
*
*/
@@ -134,9 +134,11 @@ public final class Line implements RenderInstruction {
*/
public final boolean fixed;
public final int fade;
private Line(String src, int stroke, float strokeWidth, float[] strokeDasharray,
Cap strokeLinecap, int level,
int outline, boolean fixed)
int outline, boolean fixed, int fade)
throws IOException {
super();
@@ -151,11 +153,18 @@ public final class Line implements RenderInstruction {
}
paint.setStrokeCap(strokeLinecap);
round = (strokeLinecap == Cap.ROUND);
this.color = stroke;
color = new float[4];
color[0] = (stroke >> 16 & 0xff) / 255.0f;
color[1] = (stroke >> 8 & 0xff) / 255.0f;
color[2] = (stroke >> 0 & 0xff) / 255.0f;
color[3] = (stroke >> 24 & 0xff) / 255.0f;
this.strokeWidth = strokeWidth;
this.level = level;
this.outline = outline;
this.fixed = fixed;
this.fade = fade;
}
@Override

View File

@@ -22,6 +22,7 @@ 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.core.Tag;
import org.mapsforge.core.Tile;
@@ -218,8 +219,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
}
@Override
public void renderAreaCaption(String textKey, float verticalOffset, Paint paint,
Paint stroke) {
public void renderAreaCaption(Caption caption) {
// mapDatabase.readTag(caption);
// if (caption.value != null) {
// float[] centerPosition = GeometryUtils
@@ -241,7 +241,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
}
@Override
public void renderPointOfInterest(byte layer, int latitude, int longitude, Tag[] tags) {
public void renderPointOfInterest(byte layer, float latitude, float longitude,
Tag[] tags) {
mDrawingLayer = mWays[getValidLayer(layer)];
mPoiX = scaleLongitude(longitude);
mPoiY = scaleLatitude(latitude);
@@ -249,8 +250,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
}
@Override
public void renderPointOfInterestCaption(String textKey, float verticalOffset,
Paint paint, Paint stroke) {
public void renderPointOfInterestCaption(Caption caption) {
// mapDatabase.readTag(caption);
// if (caption.value != null) {
// nodes.add(new PointTextContainer(caption.value, poiX, poiY + verticalOffset, paint, stroke));
@@ -298,7 +298,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
// private byte mPrevLayer = 0;
@Override
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, int[] wayLengths,
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLengths,
boolean changed) {
// if (mCoords == null)
// mCoords = mMapDatabase.getCoordinates();
@@ -526,4 +526,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback,
// TODO Auto-generated method stub
}
@Override
public boolean checkWay(Tag[] tags, boolean closed) {
// TODO Auto-generated method stub
return false;
}
}

View File

@@ -101,6 +101,7 @@ public class GlUtils {
int program = GLES20.glCreateProgram();
if (program != 0) {
checkGlError("glCreateProgram");
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader);