draw text textures only once per string
- unify duplicate strings from different tiles (as side-effect save some bytes) - fix 'advance by width' in texture drawing
This commit is contained in:
parent
928c7e7328
commit
e1fb97ae30
@ -22,7 +22,6 @@ import android.util.Log;
|
|||||||
* @author Hannes Janetzek
|
* @author Hannes Janetzek
|
||||||
*/
|
*/
|
||||||
public class Layers {
|
public class Layers {
|
||||||
|
|
||||||
// mixed Polygon and Line layers
|
// mixed Polygon and Line layers
|
||||||
public Layer layers;
|
public Layer layers;
|
||||||
public Layer textureLayers;
|
public Layer textureLayers;
|
||||||
@ -34,6 +33,10 @@ public class Layers {
|
|||||||
// 3. other layers keep their byte offset in Layer.offset
|
// 3. other layers keep their byte offset in Layer.offset
|
||||||
public int lineOffset;
|
public int lineOffset;
|
||||||
|
|
||||||
|
// time when layers became first rendered (in uptime)
|
||||||
|
// used for animations
|
||||||
|
public long time;
|
||||||
|
|
||||||
private Layer mCurLayer;
|
private Layer mCurLayer;
|
||||||
|
|
||||||
// get or add the line- or polygon-layer for a level.
|
// get or add the line- or polygon-layer for a level.
|
||||||
@ -198,7 +201,6 @@ public class Layers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (l = textureLayers; l != null; l = l.next) {
|
for (l = textureLayers; l != null; l = l.next) {
|
||||||
VertexPool.release(l.pool);
|
|
||||||
l.clear();
|
l.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +207,13 @@ public final class SymbolLayer extends TextureLayer {
|
|||||||
short tx = (short) ((int) (SCALE * it2.x) & LBIT_MASK | (it2.billboard ? 1 : 0));
|
short tx = (short) ((int) (SCALE * it2.x) & LBIT_MASK | (it2.billboard ? 1 : 0));
|
||||||
short ty = (short) (SCALE * it2.y);
|
short ty = (short) (SCALE * it2.y);
|
||||||
|
|
||||||
|
if (pos == VertexPoolItem.SIZE) {
|
||||||
|
si.used = VertexPoolItem.SIZE;
|
||||||
|
si = si.next = VertexPool.get();
|
||||||
|
buf = si.vertices;
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// top-left
|
// top-left
|
||||||
buf[pos++] = tx;
|
buf[pos++] = tx;
|
||||||
buf[pos++] = ty;
|
buf[pos++] = ty;
|
||||||
@ -238,17 +245,9 @@ public final class SymbolLayer extends TextureLayer {
|
|||||||
|
|
||||||
// six elements used to draw the four vertices
|
// six elements used to draw the four vertices
|
||||||
curIndices += TextureRenderer.INDICES_PER_SPRITE;
|
curIndices += TextureRenderer.INDICES_PER_SPRITE;
|
||||||
|
|
||||||
if (pos == VertexPoolItem.SIZE) {
|
|
||||||
si.used = VertexPoolItem.SIZE;
|
|
||||||
si = si.next = VertexPool.get();
|
|
||||||
buf = si.vertices;
|
|
||||||
pos = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x += width;
|
x += width;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
to.offset = offsetIndices;
|
to.offset = offsetIndices;
|
||||||
to.vertices = curIndices;
|
to.vertices = curIndices;
|
||||||
@ -263,8 +262,10 @@ public final class SymbolLayer extends TextureLayer {
|
|||||||
protected void clear() {
|
protected void clear() {
|
||||||
TextureObject.release(textures);
|
TextureObject.release(textures);
|
||||||
SymbolItem.release(symbols);
|
SymbolItem.release(symbols);
|
||||||
|
VertexPool.release(pool);
|
||||||
textures = null;
|
textures = null;
|
||||||
symbols = null;
|
symbols = null;
|
||||||
|
pool = null;
|
||||||
verticesCnt = 0;
|
verticesCnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,21 @@ public class TextItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void append(TextItem ti, TextItem in) {
|
||||||
|
if (ti == null)
|
||||||
|
return;
|
||||||
|
if (ti.next == null) {
|
||||||
|
in.next = ti.next;
|
||||||
|
ti.next = in;
|
||||||
|
}
|
||||||
|
TextItem t = ti;
|
||||||
|
while (t.next != null)
|
||||||
|
t = t.next;
|
||||||
|
|
||||||
|
in.next = t.next;
|
||||||
|
t.next = in;
|
||||||
|
}
|
||||||
|
|
||||||
public static void release(TextItem ti) {
|
public static void release(TextItem ti) {
|
||||||
if (ti == null)
|
if (ti == null)
|
||||||
return;
|
return;
|
||||||
|
@ -22,7 +22,7 @@ import android.util.Log;
|
|||||||
|
|
||||||
public final class TextLayer extends TextureLayer {
|
public final class TextLayer extends TextureLayer {
|
||||||
|
|
||||||
// private static String TAG = TextureLayer.class.getSimpleName();
|
//private static String TAG = TextureLayer.class.getName();
|
||||||
|
|
||||||
private final static int TEXTURE_WIDTH = TextureObject.TEXTURE_WIDTH;
|
private final static int TEXTURE_WIDTH = TextureObject.TEXTURE_WIDTH;
|
||||||
private final static int TEXTURE_HEIGHT = TextureObject.TEXTURE_HEIGHT;
|
private final static int TEXTURE_HEIGHT = TextureObject.TEXTURE_HEIGHT;
|
||||||
@ -61,10 +61,8 @@ public final class TextLayer extends TextureLayer {
|
|||||||
else
|
else
|
||||||
prev.next = it.next;
|
prev.next = it.next;
|
||||||
|
|
||||||
verticesCnt -= 4;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = it;
|
prev = it;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,21 +70,42 @@ public final class TextLayer extends TextureLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addText(TextItem item) {
|
public void addText(TextItem item) {
|
||||||
verticesCnt += 4;
|
|
||||||
TextItem it = labels;
|
TextItem it = labels;
|
||||||
|
|
||||||
for (; it != null; it = it.next) {
|
for (; it != null; it = it.next) {
|
||||||
if (it.text == item.text) {
|
// todo add captions at the end
|
||||||
// insert after text of same type
|
//if (item.text.caption && !it.text.caption)
|
||||||
|
//continue;
|
||||||
|
//if (!item.text.caption && it.text.caption)
|
||||||
|
//continue;
|
||||||
|
|
||||||
|
if (item.text == it.text) {
|
||||||
|
while (it.next != null
|
||||||
|
// break if next item uses different text style
|
||||||
|
&& item.text == it.next.text
|
||||||
|
// check same string instance
|
||||||
|
&& item.string != it.string
|
||||||
|
// check same string
|
||||||
|
&& !item.string.equals(it.string))
|
||||||
|
it = it.next;
|
||||||
|
|
||||||
|
// unify duplicate string :)
|
||||||
|
// Note: this is required for 'packing test' in prepare to work!
|
||||||
|
if (item.string != it.string && item.string.equals(it.string))
|
||||||
|
item.string = it.string;
|
||||||
|
|
||||||
|
// insert after text of same type and/or before same string
|
||||||
item.next = it.next;
|
item.next = it.next;
|
||||||
it.next = item;
|
it.next = item;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item.next = labels;
|
item.next = labels;
|
||||||
labels = item;
|
labels = item;
|
||||||
|
// for (it = labels; it != null; it = it.next)
|
||||||
|
// Log.d(TAG, "> " + it.text + " " + it.string);
|
||||||
|
// Log.d(TAG, "< ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,19 +113,14 @@ public final class TextLayer extends TextureLayer {
|
|||||||
if (TextureRenderer.debug)
|
if (TextureRenderer.debug)
|
||||||
Log.d("...", "prepare");
|
Log.d("...", "prepare");
|
||||||
|
|
||||||
// int numLabel = 0;
|
|
||||||
// int numTextures = 0;
|
|
||||||
|
|
||||||
short numIndices = 0;
|
short numIndices = 0;
|
||||||
short offsetIndices = 0;
|
short offsetIndices = 0;
|
||||||
|
|
||||||
curItem = VertexPool.get();
|
VertexPoolItem vi = pool = VertexPool.get();
|
||||||
pool = curItem;
|
int pos = vi.used; // 0
|
||||||
|
short buf[] = vi.vertices;
|
||||||
|
|
||||||
VertexPoolItem si = curItem;
|
verticesCnt = 0;
|
||||||
|
|
||||||
int pos = si.used;
|
|
||||||
short buf[] = si.vertices;
|
|
||||||
|
|
||||||
int advanceY = 0;
|
int advanceY = 0;
|
||||||
float x = 0;
|
float x = 0;
|
||||||
@ -117,8 +131,7 @@ public final class TextLayer extends TextureLayer {
|
|||||||
textures = to;
|
textures = to;
|
||||||
mCanvas.setBitmap(to.bitmap);
|
mCanvas.setBitmap(to.bitmap);
|
||||||
|
|
||||||
for (TextItem it = labels; it != null; it = it.next) {
|
for (TextItem it = labels; it != null;) {
|
||||||
// numLabel++;
|
|
||||||
|
|
||||||
float width = it.width + 2 * mFontPadX;
|
float width = it.width + 2 * mFontPadX;
|
||||||
float height = (int) (it.text.fontHeight) + 2 * mFontPadY + 0.5f;
|
float height = (int) (it.text.fontHeight) + 2 * mFontPadY + 0.5f;
|
||||||
@ -165,6 +178,34 @@ public final class TextLayer extends TextureLayer {
|
|||||||
float hw = width / 2.0f;
|
float hw = width / 2.0f;
|
||||||
float hh = height / 2.0f;
|
float hh = height / 2.0f;
|
||||||
|
|
||||||
|
float hh2 = 0;
|
||||||
|
if (!it.text.caption) {
|
||||||
|
hw /= mScale;
|
||||||
|
hh2 = hh + it.text.fontDescent / 2;
|
||||||
|
hh -= it.text.fontDescent / 2;
|
||||||
|
hh /= mScale;
|
||||||
|
hh2 /= mScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// texture coordinates
|
||||||
|
short u1 = (short) (SCALE * x);
|
||||||
|
short v1 = (short) (SCALE * y);
|
||||||
|
short u2 = (short) (SCALE * (x + width));
|
||||||
|
short v2 = (short) (SCALE * (y + height));
|
||||||
|
|
||||||
|
// add symbol items referencing the same bitmap / drawable
|
||||||
|
for (TextItem it2 = it;; it2 = it2.next) {
|
||||||
|
|
||||||
|
if (it != it2) {
|
||||||
|
if (it2 == null
|
||||||
|
|| (it2.text != it.text)
|
||||||
|
|| (it2.string != it.string)) {
|
||||||
|
it = it2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Log.d(TAG, "pack strings: " + it.string);
|
||||||
|
}
|
||||||
|
|
||||||
short x1, x2, x3, x4, y1, y3, y2, y4;
|
short x1, x2, x3, x4, y1, y3, y2, y4;
|
||||||
|
|
||||||
if (it.text.caption) {
|
if (it.text.caption) {
|
||||||
@ -175,8 +216,8 @@ public final class TextLayer extends TextureLayer {
|
|||||||
// x1 = x3 = (short) (0);
|
// x1 = x3 = (short) (0);
|
||||||
// x2 = x4 = (short) (SCALE * width);
|
// x2 = x4 = (short) (SCALE * width);
|
||||||
} else {
|
} else {
|
||||||
float vx = it.x1 - it.x2;
|
float vx = it2.x1 - it2.x2;
|
||||||
float vy = it.y1 - it.y2;
|
float vy = it2.y1 - it2.y2;
|
||||||
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||||
vx = vx / a;
|
vx = vx / a;
|
||||||
vy = vy / a;
|
vy = vy / a;
|
||||||
@ -184,13 +225,6 @@ public final class TextLayer extends TextureLayer {
|
|||||||
float ux = -vy;
|
float ux = -vy;
|
||||||
float uy = vx;
|
float uy = vx;
|
||||||
|
|
||||||
hw /= mScale;
|
|
||||||
float hh2 = hh + it.text.fontDescent / 2;
|
|
||||||
hh -= it.text.fontDescent / 2;
|
|
||||||
|
|
||||||
hh /= mScale;
|
|
||||||
hh2 /= mScale;
|
|
||||||
|
|
||||||
x1 = (short) (SCALE * (vx * hw - ux * hh));
|
x1 = (short) (SCALE * (vx * hw - ux * hh));
|
||||||
y1 = (short) (SCALE * (vy * hw - uy * hh));
|
y1 = (short) (SCALE * (vy * hw - uy * hh));
|
||||||
x2 = (short) (SCALE * (-vx * hw - ux * hh));
|
x2 = (short) (SCALE * (-vx * hw - ux * hh));
|
||||||
@ -201,16 +235,17 @@ public final class TextLayer extends TextureLayer {
|
|||||||
y3 = (short) (SCALE * (vy * hw + uy * 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
|
// add vertices
|
||||||
int tmp = (int) (SCALE * it.x) & LBIT_MASK;
|
int tmp = (int) (SCALE * it2.x) & LBIT_MASK;
|
||||||
short tx = (short) (tmp | (it.text.caption ? 1 : 0));
|
short tx = (short) (tmp | (it2.text.caption ? 1 : 0));
|
||||||
|
short ty = (short) (SCALE * it2.y);
|
||||||
|
|
||||||
short ty = (short) (SCALE * it.y);
|
if (pos == VertexPoolItem.SIZE) {
|
||||||
|
vi.used = VertexPoolItem.SIZE;
|
||||||
|
vi = vi.next = VertexPool.get();
|
||||||
|
buf = vi.vertices;
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// top-left
|
// top-left
|
||||||
buf[pos++] = tx;
|
buf[pos++] = tx;
|
||||||
@ -242,14 +277,8 @@ public final class TextLayer extends TextureLayer {
|
|||||||
buf[pos++] = v1;
|
buf[pos++] = v1;
|
||||||
|
|
||||||
// six indices to draw the four vertices
|
// six indices to draw the four vertices
|
||||||
numIndices += 6;
|
numIndices += TextureRenderer.INDICES_PER_SPRITE;
|
||||||
|
verticesCnt += 4;
|
||||||
if (pos == VertexPoolItem.SIZE) {
|
|
||||||
si.used = VertexPoolItem.SIZE;
|
|
||||||
si = si.next = VertexPool.get();
|
|
||||||
buf = si.vertices;
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME this does not work, need to draw bitmap on next
|
// FIXME this does not work, need to draw bitmap on next
|
||||||
// texture...
|
// texture...
|
||||||
@ -259,15 +288,15 @@ public final class TextLayer extends TextureLayer {
|
|||||||
// pos = 0;
|
// pos = 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
x += width;
|
x += width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vi.used = pos;
|
||||||
|
|
||||||
to.offset = offsetIndices;
|
to.offset = offsetIndices;
|
||||||
to.vertices = (short) (numIndices - offsetIndices);
|
to.vertices = (short) (numIndices - offsetIndices);
|
||||||
|
|
||||||
si.used = pos;
|
|
||||||
curItem = si;
|
|
||||||
|
|
||||||
// Log.d(TAG, "added labels " + numTextures + " " + numLabel);
|
// Log.d(TAG, "added labels " + numTextures + " " + numLabel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -277,8 +306,10 @@ public final class TextLayer extends TextureLayer {
|
|||||||
protected void clear() {
|
protected void clear() {
|
||||||
TextureObject.release(textures);
|
TextureObject.release(textures);
|
||||||
TextItem.release(labels);
|
TextItem.release(labels);
|
||||||
|
VertexPool.release(pool);
|
||||||
textures = null;
|
textures = null;
|
||||||
labels = null;
|
labels = null;
|
||||||
|
pool = null;
|
||||||
verticesCnt = 0;
|
verticesCnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,11 @@ public class TextOverlay extends RenderOverlay {
|
|||||||
private LabelThread mThread;
|
private LabelThread mThread;
|
||||||
|
|
||||||
private MapPosition mWorkPos;
|
private MapPosition mWorkPos;
|
||||||
|
|
||||||
|
// TextLayer that is updating
|
||||||
private TextLayer mWorkLayer;
|
private TextLayer mWorkLayer;
|
||||||
private TextLayer mNewLayer;
|
// TextLayer that is ready to be added to 'layers'
|
||||||
|
private TextLayer mCurLayer;
|
||||||
|
|
||||||
/* package */boolean mRun;
|
/* package */boolean mRun;
|
||||||
/* package */boolean mRerun;
|
/* package */boolean mRerun;
|
||||||
@ -97,8 +100,9 @@ public class TextOverlay extends RenderOverlay {
|
|||||||
|
|
||||||
// only relabel when tiles belong to the current zoomlevel or its parent
|
// only relabel when tiles belong to the current zoomlevel or its parent
|
||||||
if (diff > 1 || diff < -2) {
|
if (diff > 1 || diff < -2) {
|
||||||
|
// pass back the current layer
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mNewLayer = tl;
|
mCurLayer = tl;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -257,7 +261,7 @@ public class TextOverlay extends RenderOverlay {
|
|||||||
|
|
||||||
// everything synchronized?
|
// everything synchronized?
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mNewLayer = tl;
|
mCurLayer = tl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,14 +272,17 @@ public class TextOverlay extends RenderOverlay {
|
|||||||
if (mHolding)
|
if (mHolding)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mNewLayer != null) {
|
if (mCurLayer != null) {
|
||||||
|
// keep text layer, not recrating its canvas each time
|
||||||
// keep text layer, not recrating its canvas each time...
|
|
||||||
mWorkLayer = (TextLayer) layers.textureLayers;
|
mWorkLayer = (TextLayer) layers.textureLayers;
|
||||||
|
|
||||||
|
// clear textures and text items from previous layer
|
||||||
layers.clear();
|
layers.clear();
|
||||||
|
|
||||||
layers.textureLayers = mNewLayer;
|
// set new TextLayer to be uploaded and used
|
||||||
mNewLayer = null;
|
layers.textureLayers = mCurLayer;
|
||||||
|
|
||||||
|
mCurLayer = null;
|
||||||
|
|
||||||
// make the 'labeled' MapPosition current
|
// make the 'labeled' MapPosition current
|
||||||
MapPosition tmp = mMapPosition;
|
MapPosition tmp = mMapPosition;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user