diff --git a/documentation/docs/help/en/Advanced preferences.md b/documentation/docs/help/en/Advanced preferences.md index 1d96294b40..363461daaa 100644 --- a/documentation/docs/help/en/Advanced preferences.md +++ b/documentation/docs/help/en/Advanced preferences.md @@ -395,7 +395,7 @@ Enable voice command support: Default: _off_. ### Enable hardware acceleration -Do not use, may cause hangs of the app and other problems. +Turn on use of hardware rendering on Android 10 and later. Default: _off_ ### Enable split window property editor diff --git a/src/main/assets/help/en/Advanced preferences.html b/src/main/assets/help/en/Advanced preferences.html index 21cd991d05..9b88d8131e 100644 --- a/src/main/assets/help/en/Advanced preferences.html +++ b/src/main/assets/help/en/Advanced preferences.html @@ -203,7 +203,7 @@ <h3>Enable JS Console</h3> <h3>Enable voice commands</h3> <p>Enable voice command support: Default: <em>off</em>.</p> <h3>Enable hardware acceleration</h3> -<p>Do not use, may cause hangs of the app and other problems.</p> +<p>Turn on use of hardware rendering on Android 10 and later. Default: <em>off</em></p> <h3>Enable split window property editor</h3> <p>Enable displaying the property editor in a separate window if available. Default: <em>off</em></p> <h3>Use "new task" mode for property editor</h3> diff --git a/src/main/assets/styles/Color-round-no-mp.xml b/src/main/assets/styles/Color-round-no-mp.xml index 645aed1cf3..916a1ace46 100644 --- a/src/main/assets/styles/Color-round-no-mp.xml +++ b/src/main/assets/styles/Color-round-no-mp.xml @@ -32,7 +32,7 @@ </dash> </feature> <!-- Validation --> - <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="STROKE" cap="ROUND" join="MITER" /> + <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="FILL" cap="ROUND" join="MITER" /> <feature type="problem_node_tagged" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="FILL" cap="BUTT" join="MITER" /> <feature type="problem_node_thin" updateWidth="false" widthFactor="1.0" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" strokeWidth="1.0" typefacestyle="0" textsize="12.0" /> <feature type="problem_way" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" labelKey="name" /> diff --git a/src/main/assets/styles/Color-round.xml b/src/main/assets/styles/Color-round.xml index dcab5ac43d..20a64acac0 100644 --- a/src/main/assets/styles/Color-round.xml +++ b/src/main/assets/styles/Color-round.xml @@ -32,7 +32,7 @@ </dash> </feature> <!-- Validation --> - <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="STROKE" cap="ROUND" join="MITER" /> + <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="FILL" cap="ROUND" join="MITER" /> <feature type="problem_node_tagged" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="FILL" cap="BUTT" join="MITER" /> <feature type="problem_node_thin" updateWidth="false" widthFactor="1.0" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" strokeWidth="1.0" typefacestyle="0" textsize="12.0" /> <feature type="problem_way" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" labelKey="name" /> diff --git a/src/main/assets/styles/No-path-patterns.xml b/src/main/assets/styles/No-path-patterns.xml index 701d91067a..ce14f25945 100644 --- a/src/main/assets/styles/No-path-patterns.xml +++ b/src/main/assets/styles/No-path-patterns.xml @@ -32,7 +32,7 @@ </dash> </feature> <!-- Validation --> - <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="STROKE" cap="ROUND" join="MITER" /> + <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="FILL" cap="ROUND" join="MITER" /> <feature type="problem_node_tagged" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="FILL" cap="BUTT" join="MITER" /> <feature type="problem_node_thin" updateWidth="false" widthFactor="1.0" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" strokeWidth="1.0" typefacestyle="0" textsize="12.0" /> <feature type="problem_way" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" labelKey="name" /> diff --git a/src/main/assets/styles/Pen-round.xml b/src/main/assets/styles/Pen-round.xml index 93b8d2d35d..dcde98b697 100644 --- a/src/main/assets/styles/Pen-round.xml +++ b/src/main/assets/styles/Pen-round.xml @@ -32,7 +32,7 @@ </dash> </feature> <!-- Validation --> - <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="STROKE" cap="ROUND" join="MITER" /> + <feature type="problem_node" updateWidth="true" widthFactor="2.0" color="ffff00ff" style="FILL" cap="ROUND" join="MITER" /> <feature type="problem_node_tagged" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="FILL" cap="BUTT" join="MITER" /> <feature type="problem_node_thin" updateWidth="false" widthFactor="1.0" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" strokeWidth="1.0" typefacestyle="0" textsize="12.0" /> <feature type="problem_way" updateWidth="true" widthFactor="1.5" color="ffff00ff" style="STROKE" cap="BUTT" join="MITER" labelKey="name" /> diff --git a/src/main/java/de/blau/android/Map.java b/src/main/java/de/blau/android/Map.java index c031fc93a4..1c99e1b4bb 100755 --- a/src/main/java/de/blau/android/Map.java +++ b/src/main/java/de/blau/android/Map.java @@ -172,6 +172,8 @@ public class Map extends View implements IMapView { private TrackerService tracker = null; + private final boolean hardwareLayerType; + /** * Construct a new Map object that orchestrates the layer drawing and related rendering * @@ -192,7 +194,8 @@ public Map(@NonNull final Context context) { iconRadius = Density.dpToPx(context, ICON_SIZE_DP / 2); - setLayerType(View.LAYER_TYPE_SOFTWARE, null); + hardwareLayerType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && App.getPreferences(context).hwAccelerationEnabled(); + setLayerType(hardwareLayerType ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_SOFTWARE, null); } /** @@ -225,7 +228,7 @@ public void setUpLayers(@NonNull Context ctx) { layer = new de.blau.android.layer.mvt.MapOverlay(this, new VectorTileRenderer(), false); ((MapTilesOverlayLayer<?>) layer).setRendererInfo(backgroundSource); } else { - layer = new MapTilesLayer<Bitmap>(this, backgroundSource, null, new MapTilesLayer.BitmapTileRenderer()); + layer = new MapTilesLayer<Bitmap>(this, backgroundSource, null, new MapTilesLayer.BitmapTileRenderer(hardwareLayerType)); } } break; @@ -235,7 +238,7 @@ public void setUpLayers(@NonNull Context ctx) { if (overlaySource.getTileType() == TileType.MVT) { layer = new de.blau.android.layer.mvt.MapOverlay(this, new VectorTileRenderer(), true); } else { - layer = new MapTilesOverlayLayer<Bitmap>(this, new MapTilesLayer.BitmapTileRenderer()); + layer = new MapTilesOverlayLayer<Bitmap>(this, new MapTilesLayer.BitmapTileRenderer(hardwareLayerType)); } ((MapTilesOverlayLayer<?>) layer).setRendererInfo(overlaySource); } @@ -1302,4 +1305,15 @@ public TrackerService getTracker() { public boolean rtlLayout() { return getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; } + + /** + * Check if we configured hardware acceleration + * + * The value returned from isHardwareAccelerated seems to not necessarily be consistent with what we set + * + * @return true if we enabled hardware acceleration + */ + public boolean isHardwareLayerType() { + return hardwareLayerType; + } } \ No newline at end of file diff --git a/src/main/java/de/blau/android/dialogs/TileSourceDiagnostics.java b/src/main/java/de/blau/android/dialogs/TileSourceDiagnostics.java index 6ae319fa31..6a424f6133 100644 --- a/src/main/java/de/blau/android/dialogs/TileSourceDiagnostics.java +++ b/src/main/java/de/blau/android/dialogs/TileSourceDiagnostics.java @@ -153,7 +153,7 @@ protected Void doInBackground(Void param) { text.setText(tester.getOutput()); byte[] image = tester.getTile(); if (result && tester.getTileType() == TileType.BITMAP && image != null && image.length > 0) { - BitmapDecoder decoder = new BitmapDecoder(); + BitmapDecoder decoder = new BitmapDecoder(false); Bitmap bitmap = decoder.decode(image, false); if (bitmap != null) { tileView.setVisibility(View.VISIBLE); diff --git a/src/main/java/de/blau/android/layer/data/MapOverlay.java b/src/main/java/de/blau/android/layer/data/MapOverlay.java index 17555005e8..f020f28014 100644 --- a/src/main/java/de/blau/android/layer/data/MapOverlay.java +++ b/src/main/java/de/blau/android/layer/data/MapOverlay.java @@ -478,7 +478,7 @@ protected void onDraw(Canvas canvas, IMapView osmv) { @SuppressWarnings("unchecked") private void paintOsmData(@NonNull final Canvas canvas) { - boolean hwAccelarationWorkaround = canvas.isHardwareAccelerated(); + boolean hwAccelerated = canvas.isHardwareAccelerated(); int screenWidth = map.getWidth(); int screenHeight = map.getHeight(); @@ -607,8 +607,7 @@ private void paintOsmData(@NonNull final Canvas canvas) { coordSize++; } } - paintNode(canvas, n, x, y, hwAccelarationWorkaround, - drawTolerance && !noTolerance && (n.getState() != OsmElement.STATE_UNCHANGED || isInDownload(lon, lat))); + paintNode(canvas, n, x, y, hwAccelerated, drawTolerance && !noTolerance && (n.getState() != OsmElement.STATE_UNCHANGED || isInDownload(lon, lat))); } // turn restrictions if (inNodeIconZoomRange && showIcons) { @@ -977,10 +976,10 @@ private void paintRestriction(@NonNull final Canvas canvas, int screenWidth, int * @param node Node to be painted. * @param x screen x coordinate * @param y screen y coordinate - * @param hwAccelarationWorkaround use a workaround for unsupported operations when HW acceleration is used + * @param hwAccelerated use a workaround for unsupported operations when HW acceleration is used * @param drawTolerance draw the touch halo */ - private void paintNode(@NonNull final Canvas canvas, @NonNull final Node node, final float x, final float y, final boolean hwAccelarationWorkaround, + private void paintNode(@NonNull final Canvas canvas, @NonNull final Node node, final float x, final float y, final boolean hwAccelerated, final boolean drawTolerance) { boolean isSelected = tmpDrawingSelectedNodes != null && tmpDrawingSelectedNodes.contains(node); @@ -1068,57 +1067,58 @@ private void paintNode(@NonNull final Canvas canvas, @NonNull final Node node, f isTagged = false; } - if (isTagged) { - boolean noIcon = true; - if (inNodeIconZoomRange && showIcons) { - Float direction = getDirection(node); - if (direction != null && !direction.equals(Float.NaN)) { - canvas.save(); - canvas.rotate(direction + 90, x, y); - canvas.translate(x - iconRadius, y); - canvas.drawPath(currentStyle.getDirectionArrowPath(), nodeFeatureStyle.getPaint()); - canvas.restore(); - } + if (!isTagged) { + // this bit of code duplication makes sense + if (zoomLevel < featureStyle.getMinVisibleZoom()) { + return; + } + Paint paint = featureStyle.getPaint(); + if (hwAccelerated) { // we don't actually know if this is slower than drawPoint + canvas.drawCircle(x, y, paint.getStrokeWidth() / 2, paint); + } else { + canvas.drawPoint(x, y, paint); + } + return; + } - noIcon = tmpPresets == null || !paintNodeIcon(node, canvas, x, y, isSelected || hasProblem ? featureStyleTagged : null); - if (noIcon) { - String houseNumber = node.getTagWithKey(Tags.KEY_ADDR_HOUSENUMBER); - if (houseNumber != null && !"".equals(houseNumber)) { // draw house-numbers - paintHouseNumber(x, y, canvas, featureStyleThin, featureStyleFontSmall, houseNumber); - return; - } - } else if (zoomLevel > showIconLabelZoomLimit) { - paintLabel(x, y, canvas, featureStyleFont, node, nodeFeatureStyleTagged.getPaint().getStrokeWidth(), true); - } + boolean noIcon = true; + if (inNodeIconZoomRange && showIcons) { + Float direction = getDirection(node); + if (direction != null && !direction.equals(Float.NaN)) { + canvas.save(); + canvas.rotate(direction + 90, x, y); + canvas.translate(x - iconRadius, y); + canvas.drawPath(currentStyle.getDirectionArrowPath(), nodeFeatureStyle.getPaint()); + canvas.restore(); } + noIcon = tmpPresets == null || !paintNodeIcon(node, canvas, x, y, isSelected || hasProblem ? featureStyleTagged : null); if (noIcon) { - // draw regular nodes or without icons - if (zoomLevel < featureStyleTagged.getMinVisibleZoom()) { + String houseNumber = node.getTagWithKey(Tags.KEY_ADDR_HOUSENUMBER); + if (houseNumber != null && !"".equals(houseNumber)) { // draw house-numbers + paintHouseNumber(x, y, canvas, featureStyleThin, featureStyleFontSmall, houseNumber); return; } - Paint paint = featureStyleTagged.getPaint(); - float strokeWidth = paint.getStrokeWidth(); - if (hwAccelarationWorkaround) { - canvas.drawCircle(x, y, strokeWidth / 2, paint); - } else { - canvas.drawPoint(x, y, paint); - } - if (inNodeIconZoomRange) { - paintLabel(x, y, canvas, featureStyleFont, node, strokeWidth, false); - } + } else if (zoomLevel > showIconLabelZoomLimit) { + paintLabel(x, y, canvas, featureStyleFont, node, nodeFeatureStyleTagged.getPaint().getStrokeWidth(), true); } - } else { - // this bit of code duplication makes sense - if (zoomLevel < featureStyle.getMinVisibleZoom()) { + } + + if (noIcon) { + // draw regular nodes or without icons + if (zoomLevel < featureStyleTagged.getMinVisibleZoom()) { return; } - Paint paint = featureStyle.getPaint(); - if (hwAccelarationWorkaround) { // FIXME we don't actually know if this is slower than drawPoint - canvas.drawCircle(x, y, paint.getStrokeWidth() / 2, paint); + Paint paint = featureStyleTagged.getPaint(); + float strokeWidth = paint.getStrokeWidth(); + if (hwAccelerated) { + canvas.drawCircle(x, y, strokeWidth / 2, paint); } else { canvas.drawPoint(x, y, paint); } + if (inNodeIconZoomRange) { + paintLabel(x, y, canvas, featureStyleFont, node, strokeWidth, false); + } } } @@ -1271,8 +1271,13 @@ private void retrieveIcon(@NonNull OsmElement element, boolean isWay, @NonNull W } Bitmap icon; if (iconDrawable != null) { - icon = Bitmap.createBitmap(iconRadius * 2, iconRadius * 2, Config.ARGB_8888); + icon = Bitmap.createBitmap(iconRadius * 2, iconRadius * 2, Bitmap.Config.ARGB_8888); iconDrawable.draw(new Canvas(icon)); + if (map.isHardwareLayerType()) { + Bitmap temp = icon; + icon = temp.copy(Bitmap.Config.HARDWARE, false); + temp.recycle(); + } } else { icon = NOICON; } diff --git a/src/main/java/de/blau/android/layer/tasks/MapOverlay.java b/src/main/java/de/blau/android/layer/tasks/MapOverlay.java index e481ab3e31..61ff5e62c4 100644 --- a/src/main/java/de/blau/android/layer/tasks/MapOverlay.java +++ b/src/main/java/de/blau/android/layer/tasks/MapOverlay.java @@ -1,5 +1,7 @@ package de.blau.android.layer.tasks; +import static de.blau.android.contract.Constants.LOG_TAG_LEN; + import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; @@ -59,7 +61,8 @@ public class MapOverlay extends MapViewLayer implements ExtentInterface, DiscardInterface, ClickableInterface<Task>, LayerInfoInterface, ConfigureInterface, PruneableInterface { - private static final String DEBUG_TAG = MapOverlay.class.getSimpleName().substring(0, Math.min(23, MapOverlay.class.getSimpleName().length())); + private static final int TAG_LEN = Math.min(LOG_TAG_LEN, MapOverlay.class.getSimpleName().length()); + private static final String DEBUG_TAG = MapOverlay.class.getSimpleName().substring(0, TAG_LEN); public static final String FILENAME = "selectedtask" + "." + FileExtensions.RES; @@ -120,10 +123,11 @@ public MapOverlay(@NonNull final Map map) { setPrefs(prefs); download = new TaskDownloader(prefs.getServer()); // the following sets up the static icon caches - Note.setupIconCache(context); - OsmoseBug.setupIconCache(context); - MapRouletteTask.setupIconCache(context); - Todo.setupIconCache(context); + boolean hwAccelerated = map.isHardwareLayerType(); + Note.setupIconCache(context, hwAccelerated); + OsmoseBug.setupIconCache(context, hwAccelerated); + MapRouletteTask.setupIconCache(context, hwAccelerated); + Todo.setupIconCache(context, hwAccelerated); } @Override diff --git a/src/main/java/de/blau/android/prefs/AdvancedPrefEditorFragment.java b/src/main/java/de/blau/android/prefs/AdvancedPrefEditorFragment.java index 5f8225ccce..0c7abd3012 100644 --- a/src/main/java/de/blau/android/prefs/AdvancedPrefEditorFragment.java +++ b/src/main/java/de/blau/android/prefs/AdvancedPrefEditorFragment.java @@ -1,5 +1,7 @@ package de.blau.android.prefs; +import static de.blau.android.contract.Constants.LOG_TAG_LEN; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -21,7 +23,8 @@ public class AdvancedPrefEditorFragment extends ExtendedPreferenceFragment { - private static final String DEBUG_TAG = AdvancedPrefEditorFragment.class.getSimpleName().substring(0, Math.min(23, AdvancedPrefEditorFragment.class.getSimpleName().length())); + private static final int TAG_LEN = Math.min(LOG_TAG_LEN, AdvancedPrefEditorFragment.class.getSimpleName().length()); + private static final String DEBUG_TAG = AdvancedPrefEditorFragment.class.getSimpleName().substring(0, TAG_LEN); private Resources r; AdvancedPrefDatabase db; @@ -87,6 +90,7 @@ public void onResume() { setRestartRequiredMessage(R.string.config_autosaveMaxFiles_key); setRestartRequiredMessage(R.string.config_indexMediaStore_key); setRestartRequiredMessage(R.string.config_supportPresetLabels_key); + setRestartRequiredMessage(R.string.config_enableHwAcceleration_key); setTitle(); } diff --git a/src/main/java/de/blau/android/tasks/MapRouletteTask.java b/src/main/java/de/blau/android/tasks/MapRouletteTask.java index 7e389c1d28..c113952c23 100644 --- a/src/main/java/de/blau/android/tasks/MapRouletteTask.java +++ b/src/main/java/de/blau/android/tasks/MapRouletteTask.java @@ -59,12 +59,15 @@ public class MapRouletteTask extends LongIdTask { /** * Setup the icon caches + * + * @param context android Context + * @param hwAccelerated true if the Canvas is hw accelerated */ - public static void setupIconCache(Context context) { - cachedIconRouletteOpen = getIcon(context, R.drawable.roulette_open); - cachedIconRouletteChanged = getIcon(context, R.drawable.roulette_changed); - cachedIconChangedRouletteClosed = getIcon(context, R.drawable.roulette_closed_changed); - cachedIconRouletteClosed = getIcon(context, R.drawable.roulette_closed); + public static void setupIconCache(@NonNull Context context, boolean hwAccelerated) { + cachedIconRouletteOpen = getIcon(context, R.drawable.roulette_open, hwAccelerated); + cachedIconRouletteChanged = getIcon(context, R.drawable.roulette_changed, hwAccelerated); + cachedIconChangedRouletteClosed = getIcon(context, R.drawable.roulette_closed_changed, hwAccelerated); + cachedIconRouletteClosed = getIcon(context, R.drawable.roulette_closed, hwAccelerated); } @Override diff --git a/src/main/java/de/blau/android/tasks/Note.java b/src/main/java/de/blau/android/tasks/Note.java index 33978c0e22..6f34af2071 100644 --- a/src/main/java/de/blau/android/tasks/Note.java +++ b/src/main/java/de/blau/android/tasks/Note.java @@ -109,12 +109,15 @@ public Note(XmlPullParser parser) throws XmlPullParserException, IOException, Nu /** * Setup the icon caches + * + * @param context android Context + * @param hwAccelerated true if the Canvas is hw accelerated */ - public static void setupIconCache(Context context) { - cachedIconNoteOpen = getIcon(context, R.drawable.note_open); - cachedIconNoteChanged = getIcon(context, R.drawable.note_changed); - cachedIconNoteChangedClosed = getIcon(context, R.drawable.note_changed_closed); - cachedIconNoteClosed = getIcon(context, R.drawable.note_closed); + public static void setupIconCache(@NonNull Context context, boolean hwAccelerated) { + cachedIconNoteOpen = getIcon(context, R.drawable.note_open, hwAccelerated); + cachedIconNoteChanged = getIcon(context, R.drawable.note_changed, hwAccelerated); + cachedIconNoteChangedClosed = getIcon(context, R.drawable.note_changed_closed, hwAccelerated); + cachedIconNoteClosed = getIcon(context, R.drawable.note_closed, hwAccelerated); } /** diff --git a/src/main/java/de/blau/android/tasks/OsmoseBug.java b/src/main/java/de/blau/android/tasks/OsmoseBug.java index f9a4e21b97..8ef023e42a 100644 --- a/src/main/java/de/blau/android/tasks/OsmoseBug.java +++ b/src/main/java/de/blau/android/tasks/OsmoseBug.java @@ -1,5 +1,7 @@ package de.blau.android.tasks; +import static de.blau.android.contract.Constants.LOG_TAG_LEN; + import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -27,7 +29,8 @@ public final class OsmoseBug extends Bug implements Serializable { private static final long serialVersionUID = 5L; - private static final String DEBUG_TAG = OsmoseBug.class.getSimpleName().substring(0, Math.min(23, OsmoseBug.class.getSimpleName().length())); + private static final int TAG_LEN = Math.min(LOG_TAG_LEN, OsmoseBug.class.getSimpleName().length()); + private static final String DEBUG_TAG = OsmoseBug.class.getSimpleName().substring(0, TAG_LEN); private static final String OSMOSE_ISSUES = "issues"; private static final String OSMOSE_LAT = "lat"; @@ -56,12 +59,15 @@ public final class OsmoseBug extends Bug implements Serializable { /** * Setup the icon caches + * + * @param context android Context + * @param hwAccelerated true if the Canvas is hw accelerated */ - public static void setupIconCache(Context context) { - cachedIconBugOpen = getIcon(context, R.drawable.bug_open); - cachedIconBugChanged = getIcon(context, R.drawable.bug_changed); - cachedIconChangedBugClosed = getIcon(context, R.drawable.bug_changed_closed); - cachedIconBugClosed = getIcon(context, R.drawable.bug_closed); + public static void setupIconCache(@NonNull Context context, boolean hwAccelerated) { + cachedIconBugOpen = getIcon(context, R.drawable.bug_open, hwAccelerated); + cachedIconBugChanged = getIcon(context, R.drawable.bug_changed, hwAccelerated); + cachedIconChangedBugClosed = getIcon(context, R.drawable.bug_changed_closed, hwAccelerated); + cachedIconBugClosed = getIcon(context, R.drawable.bug_closed, hwAccelerated); } /** diff --git a/src/main/java/de/blau/android/tasks/Task.java b/src/main/java/de/blau/android/tasks/Task.java index 64422382f4..829fdec327 100644 --- a/src/main/java/de/blau/android/tasks/Task.java +++ b/src/main/java/de/blau/android/tasks/Task.java @@ -224,12 +224,15 @@ public void setChanged(boolean changed) { * * @param context Android Context * @param icon the icon resource + * @param hwAccelerated true is the canvas is hw accellerated * @return the Bitmap */ @NonNull - static BitmapWithOffset getIcon(@NonNull Context context, int icon) { + static BitmapWithOffset getIcon(@NonNull Context context, int icon, boolean hwAccelerated) { BitmapWithOffset bitmap = new BitmapWithOffset(); - bitmap.icon = BitmapFactory.decodeResource(context.getResources(), icon); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inPreferredConfig = hwAccelerated ? Bitmap.Config.HARDWARE : Bitmap.Config.ARGB_8888; + bitmap.icon = BitmapFactory.decodeResource(context.getResources(), icon, options); bitmap.w2 = bitmap.icon.getWidth() / 2f; bitmap.h2 = bitmap.icon.getHeight() / 2f; bitmap.iconSelectedBorder = Density.dpToPx(context, ICON_SELECTED_BORDER); diff --git a/src/main/java/de/blau/android/tasks/Todo.java b/src/main/java/de/blau/android/tasks/Todo.java index f0147f3bad..8340580ea3 100644 --- a/src/main/java/de/blau/android/tasks/Todo.java +++ b/src/main/java/de/blau/android/tasks/Todo.java @@ -67,12 +67,15 @@ public final class Todo extends Bug implements Serializable { /** * Setup the icon caches + * + * @param context android Context + * @param hwAccelerated true if the Canvas is hw accelerated */ - public static void setupIconCache(Context context) { - cachedIconTodoOpen = getIcon(context, R.drawable.todo_open); - cachedIconTogoChanged = getIcon(context, R.drawable.todo_open); - cachedIconTodoChangedClosed = getIcon(context, R.drawable.todo_closed); - cachedIconTodoClosed = getIcon(context, R.drawable.todo_closed); + public static void setupIconCache(@NonNull Context context, boolean hwAccelerated) { + cachedIconTodoOpen = getIcon(context, R.drawable.todo_open, hwAccelerated); + cachedIconTogoChanged = getIcon(context, R.drawable.todo_open, hwAccelerated); + cachedIconTodoChangedClosed = getIcon(context, R.drawable.todo_closed, hwAccelerated); + cachedIconTodoClosed = getIcon(context, R.drawable.todo_closed, hwAccelerated); } /** diff --git a/src/main/java/de/blau/android/views/layers/MapTilesLayer.java b/src/main/java/de/blau/android/views/layers/MapTilesLayer.java index 5e44607614..cf62d4abf6 100644 --- a/src/main/java/de/blau/android/views/layers/MapTilesLayer.java +++ b/src/main/java/de/blau/android/views/layers/MapTilesLayer.java @@ -1,5 +1,7 @@ package de.blau.android.views.layers; +import static de.blau.android.contract.Constants.LOG_TAG_LEN; + import java.io.IOException; import java.util.BitSet; import java.util.Collection; @@ -68,7 +70,8 @@ */ public class MapTilesLayer<T> extends MapViewLayer implements ExtentInterface, LayerInfoInterface, DiscardInterface, AttributionInterface { - private static final String DEBUG_TAG = MapTilesLayer.class.getSimpleName().substring(0, Math.min(23, MapTilesLayer.class.getSimpleName().length())); + private static final int TAG_LEN = Math.min(LOG_TAG_LEN, MapTilesLayer.class.getSimpleName().length()); + private static final String DEBUG_TAG = MapTilesLayer.class.getSimpleName().substring(0, TAG_LEN); /** Define a minimum active area for taps on the tile attribution data. */ private static final int TAPAREA_MIN_WIDTH = 40; @@ -173,6 +176,16 @@ default void postRender(@NonNull Canvas c, int z) { } public static class BitmapTileRenderer implements TileRenderer<Bitmap> { + private final boolean hardwareRenderer; + + /** + * Construct a new renderer + * + * @param hardwareRenderer decode bitmap for hardware rendering if true + */ + public BitmapTileRenderer(boolean hardwareRenderer) { + this.hardwareRenderer = hardwareRenderer; + } @Override public void render(@NonNull Canvas c, @NonNull Bitmap tileBlob, int z, @Nullable Rect fromRect, @NonNull Rect screenRect, @NonNull Paint paint) { @@ -182,7 +195,7 @@ public void render(@NonNull Canvas c, @NonNull Bitmap tileBlob, int z, @Nullable @Override @NonNull public TileDecoder<Bitmap> decoder() { - return new MapTileProvider.BitmapDecoder(); + return new MapTileProvider.BitmapDecoder(hardwareRenderer); } } diff --git a/src/main/java/de/blau/android/views/util/MapTileProvider.java b/src/main/java/de/blau/android/views/util/MapTileProvider.java index 7f2b63ca2f..7968ab6be2 100644 --- a/src/main/java/de/blau/android/views/util/MapTileProvider.java +++ b/src/main/java/de/blau/android/views/util/MapTileProvider.java @@ -1,5 +1,7 @@ package de.blau.android.views.util; +import static de.blau.android.contract.Constants.LOG_TAG_LEN; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -46,7 +48,8 @@ public class MapTileProvider<T> { /** * Tag used in debug log-entries. */ - private static final String DEBUG_TAG = MapTileProvider.class.getSimpleName().substring(0, Math.min(23, MapTileProvider.class.getSimpleName().length())); + private static final int TAG_LEN = Math.min(LOG_TAG_LEN, MapTileProvider.class.getSimpleName().length()); + private static final String DEBUG_TAG = MapTileProvider.class.getSimpleName().substring(0, TAG_LEN); private static final int MVT_CACHE_SIZE = 128; @@ -85,17 +88,30 @@ public interface TileDecoder<D> { public static class BitmapDecoder implements TileDecoder<Bitmap> { private BitmapFactory.Options options = new BitmapFactory.Options(); + private boolean hardwareRendering; + + /** + * Construct a new decoder + * + * @param hardwareRendering if true decode for hardware rendering + */ + public BitmapDecoder(boolean hardwareRendering) { + this.hardwareRendering = hardwareRendering; + } + @Override public Bitmap decode(@NonNull byte[] data, boolean small) { - if (small) { + if (hardwareRendering) { + options.inPreferredConfig = Bitmap.Config.HARDWARE; + } else if (small) { options.inPreferredConfig = Bitmap.Config.RGB_565; } else { options.inPreferredConfig = Bitmap.Config.ARGB_8888; } return BitmapFactory.decodeByteArray(data, 0, data.length, options); } - } + // =========================================================== // Constructors // =========================================================== diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 30838ad88c..5c688dbc1c 100755 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -1314,7 +1314,7 @@ <string name="config_enableAntiAliasing_title">Enable anti-aliasing</string> <string name="config_enableAntiAliasing_summary">Makes the lines smoother.</string> <string name="config_enableHwAcceleration_title">Enable hardware acceleration</string> - <string name="config_enableHwAcceleration_summary">Allows use of hardware acceleration if and where supported, currently setting this has no effect.</string> + <string name="config_enableHwAcceleration_summary">Turn on use of hardware rendering on Android 10 and later.</string> <string name="config_maxStrokeWidth_title">Max line width</string> <string name="config_maxStrokeWidth_summary">Do not draw a way thicker than this.</string> <string name="config_maxStrokeWidth_current">%1$d px</string>