diff --git a/OsmAnd/res/layout-land/map_hud_top.xml b/OsmAnd/res/layout-land/map_hud_top.xml index 10f5000b98..dcb81661ae 100644 --- a/OsmAnd/res/layout-land/map_hud_top.xml +++ b/OsmAnd/res/layout-land/map_hud_top.xml @@ -563,7 +563,11 @@ + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginLeft="@dimen/widget_turn_lane_border" + android:layout_marginRight="@dimen/widget_turn_lane_border" + android:layout_marginTop="@dimen/widget_turn_lane_border"/> + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginLeft="@dimen/widget_turn_lane_border" + android:layout_marginRight="@dimen/widget_turn_lane_border" + android:layout_marginTop="@dimen/widget_turn_lane_border"/> + 36dp + 3dp + 2dp + 16dp + 48dp 36dp diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 1d152d6a89..fc0f61819f 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -140,13 +140,13 @@ Reload Reload tiles to see up to date data. Tile cache - Wrong user name! + Wrong username! To From - View images added in a certain period. - Dates - Type user name - View images added by a certain user. + View only images added + Date + Type username + View only images added by Username You can filter images by submitter or by date. Filters apply only for closeup zoom. Radius ruler @@ -1985,7 +1985,7 @@ Visibility Tags Description - Please specify OSM user name and password to upload GPX files. + Please specify OSM username and password to upload GPX files. Support Support new features Donate to see new features implemented in the application. @@ -2096,7 +2096,7 @@ General Configure display and common settings for the application. Global app settings - Your OSM user name + Your OSM username Needed for openstreetmap.org submissions. Your OSM password Background mode diff --git a/OsmAnd/src/net/osmand/plus/views/TurnPathHelper.java b/OsmAnd/src/net/osmand/plus/views/TurnPathHelper.java index 2cca347210..b9df08a3ba 100644 --- a/OsmAnd/src/net/osmand/plus/views/TurnPathHelper.java +++ b/OsmAnd/src/net/osmand/plus/views/TurnPathHelper.java @@ -1,12 +1,6 @@ package net.osmand.plus.views; -import java.util.Map; - -import net.osmand.plus.R; -import net.osmand.router.TurnType; import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -18,6 +12,12 @@ import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; + +import net.osmand.plus.R; +import net.osmand.router.TurnType; + +import java.util.Map; public class TurnPathHelper { @@ -134,8 +134,9 @@ public class TurnPathHelper { } // 72x72 - public static void calcTurnPath(Path pathForTurn, Path outlay, TurnType turnType, - Matrix transform, PointF center, boolean mini) { + public static void calcTurnPath(Path pathForTurn, Path outlay, TurnType turnType, + Matrix transform, PointF center, boolean mini, + boolean shortArrow, boolean noOverlap, boolean smallArrow) { if(turnType == null){ return; } @@ -146,13 +147,16 @@ public class TurnPathHelper { int ha = 72; int wa = 72; int lowMargin = 6; - if (TurnType.C == turnType.getValue()) { - TurnVariables tv = new TurnVariables(false, 0, 0, wa, ha, 1.5f); + float scaleTriangle = smallArrow ? 1.f : 1.5f; + int turnTypeId = turnType.getValue(); + + if (TurnType.C == turnTypeId) { + TurnVariables tv = new TurnVariables(false, 0, 0, wa, ha, scaleTriangle); pathForTurn.moveTo(wa / 2 + tv.widthStepIn / 2, ha - lowMargin); tv.drawTriangle(pathForTurn); pathForTurn.lineTo(wa / 2 - tv.widthStepIn / 2, ha - lowMargin); - } else if (TurnType.OFFR == turnType.getValue()){ - TurnVariables tv = new TurnVariables(false, 0, 0, wa, ha, 1.5f); + } else if (TurnType.OFFR == turnTypeId){ + TurnVariables tv = new TurnVariables(false, 0, 0, wa, ha, scaleTriangle); float rightX = wa / 2 + tv.widthStepIn / 2; float leftX = wa / 2 - tv.widthStepIn / 2; int step = 7; @@ -178,14 +182,15 @@ public class TurnPathHelper { pathForTurn.moveTo(rightX, ha - 4 * lowMargin - 3 * step); tv.drawTriangle(pathForTurn); pathForTurn.lineTo(leftX, ha - 4 * lowMargin - 3 * step); - } else if (TurnType.TR == turnType.getValue()|| TurnType.TL == turnType.getValue()) { - int b = TurnType.TR == turnType.getValue()? 1 : -1; - TurnVariables tv = new TurnVariables(b != 1, b == 1 ? 90 : -90, 0, wa, ha / 2, 1.5f); - float centerCurveX = wa / 2 + b * 4; - float centerCurveY = ha / 2; + } else if (TurnType.TR == turnTypeId|| TurnType.TL == turnTypeId) { + int b = TurnType.TR == turnTypeId? 1 : -1; + TurnVariables tv = new TurnVariables(b != 1, b == 1 ? 90 : -90, 0, wa, (shortArrow ? ha : ha / 2), scaleTriangle); // calculated - float h = centerCurveY - lowMargin; - float r = tv.cy - tv.widthStepIn / 2; + float rDiv = (shortArrow ? 4 : noOverlap ? 1 : 2); + float r = (tv.cy - tv.widthStepIn / 2) / rDiv; + float centerCurveX = wa / 2 + b * (noOverlap ? 4 : r + tv.widthStepIn / 2); + float centerCurveY = ha / 2 + (shortArrow ? r + tv.widthStepIn / 2 : !noOverlap ? -r : 0); + float h = ha - centerCurveY - lowMargin; float centerLineX = centerCurveX - b * (r + tv.widthStepIn / 2); RectF innerOval = new RectF(centerCurveX - r, centerCurveY - r, centerCurveX + r, centerCurveY + r); RectF outerOval = new RectF(innerOval); @@ -197,13 +202,15 @@ public class TurnPathHelper { tv.drawTriangle(pathForTurn); pathForTurn.arcTo(outerOval, -90, - b *90); pathForTurn.rLineTo(0, h); - } else if (TurnType.TSLR == turnType.getValue() || TurnType.TSLL == turnType.getValue()) { - int b = TurnType.TSLR == turnType.getValue() ? 1 : -1; - TurnVariables tv = new TurnVariables(b != 1, b == 1 ? 45 : -45, 0, wa, ha, 1.5f); - tv.cx -= b * 7; - float centerBottomX = wa / 2 - b * 6; - float centerCurveY = ha / 2 + 8; - float centerCurveX = centerBottomX + b * (wa / 2); + } else if (TurnType.TSLR == turnTypeId || TurnType.TSLL == turnTypeId) { + int b = TurnType.TSLR == turnTypeId ? 1 : -1; + float angle = shortArrow ? 65 : 45; + TurnVariables tv = new TurnVariables(b != 1, b == 1 ? angle : -angle, 0, wa, ha, scaleTriangle); + tv.cx -= b * (shortArrow ? 0 : 7); + tv.cy += shortArrow ? 12 : 0; + float centerBottomX = wa / 2 - (noOverlap ? b * 6 : 0); + float centerCurveY = shortArrow ? ha - 6 : ha / 2 + 8; + float centerCurveX = centerBottomX + b * (wa / 2 - (shortArrow && noOverlap ? 6 : 0)); // calculated float rx1 = Math.abs(centerCurveX - centerBottomX) - tv.widthStepIn / 2; float rx2 = Math.abs(centerCurveX - centerBottomX) + tv.widthStepIn / 2; @@ -222,16 +229,20 @@ public class TurnPathHelper { tv.drawTriangle(pathForTurn); pathForTurn.arcTo(outerOval, -90 - b * (90 - (ellipseAngle2)), -b * (ellipseAngle2)); pathForTurn.lineTo(centerBottomX - b * tv.widthStepIn / 2, ha - lowMargin); - } else if (TurnType.TSHR == turnType.getValue() || TurnType.TSHL == turnType.getValue()) { - int b = TurnType.TSHR == turnType.getValue() ? 1 : -1; - float centerCircleY = ha / 4; - float centerCircleX = wa / 2 - b * (wa / 5); - TurnVariables tv = new TurnVariables(b != 1, b == 1 ? 135 : -135, 0, wa, ha, 1.5f); + } else if (TurnType.TSHR == turnTypeId || TurnType.TSHL == turnTypeId) { + int b = TurnType.TSHR == turnTypeId ? 1 : -1; + float centerCircleY = shortArrow ? ha / 2 : ha / 4; + float centerCircleX = wa / 2 - (noOverlap ? b * (wa / 5) : 0); + TurnVariables tv = new TurnVariables(b != 1, b == 1 ? 135 : -135, 0, wa, ha, scaleTriangle); // calculated float angle = 45; - float r = tv.widthStepIn / 2; + float r = tv.widthStepIn / 2; tv.cx = centerCircleX; tv.cy = centerCircleY; + if (shortArrow) { + tv.cx -= b * 2; + tv.cy -= 2; + } RectF innerOval = new RectF(centerCircleX - r, centerCircleY - r, centerCircleX + r, centerCircleY + r); pathForTurn.moveTo(centerCircleX + b * tv.widthStepIn / 2, ha - lowMargin); pathForTurn.lineTo(centerCircleX + b * tv.widthStepIn / 2, (float) (centerCircleY + @@ -241,16 +252,16 @@ public class TurnPathHelper { // pathForTurn.lineTo(centerCircleX - b * tv.widthStepIn / 2, (float) (centerCircleY - 2 *r)); pathForTurn.arcTo(innerOval, -90 + b * angle, - b * (90 + angle)); pathForTurn.lineTo(centerCircleX - b * tv.widthStepIn / 2, ha - lowMargin); - } else if(TurnType.TU == turnType.getValue() || TurnType.TRU == turnType.getValue()) { - int b = TurnType.TU == turnType.getValue() ? -1 : 1; - float radius = 16; - float centerRadiusY = ha / 2 - 10; - float extraMarginBottom = 5; - TurnVariables tv = new TurnVariables(b != 1, 180, 0, wa, ha, 1.5f); + } else if(TurnType.TU == turnTypeId || TurnType.TRU == turnTypeId) { + int b = TurnType.TU == turnTypeId ? -1 : 1; + float radius = shortArrow ? 10 : 16; + float centerRadiusY = ha / 2 + (shortArrow ? 10 : -10); + float extraMarginBottom = shortArrow ? 0 : 5; + TurnVariables tv = new TurnVariables(b != 1, 180, 0, wa, ha, scaleTriangle); // calculated - float centerRadiusX = wa / 2; + float centerRadiusX = wa / 2 + (shortArrow ? b * radius : 0); tv.cx = centerRadiusX + b * radius; - tv.cy = centerRadiusY - extraMarginBottom; + tv.cy = shortArrow ? ha - centerRadiusY : centerRadiusY - extraMarginBottom; lowMargin += extraMarginBottom; tv.rot = 0; @@ -265,29 +276,31 @@ public class TurnPathHelper { tv.drawTriangle(pathForTurn); pathForTurn.arcTo(outerOval, -90 + b * 90, -b * 180); pathForTurn.lineTo(centerRadiusX - b * (radius + tv.widthStepIn / 2), ha - lowMargin); - } else if (TurnType.KL == turnType.getValue() || TurnType.KR == turnType.getValue()) { - int b = TurnType.KR == turnType.getValue()? 1 : -1; - float shiftX = 8; + } else if (TurnType.KL == turnTypeId || TurnType.KR == turnTypeId) { + int b = TurnType.KR == turnTypeId ? 1 : -1; + float shiftX = shortArrow ? 12 : 8; float firstH = 18; float secondH = 20; - TurnVariables tv = new TurnVariables(false, 0, 0, wa, ha, 1.5f); + TurnVariables tv = new TurnVariables(false, 0, 0, wa, ha, scaleTriangle); // calculated - tv.cx += b * shiftX; - pathForTurn.moveTo(wa / 2 + tv.widthStepIn / 2 - b * shiftX, ha - lowMargin); - pathForTurn.lineTo(wa / 2 + tv.widthStepIn / 2 - b * shiftX, ha - lowMargin - firstH); - // pathForTurn.lineTo(wa / 2 + tv.widthStepIn / 2 + b * shiftX, ha - lowMargin - firstH - secondH); + tv.cx += b * shiftX * (noOverlap ? 1 : 2); + float dx = b * shiftX * (noOverlap ? 1 : 2); + float mdx = -b * shiftX * (noOverlap ? 1 : 0); + pathForTurn.moveTo(wa / 2 + tv.widthStepIn / 2 + mdx, ha - lowMargin); + pathForTurn.lineTo(wa / 2 + tv.widthStepIn / 2 + mdx, ha - lowMargin - firstH); + // pathForTurn.lineTo(wa / 2 + tv.widthStepIn / 2 + dx, ha - lowMargin - firstH - secondH); pathForTurn.cubicTo( - wa / 2 + tv.widthStepIn / 2 - b * shiftX, ha - lowMargin - firstH - secondH / 2 + b * 3, - wa / 2 + tv.widthStepIn / 2 + b * shiftX, ha - lowMargin - firstH - secondH / 2 + b * 3, - wa / 2 + tv.widthStepIn / 2 + b * shiftX, ha - lowMargin - firstH - secondH); + wa / 2 + tv.widthStepIn / 2 + mdx, ha - lowMargin - firstH - secondH / 2 + b * 3, + wa / 2 + tv.widthStepIn / 2 + dx, ha - lowMargin - firstH - secondH / 2 + b * 3, + wa / 2 + tv.widthStepIn / 2 + dx, ha - lowMargin - firstH - secondH); tv.drawTriangle(pathForTurn); - pathForTurn.lineTo(wa / 2 - tv.widthStepIn / 2 + b * shiftX, ha - lowMargin - firstH - secondH); + pathForTurn.lineTo(wa / 2 - tv.widthStepIn / 2 + dx, ha - lowMargin - firstH - secondH); pathForTurn.cubicTo( - wa / 2 - tv.widthStepIn / 2 + b * shiftX, ha - lowMargin - firstH - secondH / 2 - b * 2, - wa / 2 - tv.widthStepIn / 2 - b * shiftX, ha - lowMargin - firstH - secondH / 2 - b * 2, - wa / 2 - tv.widthStepIn / 2 - b * shiftX, ha - lowMargin - firstH ); -// pathForTurn.lineTo(wa / 2 - tv.widthStepIn / 2 - b * shiftX, ha - lowMargin - firstH); - pathForTurn.lineTo(wa / 2 - tv.widthStepIn / 2 - b * shiftX, ha - lowMargin); + wa / 2 - tv.widthStepIn / 2 + dx, ha - lowMargin - firstH - secondH / 2 - b * 2, + wa / 2 - tv.widthStepIn / 2 + mdx, ha - lowMargin - firstH - secondH / 2 - b * 2, + wa / 2 - tv.widthStepIn / 2 + mdx, ha - lowMargin - firstH ); +// pathForTurn.lineTo(wa / 2 - tv.widthStepIn / 2 + mdx, ha - lowMargin - firstH); + pathForTurn.lineTo(wa / 2 - tv.widthStepIn / 2 + mdx, ha - lowMargin); } else if(turnType != null && turnType.isRoundAbout() ) { int out = turnType.getExitOut(); boolean leftSide = turnType.isLeftSide(); @@ -477,7 +490,8 @@ public class TurnPathHelper { paintRouteDirectionOutlay.setStyle(Style.STROKE); paintRouteDirectionOutlay.setColor(Color.BLACK); paintRouteDirectionOutlay.setAntiAlias(true); - TurnPathHelper.calcTurnPath(dp, dpOutlay, TurnType.straight(), null, null, mini); + TurnPathHelper.calcTurnPath(dp, dpOutlay, TurnType.straight(), null, null, mini, + false, true, false); } @Override @@ -489,12 +503,13 @@ public class TurnPathHelper { } public void setRouteType(TurnType t){ - TurnPathHelper.calcTurnPath(p, pOutlay, t, null, null, mini); + TurnPathHelper.calcTurnPath(p, pOutlay, t, null, null, mini, + false, true, false); onBoundsChange(getBounds()); } @Override - public void draw(Canvas canvas) { + public void draw(@NonNull Canvas canvas) { canvas.drawPath(dpOutlay, paintRouteDirectionOutlay); canvas.drawPath(dp, paintRouteDirection); } @@ -519,113 +534,42 @@ public class TurnPathHelper { public static class TurnResource { - boolean flip; - int resourceId; - public TurnResource(){} + int turnType; + boolean shortArrow; + boolean noOverlap; + boolean leftSide; - public TurnResource(int resourceId, boolean value) { - this.resourceId = resourceId; - this.flip = value; + TurnResource() {} + + TurnResource(int turnType, boolean shortArrow, boolean noOverlap, boolean leftSide) { + this.turnType = turnType == 0 ? 1 : turnType; + this.shortArrow = shortArrow; + this.noOverlap = noOverlap; + this.leftSide = leftSide; } @Override - public boolean equals(Object o) { - return super.equals(o); + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + TurnResource other = (TurnResource) obj; + return other.turnType == turnType && other.shortArrow == shortArrow + && other.noOverlap == noOverlap && other.leftSide == leftSide; } @Override public int hashCode() { - return resourceId * (flip ? -1 : 1); + return (turnType + (noOverlap ? 100 : 1) + (shortArrow ? 1000 : 1)) * (leftSide ? -1 : 1); } } - private static TurnResource getTallArrow(int tt, boolean nooverlap){ - - TurnResource result = new TurnResource(); - - switch (tt){ - case TurnType.C: - result.resourceId = R.drawable.map_turn_forward_small; - break; - case TurnType.TR: - case TurnType.TL: - result.resourceId = nooverlap ? R.drawable.map_turn_right_small : R.drawable.map_turn_right2_small; - break; - case TurnType.KR: - case TurnType.KL: - result.resourceId = R.drawable.map_turn_keep_right_small; - break; - case TurnType.TSLR: - case TurnType.TSLL: - result.resourceId = R.drawable.map_turn_slight_right_small; - break; - case TurnType.TSHR: - case TurnType.TSHL: - result.resourceId = R.drawable.map_turn_sharp_right_small; - break; - case TurnType.TRU: - case TurnType.TU: - result.resourceId = R.drawable.map_turn_uturn_right_small; - break; - default: - result.resourceId = R.drawable.map_turn_forward_small; - break; - } - - if(tt == TurnType.TL || tt == TurnType.KL || tt == TurnType.TSLL - || tt == TurnType.TSHL || tt == TurnType.TU){ - result.flip = true; - } - - return result; - - } - - private static TurnResource getShortArrow(int tt){ - - TurnResource result = new TurnResource(); - - switch (tt) { - case TurnType.C: - result.resourceId = R.drawable.map_turn_forward_small; - break; - case TurnType.TR: - case TurnType.TL: - result.resourceId = R.drawable.map_turn_forward_right_turn_small; - break; - case TurnType.KR: - case TurnType.KL: - result.resourceId = R.drawable.map_turn_forward_keep_right_small; - break; - case TurnType.TSLR: - case TurnType.TSLL: - result.resourceId = R.drawable.map_turn_forward_slight_right_turn_small; - break; - case TurnType.TSHR: - case TurnType.TSHL: - result.resourceId = R.drawable.map_turn_forward_turn_sharp_small; - break; - case TurnType.TRU: - case TurnType.TU: - result.resourceId = R.drawable.map_turn_forward_uturn_right_small; - break; - default: - result.resourceId = R.drawable.map_turn_forward_small; - break; - } - - if(tt == TurnType.TL || tt == TurnType.KL || tt == TurnType.TSLL - || tt == TurnType.TSHL || tt == TurnType.TU){ - result.flip = true; - } - - return result; - - } - - public static Bitmap getBitmapFromTurnType(Resources res, Map cache, int firstTurn, - int secondTurn, int thirdTurn, int turnIndex, float coef, boolean leftSide) { + public static Path getPathFromTurnType(Resources res, Map cache, int firstTurn, + int secondTurn, int thirdTurn, int turnIndex, float coef, boolean leftSide, boolean smallArrow) { int firstTurnType = TurnType.valueOf(firstTurn, leftSide).getValue(); int secondTurnType = TurnType.valueOf(secondTurn, leftSide).getValue(); @@ -635,14 +579,14 @@ public class TurnPathHelper { if (turnIndex == FIRST_TURN) { if (secondTurnType == 0) { - turnResource = getTallArrow(firstTurnType, true); + turnResource = new TurnResource(firstTurnType, false, false, leftSide); } else if (secondTurnType == TurnType.C || thirdTurnType == TurnType.C) { - turnResource = getShortArrow(firstTurnType); + turnResource = new TurnResource(firstTurnType, true, false, leftSide); } else { if (firstTurnType == TurnType.TU || firstTurnType == TurnType.TRU) { - turnResource = getShortArrow(firstTurnType); + turnResource = new TurnResource(firstTurnType, true, false, leftSide); } else { - turnResource = getTallArrow(firstTurnType, false); + turnResource = new TurnResource(firstTurnType, false, false, leftSide); } } } else if (turnIndex == SECOND_TURN) { @@ -652,9 +596,9 @@ public class TurnPathHelper { turnResource = null; } else if (firstTurnType == TurnType.C || thirdTurnType == TurnType.C) { // get the small one - turnResource = getShortArrow(secondTurnType); + turnResource = new TurnResource(secondTurnType, true, false, leftSide); } else { - turnResource = getTallArrow(secondTurnType, false); + turnResource = new TurnResource(secondTurnType, false, false, leftSide); } } else if (turnIndex == THIRD_TURN) { if ((TurnType.isLeftTurn(firstTurnType) || TurnType.isLeftTurn(secondTurnType)) && TurnType.isLeftTurn(thirdTurnType)) { @@ -662,18 +606,18 @@ public class TurnPathHelper { } else if ((TurnType.isRightTurn(firstTurnType) || TurnType.isRightTurn(secondTurnType)) && TurnType.isRightTurn(thirdTurnType)) { turnResource = null; } else { - turnResource = getShortArrow(thirdTurnType); + turnResource = new TurnResource(thirdTurnType, true, false, leftSide); } } if (turnResource == null) { return null; } - Bitmap b = cache.get(turnResource); - if (b == null) { - b = turnResource.flip ? getFlippedBitmap(res, turnResource.resourceId) : BitmapFactory.decodeResource(res, - turnResource.resourceId); - cache.put(turnResource, b); + Path p = cache.get(turnResource); + if (p == null) { + int size = res.getDimensionPixelSize(R.dimen.widget_turn_lane_size); + p = getPathFromTurnResource(turnResource, size, smallArrow); + cache.put(turnResource, p); } // Maybe redundant scaling @@ -682,27 +626,17 @@ public class TurnPathHelper { * bRatio); int hq = Math.round(s); b = Bitmap.createScaledBitmap(b, wq, hq, false); */ - return b; + return p; } - public static Bitmap getFlippedBitmap(Resources res, int resId){ - - BitmapFactory.Options opt = new BitmapFactory.Options(); - opt.inJustDecodeBounds = true; - //Below line is necessary to fill in opt.outWidth, opt.outHeight - Bitmap b = BitmapFactory.decodeResource(res, resId, opt); - - b = Bitmap.createBitmap(opt.outWidth, opt.outHeight, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(b); - - Matrix flipHorizontalMatrix = new Matrix(); - flipHorizontalMatrix.setScale(-1, 1); - flipHorizontalMatrix.postTranslate(b.getWidth(), 0); - - Bitmap bb = BitmapFactory.decodeResource(res, resId); - canvas.drawBitmap(bb, flipHorizontalMatrix, null); - - return b; + private static Path getPathFromTurnResource(TurnResource turnResource, int size, boolean smallArrow) { + float coef = size / 72.f; + Path p = new Path(); + Matrix matrix = new Matrix(); + matrix.postScale(coef, coef); + calcTurnPath(p, null, TurnType.valueOf(turnResource.turnType, turnResource.leftSide), + matrix, null, false, turnResource.shortArrow, turnResource.noOverlap, smallArrow); + return p; } diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java index e18ed456e1..20b4fb69c3 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java @@ -1,13 +1,5 @@ package net.osmand.plus.views.mapwidgets; -import net.osmand.plus.OsmAndFormatter; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.R; -import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.views.OsmandMapLayer.DrawSettings; -import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopTextView; -import net.osmand.plus.views.TurnPathHelper; -import net.osmand.router.TurnType; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; @@ -22,8 +14,17 @@ import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.annotation.ColorRes; +import android.support.annotation.NonNull; import android.text.TextPaint; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.views.OsmandMapLayer.DrawSettings; +import net.osmand.plus.views.TurnPathHelper; +import net.osmand.router.TurnType; + public class NextTurnInfoWidget extends TextInfoWidget { @@ -185,7 +186,7 @@ public class NextTurnInfoWidget extends TextInfoWidget { } @Override - public void draw(Canvas canvas) { + public void draw(@NonNull Canvas canvas) { /// small indent // canvas.translate(0, 3 * scaleCoefficient); canvas.drawPath(pathForTurnOutlay, paintBlack); @@ -222,7 +223,8 @@ public class NextTurnInfoWidget extends TextInfoWidget { public boolean setTurnType(TurnType turnType) { if(turnType != this.turnType) { this.turnType = turnType; - TurnPathHelper.calcTurnPath(pathForTurn, pathForTurnOutlay, turnType, null, centerText, mini); + TurnPathHelper.calcTurnPath(pathForTurn, pathForTurnOutlay, turnType, null, + centerText, mini, false, true, false); onBoundsChange(getBounds()); return true; } diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java index f8e5c1214e..d4a02fac67 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java @@ -5,28 +5,25 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.graphics.Bitmap; -import android.graphics.BlurMaskFilter; -import android.graphics.BlurMaskFilter.Blur; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; -import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.hardware.GeomagneticField; import android.os.BatteryManager; +import android.support.annotation.NonNull; import android.text.format.DateFormat; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import net.osmand.AndroidUtils; import net.osmand.Location; import net.osmand.binary.RouteDataObject; import net.osmand.data.LatLon; @@ -54,12 +51,12 @@ import net.osmand.plus.views.AnimateDraggingMapThread; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.TurnPathHelper; +import net.osmand.plus.views.TurnPathHelper.TurnResource; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WidgetState; import net.osmand.router.RouteResultPreparation; import net.osmand.router.TurnType; import net.osmand.util.Algorithms; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -726,26 +723,6 @@ public class RouteInfoWidgetsFactory { !showRelativeBearing.get() ? bearingNightResId : relativeBearingNightResId); return bearingControl; } - - private static Path getPathFromTurnType(List paths, int laneType, Path defaultType, float coef, boolean mini) { - if(laneType == 0) { - return defaultType; - } - while (paths.size() <= laneType) { - paths.add(null); - } - Path p = paths.get(laneType); - if (p != null) { - return p; - } - p = new Path(); - Matrix pathTransform = new Matrix(); - pathTransform.postScale(coef, coef ); - TurnType tp = TurnType.valueOf(laneType, false); - TurnPathHelper.calcTurnPath(p, null, tp, pathTransform, null, mini); - paths.set(laneType, p); - return p; - } public static class LanesControl { @@ -865,11 +842,8 @@ public class RouteInfoWidgetsFactory { int[] lanes = null; boolean imminent = false; private Context ctx; - private ArrayList paths = new ArrayList(); - private Map bitmapCache = new HashMap(); + private Map pathsCache = new HashMap<>(); private Paint paintBlack; - private Path laneStraight; - private final Bitmap laneStraightBitmap; private Paint paintRouteDirection; private Paint paintSecondTurn; private float scaleCoefficient; @@ -877,59 +851,107 @@ public class RouteInfoWidgetsFactory { private int width; private static final float miniCoeff = 2f; private final boolean leftSide; + private int imgMinWidth; + private int imgMargin; - public LanesDrawable(MapActivity ctx, float scaleCoefficent) { + LanesDrawable(MapActivity ctx, float scaleCoefficent) { this.ctx = ctx; OsmandSettings settings = ctx.getMyApplication().getSettings(); leftSide = settings.DRIVING_REGION.get().leftHandDriving; + imgMinWidth = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_min_width); + imgMargin = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_margin); this.scaleCoefficient = scaleCoefficent; - laneStraight = getPathFromTurnType(paths, TurnType.C, null, scaleCoefficient / miniCoeff, true); - laneStraightBitmap = TurnPathHelper.getBitmapFromTurnType(ctx.getResources(), bitmapCache, TurnType.C, 0, 0, TurnPathHelper.FIRST_TURN, scaleCoefficient / miniCoeff, leftSide); - paintBlack = new Paint(); + + paintBlack = new Paint(Paint.ANTI_ALIAS_FLAG); paintBlack.setStyle(Style.STROKE); paintBlack.setColor(Color.BLACK); - paintBlack.setAntiAlias(true); - paintBlack.setStrokeWidth(2.5f); - + paintBlack.setStrokeWidth(1.5f); + paintRouteDirection = new Paint(Paint.ANTI_ALIAS_FLAG); - paintRouteDirection.setStyle(Style.FILL_AND_STROKE); + paintRouteDirection.setStyle(Style.FILL); paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow)); paintSecondTurn = new Paint(Paint.ANTI_ALIAS_FLAG); - paintSecondTurn.setStyle(Style.FILL_AND_STROKE); + paintSecondTurn.setStyle(Style.FILL); paintSecondTurn.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); - } - public void updateBounds() { + void updateBounds() { float w = 0; - int h = 0; + float h = 0; float coef = scaleCoefficient / miniCoeff; if (lanes != null) { for (int i = 0; i < lanes.length; i++) { int turnType = TurnType.getPrimaryTurn(lanes[i]); int secondTurnType = TurnType.getSecondaryTurn(lanes[i]); int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]); - Bitmap b = TurnPathHelper.getBitmapFromTurnType(ctx.getResources(), bitmapCache, turnType, - secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide); - if (b != null) { - if (secondTurnType == 0 && thirdTurnType == 0) { - int arrowWidth = AndroidUtils.dpToPx(ctx, getArrowWidthInDp(turnType)); - int emptyWidth = b.getWidth() - arrowWidth; - w += emptyWidth / 2 + arrowWidth; - } else { - w += b.getWidth(); - } - int bitmapHeight = b.getHeight(); - if (bitmapHeight > h) { - h = bitmapHeight; + + RectF imgBounds = new RectF(); + if (thirdTurnType > 0) { + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), pathsCache, turnType, + secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + } } } + if (secondTurnType > 0) { + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), pathsCache, turnType, + secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + } + } + } + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), pathsCache, turnType, + secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + } + } + if (imgBounds.right > 0) + { + if (imgBounds.width() < imgMinWidth) { + imgBounds.inset(-(imgMinWidth - imgBounds.width()) / 2.f, 0); + } + w += imgBounds.width() + (i < lanes.length - 1 ? imgMargin * 2 : 0); + + float imageHeight = imgBounds.bottom; + if (imageHeight > h) + h = imageHeight; + } + } + if (w > 0) { + w += 4; + } + if (h > 0) { + h += 4; } } width = (int) w; - height = h; + height = (int) h; } @Override @@ -944,16 +966,13 @@ public class RouteInfoWidgetsFactory { @Override - public void draw(Canvas canvas) { - Bitmap src = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); - // setup canvas for painting - Canvas srcCanvas = new Canvas(src); + public void draw(@NonNull Canvas canvas) { // setup default color - srcCanvas.drawColor(0, PorterDuff.Mode.CLEAR); + //canvas.drawColor(0, PorterDuff.Mode.CLEAR); //to change color immediately when needed if (lanes != null && lanes.length > 0) { - srcCanvas.save(); + canvas.save(); // canvas.translate((int) (16 * scaleCoefficient), 0); for (int i = 0; i < lanes.length; i++) { if ((lanes[i] & 1) == 1) { @@ -966,127 +985,89 @@ public class RouteInfoWidgetsFactory { int secondTurnType = TurnType.getSecondaryTurn(lanes[i]); int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]); + RectF imgBounds = new RectF(); + Path thirdTurnPath = null; + Path secondTurnPath = null; + Path firstTurnPath = null; + float coef = scaleCoefficient / miniCoeff; - if(thirdTurnType > 0){ - Bitmap bSecond = null; - bSecond = TurnPathHelper.getBitmapFromTurnType(ctx.getResources(), bitmapCache, turnType, - secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide); - if (bSecond != null){ - paintSecondTurn.setColorFilter(new PorterDuffColorFilter(paintSecondTurn.getColor(), PorterDuff.Mode.SRC_ATOP)); - srcCanvas.drawBitmap(bSecond, 0f, 0f, paintSecondTurn); + if (thirdTurnType > 0) { + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), pathsCache, turnType, + secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + thirdTurnPath = p; + } } } - if(secondTurnType > 0){ - Bitmap bSecond = null; - bSecond = TurnPathHelper.getBitmapFromTurnType(ctx.getResources(), bitmapCache, turnType, - secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide); - if (bSecond != null){ - paintSecondTurn.setColorFilter(new PorterDuffColorFilter(paintSecondTurn.getColor(), PorterDuff.Mode.SRC_ATOP)); - srcCanvas.drawBitmap(bSecond, 0f, 0f, paintSecondTurn); + if (secondTurnType > 0) { + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), pathsCache, turnType, + secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + secondTurnPath = p; + } } } - Bitmap b = TurnPathHelper.getBitmapFromTurnType(ctx.getResources(), bitmapCache, turnType, - secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide); - if(b != null) { - paintRouteDirection.setColorFilter(new PorterDuffColorFilter(paintRouteDirection.getColor(), PorterDuff.Mode.SRC_ATOP)); - Bitmap bitmap; - if (secondTurnType == 0 && thirdTurnType == 0) { - bitmap = applyCrop(b, turnType); + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), pathsCache, turnType, + secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + firstTurnPath = p; + } + } + + if (firstTurnPath != null || secondTurnPath != null || thirdTurnPath != null) { + if (imgBounds.width() < imgMinWidth) { + imgBounds.inset(-(imgMinWidth - imgBounds.width()) / 2.f, 0); + } + if (i == 0) { + imgBounds.set(imgBounds.left - 2, imgBounds.top, imgBounds.right + imgMargin, imgBounds.bottom); } else { - bitmap = b; + imgBounds.inset(-imgMargin, 0); } - srcCanvas.drawBitmap(bitmap, 0f, 0f, paintRouteDirection); - srcCanvas.translate(bitmap.getWidth(), 0); + + canvas.translate(-imgBounds.left, 0); + + if (thirdTurnPath != null) { + canvas.drawPath(thirdTurnPath, paintSecondTurn); + canvas.drawPath(thirdTurnPath, paintBlack); + } + if (secondTurnPath != null) { + canvas.drawPath(secondTurnPath, paintSecondTurn); + canvas.drawPath(secondTurnPath, paintBlack); + } + if (firstTurnPath != null) { + canvas.drawPath(firstTurnPath, paintRouteDirection); + canvas.drawPath(firstTurnPath, paintBlack); + } + + canvas.translate(imgBounds.right, 0); } } - srcCanvas.restore(); - } - - // create a blur paint for capturing alpha - Paint ptBlur = new Paint(); - float density = ctx.getResources().getDisplayMetrics().density; - ptBlur.setMaskFilter(new BlurMaskFilter(1.66f * density, Blur.OUTER)); - int[] offsetXY = new int[2]; - // capture alpha into a bitmap - Bitmap bmAlpha = src.extractAlpha(ptBlur, offsetXY); - // create a color paint - Paint ptAlphaColor = new Paint(); - ptAlphaColor.setColor(0xFF000000); - // paint color for captured alpha region (bitmap) - canvas.drawBitmap(bmAlpha, offsetXY[0], offsetXY[1], ptAlphaColor); - // free memory - bmAlpha.recycle(); - - // paint the image source - canvas.drawBitmap(src, 0, 0, null); - } - - private Bitmap applyCrop(Bitmap bitmap, int turnType) { - int arrowWidth = AndroidUtils.dpToPx(ctx, getArrowWidthInDp(turnType)); - int emptyWidth = bitmap.getWidth() - arrowWidth; - int widthToCrop = emptyWidth / 4; - return Bitmap.createBitmap(bitmap, widthToCrop, 0, bitmap.getWidth() - 2 * widthToCrop, bitmap.getHeight()); - } - - private int getArrowWidthInDp(int tt) { - int result; - - switch (tt){ - case TurnType.C: - result = 12; - break; - case TurnType.TR: - case TurnType.TL: - result = 20; - break; - case TurnType.KR: - case TurnType.KL: - result = 13; - break; - case TurnType.TSLR: - case TurnType.TSLL: - result = 13; - break; - case TurnType.TSHR: - case TurnType.TSHL: - result = 19; - break; - case TurnType.TRU: - case TurnType.TU: - result = 24; - break; - default: - result = 12; - break; - } - - return result; - } - - //@Override - public void drawOld(Canvas canvas) { - float w = 72 * scaleCoefficient / miniCoeff; - //to change color immediately when needed - if (lanes != null && lanes.length > 0) { - canvas.save(); - // canvas.translate((int) (16 * scaleCoefficient), 0); - for (int i = 0; i < lanes.length; i++) { - int turnType; - if ((lanes[i] & 1) == 1) { - paintRouteDirection.setColor(imminent ? ctx.getResources().getColor(R.color.nav_arrow_imminent) : - ctx.getResources().getColor(R.color.nav_arrow)); - turnType = TurnType.getPrimaryTurn(lanes[i]); - } else { - paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); - turnType = TurnType.getPrimaryTurn(lanes[i]); - } - Path p = getPathFromTurnType(paths, turnType, laneStraight, scaleCoefficient / miniCoeff, true); - canvas.drawPath(p, paintBlack); - canvas.drawPath(p, paintRouteDirection); - canvas.translate(w, 0); - } canvas.restore(); - } + } } @Override