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
|
||||
*/
|
||||
public class Layers {
|
||||
|
||||
// mixed Polygon and Line layers
|
||||
public Layer layers;
|
||||
public Layer textureLayers;
|
||||
@ -34,6 +33,10 @@ public class Layers {
|
||||
// 3. other layers keep their byte offset in Layer.offset
|
||||
public int lineOffset;
|
||||
|
||||
// time when layers became first rendered (in uptime)
|
||||
// used for animations
|
||||
public long time;
|
||||
|
||||
private Layer mCurLayer;
|
||||
|
||||
// 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) {
|
||||
VertexPool.release(l.pool);
|
||||
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 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
|
||||
buf[pos++] = tx;
|
||||
buf[pos++] = ty;
|
||||
@ -238,17 +245,9 @@ public final class SymbolLayer extends TextureLayer {
|
||||
|
||||
// six elements used to draw the four vertices
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
to.offset = offsetIndices;
|
||||
to.vertices = curIndices;
|
||||
@ -263,8 +262,10 @@ public final class SymbolLayer extends TextureLayer {
|
||||
protected void clear() {
|
||||
TextureObject.release(textures);
|
||||
SymbolItem.release(symbols);
|
||||
VertexPool.release(pool);
|
||||
textures = null;
|
||||
symbols = null;
|
||||
pool = null;
|
||||
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) {
|
||||
if (ti == null)
|
||||
return;
|
||||
|
@ -22,7 +22,7 @@ import android.util.Log;
|
||||
|
||||
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_HEIGHT = TextureObject.TEXTURE_HEIGHT;
|
||||
@ -61,10 +61,8 @@ public final class TextLayer extends TextureLayer {
|
||||
else
|
||||
prev.next = it.next;
|
||||
|
||||
verticesCnt -= 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
prev = it;
|
||||
}
|
||||
|
||||
@ -72,21 +70,42 @@ public final class TextLayer extends TextureLayer {
|
||||
}
|
||||
|
||||
public void addText(TextItem item) {
|
||||
verticesCnt += 4;
|
||||
TextItem it = labels;
|
||||
|
||||
for (; it != null; it = it.next) {
|
||||
if (it.text == item.text) {
|
||||
// insert after text of same type
|
||||
// todo add captions at the end
|
||||
//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;
|
||||
it.next = item;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item.next = labels;
|
||||
labels = item;
|
||||
// for (it = labels; it != null; it = it.next)
|
||||
// Log.d(TAG, "> " + it.text + " " + it.string);
|
||||
// Log.d(TAG, "< ");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -94,19 +113,14 @@ public final class TextLayer extends TextureLayer {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "prepare");
|
||||
|
||||
// int numLabel = 0;
|
||||
// int numTextures = 0;
|
||||
|
||||
short numIndices = 0;
|
||||
short offsetIndices = 0;
|
||||
|
||||
curItem = VertexPool.get();
|
||||
pool = curItem;
|
||||
VertexPoolItem vi = pool = VertexPool.get();
|
||||
int pos = vi.used; // 0
|
||||
short buf[] = vi.vertices;
|
||||
|
||||
VertexPoolItem si = curItem;
|
||||
|
||||
int pos = si.used;
|
||||
short buf[] = si.vertices;
|
||||
verticesCnt = 0;
|
||||
|
||||
int advanceY = 0;
|
||||
float x = 0;
|
||||
@ -117,8 +131,7 @@ public final class TextLayer extends TextureLayer {
|
||||
textures = to;
|
||||
mCanvas.setBitmap(to.bitmap);
|
||||
|
||||
for (TextItem it = labels; it != null; it = it.next) {
|
||||
// numLabel++;
|
||||
for (TextItem it = labels; it != null;) {
|
||||
|
||||
float width = it.width + 2 * mFontPadX;
|
||||
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 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;
|
||||
|
||||
if (it.text.caption) {
|
||||
@ -175,8 +216,8 @@ public final class TextLayer extends TextureLayer {
|
||||
// x1 = x3 = (short) (0);
|
||||
// x2 = x4 = (short) (SCALE * width);
|
||||
} else {
|
||||
float vx = it.x1 - it.x2;
|
||||
float vy = it.y1 - it.y2;
|
||||
float vx = it2.x1 - it2.x2;
|
||||
float vy = it2.y1 - it2.y2;
|
||||
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
vx = vx / a;
|
||||
vy = vy / a;
|
||||
@ -184,13 +225,6 @@ public final class TextLayer extends TextureLayer {
|
||||
float ux = -vy;
|
||||
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));
|
||||
y1 = (short) (SCALE * (vy * hw - uy * 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));
|
||||
}
|
||||
|
||||
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));
|
||||
int tmp = (int) (SCALE * it2.x) & LBIT_MASK;
|
||||
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
|
||||
buf[pos++] = tx;
|
||||
@ -242,14 +277,8 @@ public final class TextLayer extends TextureLayer {
|
||||
buf[pos++] = v1;
|
||||
|
||||
// six indices to draw the four vertices
|
||||
numIndices += 6;
|
||||
|
||||
if (pos == VertexPoolItem.SIZE) {
|
||||
si.used = VertexPoolItem.SIZE;
|
||||
si = si.next = VertexPool.get();
|
||||
buf = si.vertices;
|
||||
pos = 0;
|
||||
}
|
||||
numIndices += TextureRenderer.INDICES_PER_SPRITE;
|
||||
verticesCnt += 4;
|
||||
|
||||
// FIXME this does not work, need to draw bitmap on next
|
||||
// texture...
|
||||
@ -259,15 +288,15 @@ public final class TextLayer extends TextureLayer {
|
||||
// pos = 0;
|
||||
// }
|
||||
|
||||
}
|
||||
x += width;
|
||||
}
|
||||
|
||||
vi.used = pos;
|
||||
|
||||
to.offset = offsetIndices;
|
||||
to.vertices = (short) (numIndices - offsetIndices);
|
||||
|
||||
si.used = pos;
|
||||
curItem = si;
|
||||
|
||||
// Log.d(TAG, "added labels " + numTextures + " " + numLabel);
|
||||
|
||||
return true;
|
||||
@ -277,8 +306,10 @@ public final class TextLayer extends TextureLayer {
|
||||
protected void clear() {
|
||||
TextureObject.release(textures);
|
||||
TextItem.release(labels);
|
||||
VertexPool.release(pool);
|
||||
textures = null;
|
||||
labels = null;
|
||||
pool = null;
|
||||
verticesCnt = 0;
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,11 @@ public class TextOverlay extends RenderOverlay {
|
||||
private LabelThread mThread;
|
||||
|
||||
private MapPosition mWorkPos;
|
||||
|
||||
// TextLayer that is updating
|
||||
private TextLayer mWorkLayer;
|
||||
private TextLayer mNewLayer;
|
||||
// TextLayer that is ready to be added to 'layers'
|
||||
private TextLayer mCurLayer;
|
||||
|
||||
/* package */boolean mRun;
|
||||
/* package */boolean mRerun;
|
||||
@ -97,8 +100,9 @@ public class TextOverlay extends RenderOverlay {
|
||||
|
||||
// only relabel when tiles belong to the current zoomlevel or its parent
|
||||
if (diff > 1 || diff < -2) {
|
||||
// pass back the current layer
|
||||
synchronized (this) {
|
||||
mNewLayer = tl;
|
||||
mCurLayer = tl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -257,7 +261,7 @@ public class TextOverlay extends RenderOverlay {
|
||||
|
||||
// everything synchronized?
|
||||
synchronized (this) {
|
||||
mNewLayer = tl;
|
||||
mCurLayer = tl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,14 +272,17 @@ public class TextOverlay extends RenderOverlay {
|
||||
if (mHolding)
|
||||
return;
|
||||
|
||||
if (mNewLayer != null) {
|
||||
|
||||
// keep text layer, not recrating its canvas each time...
|
||||
if (mCurLayer != null) {
|
||||
// keep text layer, not recrating its canvas each time
|
||||
mWorkLayer = (TextLayer) layers.textureLayers;
|
||||
|
||||
// clear textures and text items from previous layer
|
||||
layers.clear();
|
||||
|
||||
layers.textureLayers = mNewLayer;
|
||||
mNewLayer = null;
|
||||
// set new TextLayer to be uploaded and used
|
||||
layers.textureLayers = mCurLayer;
|
||||
|
||||
mCurLayer = null;
|
||||
|
||||
// make the 'labeled' MapPosition current
|
||||
MapPosition tmp = mMapPosition;
|
||||
|
Loading…
x
Reference in New Issue
Block a user