more work on overlay renderer:
- moved text rendering to overlay - added grid overlay
This commit is contained in:
parent
33d8865d7b
commit
4a06553ddc
@ -38,11 +38,10 @@ public class JobQueue {
|
|||||||
* the job to be added to this queue.
|
* the job to be added to this queue.
|
||||||
*/
|
*/
|
||||||
public synchronized void setJobs(ArrayList<JobTile> tiles) {
|
public synchronized void setJobs(ArrayList<JobTile> tiles) {
|
||||||
mPriorityQueue.clear();
|
// mPriorityQueue.clear();
|
||||||
// mPriorityQueue.addAll(tiles);
|
|
||||||
for (int i = 0, n = tiles.size(); i < n; i++) {
|
for (int i = 0, n = tiles.size(); i < n; i++) {
|
||||||
JobTile tile = tiles.get(i);
|
JobTile tile = tiles.get(i);
|
||||||
// tile.state = LOADING;
|
|
||||||
tile.isLoading = true;
|
tile.isLoading = true;
|
||||||
mPriorityQueue.offer(tile);
|
mPriorityQueue.offer(tile);
|
||||||
}
|
}
|
||||||
@ -52,11 +51,10 @@ public class JobQueue {
|
|||||||
* Removes all jobs from this queue.
|
* Removes all jobs from this queue.
|
||||||
*/
|
*/
|
||||||
public synchronized void clear() {
|
public synchronized void clear() {
|
||||||
for (int i = 0, n = mPriorityQueue.size(); i < n; i++) {
|
for (JobTile tile : mPriorityQueue) {
|
||||||
JobTile tile = mPriorityQueue.poll();
|
|
||||||
// tile.state = 0;
|
|
||||||
tile.isLoading = false;
|
tile.isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mPriorityQueue.clear();
|
mPriorityQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,8 +69,6 @@ public class JobQueue {
|
|||||||
* @return the most important job from this queue or null, if empty.
|
* @return the most important job from this queue or null, if empty.
|
||||||
*/
|
*/
|
||||||
public synchronized JobTile poll() {
|
public synchronized JobTile poll() {
|
||||||
JobTile tile = mPriorityQueue.poll();
|
return mPriorityQueue.poll();
|
||||||
|
|
||||||
return tile;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,9 +61,11 @@ public class MapWorker extends PausableThread {
|
|||||||
protected void doWork() {
|
protected void doWork() {
|
||||||
JobTile tile = mJobQueue.poll();
|
JobTile tile = mJobQueue.poll();
|
||||||
|
|
||||||
if (mMapGenerator == null || tile == null)
|
if (tile == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Log.d("...", "load: " + tile);
|
||||||
|
|
||||||
boolean success = mMapGenerator.executeJob(tile);
|
boolean success = mMapGenerator.executeJob(tile);
|
||||||
|
|
||||||
if (!isInterrupted() && success) {
|
if (!isInterrupted() && success) {
|
||||||
|
@ -19,15 +19,15 @@ import android.opengl.GLES20;
|
|||||||
|
|
||||||
class BufferObject {
|
class BufferObject {
|
||||||
private static BufferObject pool;
|
private static BufferObject pool;
|
||||||
|
static int counter;
|
||||||
|
|
||||||
static synchronized BufferObject get() {
|
static synchronized BufferObject get() {
|
||||||
BufferObject bo;
|
|
||||||
|
|
||||||
if (pool == null) {
|
if (pool == null)
|
||||||
return null;
|
return null;
|
||||||
}
|
counter--;
|
||||||
|
|
||||||
bo = pool;
|
BufferObject bo = pool;
|
||||||
pool = pool.next;
|
pool = pool.next;
|
||||||
bo.next = null;
|
bo.next = null;
|
||||||
return bo;
|
return bo;
|
||||||
@ -64,6 +64,7 @@ class BufferObject {
|
|||||||
static synchronized void release(BufferObject bo) {
|
static synchronized void release(BufferObject bo) {
|
||||||
bo.next = pool;
|
bo.next = pool;
|
||||||
pool = bo;
|
pool = bo;
|
||||||
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: only call from GL-Thread
|
// Note: only call from GL-Thread
|
||||||
@ -106,6 +107,7 @@ class BufferObject {
|
|||||||
bo.next = pool;
|
bo.next = pool;
|
||||||
pool = bo;
|
pool = bo;
|
||||||
}
|
}
|
||||||
|
counter = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
|
@ -37,6 +37,7 @@ import org.oscim.renderer.MapRenderer.TilesData;
|
|||||||
import org.oscim.renderer.layer.Layer;
|
import org.oscim.renderer.layer.Layer;
|
||||||
import org.oscim.renderer.layer.Layers;
|
import org.oscim.renderer.layer.Layers;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
|
import org.oscim.utils.GlUtils;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.MapViewPosition;
|
import org.oscim.view.MapViewPosition;
|
||||||
|
|
||||||
@ -44,7 +45,6 @@ import android.opengl.GLES20;
|
|||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.opengl.Matrix;
|
import android.opengl.Matrix;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.FloatMath;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class GLRenderer implements GLSurfaceView.Renderer {
|
public class GLRenderer implements GLSurfaceView.Renderer {
|
||||||
@ -61,14 +61,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
static int CACHE_TILES = CACHE_TILES_MAX;
|
static int CACHE_TILES = CACHE_TILES_MAX;
|
||||||
|
|
||||||
private final MapView mMapView;
|
private final MapView mMapView;
|
||||||
private final MapViewPosition mMapViewPosition;
|
|
||||||
|
|
||||||
private static MapPosition mMapPosition;
|
|
||||||
|
|
||||||
// private static ArrayList<BufferObject> mVBOs;
|
|
||||||
|
|
||||||
static int mWidth, mHeight;
|
static int mWidth, mHeight;
|
||||||
|
|
||||||
|
private static MapViewPosition mMapViewPosition;
|
||||||
|
private static MapPosition mMapPosition;
|
||||||
|
|
||||||
private static int rotateBuffers = 2;
|
private static int rotateBuffers = 2;
|
||||||
private static ShortBuffer shortBuffer[];
|
private static ShortBuffer shortBuffer[];
|
||||||
private static short[] mFillCoords;
|
private static short[] mFillCoords;
|
||||||
@ -82,16 +79,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
private static float[] mTileCoords = new float[8];
|
private static float[] mTileCoords = new float[8];
|
||||||
private static float[] mDebugCoords = new float[8];
|
private static float[] mDebugCoords = new float[8];
|
||||||
|
|
||||||
// mNextTiles is set by TileLoader and swapped with
|
private static float[] mClearColor = null;
|
||||||
// mDrawTiles in onDrawFrame in GL thread.
|
|
||||||
private static TilesData mNextTiles;
|
|
||||||
/* package */static TilesData mDrawTiles;
|
|
||||||
|
|
||||||
// flag set by updateVisibleList when current visible tiles
|
|
||||||
// changed. used in onDrawFrame to flip mNextTiles/mDrawTiles
|
|
||||||
private static boolean mUpdateTiles;
|
|
||||||
|
|
||||||
private float[] mClearColor = null;
|
|
||||||
|
|
||||||
// number of tiles drawn in one frame
|
// number of tiles drawn in one frame
|
||||||
private static short mDrawCount = 0;
|
private static short mDrawCount = 0;
|
||||||
@ -99,7 +87,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
private static boolean mUpdateColor = false;
|
private static boolean mUpdateColor = false;
|
||||||
|
|
||||||
// drawlock to synchronize Main- and GL-Thread
|
// drawlock to synchronize Main- and GL-Thread
|
||||||
static ReentrantLock tilelock = new ReentrantLock();
|
// static ReentrantLock tilelock = new ReentrantLock();
|
||||||
static ReentrantLock drawlock = new ReentrantLock();
|
static ReentrantLock drawlock = new ReentrantLock();
|
||||||
|
|
||||||
// Add additional tiles that serve as placeholer when flipping
|
// Add additional tiles that serve as placeholer when flipping
|
||||||
@ -108,7 +96,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// the other option would be to run scanbox each time for upload,
|
// the other option would be to run scanbox each time for upload,
|
||||||
// drawing, proxies and text layer. needing to add placeholder only
|
// drawing, proxies and text layer. needing to add placeholder only
|
||||||
// happens rarely, unless you live on Fidschi
|
// happens rarely, unless you live on Fidschi
|
||||||
|
|
||||||
/* package */static int mHolderCount;
|
/* package */static int mHolderCount;
|
||||||
|
/* package */static TilesData mDrawTiles;
|
||||||
|
|
||||||
static boolean[] vertexArray = { false, false };
|
static boolean[] vertexArray = { false, false };
|
||||||
|
|
||||||
@ -222,58 +212,18 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
shortBuffer[i].put(mFillCoords, 0, 8);
|
shortBuffer[i].put(mFillCoords, 0, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
mUpdateTiles = false;
|
mOverlays = new ArrayList<Overlay>();
|
||||||
|
|
||||||
|
// mOverlays.add(new OverlayGrid(mapView));
|
||||||
|
// mOverlays.add(new OverlayTest(mapView));
|
||||||
|
mOverlays.add(new OverlayText(mapView));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ArrayList<Overlay> mOverlays;
|
private static ArrayList<Overlay> mOverlays;
|
||||||
|
|
||||||
/**
|
public static void setRenderTheme(RenderTheme t) {
|
||||||
* Called by TileLoader when list of active tiles changed. the list is
|
mClearColor = GlUtils.colorToFloat(t.getMapBackground());
|
||||||
* copied to mNextTiles to be used in next call to onDrawFrame
|
|
||||||
*
|
|
||||||
* @param tiles
|
|
||||||
* active tiles
|
|
||||||
* @param overlays
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
static void updateTiles(TilesData tiles, ArrayList<Overlay> overlays) {
|
|
||||||
|
|
||||||
MapTile[] newTiles = tiles.tiles;
|
|
||||||
|
|
||||||
// lock tiles (and their proxies) to not be removed from cache
|
|
||||||
for (int i = 0, n = tiles.cnt; i < n; i++)
|
|
||||||
newTiles[i].lock();
|
|
||||||
|
|
||||||
mOverlays = overlays;
|
|
||||||
|
|
||||||
// dont flip next/drawTiles while copying
|
|
||||||
GLRenderer.tilelock.lock();
|
|
||||||
|
|
||||||
MapTile[] nextTiles = mNextTiles.tiles;
|
|
||||||
|
|
||||||
// unlock previously active tiles
|
|
||||||
for (int i = 0, n = mNextTiles.cnt; i < n; i++)
|
|
||||||
nextTiles[i].unlock();
|
|
||||||
|
|
||||||
// copy newTiles to nextTiles
|
|
||||||
System.arraycopy(newTiles, 0, nextTiles, 0, tiles.cnt);
|
|
||||||
|
|
||||||
mNextTiles.cnt = tiles.cnt;
|
|
||||||
|
|
||||||
// flip next/drawTiles in next onDrawFrame
|
|
||||||
mUpdateTiles = true;
|
|
||||||
|
|
||||||
GLRenderer.tilelock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRenderTheme(RenderTheme t) {
|
|
||||||
int bg = t.getMapBackground();
|
|
||||||
float[] c = new float[4];
|
|
||||||
c[3] = (bg >> 24 & 0xff) / 255.0f;
|
|
||||||
c[0] = (bg >> 16 & 0xff) / 255.0f;
|
|
||||||
c[1] = (bg >> 8 & 0xff) / 255.0f;
|
|
||||||
c[2] = (bg >> 0 & 0xff) / 255.0f;
|
|
||||||
mClearColor = c;
|
|
||||||
mUpdateColor = true;
|
mUpdateColor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,19 +232,20 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
private static boolean uploadLayers(Layers layers, BufferObject vbo, boolean addFill) {
|
private static boolean uploadLayers(Layers layers, BufferObject vbo, boolean addFill) {
|
||||||
|
|
||||||
int newSize = layers.getSize();
|
int newSize = layers.getSize();
|
||||||
if (newSize == 0)
|
if (newSize == 0) {
|
||||||
return false;
|
Log.d(TAG, "empty");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
|
GLES20.glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
|
||||||
|
|
||||||
// use multiple buffers to avoid overwriting buffer while current
|
// use multiple buffers to avoid overwriting buffer while current
|
||||||
// data is uploaded (or rather the blocking which is probably done to
|
// data is uploaded (or rather the blocking which is probably done to
|
||||||
// avoid overwriting)
|
// avoid overwriting)
|
||||||
if (uploadCnt >= rotateBuffers) {
|
int curBuffer = uploadCnt % rotateBuffers;
|
||||||
uploadCnt = 0;
|
uploadCnt++;
|
||||||
}
|
|
||||||
|
|
||||||
ShortBuffer sbuf = shortBuffer[uploadCnt];
|
ShortBuffer sbuf = shortBuffer[curBuffer];
|
||||||
|
|
||||||
// add fill coordinates
|
// add fill coordinates
|
||||||
if (addFill)
|
if (addFill)
|
||||||
@ -307,7 +258,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
.order(ByteOrder.nativeOrder())
|
.order(ByteOrder.nativeOrder())
|
||||||
.asShortBuffer();
|
.asShortBuffer();
|
||||||
|
|
||||||
shortBuffer[uploadCnt] = sbuf;
|
shortBuffer[curBuffer] = sbuf;
|
||||||
if (addFill)
|
if (addFill)
|
||||||
sbuf.put(mFillCoords, 0, 8);
|
sbuf.put(mFillCoords, 0, 8);
|
||||||
} else {
|
} else {
|
||||||
@ -345,18 +296,21 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mBufferMemoryUsage += vbo.size;
|
mBufferMemoryUsage += vbo.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadCnt++;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean uploadTileData(MapTile tile) {
|
private static boolean uploadTileData(MapTile tile) {
|
||||||
|
// synchronized (tile) {
|
||||||
if (uploadLayers(tile.layers, tile.vbo, true))
|
tile.isReady = uploadLayers(tile.layers, tile.vbo, true);
|
||||||
tile.isReady = true;
|
if (!tile.isReady) {
|
||||||
|
tile.layers.clear();
|
||||||
|
tile.layers = null;
|
||||||
|
}
|
||||||
|
|
||||||
tile.newData = false;
|
tile.newData = false;
|
||||||
|
// Log.d(TAG, "uploaded " + tile.isReady + " " + tile);
|
||||||
|
|
||||||
|
// }
|
||||||
return tile.isReady;
|
return tile.isReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,11 +381,19 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDrawFrame(GL10 glUnused) {
|
public void onDrawFrame(GL10 glUnused) {
|
||||||
long start = 0;
|
|
||||||
// prevent main thread recreating all tiles (updateMap)
|
// prevent main thread recreating all tiles (updateMap)
|
||||||
// while rendering is going. not have seen this happen
|
// while rendering is going.
|
||||||
// yet though
|
drawlock.lock();
|
||||||
GLRenderer.drawlock.lock();
|
try {
|
||||||
|
draw();
|
||||||
|
} finally {
|
||||||
|
drawlock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw() {
|
||||||
|
long start = 0;
|
||||||
|
|
||||||
if (MapView.debugFrameTime)
|
if (MapView.debugFrameTime)
|
||||||
start = SystemClock.uptimeMillis();
|
start = SystemClock.uptimeMillis();
|
||||||
@ -451,24 +413,22 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
| GLES20.GL_DEPTH_BUFFER_BIT
|
| GLES20.GL_DEPTH_BUFFER_BIT
|
||||||
| GLES20.GL_STENCIL_BUFFER_BIT);
|
| GLES20.GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
if (mUpdateTiles) {
|
int serial = 0;
|
||||||
|
if (mDrawTiles != null)
|
||||||
|
serial = mDrawTiles.serial;
|
||||||
|
|
||||||
// get current tiles to draw
|
// get current tiles to draw
|
||||||
GLRenderer.tilelock.lock();
|
mDrawTiles = MapRenderer.getActiveTiles(mDrawTiles);
|
||||||
mUpdateTiles = false;
|
|
||||||
|
|
||||||
TilesData tmp = mDrawTiles;
|
|
||||||
mDrawTiles = mNextTiles;
|
|
||||||
mNextTiles = tmp;
|
|
||||||
GLRenderer.tilelock.unlock();
|
|
||||||
|
|
||||||
// force update of mapPosition
|
|
||||||
mMapPosition.zoomLevel = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
|
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
|
||||||
GLRenderer.drawlock.unlock();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
boolean tilesChanged = false;
|
||||||
|
// check if the tiles have changed...
|
||||||
|
if (serial != mDrawTiles.serial) {
|
||||||
|
mMapPosition.zoomLevel = -1;
|
||||||
|
tilesChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
// get current MapPosition, set mTileCoords (mapping of screen to model
|
// get current MapPosition, set mTileCoords (mapping of screen to model
|
||||||
// coordinates)
|
// coordinates)
|
||||||
@ -476,10 +436,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
float[] coords = mTileCoords;
|
float[] coords = mTileCoords;
|
||||||
boolean changed = mMapViewPosition.getMapPosition(mapPosition, coords);
|
boolean changed = mMapViewPosition.getMapPosition(mapPosition, coords);
|
||||||
|
|
||||||
for (Overlay overlay : mOverlays) {
|
|
||||||
overlay.update(mMapView);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tileCnt = mDrawTiles.cnt;
|
int tileCnt = mDrawTiles.cnt;
|
||||||
MapTile[] tiles = mDrawTiles.tiles;
|
MapTile[] tiles = mDrawTiles.tiles;
|
||||||
|
|
||||||
@ -492,6 +448,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// zoom-level changed.
|
// zoom-level changed.
|
||||||
float div = scaleDiv(tiles[0]);
|
float div = scaleDiv(tiles[0]);
|
||||||
|
|
||||||
|
// transform screen coordinates to tile coordinates
|
||||||
float s = Tile.TILE_SIZE;
|
float s = Tile.TILE_SIZE;
|
||||||
float scale = mapPosition.scale / div;
|
float scale = mapPosition.scale / div;
|
||||||
float px = (float) mapPosition.x * div;
|
float px = (float) mapPosition.x * div;
|
||||||
@ -511,9 +468,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// Log.d(TAG, "visible: " + tileCnt);
|
// Log.d(TAG, "visible: " + tileCnt);
|
||||||
|
|
||||||
uploadCnt = 0;
|
uploadCnt = 0;
|
||||||
int updateTextures = 0;
|
// int updateTextures = 0;
|
||||||
|
|
||||||
// check visible tiles, upload new vertex data
|
// compile data and upload to VBOsi
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
MapTile tile = tiles[i];
|
MapTile tile = tiles[i];
|
||||||
|
|
||||||
@ -522,10 +479,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
if (!tile.isVisible)
|
if (!tile.isVisible)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (MapView.staticLabeling) {
|
// if (MapView.staticLabeling) {
|
||||||
if (tile.texture == null && TextRenderer.drawToTexture(tile))
|
// if (tile.texture == null && TextRenderer.drawToTexture(tile))
|
||||||
updateTextures++;
|
// updateTextures++;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (tile.newData) {
|
if (tile.newData) {
|
||||||
uploadTileData(tile);
|
uploadTileData(tile);
|
||||||
@ -562,10 +519,18 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
if (uploadCnt > 0)
|
if (uploadCnt > 0)
|
||||||
checkBufferUsage();
|
checkBufferUsage();
|
||||||
|
|
||||||
if (MapView.staticLabeling) {
|
tilesChanged |= (uploadCnt > 0);
|
||||||
if (updateTextures > 0)
|
|
||||||
TextRenderer.compileTextures();
|
// if (changed || tilesChanged) {
|
||||||
|
for (Overlay overlay : mOverlays) {
|
||||||
|
overlay.update(changed, tilesChanged);
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (MapView.staticLabeling) {
|
||||||
|
// if (updateTextures > 0)
|
||||||
|
// TextRenderer.compileTextures();
|
||||||
|
// }
|
||||||
|
|
||||||
GLES20.glEnable(GL_DEPTH_TEST);
|
GLES20.glEnable(GL_DEPTH_TEST);
|
||||||
GLES20.glEnable(GL_POLYGON_OFFSET_FILL);
|
GLES20.glEnable(GL_POLYGON_OFFSET_FILL);
|
||||||
@ -593,41 +558,41 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mDrawCount = 0;
|
mDrawCount = 0;
|
||||||
mDrawSerial++;
|
mDrawSerial++;
|
||||||
|
|
||||||
if (MapView.staticLabeling) {
|
|
||||||
GLES20.glEnable(GL_BLEND);
|
GLES20.glEnable(GL_BLEND);
|
||||||
int z = mapPosition.zoomLevel;
|
|
||||||
float s = mapPosition.scale;
|
|
||||||
|
|
||||||
int zoomLevelDiff = Math.max(z - TileGenerator.STROKE_MAX_ZOOM_LEVEL,
|
// if (MapView.staticLabeling) {
|
||||||
0);
|
// int z = mapPosition.zoomLevel;
|
||||||
float scale = (float) Math.pow(1.4, zoomLevelDiff);
|
// float s = mapPosition.scale;
|
||||||
if (scale < 1)
|
// int zoomLevelDiff = Math.max(z - TileGenerator.STROKE_MAX_ZOOM_LEVEL,
|
||||||
scale = 1;
|
// 0);
|
||||||
|
// float scale = (float) Math.pow(1.4, zoomLevelDiff);
|
||||||
if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
|
// if (scale < 1)
|
||||||
TextRenderer.beginDraw(scale / FloatMath.sqrt(s), mProjMatrix);
|
// scale = 1;
|
||||||
else
|
//
|
||||||
TextRenderer.beginDraw(1f / s, mProjMatrix);
|
// if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
|
||||||
|
// TextRenderer.beginDraw(scale / FloatMath.sqrt(s), mProjMatrix);
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
// else
|
||||||
MapTile t = tiles[i];
|
// TextRenderer.beginDraw(1f / s, mProjMatrix);
|
||||||
if (!t.isVisible)
|
//
|
||||||
continue;
|
// for (int i = 0; i < tileCnt; i++) {
|
||||||
|
// MapTile t = tiles[i];
|
||||||
if (t.holder == null) {
|
// if (!t.isVisible)
|
||||||
if (t.texture != null) {
|
// continue;
|
||||||
setMatrix(mMVPMatrix, t, 1, false);
|
//
|
||||||
TextRenderer.drawTile(t, mMVPMatrix);
|
// if (t.holder == null) {
|
||||||
}
|
// if (t.texture != null) {
|
||||||
} else {
|
// setMatrix(mMVPMatrix, t, 1, false);
|
||||||
if (t.holder.texture != null) {
|
// TextRenderer.drawTile(t, mMVPMatrix);
|
||||||
setMatrix(mMVPMatrix, t, 1, false);
|
// }
|
||||||
TextRenderer.drawTile(t.holder, mMVPMatrix);
|
// } else {
|
||||||
}
|
// if (t.holder.texture != null) {
|
||||||
}
|
// setMatrix(mMVPMatrix, t, 1, false);
|
||||||
}
|
// TextRenderer.drawTile(t.holder, mMVPMatrix);
|
||||||
TextRenderer.endDraw();
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// TextRenderer.endDraw();
|
||||||
|
// }
|
||||||
|
|
||||||
// call overlay renderer
|
// call overlay renderer
|
||||||
for (Overlay overlay : mOverlays) {
|
for (Overlay overlay : mOverlays) {
|
||||||
@ -675,8 +640,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mapPosition.viewMatrix, 0);
|
mapPosition.viewMatrix, 0);
|
||||||
PolygonRenderer.debugDraw(mMVPMatrix, mDebugCoords, 1);
|
PolygonRenderer.debugDraw(mMVPMatrix, mDebugCoords, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLRenderer.drawlock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to not draw a tile twice per frame.
|
// used to not draw a tile twice per frame.
|
||||||
@ -728,12 +691,12 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tile.layers.symbolLayers != null) {
|
if (tile.layers.textureLayers != null) {
|
||||||
setMatrix(mvp, tile, div, false);
|
setMatrix(mvp, tile, div, false);
|
||||||
|
|
||||||
for (Layer l = tile.layers.symbolLayers; l != null;) {
|
for (Layer l = tile.layers.textureLayers; l != null;) {
|
||||||
l = TextureRenderer.draw(l, 1, mProjMatrix, mvp,
|
l = TextureRenderer.draw(l, 1, mProjMatrix, mvp,
|
||||||
tile.layers.symbolOffset);
|
tile.layers.texOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -798,6 +761,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
|
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
|
||||||
Log.d(TAG, "SurfaceChanged:" + width + " " + height);
|
Log.d(TAG, "SurfaceChanged:" + width + " " + height);
|
||||||
|
|
||||||
|
mDrawTiles = null;
|
||||||
|
|
||||||
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -849,7 +814,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
BufferObject.init(numVBO);
|
BufferObject.init(numVBO);
|
||||||
|
|
||||||
// Set up textures
|
// Set up textures
|
||||||
TextRenderer.setup(numTiles);
|
// TextRenderer.setup(numTiles);
|
||||||
|
|
||||||
if (mClearColor != null)
|
if (mClearColor != null)
|
||||||
mUpdateColor = true;
|
mUpdateColor = true;
|
||||||
@ -861,13 +826,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mMapView.redrawMap();
|
mMapView.redrawMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME this is a bit too spaghetti
|
|
||||||
void clearTiles(int numTiles) {
|
|
||||||
mDrawTiles = new TilesData(numTiles);
|
|
||||||
mNextTiles = new TilesData(numTiles);
|
|
||||||
mMapPosition.zoomLevel = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||||
// String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
// String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||||
@ -875,7 +833,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
LineRenderer.init();
|
LineRenderer.init();
|
||||||
PolygonRenderer.init();
|
PolygonRenderer.init();
|
||||||
TextRenderer.init();
|
// TextRenderer.init();
|
||||||
TextureRenderer.init();
|
TextureRenderer.init();
|
||||||
TextureObject.init(10);
|
TextureObject.init(10);
|
||||||
|
|
||||||
@ -884,7 +842,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
GLES20.glClearStencil(0);
|
GLES20.glClearStencil(0);
|
||||||
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
||||||
GLES20.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
GLES20.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
mNewSurface = true;
|
mNewSurface = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,13 @@ package org.oscim.renderer;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
|
import org.oscim.renderer.layer.TextItem;
|
||||||
import org.oscim.renderer.layer.VertexPool;
|
import org.oscim.renderer.layer.VertexPool;
|
||||||
import org.oscim.theme.RenderTheme;
|
|
||||||
import org.oscim.utils.GlConfigChooser;
|
import org.oscim.utils.GlConfigChooser;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.MapViewPosition;
|
import org.oscim.view.MapViewPosition;
|
||||||
@ -75,22 +76,31 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// GLThread
|
// GLThread
|
||||||
static final class TilesData {
|
static final class TilesData {
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
final MapTile[] tiles;
|
int serial;
|
||||||
|
MapTile[] tiles;
|
||||||
|
|
||||||
|
TilesData() {
|
||||||
|
}
|
||||||
|
|
||||||
TilesData(int numTiles) {
|
TilesData(int numTiles) {
|
||||||
tiles = new MapTile[numTiles];
|
tiles = new MapTile[numTiles];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */static TilesData mCurrentTiles;
|
static int mUpdateCnt;
|
||||||
|
static ReentrantLock tilelock = new ReentrantLock();
|
||||||
|
static TilesData mCurrentTiles;
|
||||||
|
/* package */static TilesData mNewTiles;
|
||||||
|
|
||||||
|
static int tileCounter;
|
||||||
|
|
||||||
private static ScanBox mScanBox = new ScanBox() {
|
private static ScanBox mScanBox = new ScanBox() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void setVisible(int y, int x1, int x2) {
|
void setVisible(int y, int x1, int x2) {
|
||||||
MapTile[] tiles = mCurrentTiles.tiles;
|
MapTile[] tiles = mNewTiles.tiles;
|
||||||
int cnt = mCurrentTiles.cnt;
|
int cnt = mNewTiles.cnt;
|
||||||
int max = mCurrentTiles.tiles.length;
|
int max = tiles.length;
|
||||||
int xmax = 1 << mZoom;
|
int xmax = 1 << mZoom;
|
||||||
|
|
||||||
for (int x = x1; x < x2; x++) {
|
for (int x = x1; x < x2; x++) {
|
||||||
@ -101,7 +111,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE to myself: do not modify x, argh !!!
|
// NOTE to myself: do not modify x!
|
||||||
int xx = x;
|
int xx = x;
|
||||||
|
|
||||||
if (x < 0 || x >= xmax) {
|
if (x < 0 || x >= xmax) {
|
||||||
@ -127,13 +137,15 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
tiles[cnt++] = tile;
|
tiles[cnt++] = tile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCurrentTiles.cnt = cnt;
|
mNewTiles.cnt = cnt;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// why not try a pattern every now and then?
|
// why not try a pattern every now and then?
|
||||||
// but should do the same for GLRenderer
|
// but should do the same for GLRenderer.
|
||||||
private static MapRenderer SINGLETON;
|
// findbugs found that volatile thingy, though this class
|
||||||
|
// is created before any other thread starts
|
||||||
|
private static volatile MapRenderer SINGLETON;
|
||||||
|
|
||||||
public static MapRenderer create(Context context, MapView mapView) {
|
public static MapRenderer create(Context context, MapView mapView) {
|
||||||
if (SINGLETON != null)
|
if (SINGLETON != null)
|
||||||
@ -177,7 +189,10 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
VertexPool.init();
|
VertexPool.init();
|
||||||
QuadTree.init();
|
QuadTree.init();
|
||||||
|
|
||||||
|
mUpdateCnt = 0;
|
||||||
mInitial = true;
|
mInitial = true;
|
||||||
|
|
||||||
|
tileCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -188,7 +203,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
* @param clear
|
* @param clear
|
||||||
* whether to clear and reload all tiles
|
* whether to clear and reload all tiles
|
||||||
*/
|
*/
|
||||||
public void updateMap(final boolean clear) {
|
public synchronized void updateMap(final boolean clear) {
|
||||||
boolean changedPos = false;
|
boolean changedPos = false;
|
||||||
|
|
||||||
if (mMapView == null)
|
if (mMapView == null)
|
||||||
@ -214,7 +229,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
// TODO clear overlay items data
|
// TODO clear overlay items data
|
||||||
mOverlays.clear();
|
mOverlays.clear();
|
||||||
mOverlays.add(new Overlay());
|
// mOverlays.add(new Overlay());
|
||||||
|
|
||||||
// set up TileData arrays that are passed to gl-thread
|
// set up TileData arrays that are passed to gl-thread
|
||||||
int num = mWidth;
|
int num = mWidth;
|
||||||
@ -225,9 +240,9 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
int numTiles = (num * num) / (size * size) * 4;
|
int numTiles = (num * num) / (size * size) * 4;
|
||||||
|
|
||||||
mRenderer.clearTiles(numTiles);
|
// mRenderer.clearTiles(numTiles);
|
||||||
|
mNewTiles = new TilesData(numTiles);
|
||||||
mCurrentTiles = new TilesData(numTiles);
|
mCurrentTiles = new TilesData(numTiles);
|
||||||
|
|
||||||
// MapInfo mapInfo = mMapView.getMapDatabase().getMapInfo();
|
// MapInfo mapInfo = mMapView.getMapDatabase().getMapInfo();
|
||||||
// if (mapInfo != null)
|
// if (mapInfo != null)
|
||||||
// mZoomLevels = mapInfo.zoomLevel;
|
// mZoomLevels = mapInfo.zoomLevel;
|
||||||
@ -243,8 +258,10 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
float[] coords = mTileCoords;
|
float[] coords = mTileCoords;
|
||||||
changedPos = mMapViewPosition.getMapPosition(mapPosition, coords);
|
changedPos = mMapViewPosition.getMapPosition(mapPosition, coords);
|
||||||
|
|
||||||
if (!changedPos)
|
if (!changedPos) {
|
||||||
|
requestRender();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
float s = Tile.TILE_SIZE;
|
float s = Tile.TILE_SIZE;
|
||||||
// load some additional tiles more than currently visible
|
// load some additional tiles more than currently visible
|
||||||
@ -259,16 +276,6 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
coords[i + 1] = (py + coords[i + 1] / scale) / s;
|
coords[i + 1] = (py + coords[i + 1] / scale) / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this does not work reloably with tilt and rotation
|
|
||||||
// changedPos = false;
|
|
||||||
// for (int i = 0; i < 8; i++)
|
|
||||||
// if (mBoundaryTiles[i] != (int) coords[i]) {
|
|
||||||
// changedPos = true;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// for (int i = 0; i < 8; i++)
|
|
||||||
// mBoundaryTiles[i] = (int) coords[i];
|
|
||||||
|
|
||||||
// TODO all following should probably be done in an idler instead
|
// TODO all following should probably be done in an idler instead
|
||||||
// to drain queued events. need to check how android handles things.
|
// to drain queued events. need to check how android handles things.
|
||||||
|
|
||||||
@ -279,6 +286,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
||||||
|
|
||||||
if (remove > CACHE_THRESHOLD)
|
if (remove > CACHE_THRESHOLD)
|
||||||
limitCache(mapPosition, remove);
|
limitCache(mapPosition, remove);
|
||||||
|
|
||||||
@ -286,9 +294,51 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TilesData getActiveTiles(TilesData td) {
|
||||||
|
|
||||||
|
if (td != null && td.serial == mUpdateCnt)
|
||||||
|
return td;
|
||||||
|
|
||||||
|
// dont flip new/currentTiles while copying
|
||||||
|
MapRenderer.tilelock.lock();
|
||||||
|
try {
|
||||||
|
MapTile[] newTiles = mCurrentTiles.tiles;
|
||||||
|
int cnt = mCurrentTiles.cnt;
|
||||||
|
|
||||||
|
// lock tiles (and their proxies) to not be removed from cache
|
||||||
|
for (int i = 0; i < cnt; i++)
|
||||||
|
newTiles[i].lock();
|
||||||
|
|
||||||
|
MapTile[] nextTiles;
|
||||||
|
|
||||||
|
if (td == null)
|
||||||
|
td = new TilesData(newTiles.length);
|
||||||
|
|
||||||
|
nextTiles = td.tiles;
|
||||||
|
|
||||||
|
// unlock previously active tiles
|
||||||
|
for (int i = 0, n = td.cnt; i < n; i++)
|
||||||
|
nextTiles[i].unlock();
|
||||||
|
|
||||||
|
// copy newTiles to nextTiles
|
||||||
|
System.arraycopy(newTiles, 0, nextTiles, 0, cnt);
|
||||||
|
|
||||||
|
td.serial = mUpdateCnt;
|
||||||
|
td.cnt = cnt;
|
||||||
|
} finally {
|
||||||
|
MapRenderer.tilelock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return td;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void releaseTiles(TilesData tiles) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set mCurrentTiles for the visible tiles and pass it to GLRenderer, add
|
* set mNewTiles for the visible tiles and pass it to GLRenderer, add jobs
|
||||||
* jobs for not yet loaded tiles
|
* for not yet loaded tiles
|
||||||
*
|
*
|
||||||
* @param mapPosition
|
* @param mapPosition
|
||||||
* the current MapPosition
|
* the current MapPosition
|
||||||
@ -298,44 +348,97 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
*/
|
*/
|
||||||
private static boolean updateVisibleList(MapPosition mapPosition, int zdir) {
|
private static boolean updateVisibleList(MapPosition mapPosition, int zdir) {
|
||||||
|
|
||||||
|
// TODO keep mJobList and JobQueue in sync, no need to clear
|
||||||
mJobList.clear();
|
mJobList.clear();
|
||||||
// set non processed tiles to isLoading == false
|
|
||||||
mMapView.addJobs(null);
|
|
||||||
mCurrentTiles.cnt = 0;
|
|
||||||
mScanBox.scan(mTileCoords, mapPosition.zoomLevel);
|
|
||||||
// Log.d(TAG, "visible: " + mCurrentTiles.cnt + "/" +
|
|
||||||
// mCurrentTiles.tiles.length);
|
|
||||||
GLRenderer.updateTiles(mCurrentTiles, mOverlays);
|
|
||||||
|
|
||||||
// note: this sets isLoading == true for all job tiles
|
// sets non processed tiles to isLoading = false
|
||||||
|
// and clear job queue
|
||||||
|
mMapView.addJobs(null);
|
||||||
|
|
||||||
|
mNewTiles.cnt = 0;
|
||||||
|
mScanBox.scan(mTileCoords, mapPosition.zoomLevel);
|
||||||
|
|
||||||
|
MapTile[] newTiles = mNewTiles.tiles;
|
||||||
|
MapTile[] curTiles = mCurrentTiles.tiles;
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
for (int i = 0, n = mNewTiles.cnt; i < n && !changed; i++) {
|
||||||
|
MapTile t = newTiles[i];
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
for (int j = 0, m = mCurrentTiles.cnt; j < m; j++) {
|
||||||
|
if (t == curTiles[j]) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
MapRenderer.tilelock.lock();
|
||||||
|
try {
|
||||||
|
for (int i = 0, n = mNewTiles.cnt; i < n; i++)
|
||||||
|
newTiles[i].lock();
|
||||||
|
|
||||||
|
for (int i = 0, n = mCurrentTiles.cnt; i < n; i++)
|
||||||
|
curTiles[i].unlock();
|
||||||
|
|
||||||
|
TilesData tmp = mCurrentTiles;
|
||||||
|
mCurrentTiles = mNewTiles;
|
||||||
|
mNewTiles = tmp;
|
||||||
|
|
||||||
|
mUpdateCnt++;
|
||||||
|
} finally {
|
||||||
|
MapRenderer.tilelock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log.d(TAG, "tiles: " + tileCounter + " " + BufferObject.counter
|
||||||
|
// + " sum:" + (tileCounter + BufferObject.counter));
|
||||||
|
}
|
||||||
|
|
||||||
if (mJobList.size() > 0) {
|
if (mJobList.size() > 0) {
|
||||||
updateTileDistances(mJobList, mapPosition);
|
updateTileDistances(mJobList, mapPosition);
|
||||||
Collections.sort(mJobList);
|
Collections.sort(mJobList);
|
||||||
|
|
||||||
|
// sets tiles to isLoading = true
|
||||||
mMapView.addJobs(mJobList);
|
mMapView.addJobs(mJobList);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */
|
/**
|
||||||
static MapTile addTile(int x, int y, byte zoomLevel, int zdir) {
|
* @param x
|
||||||
|
* ...
|
||||||
|
* @param y
|
||||||
|
* ...
|
||||||
|
* @param zoomLevel
|
||||||
|
* ...
|
||||||
|
* @param zdir
|
||||||
|
* ...
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* package */static MapTile addTile(int x, int y, byte zoomLevel, int zdir) {
|
||||||
MapTile tile;
|
MapTile tile;
|
||||||
|
|
||||||
tile = QuadTree.getTile(x, y, zoomLevel);
|
tile = QuadTree.getTile(x, y, zoomLevel);
|
||||||
|
|
||||||
if (tile == null) {
|
if (tile == null) {
|
||||||
tile = new MapTile(x, y, zoomLevel);
|
tile = new MapTile(x, y, zoomLevel);
|
||||||
|
|
||||||
QuadTree.add(tile);
|
QuadTree.add(tile);
|
||||||
mTiles.add(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (!fetchProxy && !tile.isActive()) {
|
mTiles.add(tile);
|
||||||
if (!tile.isActive()) {
|
mJobList.add(tile);
|
||||||
|
tileCounter++;
|
||||||
|
} else if (!tile.isActive()) {
|
||||||
mJobList.add(tile);
|
mJobList.add(tile);
|
||||||
}
|
}
|
||||||
|
// mNewTiles.tiles[tiles++] = tile;
|
||||||
// mCurrentTiles.tiles[tiles++] = tile;
|
|
||||||
|
|
||||||
// if (fetchChildren) {
|
// if (fetchChildren) {
|
||||||
// byte z = (byte) (zoomLevel + 1);
|
// byte z = (byte) (zoomLevel + 1);
|
||||||
@ -359,22 +462,23 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
|
// if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
|
||||||
if (zdir > 0 && zoomLevel > 0) {
|
|
||||||
// prefetch parent
|
|
||||||
MapTile p = tile.rel.parent.tile;
|
|
||||||
|
|
||||||
if (p == null) {
|
// if (zdir > 0 && zoomLevel > 0) {
|
||||||
p = new MapTile(x >> 1, y >> 1, (byte) (zoomLevel - 1));
|
// // prefetch parent
|
||||||
|
// MapTile p = tile.rel.parent.tile;
|
||||||
QuadTree.add(p);
|
//
|
||||||
mTiles.add(p);
|
// if (p == null) {
|
||||||
mJobList.add(p);
|
// p = new MapTile(x >> 1, y >> 1, (byte) (zoomLevel - 1));
|
||||||
|
//
|
||||||
} else if (!p.isActive()) {
|
// QuadTree.add(p);
|
||||||
if (!mJobList.contains(p))
|
// mTiles.add(p);
|
||||||
mJobList.add(p);
|
// mJobList.add(p);
|
||||||
}
|
//
|
||||||
}
|
// } else if (!p.isActive()) {
|
||||||
|
// if (!mJobList.contains(p))
|
||||||
|
// mJobList.add(p);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,15 +493,16 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
t.layers = null;
|
t.layers = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
t.labels = null;
|
TextItem.release(t.labels);
|
||||||
|
|
||||||
if (t.vbo != null) {
|
if (t.vbo != null) {
|
||||||
BufferObject.release(t.vbo);
|
BufferObject.release(t.vbo);
|
||||||
t.vbo = null;
|
t.vbo = null;
|
||||||
}
|
}
|
||||||
if (t.texture != null)
|
// if (t.texture != null)
|
||||||
t.texture.tile = null;
|
// t.texture.tile = null;
|
||||||
|
|
||||||
|
tileCounter--;
|
||||||
QuadTree.remove(t);
|
QuadTree.remove(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,15 +584,13 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
for (int i = 1; i < remove; i++) {
|
for (int i = 1; i < remove; i++) {
|
||||||
MapTile t = mTiles.remove(size - i);
|
MapTile t = mTiles.remove(size - i);
|
||||||
|
// synchronized (t) {
|
||||||
|
|
||||||
if (t.isLocked()) {
|
if (t.isLocked()) {
|
||||||
// dont remove tile used by GLRenderer
|
// dont remove tile used by GLRenderer
|
||||||
Log.d(TAG, "X not removing " + t + " " + t.distance);
|
Log.d(TAG, "X not removing " + t + " " + t.distance);
|
||||||
mTiles.add(t);
|
mTiles.add(t);
|
||||||
continue;
|
} else if (t.isLoading) {
|
||||||
}
|
|
||||||
|
|
||||||
if (t.isLoading) {
|
|
||||||
// NOTE: if we add tile back and set loading=false, on next
|
// NOTE: if we add tile back and set loading=false, on next
|
||||||
// limitCache the tile will be removed. clearTile could
|
// limitCache the tile will be removed. clearTile could
|
||||||
// interfere with TileGenerator. so clear in passTile()
|
// interfere with TileGenerator. so clear in passTile()
|
||||||
@ -498,11 +601,11 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// t.isLoading = false;
|
// t.isLoading = false;
|
||||||
mTiles.add(t);
|
mTiles.add(t);
|
||||||
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
||||||
continue;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
clearTile(t);
|
clearTile(t);
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void limitLoadQueue() {
|
private static void limitLoadQueue() {
|
||||||
@ -516,8 +619,8 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// remove tiles already uploaded to vbo
|
// remove tiles already uploaded to vbo
|
||||||
for (int i = 0; i < size;) {
|
for (int i = 0; i < size;) {
|
||||||
MapTile t = mTilesLoaded.get(i);
|
MapTile t = mTilesLoaded.get(i);
|
||||||
|
// t.rel == null means tile was removed in limitCache
|
||||||
if (!t.newData) {
|
if (!t.newData || t.rel == null) {
|
||||||
mTilesLoaded.remove(i);
|
mTilesLoaded.remove(i);
|
||||||
size--;
|
size--;
|
||||||
continue;
|
continue;
|
||||||
@ -532,7 +635,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
|
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
|
||||||
|
|
||||||
MapTile t = mTilesLoaded.get(i);
|
MapTile t = mTilesLoaded.get(i);
|
||||||
|
// synchronized (t) {
|
||||||
if (t.isLocked()) {
|
if (t.isLocked()) {
|
||||||
// Log.d(TAG, "keep unused tile data: " + t + " " +
|
// Log.d(TAG, "keep unused tile data: " + t + " " +
|
||||||
// t.isActive);
|
// t.isActive);
|
||||||
@ -545,6 +648,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
mTiles.remove(t);
|
mTiles.remove(t);
|
||||||
clearTile(t);
|
clearTile(t);
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,16 +662,17 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
public synchronized boolean passTile(JobTile jobTile) {
|
public synchronized boolean passTile(JobTile jobTile) {
|
||||||
MapTile tile = (MapTile) jobTile;
|
MapTile tile = (MapTile) jobTile;
|
||||||
|
|
||||||
if (!tile.isLoading) {
|
// XXX this is concurrent with updateVisiblelist which set loading false
|
||||||
// no one should be able to use this tile now, TileGenerator passed
|
// temporarily
|
||||||
// it, GL-Thread does nothing until newdata is set.
|
// if (!tile.isLoading) {
|
||||||
Log.d(TAG, "passTile: canceled " + tile);
|
// // no one should be able to use this tile now, TileGenerator passed
|
||||||
synchronized (mTilesLoaded) {
|
// // it, GL-Thread does nothing until newdata is set.
|
||||||
mTilesLoaded.add(tile);
|
// Log.d(TAG, "passTile: canceled " + tile);
|
||||||
}
|
// return true;
|
||||||
return true;
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
|
// synchronized (tile) {
|
||||||
|
if (tile.vbo == null) {
|
||||||
tile.vbo = BufferObject.get();
|
tile.vbo = BufferObject.get();
|
||||||
|
|
||||||
if (tile.vbo == null) {
|
if (tile.vbo == null) {
|
||||||
@ -575,25 +680,29 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
tile.isLoading = false;
|
tile.isLoading = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
Log.d(TAG, "tile loaded before " + tile);
|
||||||
|
|
||||||
tile.newData = true;
|
tile.newData = true;
|
||||||
tile.isLoading = false;
|
tile.isLoading = false;
|
||||||
|
// }
|
||||||
|
|
||||||
if (!MapView.debugFrameTime)
|
if (!MapView.debugFrameTime)
|
||||||
requestRender();
|
requestRender();
|
||||||
|
|
||||||
synchronized (mTilesLoaded) {
|
synchronized (mTilesLoaded) {
|
||||||
|
if (!mTilesLoaded.contains(tile))
|
||||||
mTilesLoaded.add(tile);
|
mTilesLoaded.add(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRenderTheme(RenderTheme t) {
|
// public void setRenderTheme(RenderTheme t) {
|
||||||
if (mRenderer != null)
|
// if (mRenderer != null)
|
||||||
mRenderer.setRenderTheme(t);
|
// mRenderer.setRenderTheme(t);
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
|
@ -16,6 +16,7 @@ package org.oscim.renderer;
|
|||||||
|
|
||||||
import org.oscim.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
import org.oscim.renderer.layer.Layers;
|
import org.oscim.renderer.layer.Layers;
|
||||||
|
import org.oscim.renderer.layer.TextItem;
|
||||||
|
|
||||||
class MapTile extends JobTile {
|
class MapTile extends JobTile {
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ class MapTile extends JobTile {
|
|||||||
*/
|
*/
|
||||||
BufferObject vbo;
|
BufferObject vbo;
|
||||||
|
|
||||||
TextTexture texture;
|
// TextTexture texture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tile data set by TileGenerator:
|
* Tile data set by TileGenerator:
|
||||||
@ -56,10 +57,14 @@ class MapTile extends JobTile {
|
|||||||
int lastDraw = 0;
|
int lastDraw = 0;
|
||||||
|
|
||||||
// keep track which tiles are locked as proxy for this tile
|
// keep track which tiles are locked as proxy for this tile
|
||||||
final static int PROXY_PARENT = 16;
|
final static int PROXY_CHILD1 = 1 << 0;
|
||||||
final static int PROXY_GRAMPA = 32;
|
final static int PROXY_CHILD2 = 1 << 1;
|
||||||
final static int PROXY_HOLDER = 64;
|
final static int PROXY_CHILD3 = 1 << 2;
|
||||||
// 1-8: children
|
final static int PROXY_CHILD4 = 1 << 3;
|
||||||
|
final static int PROXY_PARENT = 1 << 4;
|
||||||
|
final static int PROXY_GRAMPA = 1 << 5;
|
||||||
|
final static int PROXY_HOLDER = 1 << 6;
|
||||||
|
|
||||||
byte proxies;
|
byte proxies;
|
||||||
|
|
||||||
// counting the tiles that use this tile as proxy
|
// counting the tiles that use this tile as proxy
|
||||||
@ -83,8 +88,6 @@ class MapTile extends JobTile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lock() {
|
void lock() {
|
||||||
if (holder != null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
locked++;
|
locked++;
|
||||||
|
|
||||||
@ -116,28 +119,22 @@ class MapTile extends JobTile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void unlock() {
|
void unlock() {
|
||||||
if (holder != null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
locked--;
|
locked--;
|
||||||
|
|
||||||
if (locked > 0 || proxies == 0)
|
if (locked > 0 || proxies == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((proxies & (1 << 4)) != 0) {
|
if ((proxies & PROXY_PARENT) != 0)
|
||||||
MapTile p = rel.parent.tile;
|
rel.parent.tile.refs--;
|
||||||
p.refs--;
|
|
||||||
}
|
if ((proxies & PROXY_GRAMPA) != 0)
|
||||||
if ((proxies & (1 << 5)) != 0) {
|
rel.parent.parent.tile.refs--;
|
||||||
MapTile p = rel.parent.parent.tile;
|
|
||||||
p.refs--;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if ((proxies & (1 << i)) != 0) {
|
if ((proxies & (1 << i)) != 0)
|
||||||
rel.child[i].tile.refs--;
|
rel.child[i].tile.refs--;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
proxies = 0;
|
proxies = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,121 +14,79 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.renderer.layer.Layer;
|
import org.oscim.renderer.layer.Layer;
|
||||||
import org.oscim.renderer.layer.Layers;
|
import org.oscim.renderer.layer.Layers;
|
||||||
import org.oscim.renderer.layer.LineLayer;
|
import org.oscim.utils.FastMath;
|
||||||
import org.oscim.renderer.layer.SymbolItem;
|
|
||||||
import org.oscim.renderer.layer.SymbolLayer;
|
|
||||||
import org.oscim.theme.renderinstruction.BitmapUtils;
|
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Paint.Cap;
|
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.Matrix;
|
import android.opengl.Matrix;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
public class Overlay {
|
public abstract class Overlay {
|
||||||
|
|
||||||
|
protected final MapView mMapView;
|
||||||
|
protected MapPosition mMapPosition;
|
||||||
|
protected final Layers layers;
|
||||||
|
|
||||||
BufferObject vbo;
|
|
||||||
Layers layers;
|
|
||||||
TextItem labels;
|
|
||||||
TextTexture texture;
|
|
||||||
// flag to set when data is ready for (re)compilation.
|
// flag to set when data is ready for (re)compilation.
|
||||||
boolean newData;
|
protected boolean newData;
|
||||||
boolean isReady;
|
|
||||||
MapPosition mMapPosition;
|
|
||||||
|
|
||||||
float drawScale;
|
// flag set by GLRenderer when data is compiled
|
||||||
|
protected boolean isReady;
|
||||||
|
|
||||||
private boolean first = true;
|
protected BufferObject vbo;
|
||||||
|
|
||||||
Overlay() {
|
Overlay(MapView mapView) {
|
||||||
|
mMapView = mapView;
|
||||||
mMapPosition = new MapPosition();
|
mMapPosition = new MapPosition();
|
||||||
|
|
||||||
layers = new Layers();
|
layers = new Layers();
|
||||||
|
|
||||||
LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
|
||||||
ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
|
||||||
ll.width = 2;
|
|
||||||
float[] points = { -100, -100, 100, -100, 100, 100, -100, 100, -100,
|
|
||||||
-100 };
|
|
||||||
short[] index = { (short) points.length };
|
|
||||||
ll.addLine(points, index, false);
|
|
||||||
//
|
|
||||||
// PolygonLayer pl = (PolygonLayer) layers.getLayer(0, Layer.POLYGON);
|
|
||||||
// pl.area = new Area(Color.argb(128, 255, 0, 0));
|
|
||||||
//
|
|
||||||
// float[] ppoints = {
|
|
||||||
// 0, 256,
|
|
||||||
// 0, 0,
|
|
||||||
// 256, 0,
|
|
||||||
// 256, 256,
|
|
||||||
// };
|
|
||||||
// short[] pindex = { (short) ppoints.length };
|
|
||||||
// pl.addPolygon(ppoints, pindex);
|
|
||||||
|
|
||||||
SymbolLayer sl = new SymbolLayer();
|
|
||||||
SymbolItem it = new SymbolItem();
|
|
||||||
|
|
||||||
it.x = 0;
|
|
||||||
it.y = 0;
|
|
||||||
// billboard always faces camera
|
|
||||||
it.billboard = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
sl.addSymbol(it);
|
|
||||||
|
|
||||||
SymbolItem it2 = new SymbolItem();
|
|
||||||
it2.bitmap = it.bitmap;
|
|
||||||
it2.x = 0;
|
|
||||||
it2.y = 0;
|
|
||||||
// billboard always faces camera
|
|
||||||
it2.billboard = false;
|
|
||||||
|
|
||||||
sl.addSymbol(it2);
|
|
||||||
|
|
||||||
layers.symbolLayers = sl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized boolean onTouch() {
|
synchronized boolean onTouch(boolean down) {
|
||||||
|
Log.d("...", "Overlay handle onTouch " + down);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update mMapPosition
|
||||||
|
*
|
||||||
|
* @return true if position has changed
|
||||||
|
*/
|
||||||
|
protected boolean updateMapPosition() {
|
||||||
|
return mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||||
|
}
|
||||||
|
|
||||||
// /////////////// called from GLRender Thread ////////////////////////
|
// /////////////// called from GLRender Thread ////////////////////////
|
||||||
// use synchronized (this){} when updating 'layers' from another thread
|
// use synchronized (this){} when updating 'layers' from another thread
|
||||||
|
|
||||||
synchronized void update(MapView mapView) {
|
/**
|
||||||
// keep position constant (or update layer relative to new position)
|
* @param positionChanged
|
||||||
// mapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
* true when MapPosition has changed
|
||||||
|
* @param tilesChanged
|
||||||
if (first) {
|
* true when loaded tiles changed
|
||||||
// fix at initial position
|
*/
|
||||||
mapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
synchronized void update(boolean positionChanged, boolean tilesChanged) {
|
||||||
first = false;
|
// // keep position constant (or update layer relative to new position)
|
||||||
|
// mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||||
// pass layers to be uploaded and drawn to GL Thread
|
//
|
||||||
// afterwards never modify 'layers' outside of this function!
|
// if (first) {
|
||||||
newData = true;
|
// // fix at initial position
|
||||||
}
|
// // mapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||||
|
// first = false;
|
||||||
|
//
|
||||||
|
// // pass layers to be uploaded and drawn to GL Thread
|
||||||
|
// // afterwards never modify 'layers' outside of this function!
|
||||||
|
// newData = true;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] mvp = new float[16];
|
float[] mvp = new float[16];
|
||||||
|
|
||||||
synchronized void render(MapPosition pos, float[] mv, float[] proj) {
|
synchronized void render(MapPosition pos, float[] mv, float[] proj) {
|
||||||
float div = 1;
|
float div = setMatrix(pos, mv);
|
||||||
|
|
||||||
setMatrix(pos, mv);
|
|
||||||
|
|
||||||
Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0);
|
Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0);
|
||||||
|
|
||||||
@ -140,29 +98,32 @@ public class Overlay {
|
|||||||
l = PolygonRenderer.draw(pos, l, mvp, true, false);
|
l = PolygonRenderer.draw(pos, l, mvp, true, false);
|
||||||
} else {
|
} else {
|
||||||
GLES20.glEnable(GLES20.GL_BLEND);
|
GLES20.glEnable(GLES20.GL_BLEND);
|
||||||
l = LineRenderer.draw(pos, l, mvp, div, 0, layers.lineOffset);
|
l = LineRenderer.draw(pos, l, mvp, 1 / div, 0, layers.lineOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Layer l = layers.symbolLayers; l != null;) {
|
// float scale = curPos.scale / div;
|
||||||
l = TextureRenderer.draw(l, 1, proj, mv, layers.symbolOffset);
|
|
||||||
|
for (Layer l = layers.textureLayers; l != null;) {
|
||||||
|
l = TextureRenderer.draw(l, (mMapPosition.scale / pos.scale) * div, proj, mv,
|
||||||
|
layers.texOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMatrix(MapPosition mPos, float[] matrix) {
|
private float setMatrix(MapPosition curPos, float[] matrix) {
|
||||||
|
|
||||||
MapPosition oPos = mMapPosition;
|
MapPosition oPos = mMapPosition;
|
||||||
float div = 1;
|
|
||||||
byte z = oPos.zoomLevel;
|
byte z = oPos.zoomLevel;
|
||||||
int diff = mPos.zoomLevel - z;
|
// int diff = curPos.zoomLevel - z;
|
||||||
|
float div = FastMath.pow(z - curPos.zoomLevel);
|
||||||
|
// if (diff < 0)
|
||||||
|
// div = (1 << -diff);
|
||||||
|
// else if (diff > 0)
|
||||||
|
// div = (1.0f / (1 << diff));
|
||||||
|
|
||||||
if (diff < 0)
|
float x = (float) (oPos.x - curPos.x * div);
|
||||||
div = (1 << -diff);
|
float y = (float) (oPos.y - curPos.y * div);
|
||||||
else if (diff > 0)
|
|
||||||
div = (1.0f / (1 << diff));
|
|
||||||
|
|
||||||
float x = (float) (oPos.x - mPos.x * div);
|
|
||||||
float y = (float) (oPos.y - mPos.y * div);
|
|
||||||
|
|
||||||
// flip around date-line
|
// flip around date-line
|
||||||
float max = (Tile.TILE_SIZE << z);
|
float max = (Tile.TILE_SIZE << z);
|
||||||
@ -171,7 +132,7 @@ public class Overlay {
|
|||||||
else if (x > max / 2)
|
else if (x > max / 2)
|
||||||
x = x - max;
|
x = x - max;
|
||||||
|
|
||||||
float scale = mPos.scale / div;
|
float scale = curPos.scale / div;
|
||||||
|
|
||||||
Matrix.setIdentityM(matrix, 0);
|
Matrix.setIdentityM(matrix, 0);
|
||||||
|
|
||||||
@ -179,12 +140,14 @@ public class Overlay {
|
|||||||
matrix[12] = x * scale;
|
matrix[12] = x * scale;
|
||||||
matrix[13] = y * scale;
|
matrix[13] = y * scale;
|
||||||
|
|
||||||
scale = (mPos.scale / oPos.scale) / div;
|
scale = (curPos.scale / oPos.scale) / div;
|
||||||
// scale to tile to world coordinates
|
// scale to tile to world coordinates
|
||||||
scale /= GLRenderer.COORD_MULTIPLIER;
|
scale /= GLRenderer.COORD_MULTIPLIER;
|
||||||
matrix[0] = scale;
|
matrix[0] = scale;
|
||||||
matrix[5] = scale;
|
matrix[5] = scale;
|
||||||
|
|
||||||
Matrix.multiplyMM(matrix, 0, mPos.viewMatrix, 0, matrix, 0);
|
Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0);
|
||||||
|
|
||||||
|
return div;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
143
src/org/oscim/renderer/OverlayGrid.java
Normal file
143
src/org/oscim/renderer/OverlayGrid.java
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.renderer;
|
||||||
|
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
|
import org.oscim.renderer.layer.TextItem;
|
||||||
|
import org.oscim.renderer.layer.TextLayer;
|
||||||
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint.Cap;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class OverlayGrid extends Overlay {
|
||||||
|
|
||||||
|
private float[] mPoints;
|
||||||
|
private short[] mIndex;
|
||||||
|
private Text mText;
|
||||||
|
|
||||||
|
OverlayGrid(MapView mapView) {
|
||||||
|
super(mapView);
|
||||||
|
|
||||||
|
int size = Tile.TILE_SIZE;
|
||||||
|
float[] points = new float[64];
|
||||||
|
short[] index = new short[16];
|
||||||
|
|
||||||
|
float pos = -size * 4;
|
||||||
|
|
||||||
|
// vertical lines
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
index[i] = 4;
|
||||||
|
// x1,y1,x2,y2
|
||||||
|
points[i * 4] = pos + i * size;
|
||||||
|
points[i * 4 + 1] = pos + 0;
|
||||||
|
points[i * 4 + 2] = pos + i * size;
|
||||||
|
points[i * 4 + 3] = pos + size * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// horizontal lines
|
||||||
|
for (int j = 8; j < 16; j++) {
|
||||||
|
index[j] = 4;
|
||||||
|
points[j * 4] = pos + 0;
|
||||||
|
points[j * 4 + 1] = pos + (j - 8) * size;
|
||||||
|
points[j * 4 + 2] = pos + size * 8;
|
||||||
|
points[j * 4 + 3] = pos + (j - 8) * size;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIndex = index;
|
||||||
|
mPoints = points;
|
||||||
|
|
||||||
|
// mText = Text.createText(20, 3, Color.BLACK, Color.RED, false);
|
||||||
|
mText = Text.createText(22, 0, Color.RED, 0, false);
|
||||||
|
// mText = Text.createText(22, 0, Color.RED, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLabels(int x, int y, int z) {
|
||||||
|
int size = Tile.TILE_SIZE;
|
||||||
|
|
||||||
|
TextLayer tl = new TextLayer();
|
||||||
|
|
||||||
|
for (int i = -2; i < 2; i++) {
|
||||||
|
for (int j = -2; j < 2; j++) {
|
||||||
|
TextItem ti = TextItem.get().set(size * j + size / 2, size * i + size / 2,
|
||||||
|
(x + j) + " / " + (y + i) + " / " + z, mText);
|
||||||
|
|
||||||
|
// TextItem ti = new TextItem(size * j + size / 2, size * i +
|
||||||
|
// size / 2,
|
||||||
|
// (x + j) + " / " + (y + i) + " / " + z, mText);
|
||||||
|
|
||||||
|
// rotation, TODO could also be used for slide range
|
||||||
|
ti.x1 = 0;
|
||||||
|
ti.y1 = 1; // (short) (size / 2);
|
||||||
|
ti.x2 = 1; // (short) size;
|
||||||
|
ti.y2 = 1; // (short) (size / 2);
|
||||||
|
tl.addText(ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layers.textureLayers = tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int mCurX = -1;
|
||||||
|
private int mCurY = -1;
|
||||||
|
private byte mCurZ = -1;
|
||||||
|
|
||||||
|
private boolean finished;
|
||||||
|
|
||||||
|
void timerFinished() {
|
||||||
|
Log.d("...", "timer finish!");
|
||||||
|
finished = true;
|
||||||
|
mMapView.redrawMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
synchronized void update(boolean positionChanged, boolean tilesChanged) {
|
||||||
|
|
||||||
|
updateMapPosition();
|
||||||
|
|
||||||
|
// fix map position to tile coordinates
|
||||||
|
float size = Tile.TILE_SIZE;
|
||||||
|
int x = (int) (mMapPosition.x / size);
|
||||||
|
int y = (int) (mMapPosition.y / size);
|
||||||
|
mMapPosition.x = x * size;
|
||||||
|
mMapPosition.y = y * size;
|
||||||
|
|
||||||
|
if (!finished)
|
||||||
|
mMapPosition.scale = 1;
|
||||||
|
|
||||||
|
// update layers when map moved by at least one tile
|
||||||
|
if (x != mCurX || y != mCurY || mMapPosition.zoomLevel != mCurZ) {
|
||||||
|
mCurX = x;
|
||||||
|
mCurY = y;
|
||||||
|
mCurZ = mMapPosition.zoomLevel;
|
||||||
|
|
||||||
|
layers.clear();
|
||||||
|
|
||||||
|
LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||||
|
ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
||||||
|
ll.width = 1.5f;
|
||||||
|
ll.addLine(mPoints, mIndex, false);
|
||||||
|
|
||||||
|
addLabels(x, y, mCurZ);
|
||||||
|
|
||||||
|
newData = true;
|
||||||
|
finished = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
src/org/oscim/renderer/OverlayTest.java
Normal file
110
src/org/oscim/renderer/OverlayTest.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.renderer;
|
||||||
|
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
|
import org.oscim.renderer.layer.TextItem;
|
||||||
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint.Cap;
|
||||||
|
|
||||||
|
public class OverlayTest extends Overlay {
|
||||||
|
|
||||||
|
TextItem labels;
|
||||||
|
|
||||||
|
float drawScale;
|
||||||
|
|
||||||
|
private boolean first = true;
|
||||||
|
|
||||||
|
OverlayTest(MapView mapView) {
|
||||||
|
super(mapView);
|
||||||
|
|
||||||
|
LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||||
|
ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
||||||
|
ll.width = 2;
|
||||||
|
float[] points = { -100, -100, 100, -100, 100, 100, -100, 100, -100, -100 };
|
||||||
|
short[] index = { (short) points.length };
|
||||||
|
ll.addLine(points, index, false);
|
||||||
|
//
|
||||||
|
// PolygonLayer pl = (PolygonLayer) layers.getLayer(0, Layer.POLYGON);
|
||||||
|
// pl.area = new Area(Color.argb(128, 255, 0, 0));
|
||||||
|
//
|
||||||
|
// float[] ppoints = {
|
||||||
|
// 0, 256,
|
||||||
|
// 0, 0,
|
||||||
|
// 256, 0,
|
||||||
|
// 256, 256,
|
||||||
|
// };
|
||||||
|
// short[] pindex = { (short) ppoints.length };
|
||||||
|
// pl.addPolygon(ppoints, pindex);
|
||||||
|
|
||||||
|
// SymbolLayer sl = new SymbolLayer();
|
||||||
|
// SymbolItem it = new SymbolItem();
|
||||||
|
//
|
||||||
|
// it.x = 0;
|
||||||
|
// it.y = 0;
|
||||||
|
// // billboard always faces camera
|
||||||
|
// it.billboard = true;
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// // TODO Auto-generated catch block
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// sl.addSymbol(it);
|
||||||
|
//
|
||||||
|
// SymbolItem it2 = new SymbolItem();
|
||||||
|
// it2.bitmap = it.bitmap;
|
||||||
|
// it2.x = 0;
|
||||||
|
// it2.y = 0;
|
||||||
|
// // billboard always faces camera
|
||||||
|
// it2.billboard = false;
|
||||||
|
//
|
||||||
|
// sl.addSymbol(it2);
|
||||||
|
|
||||||
|
// TextLayer tl = new TextLayer();
|
||||||
|
// Text t = Text.createText(20, 2, Color.WHITE, Color.BLACK, false);
|
||||||
|
// TextItem ti = new TextItem(0, 0, "check one, check two", t);
|
||||||
|
// ti.x1 = 0;
|
||||||
|
// ti.y1 = 0;
|
||||||
|
// ti.x2 = (short) Tile.TILE_SIZE;
|
||||||
|
// ti.y2 = (short) Tile.TILE_SIZE;
|
||||||
|
//
|
||||||
|
// tl.addText(ti);
|
||||||
|
//
|
||||||
|
// layers.textureLayers = tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
synchronized void update(boolean positionChanged, boolean tilesChanged) {
|
||||||
|
// keep position constant (or update layer relative to new position)
|
||||||
|
mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
// fix at initial position
|
||||||
|
// mapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
// pass layers to be uploaded and drawn to GL Thread
|
||||||
|
// afterwards never modify 'layers' outside of this function!
|
||||||
|
newData = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
164
src/org/oscim/renderer/OverlayText.java
Normal file
164
src/org/oscim/renderer/OverlayText.java
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oscim.renderer;
|
||||||
|
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.renderer.MapRenderer.TilesData;
|
||||||
|
import org.oscim.renderer.layer.TextItem;
|
||||||
|
import org.oscim.renderer.layer.TextLayer;
|
||||||
|
import org.oscim.utils.FastMath;
|
||||||
|
import org.oscim.utils.PausableThread;
|
||||||
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.FloatMath;
|
||||||
|
|
||||||
|
public class OverlayText extends Overlay {
|
||||||
|
|
||||||
|
private TilesData tiles;
|
||||||
|
private LabelThread mThread;
|
||||||
|
/* package */boolean mRun;
|
||||||
|
/* package */boolean mRerun;
|
||||||
|
private MapPosition mWorkPos;
|
||||||
|
private TextLayer mWorkLayer;
|
||||||
|
|
||||||
|
class LabelThread extends PausableThread {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doWork() {
|
||||||
|
SystemClock.sleep(250);
|
||||||
|
mRun = false;
|
||||||
|
updateLabels();
|
||||||
|
mMapView.redrawMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getThreadName() {
|
||||||
|
return "Labeling";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean hasWork() {
|
||||||
|
return mRun || mRerun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OverlayText(MapView mapView) {
|
||||||
|
super(mapView);
|
||||||
|
|
||||||
|
mWorkPos = new MapPosition();
|
||||||
|
mThread = new LabelThread();
|
||||||
|
mThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLabels() {
|
||||||
|
tiles = MapRenderer.getActiveTiles(tiles);
|
||||||
|
|
||||||
|
if (tiles.cnt == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mMapView.getMapViewPosition().getMapPosition(mWorkPos, null);
|
||||||
|
|
||||||
|
// TODO tiles might be from another zoomlevel than the current:
|
||||||
|
// this scales MapPosition to the zoomlevel of tiles...
|
||||||
|
int diff = tiles.tiles[0].zoomLevel - mWorkPos.zoomLevel;
|
||||||
|
float div = FastMath.pow(diff);
|
||||||
|
|
||||||
|
// fix map position to tile coordinates
|
||||||
|
float size = Tile.TILE_SIZE;
|
||||||
|
int x = (int) (mWorkPos.x / div / size);
|
||||||
|
int y = (int) (mWorkPos.y / div / size);
|
||||||
|
mWorkPos.x = x * size;
|
||||||
|
mWorkPos.y = y * size;
|
||||||
|
mWorkPos.zoomLevel += diff;
|
||||||
|
mWorkPos.scale = div;
|
||||||
|
|
||||||
|
// Log.d("...", "relabel " + mRerun + " " + x + " " + y);
|
||||||
|
|
||||||
|
TextLayer tl = new TextLayer();
|
||||||
|
|
||||||
|
float angle = (float) Math.toRadians(mWorkPos.angle);
|
||||||
|
float cos = FloatMath.cos(angle);
|
||||||
|
float sin = FloatMath.sin(angle);
|
||||||
|
|
||||||
|
for (int i = 0, n = tiles.cnt; i < n; i++) {
|
||||||
|
MapTile t = tiles.tiles[i];
|
||||||
|
if (!t.isVisible)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int dx = (t.tileX - x) * Tile.TILE_SIZE;
|
||||||
|
int dy = (t.tileY - y) * Tile.TILE_SIZE;
|
||||||
|
// Log.d("...", "update tiles " + dx + " " + dy);
|
||||||
|
|
||||||
|
for (TextItem ti = t.labels; ti != null; ti = ti.next) {
|
||||||
|
|
||||||
|
TextItem ti2 = TextItem.get().move(ti, dx, dy);
|
||||||
|
|
||||||
|
if (!ti.text.caption) {
|
||||||
|
if (cos * (ti.x2 - ti.x1) - sin * (ti.y2 - ti.y1) < 0) {
|
||||||
|
// flip label upside-down
|
||||||
|
ti2.x1 = ti.x2;
|
||||||
|
ti2.y1 = ti.y2;
|
||||||
|
ti2.x2 = ti.x1;
|
||||||
|
ti2.y2 = ti.y1;
|
||||||
|
} else {
|
||||||
|
ti2.x1 = ti.x1;
|
||||||
|
ti2.y1 = ti.y1;
|
||||||
|
ti2.x2 = ti.x2;
|
||||||
|
ti2.y2 = ti.y2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tl.addText(ti2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// everything synchronized?
|
||||||
|
synchronized (this) {
|
||||||
|
mWorkLayer = tl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
synchronized void update(boolean positionChanged, boolean tilesChanged) {
|
||||||
|
// Log.d("...", "update " + tilesChanged + " " + positionChanged);
|
||||||
|
|
||||||
|
if (mWorkLayer != null) {
|
||||||
|
layers.clear();
|
||||||
|
layers.textureLayers = mWorkLayer;
|
||||||
|
mWorkLayer = null;
|
||||||
|
|
||||||
|
// make the 'labeled' MapPosition current
|
||||||
|
MapPosition tmp = mMapPosition;
|
||||||
|
mMapPosition = mWorkPos;
|
||||||
|
mWorkPos = tmp;
|
||||||
|
|
||||||
|
// TODO should return true instead
|
||||||
|
newData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tilesChanged || positionChanged) {
|
||||||
|
|
||||||
|
if (!mRun) {
|
||||||
|
mRun = true;
|
||||||
|
synchronized (mThread) {
|
||||||
|
mThread.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,442 +14,445 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
//import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
//import java.nio.ByteOrder;
|
||||||
import java.nio.ShortBuffer;
|
//import java.nio.ShortBuffer;
|
||||||
|
//
|
||||||
import org.oscim.utils.GlUtils;
|
//import org.oscim.renderer.layer.TextItem;
|
||||||
|
//import org.oscim.utils.GlUtils;
|
||||||
import android.graphics.Bitmap;
|
//
|
||||||
import android.graphics.Canvas;
|
//import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
//import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
//import android.graphics.Color;
|
||||||
import android.opengl.GLES20;
|
//import android.graphics.Paint;
|
||||||
import android.opengl.GLUtils;
|
//import android.opengl.GLES20;
|
||||||
import android.util.FloatMath;
|
//import android.opengl.GLUtils;
|
||||||
import android.util.Log;
|
//import android.util.FloatMath;
|
||||||
|
//import android.util.Log;
|
||||||
public class TextRenderer {
|
//
|
||||||
private static String TAG = "TextRenderer";
|
//public class TextRenderer {
|
||||||
|
// private static String TAG = "TextRenderer";
|
||||||
private final static int TEXTURE_WIDTH = 256;
|
//
|
||||||
private final static int TEXTURE_HEIGHT = 256;
|
// private final static int TEXTURE_WIDTH = 256;
|
||||||
private final static float SCALE = 8.0f;
|
// private final static int TEXTURE_HEIGHT = 256;
|
||||||
private final static int LBIT_MASK = 0xfffffffe;
|
// private final static float SCALE = 8.0f;
|
||||||
// private final static int L2BIT_MASK = 0xfffffffc;
|
// private final static int LBIT_MASK = 0xfffffffe;
|
||||||
|
// // private final static int L2BIT_MASK = 0xfffffffc;
|
||||||
final static int INDICES_PER_SPRITE = 6;
|
//
|
||||||
final static int VERTICES_PER_SPRITE = 4;
|
// final static int INDICES_PER_SPRITE = 6;
|
||||||
final static int SHORTS_PER_VERTICE = 6;
|
// final static int VERTICES_PER_SPRITE = 4;
|
||||||
final static int MAX_LABELS = 35;
|
// final static int SHORTS_PER_VERTICE = 6;
|
||||||
|
// final static int MAX_LABELS = 35;
|
||||||
private static Bitmap mBitmap;
|
//
|
||||||
private static Canvas mCanvas;
|
// private static Bitmap mBitmap;
|
||||||
private static int mFontPadX = 1;
|
// private static Canvas mCanvas;
|
||||||
private static int mFontPadY = 1;
|
// private static int mFontPadX = 1;
|
||||||
private static int mBitmapFormat;
|
// private static int mFontPadY = 1;
|
||||||
private static int mBitmapType;
|
// private static int mBitmapFormat;
|
||||||
private static ShortBuffer mShortBuffer;
|
// private static int mBitmapType;
|
||||||
private static TextTexture[] mTextures;
|
// private static ShortBuffer mShortBuffer;
|
||||||
|
// private static TextTexture[] mTextures;
|
||||||
private static int mIndicesVBO;
|
//
|
||||||
private static int mVerticesVBO;
|
// private static int mIndicesVBO;
|
||||||
|
// private static int mVerticesVBO;
|
||||||
private static int mTextProgram;
|
//
|
||||||
private static int hTextMVMatrix;
|
// private static int mTextProgram;
|
||||||
private static int hTextProjectionMatrix;
|
// private static int hTextMVMatrix;
|
||||||
private static int hTextVertex;
|
// private static int hTextProjectionMatrix;
|
||||||
private static int hTextScale;
|
// private static int hTextVertex;
|
||||||
private static int hTextScreenScale;
|
// private static int hTextScale;
|
||||||
private static int hTextTextureCoord;
|
// private static int hTextScreenScale;
|
||||||
|
// private static int hTextTextureCoord;
|
||||||
private static Paint mPaint = new Paint(Color.BLACK);
|
//
|
||||||
|
// private static Paint mPaint = new Paint(Color.BLACK);
|
||||||
private static boolean debug = false;
|
//
|
||||||
private static short[] debugVertices = {
|
// private static boolean debug = false;
|
||||||
|
// private static short[] debugVertices = {
|
||||||
0, 0,
|
//
|
||||||
0, TEXTURE_HEIGHT * 4,
|
// 0, 0,
|
||||||
|
// 0, TEXTURE_HEIGHT * 4,
|
||||||
0, TEXTURE_HEIGHT - 1,
|
//
|
||||||
0, 0,
|
// 0, TEXTURE_HEIGHT - 1,
|
||||||
|
// 0, 0,
|
||||||
TEXTURE_WIDTH - 1, 0,
|
//
|
||||||
TEXTURE_WIDTH * 4, TEXTURE_HEIGHT * 4,
|
// TEXTURE_WIDTH - 1, 0,
|
||||||
|
// TEXTURE_WIDTH * 4, TEXTURE_HEIGHT * 4,
|
||||||
TEXTURE_WIDTH - 1, TEXTURE_HEIGHT - 1,
|
//
|
||||||
TEXTURE_WIDTH * 4, 0,
|
// TEXTURE_WIDTH - 1, TEXTURE_HEIGHT - 1,
|
||||||
|
// TEXTURE_WIDTH * 4, 0,
|
||||||
};
|
//
|
||||||
|
// };
|
||||||
static void init() {
|
//
|
||||||
mTextProgram = GlUtils.createProgram(Shaders.textVertexShader,
|
// static void init() {
|
||||||
Shaders.textFragmentShader);
|
// mTextProgram = GlUtils.createProgram(Shaders.textVertexShader,
|
||||||
|
// Shaders.textFragmentShader);
|
||||||
hTextMVMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_mv");
|
//
|
||||||
hTextProjectionMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_proj");
|
// hTextMVMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_mv");
|
||||||
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "u_scale");
|
// hTextProjectionMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_proj");
|
||||||
hTextScreenScale = GLES20.glGetUniformLocation(mTextProgram, "u_swidth");
|
// hTextScale = GLES20.glGetUniformLocation(mTextProgram, "u_scale");
|
||||||
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
|
// hTextScreenScale = GLES20.glGetUniformLocation(mTextProgram, "u_swidth");
|
||||||
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
|
// hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
|
||||||
|
// hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
|
||||||
}
|
//
|
||||||
|
// }
|
||||||
static boolean setup(int numTextures) {
|
//
|
||||||
int bufferSize = numTextures
|
// static boolean setup(int numTextures) {
|
||||||
* MAX_LABELS * VERTICES_PER_SPRITE
|
// int bufferSize = numTextures
|
||||||
* SHORTS_PER_VERTICE * (Short.SIZE / 8);
|
// * MAX_LABELS * VERTICES_PER_SPRITE
|
||||||
|
// * SHORTS_PER_VERTICE * (Short.SIZE / 8);
|
||||||
// if (mBitmap == null) {
|
//
|
||||||
mBitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
|
// // if (mBitmap == null) {
|
||||||
Bitmap.Config.ARGB_8888);
|
// mBitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
|
||||||
mCanvas = new Canvas(mBitmap);
|
// Bitmap.Config.ARGB_8888);
|
||||||
|
// mCanvas = new Canvas(mBitmap);
|
||||||
mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
|
//
|
||||||
mBitmapType = GLUtils.getType(mBitmap);
|
// mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
|
||||||
|
// mBitmapType = GLUtils.getType(mBitmap);
|
||||||
ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize)
|
//
|
||||||
.order(ByteOrder.nativeOrder());
|
// ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize)
|
||||||
|
// .order(ByteOrder.nativeOrder());
|
||||||
mShortBuffer = buf.asShortBuffer();
|
//
|
||||||
// }
|
// mShortBuffer = buf.asShortBuffer();
|
||||||
|
// // }
|
||||||
int[] textureIds = new int[numTextures];
|
//
|
||||||
TextTexture[] textures = new TextTexture[numTextures];
|
// int[] textureIds = new int[numTextures];
|
||||||
GLES20.glGenTextures(numTextures, textureIds, 0);
|
// TextTexture[] textures = new TextTexture[numTextures];
|
||||||
|
// GLES20.glGenTextures(numTextures, textureIds, 0);
|
||||||
for (int i = 0; i < numTextures; i++) {
|
//
|
||||||
// setup filters for texture
|
// for (int i = 0; i < numTextures; i++) {
|
||||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[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_MIN_FILTER,
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
|
// GLES20.GL_LINEAR);
|
||||||
GLES20.GL_LINEAR);
|
// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
|
// GLES20.GL_LINEAR);
|
||||||
GLES20.GL_CLAMP_TO_EDGE); // Set U Wrapping
|
// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
|
// GLES20.GL_CLAMP_TO_EDGE); // Set U Wrapping
|
||||||
GLES20.GL_CLAMP_TO_EDGE); // Set V 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, mBitmapFormat, mBitmap,
|
// // load the generated bitmap onto the texture
|
||||||
mBitmapType, 0);
|
// GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBitmapFormat, mBitmap,
|
||||||
|
// mBitmapType, 0);
|
||||||
textures[i] = new TextTexture(textureIds[i]);
|
//
|
||||||
}
|
// textures[i] = new TextTexture(textureIds[i]);
|
||||||
|
// }
|
||||||
GlUtils.checkGlError("init textures");
|
//
|
||||||
|
// GlUtils.checkGlError("init textures");
|
||||||
mTextures = textures;
|
//
|
||||||
|
// mTextures = textures;
|
||||||
// Setup triangle indices
|
//
|
||||||
short[] indices = new short[MAX_LABELS * INDICES_PER_SPRITE];
|
// // Setup triangle indices
|
||||||
int len = indices.length;
|
// short[] indices = new short[MAX_LABELS * INDICES_PER_SPRITE];
|
||||||
short j = 0;
|
// int len = indices.length;
|
||||||
for (int i = 0; i < len; i += INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE) {
|
// short j = 0;
|
||||||
indices[i + 0] = (short) (j + 0);
|
// for (int i = 0; i < len; i += INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE) {
|
||||||
indices[i + 1] = (short) (j + 1);
|
// indices[i + 0] = (short) (j + 0);
|
||||||
indices[i + 2] = (short) (j + 2);
|
// indices[i + 1] = (short) (j + 1);
|
||||||
indices[i + 3] = (short) (j + 2);
|
// indices[i + 2] = (short) (j + 2);
|
||||||
indices[i + 4] = (short) (j + 3);
|
// indices[i + 3] = (short) (j + 2);
|
||||||
indices[i + 5] = (short) (j + 0);
|
// indices[i + 4] = (short) (j + 3);
|
||||||
}
|
// indices[i + 5] = (short) (j + 0);
|
||||||
|
// }
|
||||||
mShortBuffer.clear();
|
//
|
||||||
mShortBuffer.put(indices, 0, len);
|
// mShortBuffer.clear();
|
||||||
mShortBuffer.flip();
|
// mShortBuffer.put(indices, 0, len);
|
||||||
|
// mShortBuffer.flip();
|
||||||
int[] mVboIds = new int[2];
|
//
|
||||||
GLES20.glGenBuffers(2, mVboIds, 0);
|
// int[] mVboIds = new int[2];
|
||||||
mIndicesVBO = mVboIds[0];
|
// GLES20.glGenBuffers(2, mVboIds, 0);
|
||||||
mVerticesVBO = mVboIds[1];
|
// mIndicesVBO = mVboIds[0];
|
||||||
|
// mVerticesVBO = mVboIds[1];
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
//
|
||||||
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, len * (Short.SIZE / 8),
|
// GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
||||||
mShortBuffer, GLES20.GL_STATIC_DRAW);
|
// GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, len * (Short.SIZE / 8),
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
// mShortBuffer, GLES20.GL_STATIC_DRAW);
|
||||||
|
// GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
mShortBuffer.clear();
|
//
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
// mShortBuffer.clear();
|
||||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, bufferSize,
|
// GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
||||||
mShortBuffer, GLES20.GL_DYNAMIC_DRAW);
|
// GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, bufferSize,
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
// mShortBuffer, GLES20.GL_DYNAMIC_DRAW);
|
||||||
|
// GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||||
return true;
|
//
|
||||||
}
|
// return true;
|
||||||
|
// }
|
||||||
static boolean drawToTexture(MapTile tile) {
|
//
|
||||||
TextTexture tex = null;
|
// static boolean drawToTexture(MapTile tile) {
|
||||||
|
// TextTexture tex = null;
|
||||||
if (tile.labels == null)
|
//
|
||||||
return false;
|
// if (tile.labels == null)
|
||||||
|
// return false;
|
||||||
for (int i = 0; i < mTextures.length; i++) {
|
//
|
||||||
tex = mTextures[i];
|
// for (int i = 0; i < mTextures.length; i++) {
|
||||||
if (tex.tile == null)
|
// tex = mTextures[i];
|
||||||
break;
|
// if (tex.tile == null)
|
||||||
|
// break;
|
||||||
if (!tex.tile.isLocked())
|
//
|
||||||
break;
|
// if (!tex.tile.isLocked())
|
||||||
|
// break;
|
||||||
tex = null;
|
//
|
||||||
}
|
// tex = null;
|
||||||
|
// }
|
||||||
if (tex == null) {
|
//
|
||||||
for (int i = 0; i < mTextures.length; i++) {
|
// if (tex == null) {
|
||||||
tex = mTextures[i];
|
// for (int i = 0; i < mTextures.length; i++) {
|
||||||
if (!tex.tile.isVisible)
|
// tex = mTextures[i];
|
||||||
break;
|
// if (!tex.tile.isVisible)
|
||||||
|
// break;
|
||||||
tex = null;
|
//
|
||||||
}
|
// tex = null;
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
if (tex == null) {
|
//
|
||||||
Log.d(TAG, "no textures left");
|
// if (tex == null) {
|
||||||
return false;
|
// Log.d(TAG, "no textures left");
|
||||||
}
|
// return false;
|
||||||
if (tex.tile != null)
|
// }
|
||||||
tex.tile.texture = null;
|
// if (tex.tile != null)
|
||||||
|
// tex.tile.texture = null;
|
||||||
mBitmap.eraseColor(Color.TRANSPARENT);
|
//
|
||||||
|
// mBitmap.eraseColor(Color.TRANSPARENT);
|
||||||
int pos = 0;
|
//
|
||||||
short[] buf = tex.vertices;
|
// int pos = 0;
|
||||||
|
// short[] buf = tex.vertices;
|
||||||
float y = 0;
|
//
|
||||||
float x = mFontPadX;
|
// float y = 0;
|
||||||
float width, height;
|
// float x = mFontPadX;
|
||||||
|
// float width, height;
|
||||||
int max = MAX_LABELS;
|
//
|
||||||
|
// int max = MAX_LABELS;
|
||||||
if (debug) {
|
//
|
||||||
mCanvas.drawLine(debugVertices[0], debugVertices[1], debugVertices[4],
|
// if (debug) {
|
||||||
debugVertices[5], mPaint);
|
// mCanvas.drawLine(debugVertices[0], debugVertices[1], debugVertices[4],
|
||||||
mCanvas.drawLine(debugVertices[0], debugVertices[1], debugVertices[8],
|
// debugVertices[5], mPaint);
|
||||||
debugVertices[9], 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[4],
|
||||||
mCanvas.drawLine(debugVertices[12], debugVertices[13], debugVertices[8],
|
// debugVertices[5], mPaint);
|
||||||
debugVertices[9], mPaint);
|
// mCanvas.drawLine(debugVertices[12], debugVertices[13], debugVertices[8],
|
||||||
}
|
// debugVertices[9], mPaint);
|
||||||
|
// }
|
||||||
int advanceY = 0;
|
//
|
||||||
|
// int advanceY = 0;
|
||||||
TextItem t = tile.labels;
|
//
|
||||||
float yy;
|
// TextItem t = tile.labels;
|
||||||
|
// float yy;
|
||||||
for (int i = 0; t != null && i < max; t = t.next, i++) {
|
//
|
||||||
|
// for (int i = 0; t != null && i < max; t = t.next, i++) {
|
||||||
height = (int) (t.text.fontHeight) + 2 * mFontPadY;
|
// if (t.text.caption)
|
||||||
width = t.width + 2 * mFontPadX;
|
// continue;
|
||||||
|
//
|
||||||
if (height > advanceY)
|
// height = (int) (t.text.fontHeight) + 2 * mFontPadY;
|
||||||
advanceY = (int) height;
|
// width = t.width + 2 * mFontPadX;
|
||||||
|
//
|
||||||
if (x + width > TEXTURE_WIDTH) {
|
// if (height > advanceY)
|
||||||
x = mFontPadX;
|
// advanceY = (int) height;
|
||||||
y += advanceY;
|
//
|
||||||
advanceY = (int) height;
|
// if (x + width > TEXTURE_WIDTH) {
|
||||||
}
|
// x = mFontPadX;
|
||||||
|
// y += advanceY;
|
||||||
yy = y + (height - 1) - t.text.fontDescent - mFontPadY;
|
// advanceY = (int) height;
|
||||||
if (yy > TEXTURE_HEIGHT) {
|
// }
|
||||||
Log.d(TAG, "reached max labels");
|
//
|
||||||
break;
|
// yy = y + (height - 1) - t.text.fontDescent - mFontPadY;
|
||||||
// continue;
|
// if (yy > TEXTURE_HEIGHT) {
|
||||||
}
|
// Log.d(TAG, "reached max labels");
|
||||||
|
// break;
|
||||||
if (t.text.stroke != null)
|
// // continue;
|
||||||
mCanvas.drawText(t.string, x + t.width / 2, yy, t.text.stroke);
|
// }
|
||||||
|
//
|
||||||
mCanvas.drawText(t.string, x + t.width / 2, yy, t.text.paint);
|
// if (t.text.stroke != null)
|
||||||
|
// mCanvas.drawText(t.string, x + t.width / 2, yy, t.text.stroke);
|
||||||
if (width > TEXTURE_WIDTH)
|
//
|
||||||
width = TEXTURE_WIDTH;
|
// mCanvas.drawText(t.string, x + t.width / 2, yy, t.text.paint);
|
||||||
|
//
|
||||||
float hw = width / 2.0f;
|
// if (width > TEXTURE_WIDTH)
|
||||||
float hh = height / 2.0f;
|
// width = TEXTURE_WIDTH;
|
||||||
short x1, x2, x3, x4, y1, y2, y3, y4;
|
//
|
||||||
|
// float hw = width / 2.0f;
|
||||||
if (t.text.caption) {
|
// float hh = height / 2.0f;
|
||||||
x1 = x3 = (short) (SCALE * (-hw));
|
// short x1, x2, x3, x4, y1, y2, y3, y4;
|
||||||
y1 = y3 = (short) (SCALE * (hh));
|
//
|
||||||
x2 = x4 = (short) (SCALE * (hw));
|
// if (t.text.caption) {
|
||||||
y2 = y4 = (short) (SCALE * (-hh));
|
// x1 = x3 = (short) (SCALE * (-hw));
|
||||||
} else {
|
// y1 = y3 = (short) (SCALE * (hh));
|
||||||
float vx = t.x1 - t.x2;
|
// x2 = x4 = (short) (SCALE * (hw));
|
||||||
float vy = t.y1 - t.y2;
|
// y2 = y4 = (short) (SCALE * (-hh));
|
||||||
float a = FloatMath.sqrt(vx * vx + vy * vy);
|
// } else {
|
||||||
vx = vx / a;
|
// float vx = t.x1 - t.x2;
|
||||||
vy = vy / a;
|
// float vy = t.y1 - t.y2;
|
||||||
|
// float a = FloatMath.sqrt(vx * vx + vy * vy);
|
||||||
float ux = -vy;
|
// vx = vx / a;
|
||||||
float uy = vx;
|
// vy = vy / a;
|
||||||
|
//
|
||||||
// int dx = (int) (vx * SCALE) & L2BIT_MASK;
|
// float ux = -vy;
|
||||||
// int dy = (int) (vy * SCALE) & L2BIT_MASK;
|
// float uy = vx;
|
||||||
//
|
//
|
||||||
// x1 = (short) dx;
|
// // int dx = (int) (vx * SCALE) & L2BIT_MASK;
|
||||||
// y1 = (short) dy;
|
// // int dy = (int) (vy * SCALE) & L2BIT_MASK;
|
||||||
//
|
// //
|
||||||
// x2 = (short) (dx | 1);
|
// // x1 = (short) dx;
|
||||||
// y3 = (short) (dy | 1);
|
// // y1 = (short) dy;
|
||||||
//
|
// //
|
||||||
// x4 = (short) (dx | 3);
|
// // x2 = (short) (dx | 1);
|
||||||
// y4 = (short) (dy | 3);
|
// // y3 = (short) (dy | 1);
|
||||||
//
|
// //
|
||||||
// x3 = (short) (dx | 2);
|
// // x4 = (short) (dx | 3);
|
||||||
// y2 = (short) (dy | 2);
|
// // y4 = (short) (dy | 3);
|
||||||
|
// //
|
||||||
x1 = (short) (SCALE * (vx * hw - ux * hh));
|
// // x3 = (short) (dx | 2);
|
||||||
y1 = (short) (SCALE * (vy * hw - uy * hh));
|
// // y2 = (short) (dy | 2);
|
||||||
x2 = (short) (SCALE * (-vx * hw - ux * hh));
|
//
|
||||||
y3 = (short) (SCALE * (-vy * hw - uy * hh));
|
// x1 = (short) (SCALE * (vx * hw - ux * hh));
|
||||||
x4 = (short) (SCALE * (-vx * hw + ux * hh));
|
// y1 = (short) (SCALE * (vy * hw - uy * hh));
|
||||||
y4 = (short) (SCALE * (-vy * hw + uy * hh));
|
// x2 = (short) (SCALE * (-vx * hw - ux * hh));
|
||||||
x3 = (short) (SCALE * (vx * hw + ux * hh));
|
// y3 = (short) (SCALE * (-vy * hw - uy * hh));
|
||||||
y2 = (short) (SCALE * (vy * hw + uy * hh));
|
// x4 = (short) (SCALE * (-vx * hw + ux * hh));
|
||||||
|
// y4 = (short) (SCALE * (-vy * hw + uy * hh));
|
||||||
}
|
// x3 = (short) (SCALE * (vx * hw + ux * hh));
|
||||||
short u1 = (short) (SCALE * x);
|
// y2 = (short) (SCALE * (vy * hw + uy * hh));
|
||||||
short v1 = (short) (SCALE * y);
|
//
|
||||||
short u2 = (short) (SCALE * (x + width));
|
// }
|
||||||
short v2 = (short) (SCALE * (y + height));
|
// short u1 = (short) (SCALE * x);
|
||||||
|
// short v1 = (short) (SCALE * y);
|
||||||
// pack caption/way-text info in lowest bit
|
// short u2 = (short) (SCALE * (x + width));
|
||||||
int tmp = (int) (SCALE * t.x) & LBIT_MASK;
|
// short v2 = (short) (SCALE * (y + height));
|
||||||
short tx = (short) (tmp | (t.text.caption ? 1 : 0));
|
//
|
||||||
|
// // pack caption/way-text info in lowest bit
|
||||||
short ty = (short) (SCALE * t.y);
|
// int tmp = (int) (SCALE * t.x) & LBIT_MASK;
|
||||||
|
// short tx = (short) (tmp | (t.text.caption ? 1 : 0));
|
||||||
// top-left
|
//
|
||||||
buf[pos++] = tx;
|
// short ty = (short) (SCALE * t.y);
|
||||||
buf[pos++] = ty;
|
//
|
||||||
buf[pos++] = x1;
|
// // top-left
|
||||||
buf[pos++] = y1;
|
// buf[pos++] = tx;
|
||||||
buf[pos++] = u1;
|
// buf[pos++] = ty;
|
||||||
buf[pos++] = v2;
|
// buf[pos++] = x1;
|
||||||
|
// buf[pos++] = y1;
|
||||||
// top-right
|
// buf[pos++] = u1;
|
||||||
buf[pos++] = tx;
|
// buf[pos++] = v2;
|
||||||
buf[pos++] = ty;
|
//
|
||||||
buf[pos++] = x2;
|
// // top-right
|
||||||
buf[pos++] = y3;
|
// buf[pos++] = tx;
|
||||||
buf[pos++] = u2;
|
// buf[pos++] = ty;
|
||||||
buf[pos++] = v2;
|
// buf[pos++] = x2;
|
||||||
|
// buf[pos++] = y3;
|
||||||
// bot-right
|
// buf[pos++] = u2;
|
||||||
buf[pos++] = tx;
|
// buf[pos++] = v2;
|
||||||
buf[pos++] = ty;
|
//
|
||||||
buf[pos++] = x4;
|
// // bot-right
|
||||||
buf[pos++] = y4;
|
// buf[pos++] = tx;
|
||||||
buf[pos++] = u2;
|
// buf[pos++] = ty;
|
||||||
buf[pos++] = v1;
|
// buf[pos++] = x4;
|
||||||
|
// buf[pos++] = y4;
|
||||||
// bot-left
|
// buf[pos++] = u2;
|
||||||
buf[pos++] = tx;
|
// buf[pos++] = v1;
|
||||||
buf[pos++] = ty;
|
//
|
||||||
buf[pos++] = x3;
|
// // bot-left
|
||||||
buf[pos++] = y2;
|
// buf[pos++] = tx;
|
||||||
buf[pos++] = u1;
|
// buf[pos++] = ty;
|
||||||
buf[pos++] = v1;
|
// buf[pos++] = x3;
|
||||||
|
// buf[pos++] = y2;
|
||||||
x += width;
|
// buf[pos++] = u1;
|
||||||
|
// buf[pos++] = v1;
|
||||||
if (y > TEXTURE_HEIGHT) {
|
//
|
||||||
Log.d(TAG, "reached max labels: texture is full");
|
// x += width;
|
||||||
break;
|
//
|
||||||
}
|
// if (y > TEXTURE_HEIGHT) {
|
||||||
}
|
// Log.d(TAG, "reached max labels: texture is full");
|
||||||
|
// break;
|
||||||
tex.length = pos;
|
// }
|
||||||
tile.texture = tex;
|
// }
|
||||||
tex.tile = tile;
|
//
|
||||||
|
// tex.length = pos;
|
||||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.id);
|
// tile.texture = tex;
|
||||||
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap,
|
// tex.tile = tile;
|
||||||
mBitmapFormat, mBitmapType);
|
//
|
||||||
|
// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex.id);
|
||||||
// FIXME shouldnt be needed here, still looking for sometimes corrupted
|
// GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap,
|
||||||
// labels..
|
// mBitmapFormat, mBitmapType);
|
||||||
GLES20.glFlush();
|
//
|
||||||
|
// // FIXME shouldnt be needed here, still looking for sometimes corrupted
|
||||||
return true;
|
// // labels..
|
||||||
}
|
// GLES20.glFlush();
|
||||||
|
//
|
||||||
static void compileTextures() {
|
// return true;
|
||||||
int offset = 0;
|
// }
|
||||||
TextTexture tex;
|
//
|
||||||
|
// static void compileTextures() {
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
// int offset = 0;
|
||||||
|
// TextTexture tex;
|
||||||
mShortBuffer.clear();
|
//
|
||||||
|
// GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
||||||
for (int i = 0; i < mTextures.length; i++) {
|
//
|
||||||
tex = mTextures[i];
|
// mShortBuffer.clear();
|
||||||
if (tex.tile == null) // || !tex.tile.isLocked)
|
//
|
||||||
continue;
|
// for (int i = 0; i < mTextures.length; i++) {
|
||||||
|
// tex = mTextures[i];
|
||||||
mShortBuffer.put(tex.vertices, 0, tex.length);
|
// if (tex.tile == null) // || !tex.tile.isLocked)
|
||||||
tex.offset = offset;
|
// continue;
|
||||||
offset += tex.length;
|
//
|
||||||
}
|
// mShortBuffer.put(tex.vertices, 0, tex.length);
|
||||||
|
// tex.offset = offset;
|
||||||
mShortBuffer.flip();
|
// offset += tex.length;
|
||||||
|
// }
|
||||||
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, offset * (Short.SIZE / 8),
|
//
|
||||||
mShortBuffer);
|
// mShortBuffer.flip();
|
||||||
}
|
//
|
||||||
|
// GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, offset * (Short.SIZE / 8),
|
||||||
static void beginDraw(float scale, float[] projection) {
|
// mShortBuffer);
|
||||||
GLES20.glUseProgram(mTextProgram);
|
// }
|
||||||
|
//
|
||||||
// GLES20.glEnableVertexAttribArray(hTextTextureCoord);
|
// static void beginDraw(float scale, float[] projection) {
|
||||||
// GLES20.glEnableVertexAttribArray(hTextVertex);
|
// GLES20.glUseProgram(mTextProgram);
|
||||||
|
//
|
||||||
int va = hTextTextureCoord;
|
// // GLES20.glEnableVertexAttribArray(hTextTextureCoord);
|
||||||
if (!GLRenderer.vertexArray[va]) {
|
// // GLES20.glEnableVertexAttribArray(hTextVertex);
|
||||||
GLES20.glEnableVertexAttribArray(va);
|
//
|
||||||
GLRenderer.vertexArray[va] = true;
|
// int va = hTextTextureCoord;
|
||||||
}
|
// if (!GLRenderer.vertexArray[va]) {
|
||||||
|
// GLES20.glEnableVertexAttribArray(va);
|
||||||
va = hTextVertex;
|
// GLRenderer.vertexArray[va] = true;
|
||||||
if (!GLRenderer.vertexArray[va]) {
|
// }
|
||||||
GLES20.glEnableVertexAttribArray(va);
|
//
|
||||||
GLRenderer.vertexArray[va] = true;
|
// va = hTextVertex;
|
||||||
}
|
// if (!GLRenderer.vertexArray[va]) {
|
||||||
|
// GLES20.glEnableVertexAttribArray(va);
|
||||||
GLES20.glUniform1f(hTextScale, scale);
|
// GLRenderer.vertexArray[va] = true;
|
||||||
GLES20.glUniform1f(hTextScreenScale, 1f / GLRenderer.mWidth);
|
// }
|
||||||
GLES20.glUniformMatrix4fv(hTextProjectionMatrix, 1, false, projection, 0);
|
//
|
||||||
|
// GLES20.glUniform1f(hTextScale, scale);
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
// GLES20.glUniform1f(hTextScreenScale, 1f / GLRenderer.mWidth);
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
// GLES20.glUniformMatrix4fv(hTextProjectionMatrix, 1, false, projection, 0);
|
||||||
}
|
//
|
||||||
|
// GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
||||||
static void endDraw() {
|
// GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
// }
|
||||||
|
//
|
||||||
// GLES20.glDisableVertexAttribArray(hTextTextureCoord);
|
// static void endDraw() {
|
||||||
// GLES20.glDisableVertexAttribArray(hTextVertex);
|
// GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
//
|
||||||
|
// // GLES20.glDisableVertexAttribArray(hTextTextureCoord);
|
||||||
static void drawTile(MapTile tile, float[] matrix) {
|
// // GLES20.glDisableVertexAttribArray(hTextVertex);
|
||||||
|
// }
|
||||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.texture.id);
|
//
|
||||||
|
// static void drawTile(MapTile tile, float[] matrix) {
|
||||||
GLES20.glUniformMatrix4fv(hTextMVMatrix, 1, false, matrix, 0);
|
//
|
||||||
|
// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.texture.id);
|
||||||
GLES20.glVertexAttribPointer(hTextVertex, 4,
|
//
|
||||||
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8));
|
// GLES20.glUniformMatrix4fv(hTextMVMatrix, 1, false, matrix, 0);
|
||||||
|
//
|
||||||
GLES20.glVertexAttribPointer(hTextTextureCoord, 2,
|
// GLES20.glVertexAttribPointer(hTextVertex, 4,
|
||||||
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8)
|
// GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8));
|
||||||
+ 8);
|
//
|
||||||
|
// GLES20.glVertexAttribPointer(hTextTextureCoord, 2,
|
||||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 24) *
|
// GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8)
|
||||||
INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
|
// + 8);
|
||||||
}
|
//
|
||||||
}
|
// GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 24) *
|
||||||
|
// INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@ -14,20 +14,20 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
public class TextTexture {
|
//public class TextTexture {
|
||||||
|
//
|
||||||
final short[] vertices;
|
// final short[] vertices;
|
||||||
final int id;
|
// final int id;
|
||||||
int length;
|
// int length;
|
||||||
int offset;
|
// int offset;
|
||||||
MapTile tile;
|
// MapTile tile;
|
||||||
|
//
|
||||||
TextTexture(int textureID) {
|
// TextTexture(int textureID) {
|
||||||
vertices = new short[TextRenderer.MAX_LABELS *
|
// vertices = new short[TextRenderer.MAX_LABELS *
|
||||||
TextRenderer.VERTICES_PER_SPRITE *
|
// TextRenderer.VERTICES_PER_SPRITE *
|
||||||
TextRenderer.SHORTS_PER_VERTICE];
|
// TextRenderer.SHORTS_PER_VERTICE];
|
||||||
|
//
|
||||||
id = textureID;
|
// id = textureID;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
package org.oscim.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLUtils;
|
import android.opengl.GLUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -22,11 +24,22 @@ import android.util.Log;
|
|||||||
public class TextureObject {
|
public class TextureObject {
|
||||||
private static TextureObject pool;
|
private static TextureObject pool;
|
||||||
|
|
||||||
|
// shared bitmap and canvas for default texture size
|
||||||
|
public final static int TEXTURE_WIDTH = 256;
|
||||||
|
public final static int TEXTURE_HEIGHT = 256;
|
||||||
|
private static Bitmap mBitmap;
|
||||||
|
private static Canvas mCanvas;
|
||||||
|
private static int mBitmapFormat;
|
||||||
|
private static int mBitmapType;
|
||||||
|
private static int objectCount = 10;
|
||||||
|
|
||||||
public static synchronized TextureObject get() {
|
public static synchronized TextureObject get() {
|
||||||
TextureObject to;
|
TextureObject to;
|
||||||
|
|
||||||
if (pool == null) {
|
if (pool == null) {
|
||||||
init(10);
|
init(10);
|
||||||
|
objectCount += 10;
|
||||||
|
Log.d("...", "textures: " + objectCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
to = pool;
|
to = pool;
|
||||||
@ -36,8 +49,15 @@ public class TextureObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void release(TextureObject to) {
|
public static synchronized void release(TextureObject to) {
|
||||||
|
|
||||||
|
while (to != null) {
|
||||||
|
TextureObject next = to.next;
|
||||||
|
|
||||||
to.next = pool;
|
to.next = pool;
|
||||||
pool = to;
|
pool = to;
|
||||||
|
|
||||||
|
to = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void uploadTexture(TextureObject to, Bitmap bitmap,
|
public static void uploadTexture(TextureObject to, Bitmap bitmap,
|
||||||
@ -79,6 +99,30 @@ public class TextureObject {
|
|||||||
to.next = pool;
|
to.next = pool;
|
||||||
pool = to;
|
pool = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
|
||||||
|
Bitmap.Config.ARGB_8888);
|
||||||
|
mCanvas = new Canvas(mBitmap);
|
||||||
|
mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
|
||||||
|
mBitmapType = GLUtils.getType(mBitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Canvas getCanvas() {
|
||||||
|
mBitmap.eraseColor(Color.TRANSPARENT);
|
||||||
|
|
||||||
|
return mCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TextureObject uploadCanvas(short offset, short indices) {
|
||||||
|
TextureObject to = get();
|
||||||
|
uploadTexture(to, mBitmap,
|
||||||
|
mBitmapFormat, mBitmapType,
|
||||||
|
TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||||
|
|
||||||
|
to.offset = offset;
|
||||||
|
to.vertices = (short) (indices - offset);
|
||||||
|
|
||||||
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextureObject next;
|
public TextureObject next;
|
||||||
@ -89,7 +133,8 @@ public class TextureObject {
|
|||||||
|
|
||||||
// vertex offset from which this texture is referenced
|
// vertex offset from which this texture is referenced
|
||||||
// or store texture id with vertex?
|
// or store texture id with vertex?
|
||||||
int offset;
|
short offset;
|
||||||
|
short vertices;
|
||||||
|
|
||||||
TextureObject(int id) {
|
TextureObject(int id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -39,7 +39,7 @@ public class TextureRenderer {
|
|||||||
final static int VERTICES_PER_SPRITE = 4;
|
final static int VERTICES_PER_SPRITE = 4;
|
||||||
final static int SHORTS_PER_VERTICE = 6;
|
final static int SHORTS_PER_VERTICE = 6;
|
||||||
// per texture
|
// per texture
|
||||||
public final static int MAX_ITEMS = 40;
|
public final static int MAX_ITEMS = 50;
|
||||||
|
|
||||||
static void init() {
|
static void init() {
|
||||||
mTextureProgram = GlUtils.createProgram(Shaders.textVertexShader,
|
mTextureProgram = GlUtils.createProgram(Shaders.textVertexShader,
|
||||||
@ -89,6 +89,7 @@ public class TextureRenderer {
|
|||||||
|
|
||||||
static Layer draw(Layer layer, float scale, float[] projection,
|
static Layer draw(Layer layer, float scale, float[] projection,
|
||||||
float matrix[], int offset) {
|
float matrix[], int offset) {
|
||||||
|
|
||||||
GLES20.glUseProgram(mTextureProgram);
|
GLES20.glUseProgram(mTextureProgram);
|
||||||
GlUtils.checkGlError("draw texture1");
|
GlUtils.checkGlError("draw texture1");
|
||||||
|
|
||||||
@ -116,20 +117,25 @@ public class TextureRenderer {
|
|||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
||||||
GlUtils.checkGlError("draw texture3");
|
GlUtils.checkGlError("draw texture3");
|
||||||
|
|
||||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tl.textures.id);
|
for (TextureObject to = tl.textures; to != null; to = to.next) {
|
||||||
|
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, to.id);
|
||||||
GlUtils.checkGlError("draw texture4");
|
GlUtils.checkGlError("draw texture4");
|
||||||
|
|
||||||
GlUtils.checkGlError("draw texture5");
|
GlUtils.checkGlError("draw texture5");
|
||||||
|
|
||||||
|
// to.offset * 24(shorts) * 2(short-bytes) / 6(indices)
|
||||||
GLES20.glVertexAttribPointer(hTextureVertex, 4,
|
GLES20.glVertexAttribPointer(hTextureVertex, 4,
|
||||||
GLES20.GL_SHORT, false, 12, offset);
|
GLES20.GL_SHORT, false, 12, to.offset * 8 + offset);
|
||||||
GlUtils.checkGlError("draw texture..");
|
GlUtils.checkGlError("draw texture..");
|
||||||
|
|
||||||
GLES20.glVertexAttribPointer(hTextureTexCoord, 2,
|
GLES20.glVertexAttribPointer(hTextureTexCoord, 2,
|
||||||
GLES20.GL_SHORT, false, 12, offset + 8);
|
GLES20.GL_SHORT, false, 12, to.offset * 8 + offset + 8);
|
||||||
GlUtils.checkGlError("draw texture...");
|
GlUtils.checkGlError("draw texture...");
|
||||||
|
|
||||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tl.verticesCnt / 4)
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, to.vertices,
|
||||||
* INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
|
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
GlUtils.checkGlError("draw texture");
|
GlUtils.checkGlError("draw texture");
|
||||||
|
@ -28,6 +28,7 @@ import org.oscim.renderer.layer.LineLayer;
|
|||||||
import org.oscim.renderer.layer.PolygonLayer;
|
import org.oscim.renderer.layer.PolygonLayer;
|
||||||
import org.oscim.renderer.layer.SymbolItem;
|
import org.oscim.renderer.layer.SymbolItem;
|
||||||
import org.oscim.renderer.layer.SymbolLayer;
|
import org.oscim.renderer.layer.SymbolLayer;
|
||||||
|
import org.oscim.renderer.layer.TextItem;
|
||||||
import org.oscim.theme.IRenderCallback;
|
import org.oscim.theme.IRenderCallback;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
@ -39,6 +40,7 @@ import org.oscim.view.MapView;
|
|||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.util.FloatMath;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,6 +99,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
private float mProjectionScaleFactor;
|
private float mProjectionScaleFactor;
|
||||||
|
|
||||||
|
public static void setRenderTheme(RenderTheme theme) {
|
||||||
|
renderTheme = theme;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mapView
|
* @param mapView
|
||||||
* the MapView
|
* the MapView
|
||||||
@ -243,7 +249,9 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
if (text.textKey == mTagEmptyName.key) {
|
if (text.textKey == mTagEmptyName.key) {
|
||||||
|
|
||||||
TextItem t = new TextItem(mCoords[0], mCoords[1], mTagName.value, text);
|
// TextItem t = new TextItem(mCoords[0], mCoords[1], mTagName.value,
|
||||||
|
// text);
|
||||||
|
TextItem t = TextItem.get().set(mCoords[0], mCoords[1], mTagName.value, text);
|
||||||
t.next = mLabels;
|
t.next = mLabels;
|
||||||
mLabels = t;
|
mLabels = t;
|
||||||
}
|
}
|
||||||
@ -258,7 +266,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (text.textKey == mTagEmptyName.key) {
|
if (text.textKey == mTagEmptyName.key) {
|
||||||
TextItem t = new TextItem(mPoiX, mPoiY, mTagName.value, text);
|
TextItem t = TextItem.get().set(mPoiX, mPoiY, mTagName.value, text);
|
||||||
|
// TextItem t = new TextItem(mPoiX, mPoiY, mTagName.value, text);
|
||||||
t.next = mLabels;
|
t.next = mLabels;
|
||||||
mLabels = t;
|
mLabels = t;
|
||||||
}
|
}
|
||||||
@ -294,10 +303,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
public void renderPointOfInterestSymbol(Bitmap bitmap) {
|
public void renderPointOfInterestSymbol(Bitmap bitmap) {
|
||||||
// Log.d(TAG, "add symbol");
|
// Log.d(TAG, "add symbol");
|
||||||
|
|
||||||
if (mLayers.symbolLayers == null)
|
if (mLayers.textureLayers == null)
|
||||||
mLayers.symbolLayers = new SymbolLayer();
|
mLayers.textureLayers = new SymbolLayer();
|
||||||
|
|
||||||
SymbolLayer sl = (SymbolLayer) mLayers.symbolLayers;
|
SymbolLayer sl = (SymbolLayer) mLayers.textureLayers;
|
||||||
|
|
||||||
SymbolItem it = new SymbolItem();
|
SymbolItem it = new SymbolItem();
|
||||||
it.x = mPoiX;
|
it.x = mPoiX;
|
||||||
@ -388,12 +397,13 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
mDebugDrawPolygons = !debugSettings.mDisablePolygons;
|
mDebugDrawPolygons = !debugSettings.mDisablePolygons;
|
||||||
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
|
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
|
||||||
|
|
||||||
if (tile.newData || tile.isReady) {
|
if (tile.newData || tile.isReady || tile.layers != null) {
|
||||||
// should be fixed now.
|
// should be fixed now.
|
||||||
Log.d(TAG, "XXX tile already loaded "
|
Log.d(TAG, "XXX tile already loaded "
|
||||||
+ tile + " "
|
+ tile + " "
|
||||||
+ tile.newData + " "
|
+ tile.newData + " "
|
||||||
+ tile.isReady + " ");
|
+ tile.isReady + " "
|
||||||
|
+ tile.isLoading);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,9 +416,9 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
setScaleStrokeWidth(STROKE_MAX_ZOOM_LEVEL);
|
setScaleStrokeWidth(STROKE_MAX_ZOOM_LEVEL);
|
||||||
|
|
||||||
// acount for area changes with latitude
|
// acount for area changes with latitude
|
||||||
mProjectionScaleFactor = 0.5f + (float) (0.5 / Math.cos(MercatorProjection
|
mProjectionScaleFactor = 0.5f + 0.5f * (
|
||||||
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)
|
FloatMath.sin((float) (Math.abs(MercatorProjection
|
||||||
* (Math.PI / 180)));
|
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)) * (Math.PI / 180))));
|
||||||
|
|
||||||
mLayers = new Layers();
|
mLayers = new Layers();
|
||||||
|
|
||||||
@ -482,10 +492,6 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
return mMapDatabase;
|
return mMapDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRenderTheme(RenderTheme theme) {
|
|
||||||
TileGenerator.renderTheme = theme;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkWay(Tag[] tags, boolean closed) {
|
public boolean checkWay(Tag[] tags, boolean closed) {
|
||||||
|
|
||||||
|
@ -14,12 +14,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
|
import org.oscim.renderer.layer.TextItem;
|
||||||
import org.oscim.theme.renderinstruction.Text;
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
import org.oscim.utils.GeometryUtils;
|
import org.oscim.utils.GeometryUtils;
|
||||||
|
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
|
|
||||||
final class WayDecorator {
|
public final class WayDecorator {
|
||||||
// /**
|
// /**
|
||||||
// * Minimum distance in pixels before the symbol is repeated.
|
// * Minimum distance in pixels before the symbol is repeated.
|
||||||
// */
|
// */
|
||||||
@ -99,7 +100,7 @@ final class WayDecorator {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
static TextItem renderText(float[] coordinates, String string, Text text,
|
public static TextItem renderText(float[] coordinates, String string, Text text,
|
||||||
int pos, int len, TextItem textItems) {
|
int pos, int len, TextItem textItems) {
|
||||||
TextItem items = textItems;
|
TextItem items = textItems;
|
||||||
TextItem t = null;
|
TextItem t = null;
|
||||||
@ -256,9 +257,16 @@ final class WayDecorator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if (t == null)
|
// if (t == null)
|
||||||
t = new TextItem(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2, string,
|
t = TextItem.get();
|
||||||
text, wayNameWidth);
|
// t = new TextItem(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2,
|
||||||
|
// string,
|
||||||
|
// text, wayNameWidth);
|
||||||
|
|
||||||
|
t.x = x1 + (x2 - x1) / 2f;
|
||||||
|
t.y = y1 + (y2 - y1) / 2f;
|
||||||
|
t.string = string;
|
||||||
|
t.text = text;
|
||||||
|
t.width = wayNameWidth;
|
||||||
t.x1 = (short) x1;
|
t.x1 = (short) x1;
|
||||||
t.y1 = (short) y1;
|
t.y1 = (short) y1;
|
||||||
t.x2 = (short) x2;
|
t.x2 = (short) x2;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer.layer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
public class Layer {
|
public abstract class Layer {
|
||||||
public final static byte LINE = 0;
|
public final static byte LINE = 0;
|
||||||
public final static byte POLYGON = 1;
|
public final static byte POLYGON = 1;
|
||||||
public final static byte WAYTEXT = 2;
|
public final static byte WAYTEXT = 2;
|
||||||
@ -34,4 +34,7 @@ public class Layer {
|
|||||||
|
|
||||||
VertexPoolItem pool;
|
VertexPoolItem pool;
|
||||||
protected VertexPoolItem curItem;
|
protected VertexPoolItem curItem;
|
||||||
|
|
||||||
|
protected void clear() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,6 @@ package org.oscim.renderer.layer;
|
|||||||
|
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.renderer.TextureObject;
|
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class Layers {
|
public class Layers {
|
||||||
@ -25,8 +23,8 @@ public class Layers {
|
|||||||
public Layer layers;
|
public Layer layers;
|
||||||
public int lineOffset;
|
public int lineOffset;
|
||||||
|
|
||||||
public Layer symbolLayers;
|
public Layer textureLayers;
|
||||||
public int symbolOffset;
|
public int texOffset;
|
||||||
|
|
||||||
private Layer mCurLayer;
|
private Layer mCurLayer;
|
||||||
|
|
||||||
@ -57,10 +55,13 @@ public class Layers {
|
|||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
if (type == Layer.LINE)
|
if (type == Layer.LINE)
|
||||||
ret = new LineLayer(level);
|
ret = new LineLayer(level);
|
||||||
else
|
else if (type == Layer.POLYGON)
|
||||||
ret = new PolygonLayer(level);
|
ret = new PolygonLayer(level);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
if (l == null) {
|
if (l == null) {
|
||||||
|
// insert at start
|
||||||
ret.next = layers;
|
ret.next = layers;
|
||||||
layers = ret;
|
layers = ret;
|
||||||
} else {
|
} else {
|
||||||
@ -81,7 +82,9 @@ public class Layers {
|
|||||||
private static int TEXTURE_VERTEX_SHORTS = 6;
|
private static int TEXTURE_VERTEX_SHORTS = 6;
|
||||||
|
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
for (Layer l = layers; l != null; l = l.next) {
|
for (Layer l = layers; l != null; l = l.next) {
|
||||||
if (l.type == Layer.LINE)
|
if (l.type == Layer.LINE)
|
||||||
size += l.verticesCnt * LINE_VERTEX_SHORTS;
|
size += l.verticesCnt * LINE_VERTEX_SHORTS;
|
||||||
@ -90,7 +93,7 @@ public class Layers {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Layer l = symbolLayers; l != null; l = l.next) {
|
for (Layer l = textureLayers; l != null; l = l.next) {
|
||||||
size += l.verticesCnt * TEXTURE_VERTEX_SHORTS;
|
size += l.verticesCnt * TEXTURE_VERTEX_SHORTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,10 +112,10 @@ public class Layers {
|
|||||||
lineOffset = sbuf.position() * 2; // * short-bytes
|
lineOffset = sbuf.position() * 2; // * short-bytes
|
||||||
addLayerItems(sbuf, layers, Layer.LINE, 0);
|
addLayerItems(sbuf, layers, Layer.LINE, 0);
|
||||||
|
|
||||||
symbolOffset = sbuf.position() * 2; // * short-bytes
|
texOffset = sbuf.position() * 2; // * short-bytes
|
||||||
|
|
||||||
for (Layer l = symbolLayers; l != null; l = l.next) {
|
for (Layer l = textureLayers; l != null; l = l.next) {
|
||||||
SymbolLayer sl = (SymbolLayer) l;
|
TextureLayer sl = (TextureLayer) l;
|
||||||
sl.compile(sbuf);
|
sl.compile(sbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,19 +151,25 @@ public class Layers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
// FIXME collect pool and add as a whole
|
|
||||||
for (Layer l = layers; l != null; l = l.next) {
|
while (layers != null) {
|
||||||
|
Layer l = layers;
|
||||||
if (l.pool != null) {
|
if (l.pool != null) {
|
||||||
VertexPool.release(l.pool);
|
VertexPool.release(l.pool);
|
||||||
l.pool = null;
|
l.pool = null;
|
||||||
l.curItem = null;
|
l.curItem = null;
|
||||||
}
|
}
|
||||||
|
layers = layers.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Layer l = symbolLayers; l != null; l = l.next) {
|
while (textureLayers != null) {
|
||||||
SymbolLayer sl = (SymbolLayer) l;
|
textureLayers.clear();
|
||||||
if (sl.textures != null)
|
|
||||||
TextureObject.release(sl.textures);
|
// TextureLayer sl = (TextureLayer) textureLayers;
|
||||||
|
// if (sl.textures != null)
|
||||||
|
// TextureObject.release(sl.textures);
|
||||||
|
|
||||||
|
textureLayers = textureLayers.next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,20 +35,11 @@ public final class LineLayer extends Layer {
|
|||||||
public Line line;
|
public Line line;
|
||||||
public float width;
|
public float width;
|
||||||
|
|
||||||
// boolean isOutline;
|
|
||||||
|
|
||||||
LineLayer(int layer) {
|
LineLayer(int layer) {
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
this.type = Layer.LINE;
|
this.type = Layer.LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LineLayer(int layer, Line line, float width, boolean outline) {
|
|
||||||
// this.layer = layer;
|
|
||||||
// this.width = width;
|
|
||||||
// this.line = line;
|
|
||||||
// // this.isOutline = outline;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void addOutline(LineLayer link) {
|
public void addOutline(LineLayer link) {
|
||||||
for (LineLayer l = outlines; l != null; l = l.outlines)
|
for (LineLayer l = outlines; l != null; l = l.outlines)
|
||||||
if (link == l)
|
if (link == l)
|
||||||
@ -272,6 +263,7 @@ public final class LineLayer extends Layer {
|
|||||||
prevY = y;
|
prevY = y;
|
||||||
x = nextX;
|
x = nextX;
|
||||||
y = nextY;
|
y = nextY;
|
||||||
|
boolean flip = false;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (ipos < pos + length) {
|
if (ipos < pos + length) {
|
||||||
@ -314,10 +306,15 @@ public final class LineLayer extends Layer {
|
|||||||
ux = (ux / a);
|
ux = (ux / a);
|
||||||
uy = (uy / a);
|
uy = (uy / a);
|
||||||
|
|
||||||
// hack to avoid miter going to infinity
|
// avoid miter going to infinity...
|
||||||
if (ux > 2.0f || ux < -2.0f || uy > 2.0f || uy < -2.0f) {
|
if (ux > 4.0f || ux < -4.0f || uy > 4.0f || uy < -4.0f) {
|
||||||
ux = -wy;
|
ux = vx - wx;
|
||||||
uy = wx;
|
uy = vy - wy;
|
||||||
|
|
||||||
|
a = -wy * ux + wx * uy;
|
||||||
|
ux = (ux / a);
|
||||||
|
uy = (uy / a);
|
||||||
|
flip = !flip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,6 +324,10 @@ public final class LineLayer extends Layer {
|
|||||||
ddx = (int) (ux * DIR_SCALE);
|
ddx = (int) (ux * DIR_SCALE);
|
||||||
ddy = (int) (uy * DIR_SCALE);
|
ddy = (int) (uy * DIR_SCALE);
|
||||||
|
|
||||||
|
if (flip) {
|
||||||
|
ddx *= -1;
|
||||||
|
ddy *= -1;
|
||||||
|
}
|
||||||
if (opos == VertexPoolItem.SIZE) {
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
si = si.next = VertexPool.get();
|
si = si.next = VertexPool.get();
|
||||||
v = si.vertices;
|
v = si.vertices;
|
||||||
@ -382,6 +383,11 @@ public final class LineLayer extends Layer {
|
|||||||
ddx = (int) (ux * DIR_SCALE);
|
ddx = (int) (ux * DIR_SCALE);
|
||||||
ddy = (int) (uy * DIR_SCALE);
|
ddy = (int) (uy * DIR_SCALE);
|
||||||
|
|
||||||
|
if (flip) {
|
||||||
|
ddx *= -1;
|
||||||
|
ddy *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
v[opos++] = ox;
|
v[opos++] = ox;
|
||||||
v[opos++] = oy;
|
v[opos++] = oy;
|
||||||
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
||||||
@ -410,6 +416,11 @@ public final class LineLayer extends Layer {
|
|||||||
dx = (short) (0 | ddx & DIR_MASK);
|
dx = (short) (0 | ddx & DIR_MASK);
|
||||||
dy = (short) (0 | ddy & DIR_MASK);
|
dy = (short) (0 | ddy & DIR_MASK);
|
||||||
|
|
||||||
|
if (flip) {
|
||||||
|
ddx *= -1;
|
||||||
|
ddy *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
v[opos++] = ox;
|
v[opos++] = ox;
|
||||||
v[opos++] = oy;
|
v[opos++] = oy;
|
||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
@ -427,6 +438,11 @@ public final class LineLayer extends Layer {
|
|||||||
dx = (short) (2 | ddx & DIR_MASK);
|
dx = (short) (2 | ddx & DIR_MASK);
|
||||||
dy = (short) (0 | ddy & DIR_MASK);
|
dy = (short) (0 | ddy & DIR_MASK);
|
||||||
|
|
||||||
|
if (flip) {
|
||||||
|
ddx *= -1;
|
||||||
|
ddy *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
v[opos++] = ox;
|
v[opos++] = ox;
|
||||||
v[opos++] = oy;
|
v[opos++] = oy;
|
||||||
v[opos++] = dx;
|
v[opos++] = dx;
|
||||||
@ -457,7 +473,10 @@ public final class LineLayer extends Layer {
|
|||||||
|
|
||||||
ddx = (int) ((ux - vx) * DIR_SCALE);
|
ddx = (int) ((ux - vx) * DIR_SCALE);
|
||||||
ddy = (int) ((uy - vy) * DIR_SCALE);
|
ddy = (int) ((uy - vy) * DIR_SCALE);
|
||||||
|
if (flip) {
|
||||||
|
ddx *= -1;
|
||||||
|
ddy *= -1;
|
||||||
|
}
|
||||||
v[opos++] = ox;
|
v[opos++] = ox;
|
||||||
v[opos++] = oy;
|
v[opos++] = oy;
|
||||||
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
v[opos++] = (short) (0 | ddx & DIR_MASK);
|
||||||
@ -472,6 +491,10 @@ public final class LineLayer extends Layer {
|
|||||||
// add last vertex twice
|
// add last vertex twice
|
||||||
ddx = (int) (-(ux + vx) * DIR_SCALE);
|
ddx = (int) (-(ux + vx) * DIR_SCALE);
|
||||||
ddy = (int) (-(uy + vy) * DIR_SCALE);
|
ddy = (int) (-(uy + vy) * DIR_SCALE);
|
||||||
|
if (flip) {
|
||||||
|
ddx *= -1;
|
||||||
|
ddy *= -1;
|
||||||
|
}
|
||||||
dx = (short) (2 | ddx & DIR_MASK);
|
dx = (short) (2 | ddx & DIR_MASK);
|
||||||
dy = (short) (1 | ddy & DIR_MASK);
|
dy = (short) (1 | ddy & DIR_MASK);
|
||||||
|
|
||||||
|
@ -17,12 +17,9 @@ package org.oscim.renderer.layer;
|
|||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.renderer.TextureObject;
|
import org.oscim.renderer.TextureObject;
|
||||||
|
import org.oscim.renderer.TextureRenderer;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.opengl.GLUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
// TODO share one static texture for all poi map symabols
|
// TODO share one static texture for all poi map symabols
|
||||||
@ -30,28 +27,17 @@ import android.util.Log;
|
|||||||
public final class SymbolLayer extends TextureLayer {
|
public final class SymbolLayer extends TextureLayer {
|
||||||
private static String TAG = SymbolLayer.class.getSimpleName();
|
private static String TAG = SymbolLayer.class.getSimpleName();
|
||||||
|
|
||||||
private final static int TEXTURE_WIDTH = 256;
|
private final static int TEXTURE_WIDTH = TextureObject.TEXTURE_WIDTH;
|
||||||
private final static int TEXTURE_HEIGHT = 256;
|
private final static int TEXTURE_HEIGHT = TextureObject.TEXTURE_HEIGHT;
|
||||||
private final static float SCALE = 8.0f;
|
private final static float SCALE = 8.0f;
|
||||||
|
|
||||||
private static short[] mVertices;
|
private static short[] mVertices;
|
||||||
private static Bitmap mBitmap;
|
|
||||||
private static Canvas mCanvas;
|
|
||||||
private static int mBitmapFormat;
|
|
||||||
private static int mBitmapType;
|
|
||||||
|
|
||||||
SymbolItem symbols;
|
SymbolItem symbols;
|
||||||
|
|
||||||
public SymbolLayer() {
|
public SymbolLayer() {
|
||||||
if (mBitmap == null) {
|
if (mVertices == null)
|
||||||
mBitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
|
mVertices = new short[TextureRenderer.MAX_ITEMS * 24];
|
||||||
Bitmap.Config.ARGB_8888);
|
|
||||||
mCanvas = new Canvas(mBitmap);
|
|
||||||
mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
|
|
||||||
mBitmapType = GLUtils.getType(mBitmap);
|
|
||||||
//
|
|
||||||
mVertices = new short[40 * 24];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSymbol(SymbolItem item) {
|
public void addSymbol(SymbolItem item) {
|
||||||
@ -73,19 +59,23 @@ public final class SymbolLayer extends TextureLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final static int LBIT_MASK = 0xfffffffe;
|
private final static int LBIT_MASK = 0xfffffffe;
|
||||||
private final RectF mRect = new RectF();
|
|
||||||
|
|
||||||
// TODO ... reuse texture when only symbol position changed
|
// TODO ... reuse texture when only symbol position changed
|
||||||
|
@Override
|
||||||
public void compile(ShortBuffer sbuf) {
|
public void compile(ShortBuffer sbuf) {
|
||||||
|
|
||||||
|
short numIndices = 0;
|
||||||
|
short offsetIndices = 0;
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
short buf[] = mVertices;
|
short buf[] = mVertices;
|
||||||
|
int bufLen = buf.length;
|
||||||
|
|
||||||
int advanceY = 0;
|
int advanceY = 0;
|
||||||
float x = 0;
|
float x = 0;
|
||||||
float y = 0;
|
float y = 0;
|
||||||
|
|
||||||
mBitmap.eraseColor(Color.TRANSPARENT);
|
Canvas canvas = TextureObject.getCanvas();
|
||||||
|
|
||||||
for (SymbolItem it = symbols; it != null;) {
|
for (SymbolItem it = symbols; it != null;) {
|
||||||
|
|
||||||
@ -103,35 +93,31 @@ public final class SymbolLayer extends TextureLayer {
|
|||||||
|
|
||||||
if (y + height > TEXTURE_HEIGHT) {
|
if (y + height > TEXTURE_HEIGHT) {
|
||||||
Log.d(TAG, "reached max symbols");
|
Log.d(TAG, "reached max symbols");
|
||||||
// need to sync bitmap upload somehow???
|
|
||||||
TextureObject to = TextureObject.get();
|
TextureObject to = TextureObject.uploadCanvas(offsetIndices, numIndices);
|
||||||
TextureObject.uploadTexture(to, mBitmap,
|
offsetIndices = numIndices;
|
||||||
mBitmapFormat, mBitmapType,
|
|
||||||
TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
|
||||||
to.next = textures;
|
to.next = textures;
|
||||||
textures = to;
|
textures = to;
|
||||||
|
|
||||||
sbuf.put(buf, 0, pos);
|
sbuf.put(buf, 0, pos);
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
mRect.left = x;
|
|
||||||
mRect.top = y;
|
|
||||||
mRect.right = x + width;
|
|
||||||
mRect.bottom = y + height;
|
|
||||||
// Log.d("...", "draw " + x + " " + y + " " + width + " " + height);
|
|
||||||
|
|
||||||
mCanvas.drawBitmap(it.bitmap, null, mRect, null);
|
x = 0;
|
||||||
// mCanvas.drawBitmap(it.bitmap, x, y, null);
|
y = 0;
|
||||||
|
advanceY = (int) height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawBitmap(it.bitmap, x, y, null);
|
||||||
|
|
||||||
float hw = width / 2.0f;
|
float hw = width / 2.0f;
|
||||||
float hh = height / 2.0f;
|
float hh = height / 2.0f;
|
||||||
short x1, x2, x3, x4, y1, y2, y3, y4;
|
|
||||||
x1 = x3 = (short) (SCALE * (-hw));
|
|
||||||
x2 = x4 = (short) (SCALE * (hw));
|
|
||||||
|
|
||||||
y1 = y3 = (short) (SCALE * (hh));
|
short x1 = (short) (SCALE * (-hw));
|
||||||
y2 = y4 = (short) (SCALE * (-hh));
|
short x2 = (short) (SCALE * (hw));
|
||||||
|
short y1 = (short) (SCALE * (hh));
|
||||||
|
short y2 = (short) (SCALE * (-hh));
|
||||||
|
|
||||||
short u1 = (short) (SCALE * x);
|
short u1 = (short) (SCALE * x);
|
||||||
short v1 = (short) (SCALE * y);
|
short v1 = (short) (SCALE * y);
|
||||||
@ -157,40 +143,43 @@ public final class SymbolLayer extends TextureLayer {
|
|||||||
buf[pos++] = y1;
|
buf[pos++] = y1;
|
||||||
buf[pos++] = u1;
|
buf[pos++] = u1;
|
||||||
buf[pos++] = v2;
|
buf[pos++] = v2;
|
||||||
|
|
||||||
// top-right
|
// top-right
|
||||||
buf[pos++] = tx;
|
buf[pos++] = tx;
|
||||||
buf[pos++] = ty;
|
buf[pos++] = ty;
|
||||||
buf[pos++] = x2;
|
buf[pos++] = x2;
|
||||||
buf[pos++] = y3;
|
buf[pos++] = y1;
|
||||||
buf[pos++] = u2;
|
buf[pos++] = u2;
|
||||||
buf[pos++] = v2;
|
buf[pos++] = v2;
|
||||||
|
|
||||||
// bot-right
|
// bot-right
|
||||||
buf[pos++] = tx;
|
buf[pos++] = tx;
|
||||||
buf[pos++] = ty;
|
buf[pos++] = ty;
|
||||||
buf[pos++] = x4;
|
buf[pos++] = x2;
|
||||||
buf[pos++] = y4;
|
buf[pos++] = y2;
|
||||||
buf[pos++] = u2;
|
buf[pos++] = u2;
|
||||||
buf[pos++] = v1;
|
buf[pos++] = v1;
|
||||||
|
|
||||||
// bot-left
|
// bot-left
|
||||||
buf[pos++] = tx;
|
buf[pos++] = tx;
|
||||||
buf[pos++] = ty;
|
buf[pos++] = ty;
|
||||||
buf[pos++] = x3;
|
buf[pos++] = x1;
|
||||||
buf[pos++] = y2;
|
buf[pos++] = y2;
|
||||||
buf[pos++] = u1;
|
buf[pos++] = u1;
|
||||||
buf[pos++] = v1;
|
buf[pos++] = v1;
|
||||||
|
|
||||||
x += width + 1;
|
// six elements used to draw the four vertices
|
||||||
|
numIndices += 6;
|
||||||
|
|
||||||
|
// FIXME this does not work, need to draw bitmap on next
|
||||||
|
// texture...
|
||||||
|
if (pos == bufLen) {
|
||||||
|
sbuf.put(buf, 0, pos);
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
x += width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureObject to = TextureObject.get();
|
TextureObject to = TextureObject.uploadCanvas(offsetIndices, numIndices);
|
||||||
|
|
||||||
TextureObject.uploadTexture(to, mBitmap,
|
|
||||||
mBitmapFormat, mBitmapType,
|
|
||||||
TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
|
||||||
|
|
||||||
to.next = textures;
|
to.next = textures;
|
||||||
textures = to;
|
textures = to;
|
||||||
|
77
src/org/oscim/renderer/layer/TextItem.java
Normal file
77
src/org/oscim/renderer/layer/TextItem.java
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
|
|
||||||
|
public class TextItem {
|
||||||
|
private static Object lock = new Object();
|
||||||
|
private static TextItem pool;
|
||||||
|
|
||||||
|
public static TextItem get() {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (pool == null)
|
||||||
|
return new TextItem();
|
||||||
|
|
||||||
|
TextItem ti = pool;
|
||||||
|
pool = pool.next;
|
||||||
|
ti.next = null;
|
||||||
|
return ti;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void release(TextItem ti) {
|
||||||
|
if (ti == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
synchronized (lock) {
|
||||||
|
while (ti != null) {
|
||||||
|
TextItem next = ti.next;
|
||||||
|
|
||||||
|
ti.next = pool;
|
||||||
|
pool = ti;
|
||||||
|
|
||||||
|
ti = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextItem set(float x, float y, String string, Text text) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.string = string;
|
||||||
|
this.text = text;
|
||||||
|
this.width = text.paint.measureText(string);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextItem move(TextItem ti, float dx, float dy) {
|
||||||
|
this.x = dx + ti.x;
|
||||||
|
this.y = dy + ti.y;
|
||||||
|
this.string = ti.string;
|
||||||
|
this.text = ti.text;
|
||||||
|
this.width = ti.width;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextItem next;
|
||||||
|
|
||||||
|
public float x, y;
|
||||||
|
public String string;
|
||||||
|
public Text text;
|
||||||
|
public float width;
|
||||||
|
public short x1, y1, x2, y2;
|
||||||
|
// public byte placement
|
||||||
|
}
|
@ -14,9 +14,218 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer.layer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
import org.oscim.renderer.TextItem;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import org.oscim.renderer.TextureObject;
|
||||||
|
import org.oscim.renderer.TextureRenderer;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.util.FloatMath;
|
||||||
|
|
||||||
public final class TextLayer extends TextureLayer {
|
public final class TextLayer extends TextureLayer {
|
||||||
|
|
||||||
|
private static String TAG = SymbolLayer.class.getSimpleName();
|
||||||
|
|
||||||
|
private final static int TEXTURE_WIDTH = TextureObject.TEXTURE_WIDTH;
|
||||||
|
private final static int TEXTURE_HEIGHT = TextureObject.TEXTURE_HEIGHT;
|
||||||
|
private final static float SCALE = 8.0f;
|
||||||
|
private final static int LBIT_MASK = 0xfffffffe;
|
||||||
|
|
||||||
|
private static short[] mVertices;
|
||||||
|
private static int mFontPadX = 1;
|
||||||
|
private static int mFontPadY = 1;
|
||||||
|
|
||||||
TextItem labels;
|
TextItem labels;
|
||||||
|
|
||||||
|
public TextItem getLabels() {
|
||||||
|
return labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextLayer() {
|
||||||
|
if (mVertices == null)
|
||||||
|
mVertices = new short[TextureRenderer.MAX_ITEMS * 24];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addText(TextItem item) {
|
||||||
|
verticesCnt += 4;
|
||||||
|
TextItem it = labels;
|
||||||
|
|
||||||
|
for (; it != null; it = it.next) {
|
||||||
|
if (it.text == item.text) {
|
||||||
|
item.next = it.next;
|
||||||
|
it.next = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.next = labels;
|
||||||
|
labels = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void compile(ShortBuffer sbuf) {
|
||||||
|
// int numLabel = 0;
|
||||||
|
|
||||||
|
short numIndices = 0;
|
||||||
|
short offsetIndices = 0;
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
short buf[] = mVertices;
|
||||||
|
int bufLen = buf.length;
|
||||||
|
|
||||||
|
int advanceY = 0;
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
float yy;
|
||||||
|
|
||||||
|
Canvas canvas = TextureObject.getCanvas();
|
||||||
|
for (TextItem it = labels; it != null; it = it.next) {
|
||||||
|
// numLabel++;
|
||||||
|
|
||||||
|
float width = it.width + 2 * mFontPadX;
|
||||||
|
float height = (int) (it.text.fontHeight) + 2 * mFontPadY + 0.5f;
|
||||||
|
|
||||||
|
if (height > advanceY)
|
||||||
|
advanceY = (int) height;
|
||||||
|
|
||||||
|
if (x + width > TEXTURE_WIDTH) {
|
||||||
|
x = 0;
|
||||||
|
y += advanceY;
|
||||||
|
advanceY = (int) (height + 0.5f);
|
||||||
|
|
||||||
|
if (y + height > TEXTURE_HEIGHT) {
|
||||||
|
// Log.d(TAG, "reached max labels " + numLabel);
|
||||||
|
|
||||||
|
// need to sync bitmap upload somehow???
|
||||||
|
TextureObject to = TextureObject.uploadCanvas(offsetIndices, numIndices);
|
||||||
|
offsetIndices = numIndices;
|
||||||
|
|
||||||
|
to.next = textures;
|
||||||
|
textures = to;
|
||||||
|
|
||||||
|
sbuf.put(buf, 0, pos);
|
||||||
|
pos = 0;
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
advanceY = (int) height;
|
||||||
|
|
||||||
|
// clear bitmap, TODO rotate two canvas to reduce the chance
|
||||||
|
// of having upload lock draing to the canvas?
|
||||||
|
canvas = TextureObject.getCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yy = y + (height - 1) - it.text.fontDescent - mFontPadY;
|
||||||
|
|
||||||
|
if (it.text.stroke != null)
|
||||||
|
canvas.drawText(it.string, x + it.width / 2, yy, it.text.stroke);
|
||||||
|
|
||||||
|
canvas.drawText(it.string, x + it.width / 2, yy, it.text.paint);
|
||||||
|
|
||||||
|
// FIXME !!!
|
||||||
|
if (width > TEXTURE_WIDTH)
|
||||||
|
width = TEXTURE_WIDTH;
|
||||||
|
|
||||||
|
float hw = width / 2.0f;
|
||||||
|
float hh = height / 2.0f;
|
||||||
|
|
||||||
|
short x1, x2, x3, x4, y1, y3, y2, y4;
|
||||||
|
|
||||||
|
if (it.text.caption) {
|
||||||
|
x1 = x3 = (short) (SCALE * -hw);
|
||||||
|
x2 = x4 = (short) (SCALE * hw);
|
||||||
|
y1 = y2 = (short) (SCALE * hh);
|
||||||
|
y3 = y4 = (short) (SCALE * -hh);
|
||||||
|
// x1 = x3 = (short) (0);
|
||||||
|
// x2 = x4 = (short) (SCALE * width);
|
||||||
|
} else {
|
||||||
|
float vx = it.x1 - it.x2;
|
||||||
|
float vy = it.y1 - it.y2;
|
||||||
|
float a = FloatMath.sqrt(vx * vx + vy * vy);
|
||||||
|
vx = vx / a;
|
||||||
|
vy = vy / a;
|
||||||
|
|
||||||
|
float ux = -vy;
|
||||||
|
float uy = vx;
|
||||||
|
float hh2 = hh + it.text.fontDescent / 2;
|
||||||
|
hh -= it.text.fontDescent / 2;
|
||||||
|
x1 = (short) (SCALE * (vx * hw - ux * hh));
|
||||||
|
y1 = (short) (SCALE * (vy * hw - uy * hh));
|
||||||
|
x2 = (short) (SCALE * (-vx * hw - ux * hh));
|
||||||
|
y2 = (short) (SCALE * (-vy * hw - uy * hh));
|
||||||
|
x4 = (short) (SCALE * (-vx * hw + ux * hh2));
|
||||||
|
y4 = (short) (SCALE * (-vy * hw + uy * hh2));
|
||||||
|
x3 = (short) (SCALE * (vx * hw + ux * hh2));
|
||||||
|
y3 = (short) (SCALE * (vy * hw + uy * hh2));
|
||||||
|
}
|
||||||
|
|
||||||
|
short u1 = (short) (SCALE * x);
|
||||||
|
short v1 = (short) (SCALE * y);
|
||||||
|
short u2 = (short) (SCALE * (x + width));
|
||||||
|
short v2 = (short) (SCALE * (y + height));
|
||||||
|
|
||||||
|
// add vertices
|
||||||
|
int tmp = (int) (SCALE * it.x) & LBIT_MASK;
|
||||||
|
short tx = (short) (tmp | (it.text.caption ? 1 : 0));
|
||||||
|
|
||||||
|
short ty = (short) (SCALE * it.y);
|
||||||
|
|
||||||
|
// top-left
|
||||||
|
buf[pos++] = tx;
|
||||||
|
buf[pos++] = ty;
|
||||||
|
buf[pos++] = x1;
|
||||||
|
buf[pos++] = y1;
|
||||||
|
buf[pos++] = u1;
|
||||||
|
buf[pos++] = v2;
|
||||||
|
// top-right
|
||||||
|
buf[pos++] = tx;
|
||||||
|
buf[pos++] = ty;
|
||||||
|
buf[pos++] = x2;
|
||||||
|
buf[pos++] = y2;
|
||||||
|
buf[pos++] = u2;
|
||||||
|
buf[pos++] = v2;
|
||||||
|
// bot-right
|
||||||
|
buf[pos++] = tx;
|
||||||
|
buf[pos++] = ty;
|
||||||
|
buf[pos++] = x4;
|
||||||
|
buf[pos++] = y4;
|
||||||
|
buf[pos++] = u2;
|
||||||
|
buf[pos++] = v1;
|
||||||
|
// bot-left
|
||||||
|
buf[pos++] = tx;
|
||||||
|
buf[pos++] = ty;
|
||||||
|
buf[pos++] = x3;
|
||||||
|
buf[pos++] = y3;
|
||||||
|
buf[pos++] = u1;
|
||||||
|
buf[pos++] = v1;
|
||||||
|
|
||||||
|
// six indices to draw the four vertices
|
||||||
|
numIndices += 6;
|
||||||
|
|
||||||
|
// FIXME this does not work, need to draw bitmap on next
|
||||||
|
// texture...
|
||||||
|
if (pos == bufLen) {
|
||||||
|
sbuf.put(buf, 0, pos);
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
x += width + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureObject to = TextureObject.uploadCanvas(offsetIndices, numIndices);
|
||||||
|
|
||||||
|
to.next = textures;
|
||||||
|
textures = to;
|
||||||
|
|
||||||
|
sbuf.put(buf, 0, pos);
|
||||||
|
|
||||||
|
// Log.d(TAG, "added labels " + numLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void clear() {
|
||||||
|
TextureObject.release(textures);
|
||||||
|
TextItem.release(labels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,18 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer.layer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.renderer.TextureObject;
|
import org.oscim.renderer.TextureObject;
|
||||||
|
|
||||||
public abstract class TextureLayer extends Layer {
|
public abstract class TextureLayer extends Layer {
|
||||||
public TextureObject textures;
|
public TextureObject textures;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sbuf
|
||||||
|
* buffer to add vertices
|
||||||
|
*/
|
||||||
|
void compile(ShortBuffer sbuf) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package org.oscim.theme.renderinstruction;
|
|||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.theme.IRenderCallback;
|
import org.oscim.theme.IRenderCallback;
|
||||||
import org.oscim.theme.RenderThemeHandler;
|
import org.oscim.theme.RenderThemeHandler;
|
||||||
|
import org.oscim.utils.GlUtils;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
@ -88,11 +89,7 @@ public final class Area extends RenderInstruction {
|
|||||||
blend = -1;
|
blend = -1;
|
||||||
strokeWidth = 0;
|
strokeWidth = 0;
|
||||||
|
|
||||||
color = new float[4];
|
color = GlUtils.colorToFloatP(fill);
|
||||||
color[3] = (fill >> 24 & 0xff) / 255.0f;
|
|
||||||
color[0] = (fill >> 16 & 0xff) / 255.0f * color[3];
|
|
||||||
color[1] = (fill >> 8 & 0xff) / 255.0f * color[3];
|
|
||||||
color[2] = (fill >> 0 & 0xff) / 255.0f * color[3];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,41 +125,13 @@ public final class Area extends RenderInstruction {
|
|||||||
// Shader shader = BitmapUtils.createBitmapShader(src);
|
// Shader shader = BitmapUtils.createBitmapShader(src);
|
||||||
// paintFill.setShader(shader);
|
// paintFill.setShader(shader);
|
||||||
// }
|
// }
|
||||||
// paintFill.setStyle(Style.FILL);
|
|
||||||
// paintFill.setColor(fill);
|
|
||||||
// paintFill.setStrokeCap(Cap.ROUND);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (stroke == Color.TRANSPARENT) {
|
|
||||||
// paintOutline = null;
|
|
||||||
// } else {
|
|
||||||
// paintOutline = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
||||||
// paintOutline.setStyle(Style.STROKE);
|
|
||||||
// paintOutline.setColor(stroke);
|
|
||||||
// paintOutline.setStrokeCap(Cap.ROUND);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (stroke == Color.TRANSPARENT) {
|
color = GlUtils.colorToFloatP(fill);
|
||||||
// stroke = null;
|
|
||||||
// } else{
|
|
||||||
// stroke = new Line()
|
|
||||||
// }
|
|
||||||
|
|
||||||
color = new float[4];
|
if (blend > 0)
|
||||||
color[3] = (fill >> 24 & 0xff) / 255.0f;
|
blendColor = GlUtils.colorToFloatP(blendFill);
|
||||||
color[0] = (fill >> 16 & 0xff) / 255.0f * color[3];
|
else
|
||||||
color[1] = (fill >> 8 & 0xff) / 255.0f * color[3];
|
|
||||||
color[2] = (fill >> 0 & 0xff) / 255.0f * color[3];
|
|
||||||
|
|
||||||
if (blend > 0) {
|
|
||||||
blendColor = new float[4];
|
|
||||||
blendColor[3] = (blendFill >> 24 & 0xff) / 255.0f;
|
|
||||||
blendColor[0] = (blendFill >> 16 & 0xff) / 255.0f * blendColor[3];
|
|
||||||
blendColor[1] = (blendFill >> 8 & 0xff) / 255.0f * blendColor[3];
|
|
||||||
blendColor[2] = (blendFill >> 0 & 0xff) / 255.0f * blendColor[3];
|
|
||||||
} else {
|
|
||||||
blendColor = null;
|
blendColor = null;
|
||||||
}
|
|
||||||
|
|
||||||
this.blend = blend;
|
this.blend = blend;
|
||||||
this.strokeWidth = strokeWidth;
|
this.strokeWidth = strokeWidth;
|
||||||
@ -183,32 +152,10 @@ public final class Area extends RenderInstruction {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
public String style;
|
public String style;
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private final int level;
|
private final int level;
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
// public final Paint paintFill;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
// public final Paint paintOutline;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final float strokeWidth;
|
public final float strokeWidth;
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final float color[];
|
public final float color[];
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final int fade;
|
public final int fade;
|
||||||
|
|
||||||
public final float blendColor[];
|
public final float blendColor[];
|
||||||
|
|
||||||
public final int blend;
|
public final int blend;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import java.util.regex.Pattern;
|
|||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.theme.IRenderCallback;
|
import org.oscim.theme.IRenderCallback;
|
||||||
import org.oscim.theme.RenderThemeHandler;
|
import org.oscim.theme.RenderThemeHandler;
|
||||||
|
import org.oscim.utils.GlUtils;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
@ -121,11 +122,7 @@ public final class Line extends RenderInstruction {
|
|||||||
this.fixed = true;
|
this.fixed = true;
|
||||||
this.fade = -1;
|
this.fade = -1;
|
||||||
this.stipple = 2;
|
this.stipple = 2;
|
||||||
color = new float[4];
|
color = GlUtils.colorToFloatP(stroke);
|
||||||
color[3] = (stroke >> 24 & 0xff) / 255.0f;
|
|
||||||
color[0] = (stroke >> 16 & 0xff) / 255.0f * color[3];
|
|
||||||
color[1] = (stroke >> 8 & 0xff) / 255.0f * color[3];
|
|
||||||
color[2] = (stroke >> 0 & 0xff) / 255.0f * color[3];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void validate(float strokeWidth) {
|
private static void validate(float strokeWidth) {
|
||||||
@ -215,11 +212,7 @@ public final class Line extends RenderInstruction {
|
|||||||
|
|
||||||
this.cap = strokeLinecap;
|
this.cap = strokeLinecap;
|
||||||
|
|
||||||
color = new float[4];
|
color = GlUtils.colorToFloatP(stroke);
|
||||||
color[3] = (stroke >> 24 & 0xff) / 255.0f;
|
|
||||||
color[0] = (stroke >> 16 & 0xff) / 255.0f * color[3];
|
|
||||||
color[1] = (stroke >> 8 & 0xff) / 255.0f * color[3];
|
|
||||||
color[2] = (stroke >> 0 & 0xff) / 255.0f * color[3];
|
|
||||||
|
|
||||||
this.width = strokeWidth;
|
this.width = strokeWidth;
|
||||||
this.level = level;
|
this.level = level;
|
||||||
|
@ -53,6 +53,7 @@ public final class Text extends RenderInstruction {
|
|||||||
String style = null;
|
String style = null;
|
||||||
// boolean caption = false;
|
// boolean caption = false;
|
||||||
float dy = 0;
|
float dy = 0;
|
||||||
|
|
||||||
for (int i = 0; i < attributes.getLength(); ++i) {
|
for (int i = 0; i < attributes.getLength(); ++i) {
|
||||||
String name = attributes.getLocalName(i);
|
String name = attributes.getLocalName(i);
|
||||||
String value = attributes.getValue(i);
|
String value = attributes.getValue(i);
|
||||||
@ -82,10 +83,27 @@ public final class Text extends RenderInstruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
validate(elementName, textKey, fontSize, strokeWidth);
|
validate(elementName, textKey, fontSize, strokeWidth);
|
||||||
Typeface typeface = Typeface.create(fontFamily.toTypeface(), fontStyle.toInt());
|
|
||||||
|
Typeface typeface = null;
|
||||||
|
if (fontFamily == FontFamily.DEFAULT) {
|
||||||
|
if (fontStyle == FontStyle.NORMAL)
|
||||||
|
typeface = typefaceNormal;
|
||||||
|
else if (fontStyle == FontStyle.BOLD)
|
||||||
|
typeface = typefaceBold;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeface == null)
|
||||||
|
typeface = Typeface.create(fontFamily.toTypeface(), fontStyle.toInt());
|
||||||
|
|
||||||
return new Text(style, textKey, typeface, fontSize, fill, stroke, strokeWidth, dy, caption);
|
return new Text(style, textKey, typeface, fontSize, fill, stroke, strokeWidth, dy, caption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Typeface typefaceNormal = Typeface.create(FontFamily.DEFAULT.toTypeface(),
|
||||||
|
FontStyle.NORMAL.toInt());
|
||||||
|
|
||||||
|
private static Typeface typefaceBold = Typeface.create(FontFamily.DEFAULT.toTypeface(),
|
||||||
|
FontStyle.BOLD.toInt());
|
||||||
|
|
||||||
private static void validate(String elementName, String textKey, float fontSize,
|
private static void validate(String elementName, String textKey, float fontSize,
|
||||||
float strokeWidth) {
|
float strokeWidth) {
|
||||||
if (textKey == null) {
|
if (textKey == null) {
|
||||||
@ -110,9 +128,15 @@ public final class Text extends RenderInstruction {
|
|||||||
public final boolean caption;
|
public final boolean caption;
|
||||||
public final float dy;
|
public final float dy;
|
||||||
|
|
||||||
|
public static Text createText(float fontSize, float strokeWidth, int fill, int outline,
|
||||||
|
boolean billboard) {
|
||||||
|
|
||||||
|
return new Text("", "", typefaceNormal, fontSize, fill, outline, strokeWidth, 0, billboard);
|
||||||
|
}
|
||||||
|
|
||||||
private Text(String style, String textKey, Typeface typeface, float fontSize,
|
private Text(String style, String textKey, Typeface typeface, float fontSize,
|
||||||
int fill, int outline, float strokeWidth, float dy, boolean caption) {
|
int fill, int outline, float strokeWidth, float dy, boolean caption) {
|
||||||
super();
|
// super();
|
||||||
|
|
||||||
this.style = style;
|
this.style = style;
|
||||||
this.textKey = textKey;
|
this.textKey = textKey;
|
||||||
@ -123,19 +147,21 @@ public final class Text extends RenderInstruction {
|
|||||||
paint.setTextAlign(Align.CENTER);
|
paint.setTextAlign(Align.CENTER);
|
||||||
paint.setTypeface(typeface);
|
paint.setTypeface(typeface);
|
||||||
paint.setColor(fill);
|
paint.setColor(fill);
|
||||||
|
paint.setTextSize(fontSize);
|
||||||
|
|
||||||
|
if (strokeWidth > 0) {
|
||||||
stroke = new Paint(Paint.ANTI_ALIAS_FLAG);
|
stroke = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
stroke.setStyle(Style.STROKE);
|
stroke.setStyle(Style.STROKE);
|
||||||
stroke.setTextAlign(Align.CENTER);
|
stroke.setTextAlign(Align.CENTER);
|
||||||
stroke.setTypeface(typeface);
|
stroke.setTypeface(typeface);
|
||||||
stroke.setColor(outline);
|
stroke.setColor(outline);
|
||||||
stroke.setStrokeWidth(strokeWidth);
|
stroke.setStrokeWidth(strokeWidth);
|
||||||
|
stroke.setTextSize(fontSize);
|
||||||
|
} else
|
||||||
|
stroke = null;
|
||||||
|
|
||||||
this.fontSize = fontSize;
|
this.fontSize = fontSize;
|
||||||
|
|
||||||
paint.setTextSize(fontSize);
|
|
||||||
stroke.setTextSize(fontSize);
|
|
||||||
|
|
||||||
FontMetrics fm = paint.getFontMetrics();
|
FontMetrics fm = paint.getFontMetrics();
|
||||||
fontHeight = FloatMath.ceil(Math.abs(fm.bottom) + Math.abs(fm.top));
|
fontHeight = FloatMath.ceil(Math.abs(fm.bottom) + Math.abs(fm.top));
|
||||||
fontDescent = FloatMath.ceil(Math.abs(fm.descent));
|
fontDescent = FloatMath.ceil(Math.abs(fm.descent));
|
||||||
|
@ -47,4 +47,11 @@ public class FastMath {
|
|||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float pow(int pow) {
|
||||||
|
if (pow == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return (pow > 0 ? (1 << pow) : (1.0f / (1 << -pow)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,24 @@ public class GlUtils {
|
|||||||
GLES20.glUniform4fv(handle, 1, c, 0);
|
GLES20.glUniform4fv(handle, 1, c, 0);
|
||||||
else
|
else
|
||||||
glUniform4f(handle, c[0] * alpha, c[1] * alpha, c[2] * alpha, c[3] * alpha);
|
glUniform4f(handle, c[0] * alpha, c[1] * alpha, c[2] * alpha, c[3] * alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float[] colorToFloat(int color) {
|
||||||
|
float[] c = new float[4];
|
||||||
|
c[3] = (color >> 24 & 0xff) / 255.0f;
|
||||||
|
c[0] = (color >> 16 & 0xff) / 255.0f;
|
||||||
|
c[1] = (color >> 8 & 0xff) / 255.0f;
|
||||||
|
c[2] = (color >> 0 & 0xff) / 255.0f;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// premultiply alpha
|
||||||
|
public static float[] colorToFloatP(int color) {
|
||||||
|
float[] c = new float[4];
|
||||||
|
c[3] = (color >> 24 & 0xff) / 255.0f;
|
||||||
|
c[0] = (color >> 16 & 0xff) / 255.0f * c[3];
|
||||||
|
c[1] = (color >> 8 & 0xff) / 255.0f * c[3];
|
||||||
|
c[2] = (color >> 0 & 0xff) / 255.0f * c[3];
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||||
|
* Copyright 2012 Hannes Janetzek
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
* 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
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
@ -33,6 +34,7 @@ import org.oscim.database.OpenResult;
|
|||||||
import org.oscim.generator.JobQueue;
|
import org.oscim.generator.JobQueue;
|
||||||
import org.oscim.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
import org.oscim.generator.MapWorker;
|
import org.oscim.generator.MapWorker;
|
||||||
|
import org.oscim.renderer.GLRenderer;
|
||||||
import org.oscim.renderer.MapRenderer;
|
import org.oscim.renderer.MapRenderer;
|
||||||
import org.oscim.renderer.TileGenerator;
|
import org.oscim.renderer.TileGenerator;
|
||||||
import org.oscim.theme.ExternalRenderTheme;
|
import org.oscim.theme.ExternalRenderTheme;
|
||||||
@ -58,7 +60,7 @@ public class MapView extends FrameLayout {
|
|||||||
|
|
||||||
public static final boolean debugFrameTime = false;
|
public static final boolean debugFrameTime = false;
|
||||||
public static final boolean testRegionZoom = false;
|
public static final boolean testRegionZoom = false;
|
||||||
public static final boolean staticLabeling = true;
|
// public static final boolean staticLabeling = false;
|
||||||
|
|
||||||
private static final boolean debugDatabase = false;
|
private static final boolean debugDatabase = false;
|
||||||
|
|
||||||
@ -438,8 +440,9 @@ public class MapView extends FrameLayout {
|
|||||||
try {
|
try {
|
||||||
inputStream = theme.getRenderThemeAsStream();
|
inputStream = theme.getRenderThemeAsStream();
|
||||||
RenderTheme t = RenderThemeHandler.getRenderTheme(inputStream);
|
RenderTheme t = RenderThemeHandler.getRenderTheme(inputStream);
|
||||||
mMapRenderer.setRenderTheme(t);
|
// FIXME somehow...
|
||||||
mMapWorkers[0].getMapGenerator().setRenderTheme(t);
|
GLRenderer.setRenderTheme(t);
|
||||||
|
TileGenerator.setRenderTheme(t);
|
||||||
return true;
|
return true;
|
||||||
} catch (ParserConfigurationException e) {
|
} catch (ParserConfigurationException e) {
|
||||||
Log.e(TAG, e.getMessage());
|
Log.e(TAG, e.getMessage());
|
||||||
|
@ -523,7 +523,7 @@ public class MapViewPosition {
|
|||||||
mMapScale = newScale;
|
mMapScale = newScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pivotY != 0 || pivotY != 0)
|
if (pivotX != 0 || pivotY != 0)
|
||||||
moveMap(pivotX * (1.0f - scale),
|
moveMap(pivotX * (1.0f - scale),
|
||||||
pivotY * (1.0f - scale));
|
pivotY * (1.0f - scale));
|
||||||
|
|
||||||
|
@ -116,9 +116,10 @@ public class MapZoomControls {
|
|||||||
private final Handler mZoomControlsHideHandler;
|
private final Handler mZoomControlsHideHandler;
|
||||||
private byte mZoomLevelMax;
|
private byte mZoomLevelMax;
|
||||||
private byte mZoomLevelMin;
|
private byte mZoomLevelMin;
|
||||||
private MapView mMapView;
|
private final MapView mMapView;
|
||||||
|
|
||||||
MapZoomControls(Context context, final MapView mapView) {
|
MapZoomControls(Context context, final MapView mapView) {
|
||||||
|
mMapView = mapView;
|
||||||
mZoomControls = new ZoomControls(context);
|
mZoomControls = new ZoomControls(context);
|
||||||
mShowMapZoomControls = true;
|
mShowMapZoomControls = true;
|
||||||
mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
|
mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
|
||||||
|
@ -12,34 +12,8 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.renderer;
|
package org.oscim.view;
|
||||||
|
|
||||||
import org.oscim.theme.renderinstruction.Text;
|
public class OverlayManager {
|
||||||
|
|
||||||
public class TextItem {
|
|
||||||
TextItem next;
|
|
||||||
|
|
||||||
final float x, y;
|
|
||||||
final String string;
|
|
||||||
final Text text;
|
|
||||||
final float width;
|
|
||||||
|
|
||||||
short x1, y1, x2, y2;
|
|
||||||
|
|
||||||
public TextItem(float x, float y, String string, Text text) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.string = string;
|
|
||||||
this.text = text;
|
|
||||||
this.width = text.paint.measureText(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextItem(float x, float y, String string, Text text, float width) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.string = string;
|
|
||||||
this.text = text;
|
|
||||||
this.width = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -18,6 +18,8 @@ import org.oscim.core.Tile;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.CountDownTimer;
|
import android.os.CountDownTimer;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
@ -53,6 +55,9 @@ final class TouchHandler
|
|||||||
private boolean mMoveStart;
|
private boolean mMoveStart;
|
||||||
private boolean mBeginRotate;
|
private boolean mBeginRotate;
|
||||||
private boolean mBeginTilt;
|
private boolean mBeginTilt;
|
||||||
|
private boolean mLongPress;
|
||||||
|
private long mLongPressTime;
|
||||||
|
|
||||||
private float mPosX;
|
private float mPosX;
|
||||||
private float mPosY;
|
private float mPosY;
|
||||||
private double mAngle;
|
private double mAngle;
|
||||||
@ -124,6 +129,7 @@ final class TouchHandler
|
|||||||
|
|
||||||
private boolean onActionCancel() {
|
private boolean onActionCancel() {
|
||||||
mActivePointerId = INVALID_POINTER_ID;
|
mActivePointerId = INVALID_POINTER_ID;
|
||||||
|
mLongPress = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +180,12 @@ final class TouchHandler
|
|||||||
mPosX = event.getX(id);
|
mPosX = event.getX(id);
|
||||||
mPosY = event.getY(id);
|
mPosY = event.getY(id);
|
||||||
|
|
||||||
|
if (mLongPress) {
|
||||||
|
mMapPosition.scaleMap(1 - moveY / 100, 0, 0);
|
||||||
|
mMapView.redrawMap();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!scaling) {
|
if (!scaling) {
|
||||||
mMapPosition.moveMap(moveX, moveY);
|
mMapPosition.moveMap(moveX, moveY);
|
||||||
mMapView.redrawMap();
|
mMapView.redrawMap();
|
||||||
@ -207,7 +219,16 @@ final class TouchHandler
|
|||||||
if (!mBeginRotate && !mBeginScale && !mBeginTilt) {
|
if (!mBeginRotate && !mBeginScale && !mBeginTilt) {
|
||||||
if (Math.abs(r) > 0.03)
|
if (Math.abs(r) > 0.03)
|
||||||
mBeginRotate = true;
|
mBeginRotate = true;
|
||||||
} else if (mBeginRotate) {
|
}
|
||||||
|
|
||||||
|
// quick way to prevent flipping...
|
||||||
|
// Log.d("", "rotation " + rad + " " + r);
|
||||||
|
if (Math.abs(r) > 0.1) {
|
||||||
|
rad = mAngle;
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBeginRotate) {
|
||||||
double rsin = Math.sin(r);
|
double rsin = Math.sin(r);
|
||||||
double rcos = Math.cos(r);
|
double rcos = Math.cos(r);
|
||||||
|
|
||||||
@ -260,6 +281,8 @@ final class TouchHandler
|
|||||||
}
|
}
|
||||||
multi--;
|
multi--;
|
||||||
|
|
||||||
|
mLongPress = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,6 +295,28 @@ final class TouchHandler
|
|||||||
mActivePointerId = INVALID_POINTER_ID;
|
mActivePointerId = INVALID_POINTER_ID;
|
||||||
mScaling = false;
|
mScaling = false;
|
||||||
multi = 0;
|
multi = 0;
|
||||||
|
|
||||||
|
// if (mLongPress && SystemClock.uptimeMillis() - mLongPressTime < 150)
|
||||||
|
// {
|
||||||
|
// mScrollX = (mPosX - (mMapView.getWidth() >> 1)) * 2f;
|
||||||
|
// mScrollY = (mPosY - (mMapView.getHeight() >> 1)) * 2f;
|
||||||
|
// mPrevScale = 0;
|
||||||
|
//
|
||||||
|
// mTimer = new CountDownTimer((int) SCALE_DURATION, 30) {
|
||||||
|
// @Override
|
||||||
|
// public void onTick(long tick) {
|
||||||
|
// scale2(tick);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void onFinish() {
|
||||||
|
// scale2(0);
|
||||||
|
// }
|
||||||
|
// }.start();
|
||||||
|
// }
|
||||||
|
|
||||||
|
mLongPress = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +337,6 @@ final class TouchHandler
|
|||||||
}
|
}
|
||||||
fling = false;
|
fling = false;
|
||||||
}
|
}
|
||||||
// Log.d("mapsforge", "onDown");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -353,6 +397,7 @@ final class TouchHandler
|
|||||||
Log.d("mapsforge", "long press");
|
Log.d("mapsforge", "long press");
|
||||||
mMapView.mRegionLookup.updateRegion(-1, null);
|
mMapView.mRegionLookup.updateRegion(-1, null);
|
||||||
}
|
}
|
||||||
|
mLongPress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean scale2(long tick) {
|
boolean scale2(long tick) {
|
||||||
@ -360,11 +405,12 @@ final class TouchHandler
|
|||||||
fling = true;
|
fling = true;
|
||||||
if (mPrevScale >= 1)
|
if (mPrevScale >= 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float adv = (SCALE_DURATION - tick) / SCALE_DURATION;
|
float adv = (SCALE_DURATION - tick) / SCALE_DURATION;
|
||||||
adv = mInterpolator.getInterpolation(adv);
|
adv = mInterpolator.getInterpolation(adv);
|
||||||
|
|
||||||
float scale = adv - mPrevScale;
|
float scale = adv - mPrevScale;
|
||||||
mPrevScale += scale;
|
mPrevScale += scale;
|
||||||
|
scale *= 0.75;
|
||||||
scale += 1;
|
scale += 1;
|
||||||
adv += 1;
|
adv += 1;
|
||||||
|
|
||||||
@ -379,26 +425,26 @@ final class TouchHandler
|
|||||||
@Override
|
@Override
|
||||||
public boolean onDoubleTap(MotionEvent e) {
|
public boolean onDoubleTap(MotionEvent e) {
|
||||||
if (MapView.testRegionZoom) {
|
if (MapView.testRegionZoom) {
|
||||||
Log.d("mapsforge", "double tap");
|
|
||||||
|
|
||||||
mMapView.mRegionLookup.updateRegion(1,
|
mMapView.mRegionLookup.updateRegion(1,
|
||||||
mMapPosition.getOffsetPoint(mPosX, mPosY));
|
mMapPosition.getOffsetPoint(mPosX, mPosY));
|
||||||
} else {
|
} else {
|
||||||
mScrollX = (e.getX(0) - (mMapView.getWidth() >> 1)) * 2f;
|
mLongPress = true;
|
||||||
mScrollY = (e.getY(0) - (mMapView.getHeight() >> 1)) * 2f;
|
mLongPressTime = SystemClock.uptimeMillis();
|
||||||
mPrevScale = 0;
|
// mScrollX = (e.getX(0) - (mMapView.getWidth() >> 1)) * 2f;
|
||||||
|
// mScrollY = (e.getY(0) - (mMapView.getHeight() >> 1)) * 2f;
|
||||||
mTimer = new CountDownTimer((int) SCALE_DURATION, 30) {
|
// mPrevScale = 0;
|
||||||
@Override
|
//
|
||||||
public void onTick(long tick) {
|
// mTimer = new CountDownTimer((int) SCALE_DURATION, 30) {
|
||||||
scale2(tick);
|
// @Override
|
||||||
}
|
// public void onTick(long tick) {
|
||||||
|
// scale2(tick);
|
||||||
@Override
|
// }
|
||||||
public void onFinish() {
|
//
|
||||||
scale(0);
|
// @Override
|
||||||
}
|
// public void onFinish() {
|
||||||
}.start();
|
// scale(0);
|
||||||
|
// }
|
||||||
|
// }.start();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -513,4 +559,120 @@ final class TouchHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* from CountDownTimer.java: Copyright (C) 2008 The Android Open Source
|
||||||
|
* Project Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License. You may
|
||||||
|
* obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
|
||||||
|
* law or agreed to in writing, software distributed under the License is
|
||||||
|
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the specific
|
||||||
|
* language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final static class Timer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Millis since epoch when alarm should stop.
|
||||||
|
*/
|
||||||
|
private final long mMillisInFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interval in millis that the user receives callbacks
|
||||||
|
*/
|
||||||
|
final long mCountdownInterval;
|
||||||
|
|
||||||
|
long mStopTimeInFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param millisInFuture
|
||||||
|
* The number of millis in the future from the call to
|
||||||
|
* {@link #start()} until the countdown is done and
|
||||||
|
* {@link #onFinish()} is called.
|
||||||
|
* @param countDownInterval
|
||||||
|
* The interval along the way to receive
|
||||||
|
* {@link #onTick(long)} callbacks.
|
||||||
|
*/
|
||||||
|
public Timer(long millisInFuture, long countDownInterval) {
|
||||||
|
mMillisInFuture = millisInFuture;
|
||||||
|
mCountdownInterval = countDownInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel the countdown.
|
||||||
|
*/
|
||||||
|
public final void cancel() {
|
||||||
|
mHandler.removeMessages(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the countdown.
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public synchronized final Timer start() {
|
||||||
|
if (mMillisInFuture <= 0) {
|
||||||
|
onFinish();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(MSG));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback fired on regular interval.
|
||||||
|
*
|
||||||
|
* @param millisUntilFinished
|
||||||
|
* The amount of time until finished.
|
||||||
|
*/
|
||||||
|
public void onTick(long millisUntilFinished) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback fired when the time is up.
|
||||||
|
*/
|
||||||
|
public void onFinish() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int MSG = 1;
|
||||||
|
|
||||||
|
// handles counting down
|
||||||
|
private Handler mHandler = new Handler() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
|
||||||
|
synchronized (Timer.this) {
|
||||||
|
final long millisLeft = mStopTimeInFuture
|
||||||
|
- SystemClock.elapsedRealtime();
|
||||||
|
|
||||||
|
if (millisLeft <= 0) {
|
||||||
|
onFinish();
|
||||||
|
} else if (millisLeft < mCountdownInterval) {
|
||||||
|
// no tick, just delay until done
|
||||||
|
sendMessageDelayed(obtainMessage(MSG), millisLeft);
|
||||||
|
} else {
|
||||||
|
long lastTickStart = SystemClock.elapsedRealtime();
|
||||||
|
onTick(millisLeft);
|
||||||
|
|
||||||
|
// take into account user's onTick taking time to
|
||||||
|
// execute
|
||||||
|
long delay = lastTickStart + mCountdownInterval
|
||||||
|
- SystemClock.elapsedRealtime();
|
||||||
|
|
||||||
|
// special case: user's onTick took more than interval
|
||||||
|
// to
|
||||||
|
// complete, skip to next interval
|
||||||
|
while (delay < 0)
|
||||||
|
delay += mCountdownInterval;
|
||||||
|
|
||||||
|
sendMessageDelayed(obtainMessage(MSG), delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user