From 87271f9daf4a58d5d9e002b1e9d82a48529b2438 Mon Sep 17 00:00:00 2001 From: ClemensFischer Date: Mon, 23 Feb 2026 16:47:53 +0100 Subject: [PATCH] Removed TileRenderer class --- .../Avalonia/MapsforgeTileSource.Avalonia.cs | 4 +- MapsforgeTiles/README.md | 11 +- MapsforgeTiles/Shared/MapsforgeTileSource.cs | 105 ++++++++++++++++-- MapsforgeTiles/Shared/TileRenderer.cs | 92 --------------- MapsforgeTiles/WPF/MapsforgeTileSource.WPF.cs | 4 +- .../WinUI/MapsforgeTileSource.WinUI.cs | 4 +- 6 files changed, 108 insertions(+), 112 deletions(-) delete mode 100644 MapsforgeTiles/Shared/TileRenderer.cs diff --git a/MapsforgeTiles/Avalonia/MapsforgeTileSource.Avalonia.cs b/MapsforgeTiles/Avalonia/MapsforgeTileSource.Avalonia.cs index fad2bb99..b9441319 100644 --- a/MapsforgeTiles/Avalonia/MapsforgeTileSource.Avalonia.cs +++ b/MapsforgeTiles/Avalonia/MapsforgeTileSource.Avalonia.cs @@ -16,11 +16,11 @@ namespace MapControl.MapsforgeTiles try { - var pixels = tileRenderer.RenderTile(zoomLevel, column, row); + var pixels = RenderTile(zoomLevel, column, row); if (pixels != null) { - var size = TileRenderer.TileSize; + var size = displayModel.getTileSize(); unsafe { diff --git a/MapsforgeTiles/README.md b/MapsforgeTiles/README.md index 8048b202..4bf37c25 100644 --- a/MapsforgeTiles/README.md +++ b/MapsforgeTiles/README.md @@ -2,9 +2,8 @@ Tile source libraries for loading map content from vector map files. -The `MapsforgeTileSource` classes in these libraries make use of a `TileRenderer` class that wraps the -[Mapsforge](https://github.com/mapsforge/mapsforge) Java library, which is made accessible to .NET via -[IKVM](https://github.com/ikvmnet/ikvm), a Java Virtual Machine for .NET. +The `MapsforgeTileSource` class in these libraries uses parts of the [Mapsforge](https://github.com/mapsforge/mapsforge) +Java library, which is made accessible to .NET via [IKVM](https://github.com/ikvmnet/ikvm), a Java Virtual Machine for .NET. [Mapsforge](https://github.com/mapsforge/mapsforge) is published under a simplified variant of the [LGPL v3 license](https://www.gnu.org/licenses/lgpl-3.0). @@ -13,9 +12,11 @@ Map files can be downloaded from the [Mapsforge Download Server](https://downloa `MapsforgeTileSource` is initialized by a static `Initialize` method that takes the file path to either a single map file or a directory containing multiple map files, and a DPI scale factor that controls the size of the rendered map tiles. -The `MapsforgeTileSource` instance constructor takes a string parameter that specifies the Mapsforge theme used by its `TileRenderer`. +The `MapsforgeTileSource` instance constructor takes a string parameter that specifies a Mapsforge theme. This is either +the full path of an XML `rendertheme` file, or the name of one of the built-in themes (ignoring case), e.g. `Default`. See [MapsforgeThemes.java](https://github.com/mapsforge/mapsforge/blob/master/mapsforge-themes/src/main/java/org/mapsforge/map/rendertheme/internal/MapsforgeThemes.java) -for available theme names. A second, optional constructor parameter specifies the size of the TileRenderer's internal tile cache. +for available theme names. The second and third optional constructor parameters specify the size of the tile source's +internal tile cache and the relative scale of rendered text. Code sample: ``` diff --git a/MapsforgeTiles/Shared/MapsforgeTileSource.cs b/MapsforgeTiles/Shared/MapsforgeTileSource.cs index c9fb253c..2cb759db 100644 --- a/MapsforgeTiles/Shared/MapsforgeTileSource.cs +++ b/MapsforgeTiles/Shared/MapsforgeTileSource.cs @@ -1,34 +1,121 @@ using Microsoft.Extensions.Logging; +using org.mapsforge.map.awt.graphics; +using org.mapsforge.map.datastore; +using org.mapsforge.map.layer.cache; +using org.mapsforge.map.layer.renderer; +using org.mapsforge.map.model; +using org.mapsforge.map.reader; +using org.mapsforge.map.rendertheme; +using org.mapsforge.map.rendertheme.@internal; +using org.mapsforge.map.rendertheme.rule; using System.Collections.Generic; using System.IO; namespace MapControl.MapsforgeTiles { - public partial class MapsforgeTileSource(string theme, int cacheCapacity = 200, float textScale = 1f) : TileSource + public partial class MapsforgeTileSource : TileSource { private static ILogger Logger => field ??= ImageLoader.LoggerFactory?.CreateLogger(); - private readonly TileRenderer tileRenderer = new TileRenderer(theme, cacheCapacity, textScale); + private static DisplayModel displayModel; + private static MapDataStore mapDataStore; - public static void Initialize(string mapFilePath, float dpiScale) + private readonly InMemoryTileCache tileCache; + private readonly DatabaseRenderer renderer; + private readonly RenderThemeFuture renderThemeFuture; + private readonly float renderTextScale; + + public static void Initialize(string mapFile, float dpiScale) { List mapFiles; - if (mapFilePath.EndsWith(".map")) + if (mapFile.EndsWith(".map")) { - mapFiles = [mapFilePath]; + mapFiles = [mapFile]; } else { - mapFiles = [.. Directory.EnumerateFiles(mapFilePath, "*.map")]; + mapFiles = [.. Directory.EnumerateFiles(mapFile, "*.map")]; } - foreach (var mapFile in mapFiles) + Initialize(mapFiles, dpiScale); + } + + public static void Initialize(List mapFiles, float dpiScale) + { + DisplayModel.setDeviceScaleFactor(dpiScale); + displayModel = new DisplayModel(); + + if (mapFiles.Count == 1) { - Logger?.LogInformation("Loading {mapFile}", mapFile); + Logger?.LogInformation("Loading {mapFile}", mapFiles[0]); + + mapDataStore = new MapFile(mapFiles[0]); + } + else + { + var multiMapDataStore = new MultiMapDataStore(MultiMapDataStore.DataPolicy.DEDUPLICATE); + mapDataStore = multiMapDataStore; + + foreach (var mapFile in mapFiles) + { + Logger?.LogInformation("Loading {mapFile}", mapFile); + + multiMapDataStore.addMapDataStore(new MapFile(mapFile), false, false); + } + } + } + + public MapsforgeTileSource(string theme, int cacheCapacity = 200, float textScale = 1f) + { + XmlRenderTheme renderTheme; + + if (theme.EndsWith(".xml")) + { + renderTheme = new ExternalRenderTheme(theme); + } + else + { + renderTheme = MapsforgeThemes.valueOf(theme.ToUpper()); } - TileRenderer.Initialize(mapFiles, dpiScale); + tileCache = new InMemoryTileCache(cacheCapacity); + renderer = new DatabaseRenderer(mapDataStore, AwtGraphicFactory.INSTANCE, tileCache, null, true, false, null); + renderThemeFuture = new RenderThemeFuture(AwtGraphicFactory.INSTANCE, renderTheme, displayModel); + renderTextScale = textScale; + } + + private int[] RenderTile(int zoomLevel, int column, int row) + { + if (!renderThemeFuture.isDone()) + { + lock (renderThemeFuture) + { + if (!renderThemeFuture.isDone()) + { + Logger?.LogInformation("Loading render theme..."); + renderThemeFuture.run(); + Logger?.LogInformation("Loading render theme done."); + } + } + } + + int[] imageBuffer = null; + var tile = new org.mapsforge.core.model.Tile(column, row, (byte)zoomLevel, displayModel.getTileSize()); + var job = new RendererJob(tile, mapDataStore, renderThemeFuture, displayModel, renderTextScale, false, false); + var bitmap = tileCache.get(job) ?? renderer.executeJob(job); + + if (bitmap != null) + { + var image = AwtGraphicFactory.getBitmap(bitmap); + + if (image != null) + { + imageBuffer = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth()); + } + } + + return imageBuffer; } } } diff --git a/MapsforgeTiles/Shared/TileRenderer.cs b/MapsforgeTiles/Shared/TileRenderer.cs deleted file mode 100644 index 191f646b..00000000 --- a/MapsforgeTiles/Shared/TileRenderer.cs +++ /dev/null @@ -1,92 +0,0 @@ -using org.mapsforge.map.awt.graphics; -using org.mapsforge.map.datastore; -using org.mapsforge.map.layer.cache; -using org.mapsforge.map.layer.renderer; -using org.mapsforge.map.model; -using org.mapsforge.map.reader; -using org.mapsforge.map.rendertheme; -using org.mapsforge.map.rendertheme.@internal; -using org.mapsforge.map.rendertheme.rule; -using System.Collections.Generic; - -namespace MapControl.MapsforgeTiles -{ - public class TileRenderer - { - private static DisplayModel displayModel; - private static MapDataStore mapDataStore; - - public static int TileSize => displayModel.getTileSize(); - - public static void Initialize(List mapFiles, float dpiScale) - { - DisplayModel.setDeviceScaleFactor(dpiScale); - displayModel = new DisplayModel(); - - if (mapFiles.Count == 1) - { - mapDataStore = new MapFile(mapFiles[0]); - } - else - { - var multiMapDataStore = new MultiMapDataStore(MultiMapDataStore.DataPolicy.DEDUPLICATE); - mapDataStore = multiMapDataStore; - - foreach (var mapFile in mapFiles) - { - multiMapDataStore.addMapDataStore(new MapFile(mapFile), false, false); - } - } - } - - private readonly InMemoryTileCache tileCache; - private readonly DatabaseRenderer renderer; - private readonly RenderThemeFuture renderThemeFuture; - private readonly float textScale; - - public TileRenderer(string theme, int cacheCapacity, float renderTextScale) - { - XmlRenderTheme renderTheme; - - if (theme.EndsWith(".xml")) - { - renderTheme = new ExternalRenderTheme(theme); - } - else - { - renderTheme = MapsforgeThemes.valueOf(theme.ToUpper()); - } - - tileCache = new InMemoryTileCache(cacheCapacity); - renderer = new DatabaseRenderer(mapDataStore, AwtGraphicFactory.INSTANCE, tileCache, null, true, false, null); - renderThemeFuture = new RenderThemeFuture(AwtGraphicFactory.INSTANCE, renderTheme, displayModel); - textScale = renderTextScale; - } - - public int[] RenderTile(int zoomLevel, int column, int row) - { - if (!renderThemeFuture.isDone()) - { - renderThemeFuture.run(); - } - - int[] imageBuffer = null; - var tile = new org.mapsforge.core.model.Tile(column, row, (byte)zoomLevel, displayModel.getTileSize()); - var job = new RendererJob(tile, mapDataStore, renderThemeFuture, displayModel, textScale, false, false); - var bitmap = tileCache.get(job) ?? renderer.executeJob(job); - - if (bitmap != null) - { - var image = AwtGraphicFactory.getBitmap(bitmap); - - if (image != null) - { - imageBuffer = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth()); - } - } - - return imageBuffer; - } - - } -} diff --git a/MapsforgeTiles/WPF/MapsforgeTileSource.WPF.cs b/MapsforgeTiles/WPF/MapsforgeTileSource.WPF.cs index 292008ea..094091bd 100644 --- a/MapsforgeTiles/WPF/MapsforgeTileSource.WPF.cs +++ b/MapsforgeTiles/WPF/MapsforgeTileSource.WPF.cs @@ -14,11 +14,11 @@ namespace MapControl.MapsforgeTiles try { - var pixels = tileRenderer.RenderTile(zoomLevel, column, row); + var pixels = RenderTile(zoomLevel, column, row); if (pixels != null) { - var size = TileRenderer.TileSize; + var size = displayModel.getTileSize(); bitmap = BitmapSource.Create(size, size, 96d, 96d, PixelFormats.Bgra32, null, pixels, size * 4); bitmap.Freeze(); diff --git a/MapsforgeTiles/WinUI/MapsforgeTileSource.WinUI.cs b/MapsforgeTiles/WinUI/MapsforgeTileSource.WinUI.cs index ceddca52..7f07277c 100644 --- a/MapsforgeTiles/WinUI/MapsforgeTileSource.WinUI.cs +++ b/MapsforgeTiles/WinUI/MapsforgeTileSource.WinUI.cs @@ -19,7 +19,7 @@ namespace MapControl.MapsforgeTiles public override async Task LoadImageAsync(int zoomLevel, int column, int row) { ImageSource image = null; - var size = TileRenderer.TileSize; + var size = displayModel.getTileSize(); var bitmap = new WriteableBitmap(size, size); using var stream = bitmap.PixelBuffer.AsStream(); @@ -29,7 +29,7 @@ namespace MapControl.MapsforgeTiles // await Task.Run(() => { - var pixels = tileRenderer.RenderTile(zoomLevel, column, row); + var pixels = RenderTile(zoomLevel, column, row); if (pixels != null) {