Improve rendering speed of sqlite files
This commit is contained in:
parent
2895882d8c
commit
d539e31c20
5 changed files with 152 additions and 201 deletions
|
@ -21,19 +21,14 @@ import org.apache.commons.logging.Log;
|
|||
|
||||
import android.database.sqlite.SQLiteDiskIOException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
||||
|
||||
public class SQLiteTileSource implements ITileSource {
|
||||
|
||||
|
||||
public static final String EXT = IndexConstants.SQLITE_EXT;
|
||||
private static final Log log = PlatformUtil.getLog(SQLiteTileSource.class);
|
||||
private static final Log log = PlatformUtil.getLog(SQLiteTileSource.class);
|
||||
|
||||
private ITileSource base;
|
||||
private String urlTemplate = null;
|
||||
|
@ -42,15 +37,15 @@ public class SQLiteTileSource implements ITileSource {
|
|||
private final File file;
|
||||
private int minZoom = 1;
|
||||
private int maxZoom = 17;
|
||||
private int baseZoom = 17; //Default base zoom
|
||||
private boolean inversiveZoom = true; // BigPlanet
|
||||
private boolean timeSupported = false;
|
||||
private int expirationTimeMillis = -1; // never
|
||||
|
||||
static final int margin = 1;
|
||||
static final int tileSize = 256;
|
||||
static final int minScaledSize = 8;
|
||||
private ClientContext ctx;
|
||||
|
||||
|
||||
|
||||
public SQLiteTileSource(ClientContext ctx, File f, List<TileSourceTemplate> toFindUrl){
|
||||
this.ctx = ctx;
|
||||
this.file = f;
|
||||
|
@ -106,7 +101,7 @@ public class SQLiteTileSource implements ITileSource {
|
|||
|
||||
@Override
|
||||
public String getUrlToLoad(int x, int y, int zoom) {
|
||||
if (zoom > baseZoom)
|
||||
if (zoom > maxZoom)
|
||||
return null;
|
||||
SQLiteConnection db = getDatabase();
|
||||
if(db == null || db.isReadOnly() || urlTemplate == null){
|
||||
|
@ -175,6 +170,16 @@ public class SQLiteTileSource implements ITileSource {
|
|||
timeSupported = hasTimeColumn();
|
||||
addInfoColumn("timecolumn", timeSupported?"yes" : "no");
|
||||
}
|
||||
int expireminutes = list.indexOf("expireminutes");
|
||||
this.expirationTimeMillis = -1;
|
||||
if(expireminutes != -1) {
|
||||
int minutes = (int) cursor.getInt(expireminutes);
|
||||
if(minutes > 0) {
|
||||
this.expirationTimeMillis = minutes * 60 * 1000;
|
||||
}
|
||||
} else {
|
||||
addInfoColumn("expireminutes", "0");
|
||||
}
|
||||
//boolean inversiveInfoZoom = tnumbering != -1 && "BigPlanet".equals(cursor.getString(tnumbering));
|
||||
boolean inversiveInfoZoom = inversiveZoom;
|
||||
int mnz = list.indexOf("minzoom");
|
||||
|
@ -183,20 +188,15 @@ public class SQLiteTileSource implements ITileSource {
|
|||
}
|
||||
int mxz = list.indexOf("maxzoom");
|
||||
if(mxz != -1) {
|
||||
baseZoom = (int) cursor.getInt(mxz);
|
||||
maxZoom = (int) cursor.getInt(mxz);
|
||||
}
|
||||
if(inversiveInfoZoom) {
|
||||
mnz = minZoom;
|
||||
minZoom = 17 - baseZoom;
|
||||
baseZoom = 17 - mnz;
|
||||
minZoom = 17 - maxZoom;
|
||||
maxZoom = 17 - mnz;
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
maxZoom = 24; // Cheat to have tiles request even if zoom level not in sqlite
|
||||
// decrease maxZoom if too much scaling would be required
|
||||
while ((tileSize >> (maxZoom - baseZoom)) < minScaledSize)
|
||||
maxZoom--;
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -219,40 +219,27 @@ public class SQLiteTileSource implements ITileSource {
|
|||
return timeSupported;
|
||||
}
|
||||
|
||||
public boolean exists(int x, int y, int zoom, boolean exact) {
|
||||
public boolean exists(int x, int y, int zoom) {
|
||||
SQLiteConnection db = getDatabase();
|
||||
if(db == null){
|
||||
if (db == null) {
|
||||
return false;
|
||||
}
|
||||
long time = System.currentTimeMillis();
|
||||
if (exact || zoom <= baseZoom) {
|
||||
try {
|
||||
int z = getFileZoom(zoom);
|
||||
SQLiteCursor cursor = db.rawQuery("SELECT 1 FROM tiles WHERE x = ? AND y = ? AND z = ?", new String[] {x+"", y+"",z+""}); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
SQLiteCursor cursor = db.rawQuery(
|
||||
"SELECT 1 FROM tiles WHERE x = ? AND y = ? AND z = ?", new String[] { x + "", y + "", z + "" }); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
try {
|
||||
boolean e = cursor.moveToFirst();
|
||||
cursor.close();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Checking tile existance x = " + x + " y = " + y + " z = " + zoom + " for " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
|
||||
return e;
|
||||
} catch (SQLiteDiskIOException e) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
int n = zoom - baseZoom;
|
||||
int base_xtile = x >> n;
|
||||
int base_ytile = y >> n;
|
||||
int z = getFileZoom(baseZoom);
|
||||
SQLiteCursor cursor = db.rawQuery("SELECT 1 FROM tiles WHERE x = ? AND y = ? AND z = ?", new String[] {base_xtile+"", base_ytile+"",z+""}); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
try {
|
||||
boolean e = cursor.moveToFirst();
|
||||
cursor.close();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Checking parent tile existance x = " + base_xtile + " y = " + base_ytile + " z = " + baseZoom + " for " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
return e;
|
||||
} catch (SQLiteDiskIOException e) {
|
||||
return false;
|
||||
} finally {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Checking tile existance x = " + x + " y = " + y + " z = " + zoom + " for " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,113 +252,43 @@ public class SQLiteTileSource implements ITileSource {
|
|||
return db.isDbLockedByOtherThreads();
|
||||
}
|
||||
|
||||
private Bitmap getMetaTile(int x, int y, int zoom, int flags) {
|
||||
// return a (tileSize+2*margin)^2 tile around a given tile
|
||||
// based on its neighbor. This is needed to have a nice bilinear resampling
|
||||
// on tile edges. Margin of 1 is enough for bilinear resampling.
|
||||
|
||||
public Bitmap getImage(int x, int y, int zoom, long[] timeHolder) {
|
||||
SQLiteConnection db = getDatabase();
|
||||
if(db == null){
|
||||
return null;
|
||||
}
|
||||
|
||||
Bitmap stitchedImage = Bitmap.createBitmap(tileSize + 2 * margin, tileSize + 2 * margin, Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(stitchedImage);
|
||||
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
if ((flags & (0x400 >> (4 * (dy + 1) + (dx + 1)))) == 0)
|
||||
continue;
|
||||
|
||||
|
||||
int xOff, yOff, w, h;
|
||||
int dstx, dsty;
|
||||
SQLiteCursor cursor = db.rawQuery(
|
||||
"SELECT image FROM tiles WHERE x = ? AND y = ? AND z = ?",
|
||||
new String[] {(x + dx) + "", (y + dy) + "", getFileZoom(zoom) + ""}); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
long ts = System.currentTimeMillis();
|
||||
try {
|
||||
if (zoom <= maxZoom) {
|
||||
// return the normal tile if exists
|
||||
String[] params = new String[] { x + "", y + "", getFileZoom(zoom) + "" };
|
||||
boolean queryTime = timeHolder != null && timeHolder.length > 0 && timeSupported;
|
||||
SQLiteCursor cursor = db.rawQuery("SELECT image " +(queryTime?", time":"")+" FROM tiles WHERE x = ? AND y = ? AND z = ?",
|
||||
params); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
byte[] blob = null;
|
||||
if(cursor.moveToFirst()) {
|
||||
if (cursor.moveToFirst()) {
|
||||
blob = cursor.getBlob(0);
|
||||
if(queryTime) {
|
||||
timeHolder[0] = cursor.getLong(1);
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
if (dx < 0) xOff = tileSize - margin; else xOff = 0;
|
||||
if (dx == 0) w = tileSize; else w = margin;
|
||||
if (dy < 0) yOff = tileSize - margin; else yOff = 0;
|
||||
if (dy == 0) h = tileSize; else h = margin;
|
||||
dstx = dx * tileSize + xOff + margin;
|
||||
dsty = dy * tileSize + yOff + margin;
|
||||
if(blob != null){
|
||||
|
||||
Bitmap Tile = BitmapFactory.decodeByteArray(blob, 0, blob.length);
|
||||
blob = null;
|
||||
Rect src = new Rect(xOff, yOff, xOff + w, yOff + h);
|
||||
Rect dst = new Rect(dstx, dsty, dstx + w, dsty + h);
|
||||
canvas.drawBitmap(Tile, src, dst, null);
|
||||
Tile.recycle();
|
||||
if (blob != null) {
|
||||
Bitmap bmp = null;
|
||||
bmp = BitmapFactory.decodeByteArray(blob, 0, blob.length);
|
||||
if(bmp == null) {
|
||||
// broken image delete it
|
||||
db.execSQL("DELETE FROM tiles WHERE x = ? AND y = ? AND z = ?", params);
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return stitchedImage; // return a tileSize+2*margin size image
|
||||
|
||||
}
|
||||
|
||||
public Bitmap getImage(int x, int y, int zoom) {
|
||||
SQLiteConnection db = getDatabase();
|
||||
if(db == null){
|
||||
return null;
|
||||
}
|
||||
if (zoom <= baseZoom) {
|
||||
// return the normal tile if exists
|
||||
SQLiteCursor cursor = db.rawQuery("SELECT image FROM tiles WHERE x = ? AND y = ? AND z = ?",
|
||||
new String[] {x+"", y+"", getFileZoom(zoom)+""}); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
byte[] blob = null;
|
||||
if(cursor.moveToFirst()) {
|
||||
blob = cursor.getBlob(0);
|
||||
} finally {
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug("Load tile " + x + "/" + y + "/" + zoom + " for " + (System.currentTimeMillis() - ts)
|
||||
+ " ms ");
|
||||
}
|
||||
cursor.close();
|
||||
if(blob != null){
|
||||
return BitmapFactory.decodeByteArray(blob, 0, blob.length);
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
// return a resampled tile from its last parent
|
||||
int n = zoom - baseZoom;
|
||||
int base_xtile = x >> n;
|
||||
int base_ytile = y >> n;
|
||||
|
||||
int scaledSize= tileSize >> n;
|
||||
int offset_x= x - (base_xtile << n);
|
||||
int offset_y= y - (base_ytile << n);
|
||||
int flags = 0x020;
|
||||
|
||||
if (scaledSize < minScaledSize)
|
||||
return null;
|
||||
|
||||
if (offset_x == 0)
|
||||
flags |= 0x444;
|
||||
else if (offset_x == (1 << n) - 1)
|
||||
flags |= 0x111;
|
||||
if (offset_y == 0)
|
||||
flags |= 0x700;
|
||||
else if (offset_y == (1 << n) - 1)
|
||||
flags |= 0x007;
|
||||
|
||||
Bitmap metaTile = getMetaTile(base_xtile, base_ytile, baseZoom, flags);
|
||||
|
||||
if(metaTile != null){
|
||||
// in tile space:
|
||||
int delta_px = scaledSize * offset_x;
|
||||
int delta_py = scaledSize * offset_y;
|
||||
|
||||
RectF src = new RectF(0.5f, 0.5f,
|
||||
scaledSize + 2 * margin - 0.5f, scaledSize + 2 * margin - 0.5f);
|
||||
RectF dest = new RectF(0, 0, tileSize, tileSize);
|
||||
Matrix m = new Matrix();
|
||||
m.setRectToRect(src, dest, Matrix.ScaleToFit.FILL);
|
||||
return Bitmap.createBitmap(metaTile, delta_px, delta_py,
|
||||
scaledSize + 2*margin-1, scaledSize + 2*margin-1, m, true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,7 +342,7 @@ public class SQLiteTileSource implements ITileSource {
|
|||
if (db == null || db.isReadOnly()) {
|
||||
return;
|
||||
}
|
||||
if (exists(x, y, zoom, true)) {
|
||||
if (exists(x, y, zoom)) {
|
||||
return;
|
||||
}
|
||||
ByteBuffer buf = ByteBuffer.allocate((int) fileToSave.length());
|
||||
|
@ -437,15 +354,15 @@ public class SQLiteTileSource implements ITileSource {
|
|||
}
|
||||
|
||||
|
||||
String query = timeSupported? "INSERT INTO tiles(x,y,z,s,image,time) VALUES(?, ?, ?, ?, ?, ?)" :
|
||||
"INSERT INTO tiles(x,y,z,s,image) VALUES(?, ?, ?, ?, ?)";
|
||||
String query = timeSupported ? "INSERT INTO tiles(x,y,z,s,image,time) VALUES(?, ?, ?, ?, ?, ?)"
|
||||
: "INSERT INTO tiles(x,y,z,s,image) VALUES(?, ?, ?, ?, ?)";
|
||||
net.osmand.plus.api.SQLiteAPI.SQLiteStatement statement = db.compileStatement(query); //$NON-NLS-1$
|
||||
statement.bindLong(1, x);
|
||||
statement.bindLong(2, y);
|
||||
statement.bindLong(3, getFileZoom(zoom));
|
||||
statement.bindLong(4, 0);
|
||||
statement.bindBlob(5, buf.array());
|
||||
if(timeSupported) {
|
||||
if (timeSupported) {
|
||||
statement.bindLong(6, System.currentTimeMillis());
|
||||
}
|
||||
statement.execute();
|
||||
|
@ -478,15 +395,17 @@ public class SQLiteTileSource implements ITileSource {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getExpirationTimeMillis() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getExpirationTimeMinutes() {
|
||||
return -1;
|
||||
if(expirationTimeMillis < 0) {
|
||||
return -1;
|
||||
}
|
||||
return expirationTimeMillis / (60 * 1000);
|
||||
}
|
||||
|
||||
public int getExpirationTimeMillis() {
|
||||
return expirationTimeMillis;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ public class DownloadTilesDialog {
|
|||
for (int x = x1; x <= x2 && !cancel; x++) {
|
||||
for (int y = y1; y <= y2 && !cancel; y++) {
|
||||
String tileId = rm.calculateTileId(map, x, y, z);
|
||||
if (rm.tileExistOnFileSystem(tileId, map, x, y, z, true)) {
|
||||
if (rm.tileExistOnFileSystem(tileId, map, x, y, z)) {
|
||||
progressDlg.setProgress(progressDlg.getProgress() + 1);
|
||||
} else {
|
||||
rm.getTileImageForMapSync(tileId, map, x, y, z, true);
|
||||
|
|
|
@ -207,6 +207,10 @@ public class ResourceManager {
|
|||
return cacheOfImages.get(file);
|
||||
}
|
||||
|
||||
public void putTileInTheCache(String file, Bitmap bmp) {
|
||||
cacheOfImages.put(file, bmp);
|
||||
}
|
||||
|
||||
|
||||
public Bitmap getTileImageForMapSync(String file, ITileSource map, int x, int y, int zoom, boolean loadFromInternetIfNeeded) {
|
||||
return getTileImageForMap(file, map, x, y, zoom, loadFromInternetIfNeeded, true, true);
|
||||
|
@ -236,14 +240,14 @@ public class ResourceManager {
|
|||
|
||||
}
|
||||
|
||||
public synchronized boolean tileExistOnFileSystem(String file, ITileSource map, int x, int y, int zoom, boolean exact){
|
||||
public synchronized boolean tileExistOnFileSystem(String file, ITileSource map, int x, int y, int zoom){
|
||||
if(!imagesOnFS.containsKey(file)){
|
||||
boolean ex = false;
|
||||
if(map instanceof SQLiteTileSource){
|
||||
if(((SQLiteTileSource) map).isLocked()){
|
||||
return false;
|
||||
}
|
||||
ex = ((SQLiteTileSource) map).exists(x, y, zoom, exact);
|
||||
ex = ((SQLiteTileSource) map).exists(x, y, zoom);
|
||||
} else {
|
||||
if(file == null){
|
||||
file = calculateTileId(map, x, y, zoom);
|
||||
|
@ -256,7 +260,7 @@ public class ResourceManager {
|
|||
imagesOnFS.put(file, null);
|
||||
}
|
||||
}
|
||||
return imagesOnFS.get(file) != null;
|
||||
return imagesOnFS.get(file) != null || cacheOfImages.get(file) != null;
|
||||
}
|
||||
|
||||
public void clearTileImageForMap(String file, ITileSource map, int x, int y, int zoom){
|
||||
|
@ -320,7 +324,7 @@ public class ResourceManager {
|
|||
|
||||
if (loadFromFs && cacheOfImages.get(tileId) == null && map != null) {
|
||||
boolean locked = map instanceof SQLiteTileSource && ((SQLiteTileSource) map).isLocked();
|
||||
if(!loadFromInternetIfNeeded && !locked && !tileExistOnFileSystem(tileId, map, x, y, zoom, false)){
|
||||
if(!loadFromInternetIfNeeded && !locked && !tileExistOnFileSystem(tileId, map, x, y, zoom)){
|
||||
return null;
|
||||
}
|
||||
String url = loadFromInternetIfNeeded ? map.getUrlToLoad(x, y, zoom) : null;
|
||||
|
@ -364,11 +368,14 @@ public class ResourceManager {
|
|||
Bitmap bmp = null;
|
||||
if (req.tileSource instanceof SQLiteTileSource) {
|
||||
try {
|
||||
bmp = ((SQLiteTileSource) req.tileSource).getImage(req.xTile, req.yTile, req.zoom);
|
||||
// int ts = req.tileSource.getExpirationTimeMillis();
|
||||
// if(ts != -1 && req.url != null && time - en.lastModified() > ts) {
|
||||
// asyncLoadingThread.requestToDownload(req);
|
||||
// }
|
||||
long[] tm = new long[1];
|
||||
bmp = ((SQLiteTileSource) req.tileSource).getImage(req.xTile, req.yTile, req.zoom, tm);
|
||||
if (tm[0] != 0) {
|
||||
int ts = req.tileSource.getExpirationTimeMillis();
|
||||
if (ts != -1 && req.url != null && time - tm[0] > ts) {
|
||||
asyncLoadingThread.requestToDownload(req);
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError e) {
|
||||
log.error("Out of memory error", e); //$NON-NLS-1$
|
||||
clearTiles();
|
||||
|
|
|
@ -153,24 +153,25 @@ public class HillshadeLayer extends MapTileLayer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(int x, int y, int zoom, boolean exact) {
|
||||
return !getTileSource(x, y, zoom).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getImage(int x, int y, int zoom) {
|
||||
public boolean exists(int x, int y, int zoom) {
|
||||
List<String> ts = getTileSource(x, y, zoom);
|
||||
for (String t : ts) {
|
||||
SQLiteTileSource sqLiteTileSource = resources.get(t);
|
||||
if(sqLiteTileSource.exists(x, y, zoom, false)) {
|
||||
return sqLiteTileSource.getImage(x, y, zoom);
|
||||
if(sqLiteTileSource.exists(x, y, zoom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getImage(int x, int y, int zoom, long[] timeHolder) {
|
||||
List<String> ts = getTileSource(x, y, zoom);
|
||||
for (String t : ts) {
|
||||
SQLiteTileSource sqLiteTileSource = resources.get(t);
|
||||
Bitmap img = sqLiteTileSource.getImage(x, y, zoom);
|
||||
if (img != null) {
|
||||
return img;
|
||||
Bitmap bmp = sqLiteTileSource.getImage(x, y, zoom, timeHolder);
|
||||
if(bmp != null) {
|
||||
return sqLiteTileSource.getImage(x, y, zoom, timeHolder);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -188,7 +189,7 @@ public class HillshadeLayer extends MapTileLayer {
|
|||
|
||||
@Override
|
||||
public int getMaximumZoomSupported() {
|
||||
return 19;
|
||||
return 11;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,14 +9,15 @@ import net.osmand.map.TileSourceManager.TileSourceTemplate;
|
|||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.resources.ResourceManager;
|
||||
import net.osmand.util.MapUtils;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.FloatMath;
|
||||
import android.widget.Toast;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
public class MapTileLayer extends BaseMapLayer {
|
||||
|
||||
|
@ -161,55 +162,78 @@ public class MapTileLayer extends BaseMapLayer {
|
|||
|
||||
int y1 = tileBox.getPixYFromTileYNoRot(topPlusJ - ellipticTileCorrection);
|
||||
int y2 = tileBox.getPixYFromTileYNoRot(topPlusJ + 1 - ellipticTileCorrection);
|
||||
bitmapToDraw.set(x1, y1, x2 , y2);
|
||||
|
||||
final int tileX = leftPlusI;
|
||||
final int tileY = topPlusJ;
|
||||
Bitmap bmp = null;
|
||||
String ordImgTile = mgr.calculateTileId(map, tileX, tileY, nzoom);
|
||||
// asking tile image async
|
||||
boolean imgExist = mgr.tileExistOnFileSystem(ordImgTile, map, tileX, tileY, nzoom, false);
|
||||
Bitmap bmp = null;
|
||||
boolean originalBeLoaded = useInternet && nzoom <= maxLevel;
|
||||
if (imgExist || originalBeLoaded) {
|
||||
boolean imgExist = mgr.tileExistOnFileSystem(ordImgTile, map, tileX, tileY, nzoom);
|
||||
boolean originalWillBeLoaded = useInternet && nzoom <= maxLevel;
|
||||
if (imgExist || originalWillBeLoaded) {
|
||||
bmp = mgr.getTileImageForMapAsync(ordImgTile, map, tileX, tileY, nzoom, useInternet);
|
||||
}
|
||||
if (bmp == null) {
|
||||
int div = 2;
|
||||
int div = 1;
|
||||
boolean readFromCache = originalWillBeLoaded || imgExist;
|
||||
boolean loadIfExists = !readFromCache;
|
||||
// asking if there is small version of the map (in cache)
|
||||
String imgTile2 = mgr.calculateTileId(map, tileX / 2, tileY / 2, nzoom - 1);
|
||||
String imgTile4 = mgr.calculateTileId(map, tileX / 4, tileY / 4, nzoom - 2);
|
||||
if (originalBeLoaded || imgExist) {
|
||||
bmp = mgr.getTileImageFromCache(imgTile2);
|
||||
div = 2;
|
||||
if (bmp == null) {
|
||||
bmp = mgr.getTileImageFromCache(imgTile4);
|
||||
div = 4;
|
||||
int allowedScale = Math.min(OVERZOOM_IN + Math.max(0, nzoom - map.getMaximumZoomSupported()), 8);
|
||||
int kzoom = 1;
|
||||
for (; kzoom <= allowedScale; kzoom++) {
|
||||
div *= 2;
|
||||
String imgTileId = mgr.calculateTileId(map, tileX / div, tileY / div, nzoom - kzoom);
|
||||
if (readFromCache) {
|
||||
bmp = mgr.getTileImageFromCache(imgTileId);
|
||||
if (bmp != null) {
|
||||
break;
|
||||
}
|
||||
} else if (loadIfExists) {
|
||||
if (mgr.tileExistOnFileSystem(imgTileId, map, tileX / div, tileY / div, nzoom - kzoom)
|
||||
|| (useInternet && nzoom - kzoom <= maxLevel)) {
|
||||
bmp = mgr.getTileImageForMapAsync(imgTileId, map, tileX / div, tileY / div, nzoom
|
||||
- kzoom, useInternet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!originalBeLoaded && !imgExist) {
|
||||
if (mgr.tileExistOnFileSystem(imgTile2, map, tileX / 2, tileY / 2, nzoom - 1, false)
|
||||
|| (useInternet && nzoom - 1 <= maxLevel)) {
|
||||
bmp = mgr.getTileImageForMapAsync(imgTile2, map, tileX / 2, tileY / 2, nzoom - 1, useInternet);
|
||||
div = 2;
|
||||
} else if (mgr.tileExistOnFileSystem(imgTile4, map, tileX / 4, tileY / 4, nzoom - 2, false)
|
||||
|| (useInternet && nzoom - 2 <= maxLevel)) {
|
||||
bmp = mgr.getTileImageForMapAsync(imgTile4, map, tileX / 4, tileY / 4, nzoom - 2, useInternet);
|
||||
div = 4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (bmp != null) {
|
||||
int xZoom = ((left + i) % div) * tileSize / div;
|
||||
int yZoom = ((top + j) % div) * tileSize / div;
|
||||
bitmapToZoom.set(xZoom, yZoom, xZoom + tileSize / div, yZoom + tileSize / div);
|
||||
bitmapToDraw.set(x1, y1, x2 , y2);
|
||||
canvas.drawBitmap(bmp, bitmapToZoom, bitmapToDraw, paintBitmap);
|
||||
oneTileShown = true;
|
||||
int xZoom = (tileX % div) * tileSize / div;
|
||||
int yZoom = (tileY % div) * tileSize / div;
|
||||
// nice scale
|
||||
boolean useSampling = kzoom > 4;
|
||||
int margin = useSampling ? 1 : 0;
|
||||
bitmapToZoom.set(Math.max(xZoom - margin, 0),
|
||||
Math.max(yZoom - margin , 0),
|
||||
Math.min(margin + xZoom + tileSize / div, tileSize),
|
||||
Math.min(margin + yZoom + tileSize / div, tileSize));
|
||||
if(!useSampling) {
|
||||
canvas.drawBitmap(bmp, bitmapToZoom, bitmapToDraw, paintBitmap);
|
||||
} else {
|
||||
int scaledSize = tileSize / div;
|
||||
RectF src = new RectF(0.5f, 0.5f,
|
||||
scaledSize + 2 * margin - 0.5f, scaledSize + 2 * margin - 0.5f);
|
||||
RectF dest = new RectF(0, 0, tileSize, tileSize);
|
||||
Matrix m = new Matrix();
|
||||
m.setRectToRect(src, dest, Matrix.ScaleToFit.FILL);
|
||||
Bitmap sampled = Bitmap.createBitmap(bmp, bitmapToZoom.left, bitmapToZoom.top,
|
||||
scaledSize + 2 * margin - 1, scaledSize + 2 * margin - 1, m, true);
|
||||
bitmapToZoom.set(0, 0, tileSize, tileSize);
|
||||
// very expensive that's why put in the cache
|
||||
mgr.putTileInTheCache(ordImgTile, sampled);
|
||||
canvas.drawBitmap(sampled, bitmapToZoom, bitmapToDraw, paintBitmap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bitmapToZoom.set(0, 0, tileSize, tileSize);
|
||||
bitmapToDraw.set(x1, y1, x2, y2 );
|
||||
canvas.drawBitmap(bmp, bitmapToZoom, bitmapToDraw, paintBitmap);
|
||||
}
|
||||
if(bmp != null) {
|
||||
oneTileShown = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue