New rendering for streets. Uses now redrawing instead of additional Bitmaps. No additional memory use. CPU usage with option shadow = 3 the same or even less than the classical one.
Changed missleading "shadowLayer" to "shadowRadius".
This commit is contained in:
parent
4f3f4cc322
commit
ed485a2702
1 changed files with 185 additions and 160 deletions
|
@ -63,31 +63,18 @@ public class OsmandRenderer {
|
|||
private Map<Integer, Bitmap> cachedIcons = new LinkedHashMap<Integer, Bitmap>();
|
||||
|
||||
private final Context context;
|
||||
//for street shadows
|
||||
private Canvas streetcv;
|
||||
|
||||
private DisplayMetrics dm;
|
||||
|
||||
private int[] shadowarray;
|
||||
private int shadownum;
|
||||
|
||||
private static class TextDrawInfo {
|
||||
|
||||
public TextDrawInfo(String text){
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
String text = null;
|
||||
Path drawOnPath = null;
|
||||
float vOffset = 0;
|
||||
float centerX = 0;
|
||||
float pathRotate = 0;
|
||||
float centerY = 0;
|
||||
float textSize = 0;
|
||||
float minDistance = 0;
|
||||
int textColor = Color.BLACK;
|
||||
int textShadow = 0;
|
||||
int textWrap = 0;
|
||||
boolean bold = false;
|
||||
int shieldRes = 0;
|
||||
int textOrder = 20;
|
||||
|
||||
public void fillProperties(RenderingContext rc, float centerX, float centerY){
|
||||
this.centerX = centerX + rc.textDx;
|
||||
|
@ -103,6 +90,21 @@ public class OsmandRenderer {
|
|||
textOrder = rc.textOrder;
|
||||
}
|
||||
}
|
||||
String text = null;
|
||||
Path drawOnPath = null;
|
||||
float vOffset = 0;
|
||||
float centerX = 0;
|
||||
float pathRotate = 0;
|
||||
float centerY = 0;
|
||||
float textSize = 0;
|
||||
float minDistance = 0;
|
||||
int textColor = Color.BLACK;
|
||||
int textShadow = 0;
|
||||
int textWrap = 0;
|
||||
boolean bold = false;
|
||||
int shieldRes = 0;
|
||||
int textOrder = 20;
|
||||
|
||||
}
|
||||
|
||||
private static class IconDrawInfo {
|
||||
|
@ -184,7 +186,7 @@ public class OsmandRenderer {
|
|||
/* package*/ static class RenderingPaintProperties {
|
||||
int color;
|
||||
float strokeWidth;
|
||||
int shadowLayer;
|
||||
int shadowRadius;
|
||||
int shadowColor;
|
||||
boolean fillArea;
|
||||
PathEffect pathEffect;
|
||||
|
@ -199,7 +201,7 @@ public class OsmandRenderer {
|
|||
fillArea = false;
|
||||
shader = null;
|
||||
shadowColor = 0;
|
||||
shadowLayer = 0;
|
||||
shadowRadius = 0;
|
||||
}
|
||||
|
||||
public void updatePaint(Paint p){
|
||||
|
@ -207,9 +209,9 @@ public class OsmandRenderer {
|
|||
p.setColor(color);
|
||||
p.setShader(shader);
|
||||
if(shadowColor == 0){
|
||||
shadowLayer = 0;
|
||||
shadowRadius = 0;
|
||||
}
|
||||
p.setShadowLayer(shadowLayer, 0, 0, shadowColor);
|
||||
p.setShadowLayer(shadowRadius, 0, 0, shadowColor);
|
||||
p.setStrokeWidth(strokeWidth);
|
||||
p.setStrokeCap(cap);
|
||||
if (!fillArea) {
|
||||
|
@ -225,7 +227,7 @@ public class OsmandRenderer {
|
|||
shader = null;
|
||||
pathEffect = null;
|
||||
shadowColor = 0;
|
||||
shadowLayer = 0;
|
||||
shadowRadius = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,16 +288,9 @@ public class OsmandRenderer {
|
|||
public Bitmap generateNewBitmap(RenderingContext rc, List<BinaryMapDataObject> objects, Bitmap bmp, boolean useEnglishNames,
|
||||
BaseOsmandRender renderer, List<IMapDownloaderCallback> notifyList) {
|
||||
long now = System.currentTimeMillis();
|
||||
//Flag for drawing the streets
|
||||
boolean streetsdrawn = false;
|
||||
|
||||
// fill area
|
||||
Canvas cv = new Canvas(bmp);
|
||||
|
||||
//needed for better street shadows
|
||||
Bitmap streetbmp = Bitmap.createBitmap(cv.getWidth(), cv.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
streetcv = new Canvas(streetbmp);
|
||||
|
||||
if(renderer != null){
|
||||
int dc = renderer.getDefaultColor(rc.nightMode);
|
||||
if(dc != 0){
|
||||
|
@ -349,29 +344,38 @@ public class OsmandRenderer {
|
|||
rc.cosRotateTileSize = FloatMath.cos((float) Math.toRadians(rc.rotate)) * TILE_SIZE;
|
||||
rc.sinRotateTileSize = FloatMath.sin((float) Math.toRadians(rc.rotate)) * TILE_SIZE;
|
||||
|
||||
//int shadow = 0; // no shadow (minumum CPU)
|
||||
//int shadow = 1; // classic shadow (the implementaton in master)
|
||||
//int shadow = 2; // blur shadow (most CPU, but still reasonable)
|
||||
int shadow = 3; // solid border (CPU use like classic version or even smaller)
|
||||
boolean repeat = false;
|
||||
|
||||
float[] keys = orderMap.keys();
|
||||
Arrays.sort(keys);
|
||||
int objCount = 0;
|
||||
|
||||
shadowarray = new int[keys.length];
|
||||
shadownum = 0;
|
||||
|
||||
for (int k = 0; k < keys.length; k++) {
|
||||
|
||||
if(repeat == true && shadowarray[shadownum] == k){
|
||||
shadownum++;
|
||||
continue;
|
||||
}
|
||||
|
||||
TIntArrayList list = orderMap.get(keys[k]);
|
||||
|
||||
for (int j = 0; j < list.size(); j++) {
|
||||
int i = list.get(j);
|
||||
int ind = i >> 8;
|
||||
int l = i & 0xff;
|
||||
BinaryMapDataObject obj = objects.get(ind);
|
||||
int l = i & 0xff;
|
||||
BinaryMapDataObject obj = objects.get(ind);
|
||||
|
||||
//draw streets with shadow when all have been drawn
|
||||
if(keys[k] > 57 && !streetsdrawn){
|
||||
drawStreetsShadow(cv, streetbmp);
|
||||
streetsdrawn = true;
|
||||
cv.drawBitmap(streetbmp, 0, 0, null);
|
||||
}
|
||||
// show text only for main type
|
||||
drawObj(obj, renderer, cv, rc, l, l == 0, shadow, k);
|
||||
|
||||
// show text only for main type
|
||||
drawObj(obj, renderer, cv, rc, l, l == 0, keys[k]);
|
||||
|
||||
objCount++;
|
||||
objCount++;
|
||||
}
|
||||
if(objCount > 25){
|
||||
notifyListeners(notifyList);
|
||||
|
@ -380,6 +384,14 @@ public class OsmandRenderer {
|
|||
if(rc.interrupted){
|
||||
return null;
|
||||
}
|
||||
|
||||
// order = 57 should be set as limit for shadows
|
||||
if(keys[k] > 57 && repeat == false && shadow > 1){
|
||||
shadow = 0;
|
||||
shadownum = 0;
|
||||
k = shadowarray[0];
|
||||
repeat = true;
|
||||
}
|
||||
}
|
||||
notifyListeners(notifyList);
|
||||
long beforeIconTextTime = System.currentTimeMillis() - now;
|
||||
|
@ -418,9 +430,6 @@ public class OsmandRenderer {
|
|||
}
|
||||
notifyListeners(notifyList);
|
||||
|
||||
//Draw streets here
|
||||
drawStreetsWithShadow(cv, streetbmp);
|
||||
|
||||
drawTextOverCanvas(rc, cv, useEnglishNames);
|
||||
long time = System.currentTimeMillis() - now;
|
||||
rc.renderingDebugInfo = String.format("Rendering done in %s (%s text) ms\n" +
|
||||
|
@ -445,15 +454,6 @@ public class OsmandRenderer {
|
|||
cv.drawBitmap(streetbmp, 0, 0, null);
|
||||
}
|
||||
|
||||
// Draw nice shadow for all streets
|
||||
private void drawStreetsShadow(Canvas cv, Bitmap streetbmp){
|
||||
Paint shadowpaint = new Paint();
|
||||
shadowpaint.setColor(Color.BLACK);
|
||||
shadowpaint.setMaskFilter(new BlurMaskFilter(1, BlurMaskFilter.Blur.SOLID));
|
||||
Bitmap shadowImage = streetbmp.extractAlpha();
|
||||
cv.drawBitmap(shadowImage, 0, 0, shadowpaint);
|
||||
}
|
||||
|
||||
private void notifyListeners(List<IMapDownloaderCallback> notifyList) {
|
||||
if (notifyList != null) {
|
||||
for (IMapDownloaderCallback c : notifyList) {
|
||||
|
@ -612,7 +612,7 @@ public class OsmandRenderer {
|
|||
boolean horizontalWayDisplay = (text.pathRotate > 45 && text.pathRotate < 135) || (text.pathRotate > 225 && text.pathRotate < 315);
|
||||
// text.minDistance = 0;
|
||||
float textWidth = paintText.measureText(text.text) + (!horizontalWayDisplay ? 0 : text.minDistance);
|
||||
// Paint.ascent is negative, so negate it.
|
||||
// Paint.ascent is negative, so negate it.
|
||||
int ascent = (int) Math.ceil(-paintText.ascent());
|
||||
int descent = (int) Math.ceil(paintText.descent());
|
||||
float textHeight = ascent + descent + (horizontalWayDisplay ? 0 : text.minDistance) + getDensityValue(rc, 5);
|
||||
|
@ -661,8 +661,8 @@ public class OsmandRenderer {
|
|||
st = 0;
|
||||
}
|
||||
// test functionality
|
||||
// cv.drawRect(bounds, paint);
|
||||
// cv.drawText(text.text.substring(0, Math.min(5, text.text.length())), bounds.centerX(), bounds.centerY(), paint);
|
||||
// cv.drawRect(bounds, paint);
|
||||
// cv.drawText(text.text.substring(0, Math.min(5, text.text.length())), bounds.centerX(), bounds.centerY(), paint);
|
||||
|
||||
for (int j = st; j < e; j++) {
|
||||
RectF b = boundsIntersect.get(j);
|
||||
|
@ -673,22 +673,23 @@ public class OsmandRenderer {
|
|||
}
|
||||
}
|
||||
// store in list sorted by left boundary
|
||||
// if(text.minDistance > 0){
|
||||
// if (verticalText) {
|
||||
// bounds.set(bounds.left + text.minDistance / 2, bounds.top,
|
||||
// bounds.right - text.minDistance / 2, bounds.bottom);
|
||||
// } else {
|
||||
// bounds.set(bounds.left, bounds.top + text.minDistance / 2, bounds.right,
|
||||
// bounds.bottom - text.minDistance / 2);
|
||||
// }
|
||||
// }
|
||||
boundsIntersect.add(index, bounds);
|
||||
// if(text.minDistance > 0){
|
||||
// if (verticalText) {
|
||||
// bounds.set(bounds.left + text.minDistance / 2, bounds.top,
|
||||
// bounds.right - text.minDistance / 2, bounds.bottom);
|
||||
// } else {
|
||||
// bounds.set(bounds.left, bounds.top + text.minDistance / 2, bounds.right,
|
||||
// bounds.bottom - text.minDistance / 2);
|
||||
// }
|
||||
// }
|
||||
boundsIntersect.add(index, bounds);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected void drawObj(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, int l, boolean renderText, float order) {
|
||||
protected void drawObj(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, int l, boolean renderText
|
||||
, int shadow, int index) {
|
||||
rc.allObjects++;
|
||||
if (obj instanceof MultyPolygon) {
|
||||
drawMultiPolygon(obj, render,canvas, rc);
|
||||
|
@ -702,7 +703,7 @@ public class OsmandRenderer {
|
|||
drawPoint(obj, render, canvas, rc, pair, renderText);
|
||||
} else if (t == MapRenderingTypes.POLYLINE_TYPE) {
|
||||
int layer = MapRenderingTypes.getNegativeWayLayer(mainType);
|
||||
drawPolyline(obj, render, canvas, rc, pair, layer, order);
|
||||
drawPolyline(obj, render, canvas, rc, pair, layer, shadow, index);
|
||||
} else if (t == MapRenderingTypes.POLYGON_TYPE) {
|
||||
drawPolygon(obj, render, canvas, rc, pair);
|
||||
} else {
|
||||
|
@ -751,6 +752,8 @@ public class OsmandRenderer {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
public void clearCachedResources(){
|
||||
cachedIcons.clear();
|
||||
shaders.clear();
|
||||
|
@ -796,8 +799,8 @@ public class OsmandRenderer {
|
|||
rc.main.updatePaint(paint);
|
||||
canvas.drawPath(path, paint);
|
||||
// for test purpose
|
||||
// rc.second.strokeWidth = 1.5f;
|
||||
// rc.second.color = Color.BLACK;
|
||||
// rc.second.strokeWidth = 1.5f;
|
||||
// rc.second.color = Color.BLACK;
|
||||
|
||||
if (rc.second.strokeWidth != 0) {
|
||||
rc.second.updatePaint(paint);
|
||||
|
@ -927,10 +930,33 @@ public class OsmandRenderer {
|
|||
|
||||
}
|
||||
|
||||
private void drawPolylineWithShadow(Canvas canvas, Path path, int shadow, int shadowRadius, int index){
|
||||
// option shadow = 1 ,2 don't need any changes in first draw
|
||||
// option shadow = 0 without any shadows
|
||||
if(shadow == 0) paint.setShadowLayer(0, 0, 0, 0);
|
||||
// option shadow = 3 with solid border
|
||||
if(shadow == 3){
|
||||
paint.setShadowLayer(0, 0, 0, 0);
|
||||
paint.setStrokeWidth(paint.getStrokeWidth() + 2);
|
||||
paint.setColor(0xffbababa);
|
||||
}
|
||||
canvas.drawPath(path, paint);
|
||||
|
||||
//check for shadow and save index in array
|
||||
if(shadowRadius > 0 && shadow > 1){
|
||||
if(shadownum == 0){
|
||||
shadowarray[shadownum] = index;
|
||||
shadownum++;
|
||||
}
|
||||
if (shadowarray[shadownum-1] != index){
|
||||
shadowarray[shadownum] = index;
|
||||
shadownum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void drawPolyline(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, TagValuePair pair, int layer) {
|
||||
private void drawPolyline(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, TagValuePair pair, int layer,
|
||||
int shadow, int index) {
|
||||
if(render == null || pair == null){
|
||||
return;
|
||||
}
|
||||
|
@ -994,20 +1020,19 @@ public class OsmandRenderer {
|
|||
}
|
||||
if (path != null) {
|
||||
rc.main.updatePaint(paint);
|
||||
//changed canvas to the global one for streets
|
||||
streetcv.drawPath(path, paint);
|
||||
drawPolylineWithShadow(canvas, path, shadow, rc.main.shadowRadius, index);
|
||||
if (rc.second.strokeWidth != 0) {
|
||||
rc.second.updatePaint(paint);
|
||||
streetcv.drawPath(path, paint);
|
||||
drawPolylineWithShadow(canvas, path, shadow, rc.second.shadowRadius, index);
|
||||
if (rc.third.strokeWidth != 0) {
|
||||
rc.third.updatePaint(paint);
|
||||
streetcv.drawPath(path, paint);
|
||||
drawPolylineWithShadow(canvas, path, shadow, rc.third.shadowRadius, index);
|
||||
}
|
||||
}
|
||||
if (rc.adds != null) {
|
||||
for (int i = 0; i < rc.adds.length; i++) {
|
||||
rc.adds[i].updatePaint(paint);
|
||||
streetcv.drawPath(path, paint);
|
||||
drawPolylineWithShadow(canvas, path, shadow, rc.adds[i].shadowRadius, index);
|
||||
}
|
||||
}
|
||||
if (obj.getName() != null && obj.getName().length() > 0) {
|
||||
|
|
Loading…
Reference in a new issue