package dk.network42.osmfocus; import android.content.ComponentCallbacks2; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.RectF; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.support.v4.util.LruCache; import android.util.Log; import android.view.View; public abstract class OsmTileLayer extends MapLayer { private static final String TAG = "OsmTileLayer"; TileLruCache mTiles; OsmTileProvider mProvider; //View mView; Handler mHandler; Handler mMainHandler=null; String mAttrib=null; int mLastZoom = -1; public OsmTileLayer(OsmTileProvider provider, int maxCacheSize) { mProvider = provider; mTiles = new TileLruCache(maxCacheSize); mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message inputMessage) { //OsmTile t = (OsmTile) inputMessage.obj; switch (inputMessage.what) { case OsmTileProvider.TASK_DOWNLOAD_START: case OsmTileProvider.TASK_DOWNLOAD_COMPLETE: //Log.d(TAG, "Got download complete, tile"+t+" tile cache size="+mTiles.size()); if (mMainHandler != null) mMainHandler.obtainMessage(MainActivity.INVALIDATE_VIEW, this).sendToTarget(); break; } } }; } static String urlFromType(int type) { if (type==MapLayer.MAPTYPE_OSM) { return "https://a.tile.openstreetmap.org"; } else if (type==MapLayer.MAPTYPE_OSMCYCLEMAP) { return "http://a.tile.opencyclemap.org/cycle"; } return ""; } public void setMainHandler(Handler handler) { mMainHandler = handler; } public void draw(Canvas canvas, RectF worldport, PaintConfig pcfg) { for (int ii=0; ii=vrect.left && xt <= vrect.right && yt >= vrect.top && yt <= vrect.bottom) drawTile(canvas, pcfg, xt, yt, zoom, layer); } for (yt=cy-(cc-1); yt<=cy+cc-1; yt++) { xt = cx+cc; //Log.d(TAG, "2: "+xt+","+yt); if (xt>=vrect.left && xt <= vrect.right && yt >= vrect.top && yt <= vrect.bottom) drawTile(canvas, pcfg, xt, yt, zoom, layer); } for (xt=cx+cc; xt>=cx-cc; xt--) { yt = cy+cc; //Log.d(TAG, "3: "+xt+","+yt); if (xt>=vrect.left && xt <= vrect.right && yt >= vrect.top && yt <= vrect.bottom) drawTile(canvas, pcfg, xt, yt, zoom, layer); } for (yt=cy+cc-1; yt>=cy-(cc-1); yt--) { xt = cx-cc; //Log.d(TAG, "4: "+xt+","+yt); if (xt>=vrect.left && xt <= vrect.right && yt >= vrect.top && yt <= vrect.bottom) drawTile(canvas, pcfg, xt, yt, zoom, layer); } } //Log.d(TAG, "Tile layer draw finished "); } public void drawLegends(Canvas canvas, RectF viewrect, PaintConfig pcfg) { if (mAttrib != null) { canvas.drawText(mAttrib, viewrect.centerX()-pcfg.attrib.measureText(mAttrib)/2, viewrect.centerY()+viewrect.height()*0.4f, pcfg.attrib); } } protected abstract String getTileId(int xt, int yt, int zoom); protected abstract OsmTile createTile(int xt, int yt, int zoom); protected abstract void handleMissingTile(OsmTile t, int layer); protected void drawTile(Canvas canvas, PaintConfig pcfg, int xt, int yt, int zoom, int layer) { //Log.d(TAG, "Draw tile: "+xt+","+yt+" zoom="+zoom); String tid = getTileId(xt, yt, zoom); OsmTile t = mTiles.get(tid); if (t == null) { t = createTile(xt, yt, zoom); mTiles.put(tid, t); //Log.d(TAG, "New tile, TID="+tid+" LruCache size="+mTiles.size()); handleMissingTile(t, layer); t.drawX(canvas, pcfg); } else { if (! t.draw(canvas, pcfg)) { t.drawX(canvas, pcfg); } } } // private void drawTileCoords(Canvas canvas, PaintConfig pcfg, OsmTile t) { // String st = ""; // st.format("%d,%d,%d", t.mX, t.mY, t.mZoom); // t.drawText(canvas, pcfg.paint, st); // } protected abstract void downloadTile(OsmTile t); protected int getZoom(PaintConfig pcfg) { return view2OsmZoom(pcfg.mScale); } // Convert from internal view scale value to OSM zoom levels protected int view2OsmZoom(float scale) { int zoom = (int) (16+(1.0+Math.log((double)scale)/Math.log(2.0))); if (zoom > OsmTile.MAX_ZOOM) zoom = OsmTile.MAX_ZOOM; //Log.d(TAG, "Scale="+scale+" OsmZoom="+zoom); return zoom; } public void onTrimMemory(int level) { if (level == ComponentCallbacks2.TRIM_MEMORY_MODERATE) { mTiles.trimToSize(mTiles.maxSize()/2); } else if (level == ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { mTiles.trimToSize(0); } } public int getMemorySize() { return mTiles.size(); } public void flushCache() { mTiles.evictAll(); } protected int getNumLayers() { return 1; } // Attribute, like OSM data attribution public void setAttrib(String attrib) { mAttrib = attrib; } protected class TileLruCache extends LruCache { public TileLruCache(int maxSize) { super(maxSize); } protected int sizeOf(String k, OsmTile v) { return v.getByteSize(); } }; }