diff --git a/OsmAnd-java/src/net/osmand/render/RenderingRuleProperty.java b/OsmAnd-java/src/net/osmand/render/RenderingRuleProperty.java index 275e55eed9..09af86b0f1 100644 --- a/OsmAnd-java/src/net/osmand/render/RenderingRuleProperty.java +++ b/OsmAnd-java/src/net/osmand/render/RenderingRuleProperty.java @@ -166,7 +166,7 @@ public class RenderingRuleProperty { try { return parseColor(value); } catch (RuntimeException e) { - log.error("Rendering parse " + e.getMessage()); + log.error("Rendering parse " + e.getMessage() + " in " + attrName); } return -1; } else if(type == FLOAT_TYPE){ @@ -178,7 +178,7 @@ public class RenderingRuleProperty { } return 0; } catch (NumberFormatException e) { - log.error("Rendering parse " + value); + log.error("Rendering parse " + value + " in " + attrName); } return -1; } else { @@ -198,7 +198,7 @@ public class RenderingRuleProperty { } return Float.parseFloat(value); } catch (NumberFormatException e) { - log.error("Rendering parse " + value); + log.error("Rendering parse " + value + " in " + attrName); } return -1; } else { diff --git a/OsmAnd/src/net/osmand/core/android/MapRendererContext.java b/OsmAnd/src/net/osmand/core/android/MapRendererContext.java index 9c3dfacf19..11adb0521f 100644 --- a/OsmAnd/src/net/osmand/core/android/MapRendererContext.java +++ b/OsmAnd/src/net/osmand/core/android/MapRendererContext.java @@ -1,7 +1,11 @@ package net.osmand.core.android; +import android.util.Log; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import net.osmand.core.jni.IMapTiledSymbolsProvider; @@ -17,6 +21,7 @@ import net.osmand.core.jni.MapStylesCollection; import net.osmand.core.jni.ObfMapObjectsProvider; import net.osmand.core.jni.QStringStringHash; import net.osmand.core.jni.ResolvedMapStyle; +import net.osmand.core.jni.SwigUtilities; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings.CommonPreference; @@ -30,7 +35,8 @@ import net.osmand.util.Algorithms; * @author Alexey Pelykh * */ -public class MapRendererContext { +public class MapRendererContext implements RendererRegistry.IRendererLoadedEventListener { + private static final String TAG = "MapRendererContext"; private static final int OBF_RASTER_LAYER = 0; private OsmandApplication app; @@ -101,7 +107,7 @@ public class MapRendererContext { } protected float getDisplayDensityFactor() { - return (float) (app.getSettings().MAP_DENSITY.get()) * Math.max(1, density); + return app.getSettings().MAP_DENSITY.get() * Math.max(1, density); } protected int getRasterTileSize() { @@ -126,7 +132,28 @@ public class MapRendererContext { rendName = "default"; } if (!mapStyles.containsKey(rendName)) { - mapStyles.put(rendName, mapStylesCollection.getResolvedStyleByName(rendName)); + Log.d(TAG, "Style '" + rendName + "' not in cache"); + if (mapStylesCollection.getStyleByName(rendName) == null) { + Log.d(TAG, "Unknown '" + rendName + "' style, need to load"); + + // Ensure parents are loaded (this may also trigger load) + app.getRendererRegistry().getRenderer(rendName); + + if (mapStylesCollection.getStyleByName(rendName) == null) { + try { + loadStyleFromStream(rendName, app.getRendererRegistry().getInputStream(rendName)); + } catch (IOException e) { + Log.e(TAG, "Failed to load '" + rendName + "'", e); + } + } + } + ResolvedMapStyle mapStyle = mapStylesCollection.getResolvedStyleByName(rendName); + if (mapStyle != null) { + mapStyles.put(rendName, mapStyle); + } else { + Log.d(TAG, "Failed to resolve '" + rendName + "', will use 'default'"); + rendName = "default"; + } } ResolvedMapStyle mapStyle = mapStyles.get(rendName); CachedMapPresentation pres = new CachedMapPresentation(langId, langPref, mapStyle, displayDensityFactor); @@ -163,10 +190,9 @@ public class MapRendererContext { } QStringStringHash convertedStyleSettings = new QStringStringHash(); - for (Iterator> itSetting = props.entrySet().iterator(); itSetting.hasNext();) { - Map.Entry setting = itSetting.next(); - convertedStyleSettings.set(setting.getKey(), setting.getValue()); - } + for (Map.Entry setting : props.entrySet()) { + convertedStyleSettings.set(setting.getKey(), setting.getValue()); + } if (nightMode) { convertedStyleSettings.set("nightMode", "true"); } @@ -221,8 +247,7 @@ public class MapRendererContext { mapRendererView.addSymbolsProvider(obfMapSymbolsProvider); } } - - + private class CachedMapPresentation { String langId ; LanguagePreference langPref; @@ -257,7 +282,45 @@ public class MapRendererContext { return false; return true; } - } - + + public void onRendererLoaded(String name, RenderingRulesStorage rules, InputStream source) { + loadStyleFromStream(name, source); + } + + private void loadStyleFromStream(String name, InputStream source) { + if (RendererRegistry.DEFAULT_RENDER.equals(name)) { + if (source != null) { + try { + source.close(); + } catch(IOException e) {} + } + return; + } + + Log.d(TAG, "Going to pass '" + name + "' style content to native"); + byte[] content; + try { + ByteArrayOutputStream intermediateBuffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[16384]; + while ((nRead = source.read(data, 0, data.length)) != -1) { + intermediateBuffer.write(data, 0, nRead); + } + intermediateBuffer.flush(); + content = intermediateBuffer.toByteArray(); + } catch(IOException e) { + Log.e(TAG, "Failed to read style content", e); + return; + } finally { + try { + source.close(); + } catch(IOException e) {} + } + + if (!mapStylesCollection.addStyleFromByteArray( + SwigUtilities.createQByteArrayAsCopyOf(content), name)) { + Log.w(TAG, "Failed to add style from byte array"); + } + } } diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java old mode 100755 new mode 100644 diff --git a/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java b/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java index d5afedf332..633a57ce2f 100644 --- a/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java +++ b/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java @@ -32,6 +32,12 @@ public class RendererRegistry { private Map internalRenderers = new LinkedHashMap(); private Map renderers = new LinkedHashMap(); + + public interface IRendererLoadedEventListener { + void onRendererLoaded(String name, RenderingRulesStorage rules, InputStream source); + } + + private IRendererLoadedEventListener rendererLoadedEventListener; public RendererRegistry(){ internalRenderers.put(DEFAULT_RENDER, "default.render.xml"); @@ -126,12 +132,16 @@ public class RendererRegistry { } finally { is.close(); } + + if (rendererLoadedEventListener != null) + rendererLoadedEventListener.onRendererLoaded(name, main, getInputStream(name)); + return main; } @SuppressWarnings("resource") - private InputStream getInputStream(String name) throws FileNotFoundException { - InputStream is = null; + public InputStream getInputStream(String name) throws FileNotFoundException { + InputStream is; if("default".equalsIgnoreCase(name)) { name = DEFAULT_RENDER; } @@ -169,5 +179,11 @@ public class RendererRegistry { this.currentSelectedRender = currentSelectedRender; } - + public void setRendererLoadedEventListener(IRendererLoadedEventListener listener) { + rendererLoadedEventListener = listener; + } + + public IRendererLoadedEventListener getRendererLoadedEventListener() { + return rendererLoadedEventListener; + } } diff --git a/OsmAnd/src/net/osmand/plus/views/corenative/NativeCoreContext.java b/OsmAnd/src/net/osmand/plus/views/corenative/NativeCoreContext.java index d6cba88d12..5001dab1b0 100644 --- a/OsmAnd/src/net/osmand/plus/views/corenative/NativeCoreContext.java +++ b/OsmAnd/src/net/osmand/plus/views/corenative/NativeCoreContext.java @@ -58,37 +58,15 @@ public class NativeCoreContext { ObfsCollection obfsCollection = new ObfsCollection(); obfsCollection.addDirectory(directory.getAbsolutePath(), false); - - MapStylesCollection mapStylesCollection = setupMapStyleCollection(app); - mapRendererContext = new MapRendererContext(app, dm.density); - mapRendererContext.setupObfMap(mapStylesCollection, obfsCollection); + + mapRendererContext = new MapRendererContext(app, dm.density); + mapRendererContext.setupObfMap(new MapStylesCollection(), obfsCollection); + app.getRendererRegistry().setRendererLoadedEventListener(mapRendererContext); init = true; } } } - private static MapStylesCollection setupMapStyleCollection( - OsmandApplication app) { - MapStylesCollection mapStylesCollection = new MapStylesCollection(); - // Alexey TODO -// internalRenderers.put("Touring-view_(more-contrast-and-details)", "Touring-view_(more-contrast-and-details)" +".render.xml"); -// internalRenderers.put("UniRS", "UniRS" + ".render.xml"); -// internalRenderers.put("LightRS", "LightRS" + ".render.xml"); -// internalRenderers.put("High-contrast-roads", "High-contrast-roads" + ".render.xml"); -// internalRenderers.put("Winter-and-ski", "Winter-and-ski" + ".render.xml"); - File renderers = app.getAppPath(IndexConstants.RENDERERS_DIR); - File[] lf = renderers.listFiles(); - if(lf != null) { - for(File f : lf) { - if(f.getName().endsWith(IndexConstants.RENDERER_INDEX_EXT)) { - mapStylesCollection.addStyleFromFile(f.getAbsolutePath()); - } - } - } - return mapStylesCollection; - } - - public static MapRendererContext getMapRendererContext() { return mapRendererContext; }