Removed TileRenderer class

This commit is contained in:
ClemensFischer 2026-02-23 16:47:53 +01:00
parent a435992dbc
commit 87271f9daf
6 changed files with 108 additions and 112 deletions

View file

@ -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
{

View file

@ -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:
```

View file

@ -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<MapsforgeTileSource>();
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<string> 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<string> 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;
}
}
}

View file

@ -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<string> 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;
}
}
}

View file

@ -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();

View file

@ -19,7 +19,7 @@ namespace MapControl.MapsforgeTiles
public override async Task<ImageSource> 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)
{