diff --git a/vtm-android-example/src/org/oscim/android/test/MarkerOverlayActivity.java b/vtm-android-example/src/org/oscim/android/test/MarkerOverlayActivity.java
index 1bb6187d..4f85160e 100644
--- a/vtm-android-example/src/org/oscim/android/test/MarkerOverlayActivity.java
+++ b/vtm-android-example/src/org/oscim/android/test/MarkerOverlayActivity.java
@@ -36,6 +36,8 @@ import android.widget.Toast;
 public class MarkerOverlayActivity extends BitmapTileMapActivity
 implements OnItemGestureListener<MarkerItem> {
 
+	private MarkerSymbol mFocusMarker;
+
 	public MarkerOverlayActivity() {
 		super(new DefaultSources.StamenToner());
 	}
@@ -47,6 +49,9 @@ implements OnItemGestureListener<MarkerItem> {
 		Drawable d = getResources().getDrawable(R.drawable.marker_poi);
 		MarkerSymbol symbol = AndroidGraphics.makeMarker(d, HotspotPlace.CENTER);
 
+		d = getResources().getDrawable(R.drawable.ic_launcher);
+		mFocusMarker = AndroidGraphics.makeMarker(d, HotspotPlace.BOTTOM_CENTER);
+
 		ItemizedLayer<MarkerItem> markerLayer =
 		        new ItemizedLayer<MarkerItem>(mMap, new ArrayList<MarkerItem>(),
 		                                          symbol, this);
@@ -69,6 +74,11 @@ implements OnItemGestureListener<MarkerItem> {
 
 	@Override
 	public boolean onItemSingleTapUp(int index, MarkerItem item) {
+		if (item.getMarker() == null)
+			item.setMarker(mFocusMarker);
+		else
+			item.setMarker(null);
+
 		Toast toast = Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT);
 		toast.show();
 		return true;
diff --git a/vtm/src/org/oscim/layers/marker/MarkerRenderer.java b/vtm/src/org/oscim/layers/marker/MarkerRenderer.java
index be47fdff..c8f2fbb3 100644
--- a/vtm/src/org/oscim/layers/marker/MarkerRenderer.java
+++ b/vtm/src/org/oscim/layers/marker/MarkerRenderer.java
@@ -17,6 +17,8 @@
 
 package org.oscim.layers.marker;
 
+import java.util.Comparator;
+
 import org.oscim.core.MapPosition;
 import org.oscim.core.MercatorProjection;
 import org.oscim.core.Point;
@@ -25,8 +27,8 @@ import org.oscim.renderer.ElementRenderer;
 import org.oscim.renderer.MapRenderer.Matrices;
 import org.oscim.renderer.elements.SymbolItem;
 import org.oscim.renderer.elements.SymbolLayer;
+import org.oscim.utils.TimSort;
 import org.oscim.utils.geom.GeometryUtils;
-import org.oscim.utils.pool.Inlist;
 
 //TODO
 //- need to sort items back to front for rendering
@@ -43,15 +45,24 @@ public class MarkerRenderer extends ElementRenderer {
 	/** increase view to show items that are partially visible */
 	protected int mExtents = 100;
 	private boolean mUpdate;
-	private InternalItem mItems;
+
+	private InternalItem[] mItems;
+
 	private final Point mMapPoint = new Point();
 
-	static class InternalItem extends Inlist<InternalItem> {
+	static class InternalItem {
 		MarkerItem item;
 		boolean visible;
 		boolean changes;
 		float x, y;
 		double px, py;
+
+		float dy;
+
+		@Override
+		public String toString() {
+			return "\n" + x + ":" + y + " / " + dy + " " + visible;
+		}
 	}
 
 	public MarkerRenderer(MarkerLayer<MarkerItem> markerLayer, MarkerSymbol defaultSymbol) {
@@ -72,8 +83,8 @@ public class MarkerRenderer extends ElementRenderer {
 		double my = pos.y;
 		double scale = Tile.SIZE * pos.scale;
 
-		int changesInvisible = 0;
-		int changedVisible = 0;
+		//int changesInvisible = 0;
+		//int changedVisible = 0;
 		int numVisible = 0;
 
 		mMarkerLayer.map().viewport().getMapExtents(mBox, mExtents);
@@ -88,8 +99,12 @@ public class MarkerRenderer extends ElementRenderer {
 			return;
 		}
 
+		double angle = Math.toRadians(pos.angle);
+		float cos = (float) Math.cos(angle);
+		float sin = (float) Math.sin(angle);
+
 		/* check visibility */
-		for (InternalItem it = mItems; it != null; it = it.next) {
+		for (InternalItem it : mItems) {
 			it.changes = false;
 			it.x = (float) ((it.px - mx) * scale);
 			it.y = (float) ((it.py - my) * scale);
@@ -102,13 +117,16 @@ public class MarkerRenderer extends ElementRenderer {
 			if (!GeometryUtils.pointInPoly(it.x, it.y, mBox, 8, 0)) {
 				if (it.visible) {
 					it.changes = true;
-					changesInvisible++;
+					//changesInvisible++;
 				}
 				continue;
 			}
+
+			it.dy = sin * it.x + cos * it.y;
+
 			if (!it.visible) {
 				it.visible = true;
-				changedVisible++;
+				//changedVisible++;
 			}
 			numVisible++;
 		}
@@ -117,15 +135,21 @@ public class MarkerRenderer extends ElementRenderer {
 
 		/* only update when zoomlevel changed, new items are visible
 		 * or more than 10 of the current items became invisible */
-		if ((numVisible == 0) && (changedVisible == 0 && changesInvisible < 10))
-			return;
-
-		/* keep position for current state */
-		mMapPosition.copy(pos);
-
+		//if ((numVisible == 0) && (changedVisible == 0 && changesInvisible < 10))
+		//	return;
 		layers.clear();
 
-		for (InternalItem it = mItems; it != null; it = it.next) {
+		if (numVisible == 0) {
+			compile();
+			return;
+		}
+		/* keep position for current state */
+		mMapPosition.copy(pos);
+		mMapPosition.angle = -mMapPosition.angle;
+
+		sort(mItems, 0, mItems.length);
+		//log.debug(Arrays.toString(mItems));
+		for (InternalItem it : mItems) {
 			if (!it.visible)
 				continue;
 
@@ -139,14 +163,9 @@ public class MarkerRenderer extends ElementRenderer {
 				marker = mDefaultMarker;
 
 			SymbolItem s = SymbolItem.pool.get();
-			s.bitmap = marker.getBitmap();
-
-			s.x = it.x;
-			s.y = it.y;
+			s.set(it.x, it.y, marker.getBitmap(), true);
 			s.offset = marker.getHotspot();
-			s.billboard = true;
-
-			mSymbolLayer.addSymbol(s);
+			mSymbolLayer.pushSymbol(s);
 		}
 
 		mSymbolLayer.prepare();
@@ -155,29 +174,13 @@ public class MarkerRenderer extends ElementRenderer {
 		compile();
 	}
 
-	@Override
-	public synchronized void compile() {
-		super.compile();
-	}
+	protected void populate(int size) {
 
-	protected synchronized void populate(int size) {
-
-		InternalItem pool = mItems;
-		mItems = null;
+		InternalItem[] tmp = new InternalItem[size];
 
 		for (int i = 0; i < size; i++) {
-			InternalItem it;
-			if (pool != null) {
-				it = pool;
-				it.visible = false;
-				it.changes = false;
-				pool = pool.next;
-			} else {
-				it = new InternalItem();
-			}
-			it.next = mItems;
-			mItems = it;
-
+			InternalItem it = new InternalItem();
+			tmp[i] = it;
 			it.item = mMarkerLayer.createItem(i);
 
 			/* pre-project points */
@@ -185,6 +188,44 @@ public class MarkerRenderer extends ElementRenderer {
 			it.px = mMapPoint.x;
 			it.py = mMapPoint.y;
 		}
+		synchronized (this) {
+			mUpdate = true;
+			mItems = tmp;
+		}
+	}
+
+	static TimSort<InternalItem> ZSORT = new TimSort<InternalItem>();
+
+	public static void sort(InternalItem[] a, int lo, int hi) {
+		int nRemaining = hi - lo;
+		if (nRemaining < 2) {
+			return;
+		}
+
+		ZSORT.doSort(a, zComparator, lo, hi);
+	}
+
+	final static Comparator<InternalItem> zComparator = new Comparator<InternalItem>() {
+		@Override
+		public int compare(InternalItem a, InternalItem b) {
+			if (a.visible && b.visible) {
+				if (a.dy > b.dy) {
+					return -1;
+				}
+				if (a.dy < b.dy) {
+					return 1;
+				}
+			} else if (a.visible) {
+				return -1;
+			} else if (b.visible) {
+				return 1;
+			}
+
+			return 0;
+		}
+	};
+
+	public void update() {
 		mUpdate = true;
 	}
 
diff --git a/vtm/src/org/oscim/renderer/ElementRenderer.java b/vtm/src/org/oscim/renderer/ElementRenderer.java
index b8ce4c9f..27650c68 100644
--- a/vtm/src/org/oscim/renderer/ElementRenderer.java
+++ b/vtm/src/org/oscim/renderer/ElementRenderer.java
@@ -47,7 +47,7 @@ import org.slf4j.LoggerFactory;
  */
 public abstract class ElementRenderer extends LayerRenderer {
 
-	static final Logger log = LoggerFactory.getLogger(ElementRenderer.class);
+	public static final Logger log = LoggerFactory.getLogger(ElementRenderer.class);
 
 	private static short[] fillCoords;
 
diff --git a/vtm/src/org/oscim/renderer/elements/SymbolLayer.java b/vtm/src/org/oscim/renderer/elements/SymbolLayer.java
index 85ae1803..7e5201c5 100644
--- a/vtm/src/org/oscim/renderer/elements/SymbolLayer.java
+++ b/vtm/src/org/oscim/renderer/elements/SymbolLayer.java
@@ -33,35 +33,42 @@ public final class SymbolLayer extends TextureLayer {
 	private final static int LBIT_MASK = 0xfffffffe;
 
 	private TextureItem prevTextures;
-	private SymbolItem symbols;
+	private List<SymbolItem> mSymbols = new List<SymbolItem>();
 
 	public SymbolLayer() {
 		super(RenderElement.SYMBOL);
 		fixed = true;
 	}
 
-	// TODO move sorting items to 'prepare'
+	/* TODO move sorting items to 'prepare' */
 	public void addSymbol(SymbolItem item) {
 
-		// needed to calculate 'sbuf' size for compile
+		/* needed to calculate 'sbuf' size for compile */
 		numVertices += VERTICES_PER_SPRITE;
 
-		for (SymbolItem it = symbols; it != null; it = it.next) {
+		for (SymbolItem it : mSymbols) {
 			if (it.bitmap == item.bitmap) {
-				// insert after same bitmap
+				/* insert after same bitmap */
 				item.next = it.next;
 				it.next = item;
 				return;
 			}
 		}
+		mSymbols.push(item);
 
-		item.next = symbols;
-		symbols = item;
+		//item.next = mSymbols;
+		//mSymbols = item;
+	}
+
+	public void pushSymbol(SymbolItem item) {
+		/* needed to calculate 'sbuf' size for compile */
+		numVertices += VERTICES_PER_SPRITE;
+		mSymbols.push(item);
 	}
 
 	@Override
 	protected void compile(ShortBuffer sbuf) {
-		// offset of layer data in vbo
+		/* offset of layer data in vbo */
 		this.offset = sbuf.position() * 2; //SHORT_BYTES;
 
 		short numIndices = 0;
@@ -75,18 +82,17 @@ public final class SymbolLayer extends TextureLayer {
 		textures = null;
 		TextureItem t = null;
 
-		for (SymbolItem it = symbols; it != null;) {
+		for (SymbolItem it = mSymbols.getHead(); it != null;) {
 			int width = 0, height = 0;
 			int x = 0;
 			int y = 0;
 
 			if (it.texRegion != null) {
-
-				// FIXME this work only with one TextureAtlas per SymbolLayer.
+				/* FIXME this work only with one TextureAtlas per SymbolLayer */
 				if (textures == null) {
 					t = it.texRegion.atlas.loadTexture();
-					// clone TextureItem to use same texID with
-					// multiple TextureItem
+					/* clone TextureItem to use same texID with
+					 * multiple TextureItem */
 					t = TextureItem.clone(t);
 					textures = Inlist.appendItem(textures, t);
 				}
@@ -124,7 +130,7 @@ public final class SymbolLayer extends TextureLayer {
 			PointF prevOffset = null;
 			short x1 = 0, y1 = 0, x2 = 0, y2 = 0;
 
-			// add symbol items referencing the same bitmap /
+			/* add symbol items referencing the same bitmap */
 			for (SymbolItem prev = it; it != null; it = it.next) {
 
 				if (prev.bitmap != null && prev.bitmap != it.bitmap)
@@ -153,7 +159,7 @@ public final class SymbolLayer extends TextureLayer {
 					}
 				}
 
-				// add vertices
+				/* add vertices */
 				short tx = (short) ((int) (SCALE * it.x) & LBIT_MASK
 				        | (it.billboard ? 1 : 0));
 
@@ -169,7 +175,7 @@ public final class SymbolLayer extends TextureLayer {
 
 				pos += TextLayer.VERTICES_PER_SPRITE * 6;
 
-				// six elements used to draw the four vertices
+				/* six elements used to draw the four vertices */
 				t.vertices += TextureLayer.INDICES_PER_SPRITE;
 			}
 			numIndices += t.vertices;
@@ -201,19 +207,13 @@ public final class SymbolLayer extends TextureLayer {
 	}
 
 	public void clearItems() {
-		symbols = SymbolItem.pool.releaseAll(symbols);
-		//numVertices = 0;
+		SymbolItem.pool.releaseAll(mSymbols.clear());
 	}
 
 	@Override
 	public void clear() {
-		// release textures
 		super.clear();
 		clearItems();
-
-		//symbols = SymbolItem.pool.releaseAll(symbols);
-		//vertexItems = VertexItem.pool.releaseAll(vertexItems);
-		//numVertices = 0;
 	}
 
 	@Override
diff --git a/vtm/src/org/oscim/renderer/elements/TextureLayer.java b/vtm/src/org/oscim/renderer/elements/TextureLayer.java
index 225c71f7..e0aef4b9 100644
--- a/vtm/src/org/oscim/renderer/elements/TextureLayer.java
+++ b/vtm/src/org/oscim/renderer/elements/TextureLayer.java
@@ -26,9 +26,13 @@ import org.oscim.renderer.GLUtils;
 import org.oscim.renderer.MapRenderer;
 import org.oscim.renderer.MapRenderer.Matrices;
 import org.oscim.renderer.elements.TextureItem.TexturePool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class TextureLayer extends RenderElement {
 
+	static final Logger log = LoggerFactory.getLogger(TextureLayer.class);
+
 	public final static int INDICES_PER_SPRITE = 6;
 	final static int VERTICES_PER_SPRITE = 4;
 	final static int SHORTS_PER_VERTICE = 6;
@@ -58,7 +62,7 @@ public abstract class TextureLayer extends RenderElement {
 		for (TextureItem t = textures; t != null; t = t.next)
 			t.upload();
 
-		// add vertices to vbo
+		/* add vertices to vbo */
 		ElementLayers.addPoolItems(this, sbuf);
 	}
 
@@ -79,28 +83,28 @@ public abstract class TextureLayer extends RenderElement {
 	        short u1, short v1,
 	        short u2, short v2) {
 
-		// top-left
+		/* top-left */
 		buf[pos + 0] = tx;
 		buf[pos + 1] = ty;
 		buf[pos + 2] = x1;
 		buf[pos + 3] = y1;
 		buf[pos + 4] = u1;
 		buf[pos + 5] = v2;
-		// bot-left
+		/* bot-left */
 		buf[pos + 6] = tx;
 		buf[pos + 7] = ty;
 		buf[pos + 8] = x1;
 		buf[pos + 9] = y2;
 		buf[pos + 10] = u1;
 		buf[pos + 11] = v1;
-		// top-right
+		/* top-right */
 		buf[pos + 12] = tx;
 		buf[pos + 13] = ty;
 		buf[pos + 14] = x2;
 		buf[pos + 15] = y1;
 		buf[pos + 16] = u2;
 		buf[pos + 17] = v2;
-		// bot-right
+		/* bot-right */
 		buf[pos + 18] = tx;
 		buf[pos + 19] = ty;
 		buf[pos + 20] = x2;
@@ -110,7 +114,6 @@ public abstract class TextureLayer extends RenderElement {
 	}
 
 	public static final class Renderer {
-		//static final Logger log = LoggerFactory.getLogger(TextureRenderer.class);
 
 		public final static boolean debug = false;
 
@@ -124,7 +127,6 @@ public abstract class TextureLayer extends RenderElement {
 		private static int hTextureSize;
 
 		static void init() {
-
 			mTextureProgram = GLUtils.createProgram(textVertexShader,
 			                                        textFragmentShader);
 
@@ -136,7 +138,7 @@ public abstract class TextureLayer extends RenderElement {
 			hTextureVertex = GL.glGetAttribLocation(mTextureProgram, "vertex");
 			hTextureTexCoord = GL.glGetAttribLocation(mTextureProgram, "tex_coord");
 
-			// FIXME pool should be disposed on exit...
+			/* FIXME pool should be disposed on exit... */
 			pool.init(0);
 		}
 
@@ -171,9 +173,10 @@ public abstract class TextureLayer extends RenderElement {
 
 				int maxVertices = MapRenderer.maxQuads * INDICES_PER_SPRITE;
 
-				// draw up to maxVertices in each iteration
+				/* draw up to maxVertices in each iteration */
 				for (int i = 0; i < t.vertices; i += maxVertices) {
-					// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
+					/* to.offset * (24(shorts) * 2(short-bytes)
+					 * / 6(indices) == 8) */
 					int off = (t.offset + i) * 8 + tl.offset;
 
 					GL.glVertexAttribPointer(hTextureVertex, 4,
diff --git a/vtm/src/org/oscim/utils/pool/Inlist.java b/vtm/src/org/oscim/utils/pool/Inlist.java
index d88466e4..020b67fd 100644
--- a/vtm/src/org/oscim/utils/pool/Inlist.java
+++ b/vtm/src/org/oscim/utils/pool/Inlist.java
@@ -80,6 +80,10 @@ public class Inlist<T extends Inlist<T>> {
 			cur = null;
 			return ret;
 		}
+
+		public T getHead() {
+			return head;
+		}
 	}
 
 	public T next;