diff --git a/src/org/oscim/layers/tile/BitmapTileLayer.java b/src/org/oscim/layers/tile/BitmapTileLayer.java
new file mode 100644
index 00000000..0f3d101d
--- /dev/null
+++ b/src/org/oscim/layers/tile/BitmapTileLayer.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013 Hannes Janetzek
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.layers.tile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.zip.GZIPInputStream;
+
+import org.oscim.layers.tile.bitmap.TileSource;
+import org.oscim.renderer.layer.BitmapLayer;
+import org.oscim.renderer.layer.Layers;
+import org.oscim.view.MapView;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+public class BitmapTileLayer extends TileLayer {
+ private static final int TIMEOUT_CONNECT = 5000;
+ private static final int TIMEOUT_READ = 10000;
+
+ final TileSource mTileSource;
+
+ public BitmapTileLayer(MapView mapView, TileSource tileSource) {
+ super(mapView);
+ mTileSource = tileSource;
+ }
+
+ @Override
+ protected TileLoader createLoader(JobQueue q, TileManager tm) {
+ return new TileLoader(q, tm) {
+
+ @Override
+ protected boolean executeJob(MapTile tile) {
+ URL url;
+ try {
+ url = mTileSource.getTileUrl(tile);
+ URLConnection urlConnection = getURLConnection(url);
+ InputStream inputStream = getInputStream(urlConnection);
+ Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+
+ tile.layers = new Layers();
+ BitmapLayer l = new BitmapLayer();
+ l.setBitmap(bitmap);
+
+ tile.layers.textureLayers = l;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ return false;
+ }
+
+ @Override
+ public void cleanup() {
+ }
+
+ private InputStream getInputStream(URLConnection urlConnection) throws IOException {
+ if ("gzip".equals(urlConnection.getContentEncoding())) {
+ return new GZIPInputStream(urlConnection.getInputStream());
+ }
+ return urlConnection.getInputStream();
+ }
+
+ private URLConnection getURLConnection(URL url) throws IOException {
+ URLConnection urlConnection = url.openConnection();
+ urlConnection.setConnectTimeout(TIMEOUT_CONNECT);
+ urlConnection.setReadTimeout(TIMEOUT_READ);
+ return urlConnection;
+ }
+ };
+ }
+}
diff --git a/src/org/oscim/layers/tile/TileLoader.java b/src/org/oscim/layers/tile/TileLoader.java
index 667df3da..c8e5f4f3 100644
--- a/src/org/oscim/layers/tile/TileLoader.java
+++ b/src/org/oscim/layers/tile/TileLoader.java
@@ -19,9 +19,6 @@ import org.oscim.utils.PausableThread;
public abstract class TileLoader extends PausableThread {
private static int id;
- public interface Factory{
- T create(JobQueue jobQueue, TileManager tileManager);
- }
private final String THREAD_NAME;
private final JobQueue mJobQueue;
diff --git a/src/org/oscim/layers/tile/TileRenderer.java b/src/org/oscim/layers/tile/TileRenderer.java
index df0d1dc3..477da6dc 100644
--- a/src/org/oscim/layers/tile/TileRenderer.java
+++ b/src/org/oscim/layers/tile/TileRenderer.java
@@ -22,6 +22,7 @@ import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
+import org.oscim.renderer.layer.BitmapRenderer;
import org.oscim.renderer.layer.Layer;
import org.oscim.renderer.layer.LineRenderer;
import org.oscim.renderer.layer.LineTexRenderer;
@@ -185,6 +186,17 @@ public class TileRenderer {
}
}
+ for (Layer l = t.layers.textureLayers; l != null;) {
+ switch (l.type) {
+ case Layer.BITMAP:
+ l = BitmapRenderer.draw(l, 1, m);
+ break;
+
+ default:
+ l = l.next;
+ }
+ }
+
// clear clip-region and could also draw 'fade-effect'
if (mFaded)
PolygonRenderer.drawOver(m, true, 0x22000000);
diff --git a/src/org/oscim/layers/tile/bitmap/AbstractTileSource.java b/src/org/oscim/layers/tile/bitmap/AbstractTileSource.java
new file mode 100644
index 00000000..ce96a37f
--- /dev/null
+++ b/src/org/oscim/layers/tile/bitmap/AbstractTileSource.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.layers.tile.bitmap;
+
+public abstract class AbstractTileSource implements TileSource {
+ protected final String hostName;
+ protected final int port;
+
+ protected AbstractTileSource(String hostName, int port) {
+ if (hostName == null || hostName.isEmpty()) {
+ throw new IllegalArgumentException("no host name specified");
+ } else if (port < 0 || port > 65535) {
+ throw new IllegalArgumentException("invalid port number: " + port);
+ }
+
+ this.hostName = hostName;
+ this.port = port;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (!(obj instanceof AbstractTileSource)) {
+ return false;
+ }
+ AbstractTileSource other = (AbstractTileSource) obj;
+ if (!this.hostName.equals(other.hostName)) {
+ return false;
+ } else if (this.port != other.port) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.hostName.hashCode();
+ result = prime * result + this.port;
+ return result;
+ }
+}
diff --git a/src/org/oscim/layers/tile/bitmap/MapQuestAerial.java b/src/org/oscim/layers/tile/bitmap/MapQuestAerial.java
new file mode 100644
index 00000000..78d99ab7
--- /dev/null
+++ b/src/org/oscim/layers/tile/bitmap/MapQuestAerial.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.layers.tile.bitmap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.oscim.core.Tile;
+
+public class MapQuestAerial extends AbstractTileSource {
+ public static final MapQuestAerial INSTANCE = new MapQuestAerial("otile1.mqcdn.com", 80);
+ private static final int PARALLEL_REQUESTS_LIMIT = 8;
+ private static final String PROTOCOL = "http";
+ private static final int ZOOM_LEVEL_MAX = 18;
+ private static final int ZOOM_LEVEL_MIN = 0;
+
+ public MapQuestAerial(String hostName, int port) {
+ super(hostName, port);
+ }
+
+ @Override
+ public int getParallelRequestsLimit() {
+ return PARALLEL_REQUESTS_LIMIT;
+ }
+
+ @Override
+ public URL getTileUrl(Tile tile) throws MalformedURLException {
+ StringBuilder stringBuilder = new StringBuilder(32);
+
+ stringBuilder.append("/tiles/1.0.0/sat/");
+ stringBuilder.append(tile.zoomLevel);
+ stringBuilder.append('/');
+ stringBuilder.append(tile.tileX);
+ stringBuilder.append('/');
+ stringBuilder.append(tile.tileY);
+ stringBuilder.append(".jpg");
+
+ return new URL(PROTOCOL, this.hostName, this.port, stringBuilder.toString());
+ }
+
+ @Override
+ public byte getZoomLevelMax() {
+ return ZOOM_LEVEL_MAX;
+ }
+
+ @Override
+ public byte getZoomLevelMin() {
+ return ZOOM_LEVEL_MIN;
+ }
+}
diff --git a/src/org/oscim/layers/tile/bitmap/OpenStreetMapMapnik.java b/src/org/oscim/layers/tile/bitmap/OpenStreetMapMapnik.java
new file mode 100644
index 00000000..0357d36b
--- /dev/null
+++ b/src/org/oscim/layers/tile/bitmap/OpenStreetMapMapnik.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.layers.tile.bitmap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.oscim.core.Tile;
+
+public class OpenStreetMapMapnik extends AbstractTileSource {
+ public static final OpenStreetMapMapnik INSTANCE = new OpenStreetMapMapnik("tile.openstreetmap.org", 80);
+ private static final int PARALLEL_REQUESTS_LIMIT = 8;
+ private static final String PROTOCOL = "http";
+ private static final int ZOOM_LEVEL_MAX = 18;
+ private static final int ZOOM_LEVEL_MIN = 0;
+
+ public OpenStreetMapMapnik(String hostName, int port) {
+ super(hostName, port);
+ }
+
+ @Override
+ public int getParallelRequestsLimit() {
+ return PARALLEL_REQUESTS_LIMIT;
+ }
+
+ @Override
+ public URL getTileUrl(Tile tile) throws MalformedURLException {
+ StringBuilder stringBuilder = new StringBuilder(32);
+
+ stringBuilder.append('/');
+ stringBuilder.append(tile.zoomLevel);
+ stringBuilder.append('/');
+ stringBuilder.append(tile.tileX);
+ stringBuilder.append('/');
+ stringBuilder.append(tile.tileY);
+ stringBuilder.append(".png");
+
+ return new URL(PROTOCOL, this.hostName, this.port, stringBuilder.toString());
+ }
+
+ @Override
+ public byte getZoomLevelMax() {
+ return ZOOM_LEVEL_MAX;
+ }
+
+ @Override
+ public byte getZoomLevelMin() {
+ return ZOOM_LEVEL_MIN;
+ }
+}
diff --git a/src/org/oscim/layers/tile/bitmap/TileSource.java b/src/org/oscim/layers/tile/bitmap/TileSource.java
new file mode 100644
index 00000000..00baa085
--- /dev/null
+++ b/src/org/oscim/layers/tile/bitmap/TileSource.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.layers.tile.bitmap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.oscim.core.Tile;
+
+public interface TileSource {
+ /**
+ * @return the maximum number of parallel requests which this {@code TileSource} supports.
+ */
+ int getParallelRequestsLimit();
+
+ /**
+ * @return the download URL for the given {@code Tile}.
+ */
+ URL getTileUrl(Tile tile) throws MalformedURLException;
+
+ /**
+ * @return the maximum zoom level which this {@code TileSource} supports.
+ */
+ byte getZoomLevelMax();
+
+ /**
+ * @return the minimum zoom level which this {@code TileSource} supports.
+ */
+ byte getZoomLevelMin();
+}
diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java
index 2e5ee532..fad51c04 100644
--- a/src/org/oscim/renderer/GLRenderer.java
+++ b/src/org/oscim/renderer/GLRenderer.java
@@ -243,8 +243,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
| GLES20.GL_DEPTH_BUFFER_BIT
| GLES20.GL_STENCIL_BUFFER_BIT);
- boolean tilesChanged = true;
- boolean positionChanged = true;
+ boolean tilesChanged = false;
+ boolean positionChanged = false;
// get current MapPosition, set mBoxCoords (mapping of screen to model
// coordinates)
@@ -253,7 +253,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
synchronized (mMapViewPosition) {
mMapViewPosition.updateAnimation();
- positionChanged |= mMapViewPosition.getMapPosition(pos);
+ positionChanged = mMapViewPosition.getMapPosition(pos);
if (positionChanged)
mMapViewPosition.getMapViewProjection(mBoxCoords);
diff --git a/src/org/oscim/renderer/layer/BitmapLayer.java b/src/org/oscim/renderer/layer/BitmapLayer.java
new file mode 100644
index 00000000..023c822b
--- /dev/null
+++ b/src/org/oscim/renderer/layer/BitmapLayer.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013 Hannes Janetzek
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.renderer.layer;
+
+import java.nio.ShortBuffer;
+
+import org.oscim.core.Tile;
+import org.oscim.renderer.GLRenderer;
+
+import android.graphics.Bitmap;
+
+public class BitmapLayer extends TextureLayer {
+ // private final static String TAG = BitmapLayer.class.getName();
+ private Bitmap mBitmap;
+
+ public BitmapLayer() {
+ type = Layer.BITMAP;
+ }
+
+ public void setBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+
+ vertexItems = VertexItem.pool.get();
+ short[] buf = vertexItems.vertices;
+ short size = (short) (Tile.SIZE * GLRenderer.COORD_SCALE);
+ short center = (short) (size >> 1);
+ short m = (short) (-(size >> 1));
+ short p = center;
+ short t = (8 * 256);
+
+ int pos = 0;
+ // top-left
+ buf[pos++] = 0;
+ buf[pos++] = 0;
+ buf[pos++] = m;
+ buf[pos++] = m;
+ buf[pos++] = 0;
+ buf[pos++] = 0;
+ // bot-left
+ buf[pos++] = 0;
+ buf[pos++] = size;
+ buf[pos++] = m;
+ buf[pos++] = p;
+ buf[pos++] = 0;
+ buf[pos++] = t;
+ // top-right
+ buf[pos++] = size;
+ buf[pos++] = 0;
+ buf[pos++] = p;
+ buf[pos++] = m;
+ buf[pos++] = t;
+ buf[pos++] = 0;
+ // bot-right
+ buf[pos++] = size;
+ buf[pos++] = size;
+ buf[pos++] = p;
+ buf[pos++] = p;
+ buf[pos++] = t;
+ buf[pos++] = t;
+
+ vertexItems.used = 24;
+
+ TextureItem ti = this.textures = new TextureItem(-1);
+ ti.ownBitmap = true;
+ ti.width = mBitmap.getWidth();
+ ti.height = mBitmap.getHeight();
+ ti.bitmap = mBitmap;
+ ti.vertices = TextureRenderer.INDICES_PER_SPRITE;
+
+ verticesCnt = 4;
+ }
+
+ @Override
+ public boolean prepare() {
+ return false;
+ }
+
+ @Override
+ protected void compile(ShortBuffer sbuf) {
+ if (mBitmap == null)
+ return;
+
+ super.compile(sbuf);
+
+ mBitmap.recycle();
+ mBitmap = null;
+ textures.bitmap = null;
+ }
+
+ @Override
+ protected void clear() {
+
+ if (mBitmap != null) {
+ mBitmap.recycle();
+ mBitmap = null;
+ textures.bitmap = null;
+ }
+
+ TextureItem.releaseTexture(textures);
+ textures = null;
+
+ VertexItem.pool.releaseAll(vertexItems);
+ vertexItems = null;
+ }
+}
diff --git a/src/org/oscim/renderer/layer/BitmapRenderer.java b/src/org/oscim/renderer/layer/BitmapRenderer.java
new file mode 100644
index 00000000..2d30cd2f
--- /dev/null
+++ b/src/org/oscim/renderer/layer/BitmapRenderer.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2012, 2013 Hannes Janetzek
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+
+package org.oscim.renderer.layer;
+
+import static org.oscim.renderer.GLRenderer.COORD_SCALE;
+import static org.oscim.renderer.layer.TextureItem.TEXTURE_HEIGHT;
+
+import org.oscim.renderer.GLRenderer;
+import org.oscim.renderer.GLRenderer.Matrices;
+import org.oscim.renderer.GLState;
+import org.oscim.utils.GlUtils;
+
+import android.opengl.GLES20;
+
+/**
+ * @author Hannes Janetzek
+ */
+public final class BitmapRenderer {
+ private final static String TAG = BitmapRenderer.class.getName();
+ public final static boolean debug = true;
+
+ private static int mTextureProgram;
+ private static int hTextureMVMatrix;
+ private static int hTextureProjMatrix;
+ private static int hTextureVertex;
+ private static int hTextureScale;
+ private static int hTextureScreenScale;
+ private static int hTextureTexCoord;
+
+ public final static int INDICES_PER_SPRITE = 6;
+ final static int VERTICES_PER_SPRITE = 4;
+ final static int SHORTS_PER_VERTICE = 6;
+
+ static void init() {
+ mTextureProgram = GlUtils.createProgram(textVertexShader,
+ textFragmentShader);
+
+ hTextureMVMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_mv");
+ hTextureProjMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_proj");
+ hTextureScale = GLES20.glGetUniformLocation(mTextureProgram, "u_scale");
+ hTextureScreenScale = GLES20.glGetUniformLocation(mTextureProgram, "u_swidth");
+ hTextureVertex = GLES20.glGetAttribLocation(mTextureProgram, "vertex");
+ hTextureTexCoord = GLES20.glGetAttribLocation(mTextureProgram, "tex_coord");
+ }
+
+ public static Layer draw(Layer layer, float scale, Matrices m) {
+ GLState.test(false, false);
+ GLState.blend(true);
+
+ GLState.useProgram(mTextureProgram);
+
+ GLState.enableVertexArrays(hTextureTexCoord, hTextureVertex);
+
+ TextureLayer tl = (TextureLayer) layer;
+
+ if (tl.fixed)
+ GLES20.glUniform1f(hTextureScale, (float) Math.sqrt(scale));
+ else
+ GLES20.glUniform1f(hTextureScale, 1);
+
+ GLES20.glUniform1f(hTextureScreenScale, 1f / GLRenderer.screenWidth);
+
+ m.proj.setAsUniform(hTextureProjMatrix);
+
+ m.mvp.setAsUniform(hTextureMVMatrix);
+
+ GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, GLRenderer.mQuadIndicesID);
+
+ for (TextureItem ti = tl.textures; ti != null; ti = ti.next) {
+ //Log.d(TAG, "render texture " + ti.id);
+
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, ti.id);
+ int maxVertices = GLRenderer.maxQuads * INDICES_PER_SPRITE;
+
+ // draw up to maxVertices in each iteration
+ for (int i = 0; i < ti.vertices; i += maxVertices) {
+ // to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
+ int off = (ti.offset + i) * 8 + tl.offset;
+
+ GLES20.glVertexAttribPointer(hTextureVertex, 4,
+ GLES20.GL_SHORT, false, 12, off);
+
+ GLES20.glVertexAttribPointer(hTextureTexCoord, 2,
+ GLES20.GL_SHORT, false, 12, off + 8);
+
+ int numVertices = ti.vertices - i;
+ if (numVertices > maxVertices)
+ numVertices = maxVertices;
+
+ GLES20.glDrawElements(GLES20.GL_TRIANGLES, numVertices,
+ GLES20.GL_UNSIGNED_SHORT, 0);
+ }
+ }
+
+ GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ return layer.next;
+ }
+
+ //private final static double TEX_COORD_DIV_X = 1.0 / (TEXTURE_WIDTH * COORD_SCALE);
+ private final static double TEX_COORD_DIV_X = 1.0 / (TEXTURE_HEIGHT* COORD_SCALE);
+ private final static double TEX_COORD_DIV_Y = 1.0 / (TEXTURE_HEIGHT * COORD_SCALE);
+ private final static double COORD_DIV = 1.0 / GLRenderer.COORD_SCALE;
+
+ private final static String textVertexShader = ""
+ + "precision mediump float; "
+ + "attribute vec4 vertex;"
+ + "attribute vec2 tex_coord;"
+ + "uniform mat4 u_mv;"
+ + "uniform mat4 u_proj;"
+ + "uniform float u_scale;"
+ + "uniform float u_swidth;"
+ + "varying vec2 tex_c;"
+ + "const vec2 div = vec2(" + TEX_COORD_DIV_X + "," + TEX_COORD_DIV_Y + ");"
+ + "const float coord_scale = " + COORD_DIV + ";"
+ + "void main() {"
+ + " gl_Position = u_mv * vec4(vertex.xy, 0.0, 1.0);"
+ + " tex_c = tex_coord * div;"
+ + "}";
+
+ private final static String textFragmentShader = ""
+ + "precision mediump float;"
+ + "uniform sampler2D tex;"
+ + "varying vec2 tex_c;"
+ + "void main() {"
+ + " gl_FragColor = texture2D(tex, tex_c.xy);"
+ + "}";
+}
diff --git a/src/org/oscim/renderer/layer/Layers.java b/src/org/oscim/renderer/layer/Layers.java
index 3d032992..65f359ac 100644
--- a/src/org/oscim/renderer/layer/Layers.java
+++ b/src/org/oscim/renderer/layer/Layers.java
@@ -28,6 +28,7 @@ public class Layers {
LineTexRenderer.init();
PolygonRenderer.init();
TextureRenderer.init();
+ BitmapRenderer.init();
TextureItem.init(10);
}
diff --git a/src/org/oscim/renderer/layer/SymbolLayer.java b/src/org/oscim/renderer/layer/SymbolLayer.java
index 99fe2b03..668117cf 100644
--- a/src/org/oscim/renderer/layer/SymbolLayer.java
+++ b/src/org/oscim/renderer/layer/SymbolLayer.java
@@ -102,7 +102,7 @@ public final class SymbolLayer extends TextureLayer {
float x = 0;
float y = 0;
- TextureItem to = TextureItem.pool.get();
+ TextureItem to = TextureItem.get(true);
textures = to;
mCanvas.setBitmap(to.bitmap);
@@ -138,7 +138,7 @@ public final class SymbolLayer extends TextureLayer {
offsetIndices = numIndices;
curIndices = 0;
- to.next = TextureItem.pool.get();
+ to.next = TextureItem.get(true);
to = to.next;
mCanvas.setBitmap(to.bitmap);
@@ -247,7 +247,8 @@ public final class SymbolLayer extends TextureLayer {
@Override
protected void clear() {
- TextureItem.pool.releaseAll(textures);
+ TextureItem.releaseAll(textures);
+
SymbolItem.pool.releaseAll(symbols);
VertexItem.pool.releaseAll(vertexItems);
textures = null;
diff --git a/src/org/oscim/renderer/layer/TextLayer.java b/src/org/oscim/renderer/layer/TextLayer.java
index cb6a1e4c..5da2f7ac 100644
--- a/src/org/oscim/renderer/layer/TextLayer.java
+++ b/src/org/oscim/renderer/layer/TextLayer.java
@@ -17,8 +17,6 @@ package org.oscim.renderer.layer;
import static org.oscim.renderer.GLRenderer.COORD_SCALE;
import static org.oscim.renderer.layer.TextureItem.TEXTURE_HEIGHT;
import static org.oscim.renderer.layer.TextureItem.TEXTURE_WIDTH;
-
-
import android.graphics.Canvas;
public final class TextLayer extends TextureLayer {
@@ -91,7 +89,7 @@ public final class TextLayer extends TextureLayer {
float y = 0;
float yy;
- TextureItem to = TextureItem.pool.get();
+ TextureItem to = TextureItem.get(true);
textures = to;
mCanvas.setBitmap(to.bitmap);
@@ -113,7 +111,7 @@ public final class TextLayer extends TextureLayer {
to.vertices = (short) (numIndices - offsetIndices);
offsetIndices = numIndices;
- to.next = TextureItem.pool.get();
+ to.next = TextureItem.get(true);
to = to.next;
mCanvas.setBitmap(to.bitmap);
@@ -266,7 +264,7 @@ public final class TextLayer extends TextureLayer {
@Override
protected void clear() {
- TextureItem.pool.releaseAll(textures);
+ TextureItem.releaseAll(textures);
TextItem.pool.releaseAll(labels);
VertexItem.pool.releaseAll(vertexItems);
textures = null;
diff --git a/src/org/oscim/renderer/layer/TextureItem.java b/src/org/oscim/renderer/layer/TextureItem.java
index 4a9bff02..6372b74b 100644
--- a/src/org/oscim/renderer/layer/TextureItem.java
+++ b/src/org/oscim/renderer/layer/TextureItem.java
@@ -16,6 +16,7 @@ package org.oscim.renderer.layer;
import java.util.ArrayList;
+import org.oscim.utils.GlUtils;
import org.oscim.utils.pool.Inlist;
import org.oscim.utils.pool.SyncPool;
@@ -44,15 +45,30 @@ public class TextureItem extends Inlist {
// temporary Bitmap
public Bitmap bitmap;
+ boolean ownBitmap;
+
TextureItem(int id) {
this.id = id;
}
- public final static SyncPool pool = new SyncPool() {
+ public synchronized static void releaseAll(TextureItem ti) {
+ pool.releaseAll(ti);
+ }
+
+ public synchronized static TextureItem get(boolean initBitmap) {
+ TextureItem ti = pool.get();
+ if (initBitmap) {
+ ti.bitmap = getBitmap();
+ ti.bitmap.eraseColor(Color.TRANSPARENT);
+ }
+ return ti;
+ }
+
+ private final static SyncPool pool = new SyncPool(20) {
@Override
public void init(int num) {
- this.pool = null;
+ super.init(num);
int[] textureIds = new int[num];
GLES20.glGenTextures(num, textureIds, 0);
@@ -60,22 +76,10 @@ public class TextureItem extends Inlist {
for (int i = 1; i < num; i++) {
initTexture(textureIds[i]);
TextureItem to = new TextureItem(textureIds[i]);
-
- to.next = this.pool;
- this.pool = to;
+ pool = Inlist.push(pool, to);
}
}
- @Override
- public TextureItem get() {
- TextureItem it = super.get();
-
- it.bitmap = TextureItem.getBitmap();
- it.bitmap.eraseColor(Color.TRANSPARENT);
-
- return it;
- }
-
@Override
protected TextureItem createItem() {
return new TextureItem(-1);
@@ -83,10 +87,22 @@ public class TextureItem extends Inlist {
@Override
protected void clearItem(TextureItem it) {
- TextureItem.releaseBitmap(it);
+ //Log.d(TAG, it.ownBitmap + " " + (it.bitmap == null));
+ if (it.ownBitmap)
+ return;
+
+ releaseBitmap(it);
+ }
+
+ @Override
+ protected void freeItem(TextureItem it) {
+ it.width = -1;
+ it.height = -1;
+ releaseTexture(it);
}
};
+ private static ArrayList mFreeTextures = new ArrayList();
private static ArrayList mBitmaps = new ArrayList(10);
public final static int TEXTURE_WIDTH = 512;
@@ -94,6 +110,27 @@ public class TextureItem extends Inlist {
private static int mBitmapFormat;
private static int mBitmapType;
+ private static int mTexCnt = 0;
+
+ static void releaseTexture(TextureItem it) {
+ synchronized (mFreeTextures) {
+ if (it.id >= 0) {
+ mFreeTextures.add(Integer.valueOf(it.id));
+ it.id = -1;
+ }
+ }
+ }
+
+ static void releaseBitmap(TextureItem it) {
+ synchronized (mBitmaps) {
+ if (it.bitmap != null) {
+ mBitmaps.add(it.bitmap);
+ it.bitmap = null;
+ }
+ it.ownBitmap = false;
+
+ }
+ }
/**
* This function may only be used in GLRenderer Thread.
@@ -102,23 +139,32 @@ public class TextureItem extends Inlist {
*/
public static void uploadTexture(TextureItem to) {
- if (TextureRenderer.debug)
- Log.d(TAG, "upload texture " + to.id);
+ // free unused textures, find a better place for this TODO
+ synchronized (mFreeTextures) {
+ int size = mFreeTextures.size();
+ int[] tmp = new int[size];
+ for (int i = 0; i < size; i++)
+ tmp[i] = mFreeTextures.get(i).intValue();
+ mFreeTextures.clear();
+ GLES20.glDeleteTextures(size, tmp, 0);
+ }
if (to.id < 0) {
+ mTexCnt++;
int[] textureIds = new int[1];
GLES20.glGenTextures(1, textureIds, 0);
to.id = textureIds[0];
initTexture(to.id);
-
if (TextureRenderer.debug)
- Log.d(TAG, "new texture " + to.id);
+ Log.d(TAG, pool.getCount() + " " + pool.getFill()
+ + " " + mTexCnt + " new texture " + to.id);
}
uploadTexture(to, to.bitmap, mBitmapFormat, mBitmapType,
TEXTURE_WIDTH, TEXTURE_HEIGHT);
- TextureItem.releaseBitmap(to);
+ if (!to.ownBitmap)
+ TextureItem.releaseBitmap(to);
}
public static void uploadTexture(TextureItem to, Bitmap bitmap,
@@ -129,13 +175,21 @@ public class TextureItem extends Inlist {
return;
}
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, to.id);
- if (to.width == w && to.height == h)
+
+ if (to.ownBitmap) {
+ GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
+
+ } else if (to.width == w && to.height == h) {
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, bitmap, format, type);
- else {
+
+ } else {
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, format, bitmap, type, 0);
to.width = w;
to.height = h;
}
+
+ if (TextureRenderer.debug)
+ GlUtils.checkGlError(TAG);
}
static void initTexture(int id) {
@@ -166,6 +220,8 @@ public class TextureItem extends Inlist {
mBitmapFormat = GLUtils.getInternalFormat(mBitmaps.get(0));
mBitmapType = GLUtils.getType(mBitmaps.get(0));
+
+ mTexCnt = num;
}
static Bitmap getBitmap() {
@@ -186,14 +242,4 @@ public class TextureItem extends Inlist {
return mBitmaps.remove(size - 1);
}
}
-
- static void releaseBitmap(TextureItem it) {
- synchronized (mBitmaps) {
-
- if (it.bitmap != null) {
- mBitmaps.add(it.bitmap);
- it.bitmap = null;
- }
- }
- }
}
diff --git a/src/org/oscim/renderer/layer/TextureRenderer.java b/src/org/oscim/renderer/layer/TextureRenderer.java
index 520a3530..c368d796 100644
--- a/src/org/oscim/renderer/layer/TextureRenderer.java
+++ b/src/org/oscim/renderer/layer/TextureRenderer.java
@@ -20,8 +20,8 @@ import static org.oscim.renderer.layer.TextureItem.TEXTURE_HEIGHT;
import static org.oscim.renderer.layer.TextureItem.TEXTURE_WIDTH;
import org.oscim.renderer.GLRenderer;
-import org.oscim.renderer.GLState;
import org.oscim.renderer.GLRenderer.Matrices;
+import org.oscim.renderer.GLState;
import org.oscim.utils.GlUtils;
import android.opengl.GLES20;
@@ -30,6 +30,7 @@ import android.opengl.GLES20;
* @author Hannes Janetzek
*/
public final class TextureRenderer {
+ //private final static String TAG = TextureRenderer.class.getName();
public final static boolean debug = false;
private static int mTextureProgram;
@@ -78,15 +79,15 @@ public final class TextureRenderer {
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, GLRenderer.mQuadIndicesID);
- for (TextureItem to = tl.textures; to != null; to = to.next) {
+ for (TextureItem ti = tl.textures; ti != null; ti = ti.next) {
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, to.id);
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, ti.id);
int maxVertices = GLRenderer.maxQuads * INDICES_PER_SPRITE;
// draw up to maxVertices in each iteration
- for (int i = 0; i < to.vertices; i += maxVertices) {
+ for (int i = 0; i < ti.vertices; i += maxVertices) {
// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
- int off = (to.offset + i) * 8 + tl.offset;
+ int off = (ti.offset + i) * 8 + tl.offset;
GLES20.glVertexAttribPointer(hTextureVertex, 4,
GLES20.GL_SHORT, false, 12, off);
@@ -94,7 +95,7 @@ public final class TextureRenderer {
GLES20.glVertexAttribPointer(hTextureTexCoord, 2,
GLES20.GL_SHORT, false, 12, off + 8);
- int numVertices = to.vertices - i;
+ int numVertices = ti.vertices - i;
if (numVertices > maxVertices)
numVertices = maxVertices;
diff --git a/src/org/oscim/renderer/overlays/TextOverlay.java b/src/org/oscim/renderer/overlays/TextOverlay.java
index f2566c1c..158bde2c 100644
--- a/src/org/oscim/renderer/overlays/TextOverlay.java
+++ b/src/org/oscim/renderer/overlays/TextOverlay.java
@@ -33,7 +33,6 @@ import org.oscim.core.Tile;
import org.oscim.graphics.Color;
import org.oscim.graphics.Paint.Cap;
import org.oscim.layers.tile.MapTile;
-import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileRenderLayer;
import org.oscim.layers.tile.TileSet;
import org.oscim.renderer.BufferObject;
@@ -61,7 +60,7 @@ import android.opengl.GLES20;
import android.os.SystemClock;
public class TextOverlay extends BasicOverlay {
- //private final static String TAG = TextOverlay.class.getName();
+private final static String TAG = TextOverlay.class.getName();
private final static float MIN_CAPTION_DIST = 5;
private final static float MIN_WAY_DIST = 3;
@@ -179,7 +178,7 @@ public class TextOverlay extends BasicOverlay {
mRun = false;
if (updateLabels()) {
- mMapView.redrawMap(true);
+ mMapView.render();
} else {
mRun = true;
}
@@ -695,14 +694,15 @@ public class TextOverlay extends BasicOverlay {
// set new TextLayer to be uploaded and rendered
layers.textureLayers = mNextLayer;
+ mNextLayer = null;
// make the 'labeled' MapPosition current
MapPosition tmp = mMapPosition;
mMapPosition = mTmpPos;
mTmpPos = tmp;
- newData = true;
- mNextLayer = null;
+ this.newData = true;
+
if (!(positionChanged || tilesChanged))
return;
}
diff --git a/src/org/oscim/utils/IOUtils.java b/src/org/oscim/utils/IOUtils.java
new file mode 100644
index 00000000..920db97e
--- /dev/null
+++ b/src/org/oscim/utils/IOUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2010, 2011, 2012 mapsforge.org
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.utils;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A utility class with IO-specific helper methods.
+ */
+public final class IOUtils {
+ private static final Logger LOGGER = Logger.getLogger(IOUtils.class.getName());
+
+ /**
+ * Invokes the {@link Closeable#close()} method on the given object. If an {@link IOException} occurs during the
+ * method call, it will be caught and logged on level {@link Level#WARNING}.
+ *
+ * @param closeable
+ * the data source which should be closed (may be null).
+ */
+ public static void closeQuietly(Closeable closeable) {
+ try {
+ if (closeable != null) {
+ closeable.close();
+ }
+ } catch (IOException e) {
+ LOGGER.log(Level.FINE, e.getMessage(), e);
+ }
+ }
+
+ private IOUtils() {
+ throw new IllegalStateException();
+ }
+}
diff --git a/src/org/oscim/utils/pool/SyncPool.java b/src/org/oscim/utils/pool/SyncPool.java
index b2dcd309..553aad4d 100644
--- a/src/org/oscim/utils/pool/SyncPool.java
+++ b/src/org/oscim/utils/pool/SyncPool.java
@@ -21,26 +21,45 @@ public abstract class SyncPool> {
protected T pool;
- public SyncPool(){
+ public SyncPool() {
maxFill = 100;
+ fill = 0;
+ count = 0;
}
public SyncPool(int maxItemsInPool) {
maxFill = maxItemsInPool;
fill = 0;
+ count = 0;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public int getFill() {
+ return fill;
}
/**
* @param items number of initial items
*/
- public void init(int items){
+ public void init(int items) {
+ count = items;
+ fill = items;
+ }
+
+ /**
+ * @param item set initial state
+ */
+ protected void clearItem(T item) {
}
/**
* @param item release resources
*/
- protected void clearItem(T item) {
+ protected void freeItem(T item) {
}
@@ -59,7 +78,8 @@ public abstract class SyncPool> {
item.next = pool;
pool = item;
}
- } else{
+ } else {
+ freeItem(item);
count--;
}
}
@@ -68,69 +88,36 @@ public abstract class SyncPool> {
if (item == null)
return;
- if (fill > maxFill)
- while (item != null) {
- clearItem(item);
+ if (fill > maxFill) {
+ while (item != null) {
+ clearItem(item);
+ freeItem(item);
+ count--;
- item = item.next;
- count--;
- }
-
- if (item == null)
+ item = item.next;
+ }
return;
+ }
synchronized (this) {
while (item != null) {
T next = item.next;
+
clearItem(item);
+ fill++;
item.next = pool;
pool = item;
- fill++;
item = next;
}
}
}
- // remove 'item' from 'list' and add back to pool
- public T release(T list, T item) {
- if (item == null)
- return list;
-
- T ret = list;
-
- clearItem(item);
-
- if (item == list) {
- ret = item.next;
- } else {
- for (T prev = list, it = list.next; it != null; it = it.next) {
- if (it == item) {
- prev.next = it.next;
- }
- prev = it;
- }
- }
-
- if (fill < maxFill) {
- synchronized (this) {
- fill++;
-
- item.next = pool;
- pool = item;
- }
- } else{
- count--;
- }
-
- return ret;
- }
-
public T get() {
synchronized (this) {
- if (pool == null){
+ if (pool == null) {
count++;
return createItem();
}
diff --git a/src/org/oscim/view/MapView.java b/src/org/oscim/view/MapView.java
index 141eafac..27a8f9ce 100644
--- a/src/org/oscim/view/MapView.java
+++ b/src/org/oscim/view/MapView.java
@@ -23,6 +23,7 @@ import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
import org.oscim.database.MapOptions;
import org.oscim.layers.Layer;
+import org.oscim.layers.tile.BitmapTileLayer;
import org.oscim.layers.tile.MapTileLayer;
import org.oscim.layers.tile.MapTileLoader;
import org.oscim.overlay.BuildingOverlay;
@@ -152,6 +153,18 @@ public class MapView extends RelativeLayout {
return baseLayer;
}
+ public void setBackgroundMap(BitmapTileLayer tileLayer) {
+ mLayerManager.add(0, tileLayer);
+ }
+
+ public MapTileLayer setBaseMap(BitmapTileLayer tileLayer) {
+ mLayerManager.add(0, new MapEventLayer(this));
+ mLayerManager.add(1, tileLayer);
+
+ //mRotationEnabled = true;
+ return null;
+ }
+
void destroy() {
mLayerManager.destroy();
}