Theme texture atlas #324 improvements, #63

This commit is contained in:
Emux 2017-03-06 15:18:07 +02:00
parent 2d3ab0b6fd
commit 808671c1fb
8 changed files with 126 additions and 353 deletions

View File

@ -35,9 +35,6 @@
<activity <activity
android:name=".AtlasThemeMapActivity" android:name=".AtlasThemeMapActivity"
android:configChanges="keyboardHidden|orientation|screenSize" /> android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".AtlasThemeMapActivity$MapFilePicker"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity <activity
android:name=".BitmapTileMapActivity" android:name=".BitmapTileMapActivity"
android:configChanges="keyboardHidden|orientation|screenSize" /> android:configChanges="keyboardHidden|orientation|screenSize" />

View File

@ -15,159 +15,22 @@
*/ */
package org.oscim.android.test; package org.oscim.android.test;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem;
import org.oscim.android.filepicker.FilePicker;
import org.oscim.android.filepicker.FilterByFileExtension;
import org.oscim.android.filepicker.ValidMapFile;
import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
import org.oscim.layers.TileGridLayer;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.renderer.BitmapRenderer;
import org.oscim.renderer.GLViewport;
import org.oscim.scalebar.DefaultMapScaleBar;
import org.oscim.scalebar.ImperialUnitAdapter;
import org.oscim.scalebar.MapScaleBar;
import org.oscim.scalebar.MapScaleBarLayer;
import org.oscim.scalebar.MetricUnitAdapter;
import org.oscim.theme.ThemeLoader; import org.oscim.theme.ThemeLoader;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.source.mapfile.MapFileTileSource;
import org.oscim.tiling.source.mapfile.MapInfo;
public class AtlasThemeMapActivity extends MapActivity { public class AtlasThemeMapActivity extends SimpleMapActivity {
private static final int SELECT_MAP_FILE = 0;
private TileGridLayer mGridLayer;
private DefaultMapScaleBar mMapScaleBar;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set flag to use TextureAtlas for Theme-Symbol's!
ThemeLoader.USE_ATLAS = true; ThemeLoader.USE_ATLAS = true;
startActivityForResult(new Intent(this, MapFilePicker.class), super.onCreate(savedInstanceState);
SELECT_MAP_FILE);
}
@Override
protected void onDestroy() {
mMapScaleBar.destroy();
super.onDestroy();
}
public static class MapFilePicker extends FilePicker {
public MapFilePicker() {
setFileDisplayFilter(new FilterByFileExtension(".map"));
setFileSelectFilter(new ValidMapFile());
}
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.theme_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.theme_default:
mMap.setTheme(VtmThemes.DEFAULT);
item.setChecked(true);
return true;
case R.id.theme_osmarender:
mMap.setTheme(VtmThemes.OSMARENDER);
item.setChecked(true);
return true;
case R.id.theme_osmagray:
mMap.setTheme(VtmThemes.OSMAGRAY);
item.setChecked(true);
return true;
case R.id.theme_tubes:
mMap.setTheme(VtmThemes.TRONRENDER);
item.setChecked(true);
return true;
case R.id.theme_newtron:
mMap.setTheme(VtmThemes.NEWTRON);
item.setChecked(true);
return true;
case R.id.gridlayer:
if (item.isChecked()) {
item.setChecked(false);
mMap.layers().remove(mGridLayer);
} else {
item.setChecked(true);
if (mGridLayer == null)
mGridLayer = new TileGridLayer(mMap, getResources().getDisplayMetrics().density);
mMap.layers().add(mGridLayer);
}
mMap.updateMap(true);
return true;
}
return false; return false;
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == SELECT_MAP_FILE) {
if (resultCode != RESULT_OK || intent == null || intent.getStringExtra(FilePicker.SELECTED_FILE) == null) {
finish();
return;
}
MapFileTileSource tileSource = new MapFileTileSource();
tileSource.setPreferredLanguage("en");
String file = intent.getStringExtra(FilePicker.SELECTED_FILE);
if (tileSource.setMapFile(file)) {
VectorTileLayer l = mMap.setBaseMap(tileSource);
loadTheme(null);
mMap.layers().add(new BuildingLayer(mMap, l));
mMap.layers().add(new LabelLayer(mMap, l));
mMapScaleBar = new DefaultMapScaleBar(mMap);
mMapScaleBar.setScaleBarMode(DefaultMapScaleBar.ScaleBarMode.BOTH);
mMapScaleBar.setDistanceUnitAdapter(MetricUnitAdapter.INSTANCE);
mMapScaleBar.setSecondaryDistanceUnitAdapter(ImperialUnitAdapter.INSTANCE);
mMapScaleBar.setScaleBarPosition(MapScaleBar.ScaleBarPosition.BOTTOM_LEFT);
MapScaleBarLayer mapScaleBarLayer = new MapScaleBarLayer(mMap, mMapScaleBar);
BitmapRenderer renderer = mapScaleBarLayer.getRenderer();
renderer.setPosition(GLViewport.Position.BOTTOM_LEFT);
renderer.setOffset(5 * getResources().getDisplayMetrics().density, 0);
mMap.layers().add(mapScaleBarLayer);
MapInfo info = tileSource.getMapInfo();
MapPosition pos = new MapPosition();
pos.setByBoundingBox(info.boundingBox, Tile.SIZE * 4, Tile.SIZE * 4);
mMap.setMapPosition(pos);
mPrefs.clear();
}
}
}
protected void loadTheme(final String styleId) {
mMap.setTheme(VtmThemes.DEFAULT);
}
} }

View File

@ -0,0 +1,31 @@
/*
* Copyright 2017 Longri
* Copyright 2017 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.test;
import org.oscim.gdx.GdxMapApp;
import org.oscim.theme.ThemeLoader;
public class AtlasThemeMapTest extends MapTest {
private AtlasThemeMapTest() {
ThemeLoader.USE_ATLAS = true;
}
public static void main(String[] args) {
GdxMapApp.init();
GdxMapApp.run(new AtlasThemeMapTest());
}
}

View File

@ -1,73 +0,0 @@
/*
* Copyright 2017 Longri
* Copyright 2017 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.test;
import org.oscim.gdx.GdxMapApp;
import org.oscim.layers.GroupLayer;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.map.Map;
import org.oscim.renderer.BitmapRenderer;
import org.oscim.renderer.GLViewport;
import org.oscim.scalebar.DefaultMapScaleBar;
import org.oscim.scalebar.ImperialUnitAdapter;
import org.oscim.scalebar.MapScaleBar;
import org.oscim.scalebar.MapScaleBarLayer;
import org.oscim.scalebar.MetricUnitAdapter;
import org.oscim.theme.ThemeLoader;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
public class AtlasThemeTest extends GdxMapApp {
public AtlasThemeTest() {
// set flag to use TextureAtlas for Theme symbols
ThemeLoader.USE_ATLAS = true;
}
@Override
public void createLayers() {
Map map = getMap();
VectorTileLayer l = map.setBaseMap(new OSciMap4TileSource());
GroupLayer groupLayer = new GroupLayer(mMap);
groupLayer.layers.add(new BuildingLayer(map, l));
groupLayer.layers.add(new LabelLayer(map, l));
map.layers().add(groupLayer);
DefaultMapScaleBar mapScaleBar = new DefaultMapScaleBar(mMap);
mapScaleBar.setScaleBarMode(DefaultMapScaleBar.ScaleBarMode.BOTH);
mapScaleBar.setDistanceUnitAdapter(MetricUnitAdapter.INSTANCE);
mapScaleBar.setSecondaryDistanceUnitAdapter(ImperialUnitAdapter.INSTANCE);
mapScaleBar.setScaleBarPosition(MapScaleBar.ScaleBarPosition.BOTTOM_LEFT);
MapScaleBarLayer mapScaleBarLayer = new MapScaleBarLayer(mMap, mapScaleBar);
BitmapRenderer renderer = mapScaleBarLayer.getRenderer();
renderer.setPosition(GLViewport.Position.BOTTOM_LEFT);
renderer.setOffset(5, 0);
map.layers().add(mapScaleBarLayer);
map.setTheme(VtmThemes.DEFAULT);
map.setMapPosition(53.075, 8.808, 1 << 17);
}
public static void main(String[] args) {
GdxMapApp.init();
GdxMapApp.run(new AtlasThemeTest());
}
}

View File

@ -1,6 +1,6 @@
/* /*
* Copyright 2013 Hannes Janetzek * Copyright 2013 Hannes Janetzek
* Copyright 2016 devemux86 * Copyright 2016-2017 devemux86
* Copyright 2017 Longri * Copyright 2017 Longri
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
@ -186,10 +186,10 @@ public abstract class CanvasAdapter {
} }
private static InputStream inputStreamFromFile(String relativePathPrefix, String src) throws IOException { private static InputStream inputStreamFromFile(String relativePathPrefix, String src) throws IOException {
File file = getFile(relativePathPrefix, src); File file = getAbsoluteFile(relativePathPrefix, src);
if (!file.exists()) { if (!file.exists()) {
if (src.length() > 0 && src.charAt(0) == File.separatorChar) { if (src.length() > 0 && src.charAt(0) == File.separatorChar) {
file = getFile(relativePathPrefix, src.substring(1)); file = getAbsoluteFile(relativePathPrefix, src.substring(1));
} }
if (!file.exists()) { if (!file.exists()) {
file = null; file = null;
@ -203,7 +203,7 @@ public abstract class CanvasAdapter {
return null; return null;
} }
private static File getFile(String parentPath, String pathName) { public static File getAbsoluteFile(String parentPath, String pathName) {
if (pathName.charAt(0) == File.separatorChar) { if (pathName.charAt(0) == File.separatorChar) {
return new File(pathName); return new File(pathName);
} }

View File

@ -1,5 +1,6 @@
/* /*
* Copyright 2017 Longri * Copyright 2017 Longri
* Copyright 2017 devemux86
* *
* This program is free software: you can redistribute it and/or modify it under the * This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software * terms of the GNU Lesser General Public License as published by the Free Software
@ -20,42 +21,36 @@ import org.oscim.backend.XMLReaderAdapter;
import org.oscim.backend.canvas.Bitmap; import org.oscim.backend.canvas.Bitmap;
import org.oscim.renderer.atlas.TextureAtlas; import org.oscim.renderer.atlas.TextureAtlas;
import org.oscim.renderer.atlas.TextureRegion; import org.oscim.renderer.atlas.TextureRegion;
import org.oscim.theme.IRenderTheme.ThemeException;
import org.oscim.theme.rule.Rule; import org.oscim.theme.rule.Rule;
import org.oscim.theme.styles.RenderStyle; import org.oscim.theme.styles.RenderStyle;
import org.oscim.theme.styles.SymbolStyle; import org.oscim.theme.styles.SymbolStyle;
import org.oscim.theme.styles.SymbolStyle.SymbolBuilder;
import org.oscim.utils.TextureAtlasUtils; import org.oscim.utils.TextureAtlasUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
public class XmlAtlasThemeBuilder extends XmlThemeBuilder { public class XmlAtlasThemeBuilder extends XmlThemeBuilder {
private static final Logger log = LoggerFactory.getLogger(XmlAtlasThemeBuilder.class); /**
* @param theme an input theme containing valid render theme XML data.
private final Map<Object, Bitmap> bitmapMap = new HashMap<>(); * @return a new RenderTheme which is created by parsing the XML data from the input theme.
private final Map<Object, TextureRegion> outputMap; * @throws ThemeException if an error occurs while parsing the render theme XML.
private final List<TextureAtlas> atlasList; */
public static IRenderTheme read(ThemeFile theme) throws ThemeException {
public XmlAtlasThemeBuilder(ThemeFile theme, ThemeCallback themeCallback, return read(theme, null);
Map<Object, TextureRegion> outputMap, List<TextureAtlas> atlasList) {
super(theme, themeCallback);
this.outputMap = outputMap;
this.atlasList = atlasList;
} }
/** /**
* @param theme an input theme containing valid render theme XML data. * @param theme an input theme containing valid render theme XML data.
* @param themeCallback the theme callback. * @param themeCallback the theme callback.
* @return a new RenderTheme which is created by parsing the XML data from the input theme. * @return a new RenderTheme which is created by parsing the XML data from the input theme.
* @throws IRenderTheme.ThemeException if an error occurs while parsing the render theme XML. * @throws ThemeException if an error occurs while parsing the render theme XML.
*/ */
public static IRenderTheme read(ThemeFile theme, ThemeCallback themeCallback) throws IRenderTheme.ThemeException { public static IRenderTheme read(ThemeFile theme, ThemeCallback themeCallback) throws ThemeException {
Map<Object, TextureRegion> outputMap = new HashMap<>(); Map<Object, TextureRegion> outputMap = new HashMap<>();
List<TextureAtlas> atlasList = new ArrayList<>(); List<TextureAtlas> atlasList = new ArrayList<>();
XmlAtlasThemeBuilder renderThemeHandler = new XmlAtlasThemeBuilder(theme, themeCallback, outputMap, atlasList); XmlAtlasThemeBuilder renderThemeHandler = new XmlAtlasThemeBuilder(theme, themeCallback, outputMap, atlasList);
@ -63,108 +58,69 @@ public class XmlAtlasThemeBuilder extends XmlThemeBuilder {
try { try {
new XMLReaderAdapter().parse(renderThemeHandler, theme.getRenderThemeAsStream()); new XMLReaderAdapter().parse(renderThemeHandler, theme.getRenderThemeAsStream());
} catch (Exception e) { } catch (Exception e) {
throw new IRenderTheme.ThemeException(e.getMessage()); throw new ThemeException(e.getMessage());
} }
TextureAtlasUtils.createTextureRegions(renderThemeHandler.bitmapMap, outputMap, atlasList, TextureAtlasUtils.createTextureRegions(renderThemeHandler.bitmapMap, outputMap, atlasList,
true, CanvasAdapter.platform == Platform.IOS); true, CanvasAdapter.platform == Platform.IOS);
return replaceSymbolStylesOnTheme(outputMap, renderThemeHandler.mRenderTheme); return replaceThemeSymbols(renderThemeHandler.mRenderTheme, outputMap);
} }
private static IRenderTheme replaceSymbolStylesOnTheme(Map<Object, TextureRegion> regionMap, RenderTheme theme) { private static IRenderTheme replaceThemeSymbols(RenderTheme renderTheme, Map<Object, TextureRegion> regionMap) {
SymbolStyle.SymbolBuilder<?> symbolBuilder = new SymbolStyle.SymbolBuilder(); SymbolBuilder<?> symbolBuilder = SymbolStyle.builder();
Rule[] rules = theme.getRules(); for (Rule rule : renderTheme.getRules()) {
for (Rule rule : rules) { replaceRuleSymbols(rule, regionMap, symbolBuilder);
replaceSymbolStylesOnRules(regionMap, symbolBuilder, rule);
} }
return theme; return renderTheme;
} }
private static void replaceSymbolStylesOnRules(Map<Object, TextureRegion> regionMap, private static void replaceRuleSymbols(Rule rule, Map<Object, TextureRegion> regionMap, SymbolBuilder<?> symbolBuilder) {
SymbolStyle.SymbolBuilder<?> symbolBuilder, Rule rule) {
for (int i = 0, n = rule.styles.length; i < n; i++) { for (int i = 0, n = rule.styles.length; i < n; i++) {
RenderStyle style = rule.styles[i]; RenderStyle style = rule.styles[i];
if (style instanceof SymbolStyle) { if (style instanceof SymbolStyle) {
String sourceName = ((SymbolStyle) style).sourceName; int hash = ((SymbolStyle) style).hash;
TextureRegion region = regionMap.get(hash);
TextureRegion region = regionMap.get(sourceName);
if (region != null) { if (region != null) {
symbolBuilder = symbolBuilder.reset(); SymbolBuilder<?> b = symbolBuilder.reset();
rule.styles[i] = symbolBuilder.texture(region).build(); rule.styles[i] = b.texture(region).build();
} }
} }
} }
for (Rule subRule : rule.subRules) { for (Rule subRule : rule.subRules) {
replaceSymbolStylesOnRules(regionMap, symbolBuilder, subRule); replaceRuleSymbols(subRule, regionMap, symbolBuilder);
} }
} }
/** private final Map<Object, TextureRegion> regionMap;
* @return a new Symbol with the given rendering attributes. private final List<TextureAtlas> atlasList;
*/
protected SymbolStyle createSymbol(String elementName, Attributes attributes) {
SymbolStyle.SymbolBuilder<?> b = mSymbolBuilder.reset();
String src = null;
for (int i = 0; i < attributes.getLength(); i++) { private final Map<Object, Bitmap> bitmapMap = new HashMap<>();
String name = attributes.getLocalName(i);
String value = attributes.getValue(i);
if ("src".equals(name)) public XmlAtlasThemeBuilder(ThemeFile theme,
src = value; Map<Object, TextureRegion> regionMap, List<TextureAtlas> atlasList) {
this(theme, null, regionMap, atlasList);
}
else if ("cat".equals(name)) public XmlAtlasThemeBuilder(ThemeFile theme, ThemeCallback themeCallback,
b.cat(value); Map<Object, TextureRegion> regionMap, List<TextureAtlas> atlasList) {
super(theme, themeCallback);
else if ("symbol-width".equals(name)) this.regionMap = regionMap;
b.symbolWidth = (int) (Integer.parseInt(value) * mScale); this.atlasList = atlasList;
else if ("symbol-height".equals(name))
b.symbolHeight = (int) (Integer.parseInt(value) * mScale);
else if ("symbol-percent".equals(name))
b.symbolPercent = Integer.parseInt(value);
else
logUnknownAttribute(elementName, name, value, i);
}
validateExists("src", src, elementName);
String lowSrc = src.toLowerCase(Locale.ENGLISH);
if (lowSrc.endsWith(".png") || lowSrc.endsWith(".svg")) {
try {
Bitmap bitmap = CanvasAdapter.getBitmapAsset(mTheme.getRelativePathPrefix(), src, b.symbolWidth, b.symbolHeight, b.symbolPercent);
if (bitmap != null) {
//create a property depends name! (needed if the same image used with different sizes)
String sourceName = lowSrc + b.symbolWidth + "/" + b.symbolHeight + "/" + b.symbolPercent;
bitmapMap.put(sourceName, bitmap);
return b.sourceName(sourceName).build();
}
} catch (Exception e) {
log.debug(e.getMessage());
}
return null;
}
return b.texture(getAtlasRegion(src)).build();
} }
@Override @Override
public void endDocument() { RenderTheme createTheme(Rule[] rules) {
Rule[] rules = new Rule[mRulesList.size()]; return new AtlasRenderTheme(mMapBackground, mTextScale, rules, mLevels, regionMap, atlasList);
for (int i = 0, n = rules.length; i < n; i++) }
rules[i] = mRulesList.get(i).onComplete(null);
mRenderTheme = new AtlasRenderTheme(mMapBackground, mTextScale, rules, mLevels, this.outputMap, this.atlasList); @Override
SymbolStyle buildSymbol(SymbolBuilder<?> b, String src, Bitmap bitmap) {
mRulesList.clear(); // we need to hash with the width/height included as the same symbol could be required
mStyles.clear(); // in a different size and must be cached with a size-specific hash
mRuleStack.clear(); String absoluteName = CanvasAdapter.getAbsoluteFile(mTheme.getRelativePathPrefix(), src).getAbsolutePath();
mElementStack.clear(); int hash = new StringBuilder().append(absoluteName).append(b.symbolWidth).append(b.symbolHeight).append(b.symbolPercent).toString().hashCode();
bitmapMap.put(hash, bitmap);
mTextureAtlas = null; return b.hash(hash).build();
} }
} }

View File

@ -120,16 +120,16 @@ public class XmlThemeBuilder extends DefaultHandler {
* @param value the XML attribute value. * @param value the XML attribute value.
* @param attributeIndex the XML attribute index position. * @param attributeIndex the XML attribute index position.
*/ */
static void logUnknownAttribute(String element, String name, private static void logUnknownAttribute(String element, String name,
String value, int attributeIndex) { String value, int attributeIndex) {
log.debug("unknown attribute in element {} () : {} = {}", log.debug("unknown attribute in element {} () : {} = {}",
element, attributeIndex, name, value); element, attributeIndex, name, value);
} }
final ArrayList<RuleBuilder> mRulesList = new ArrayList<>(); private final ArrayList<RuleBuilder> mRulesList = new ArrayList<>();
final Stack<Element> mElementStack = new Stack<>(); private final Stack<Element> mElementStack = new Stack<>();
final Stack<RuleBuilder> mRuleStack = new Stack<>(); private final Stack<RuleBuilder> mRuleStack = new Stack<>();
final HashMap<String, RenderStyle> mStyles = new HashMap<>(10); private final HashMap<String, RenderStyle> mStyles = new HashMap<>(10);
private final HashMap<String, TextStyle.TextBuilder<?>> mTextStyles = new HashMap<>(10); private final HashMap<String, TextStyle.TextBuilder<?>> mTextStyles = new HashMap<>(10);
@ -137,11 +137,11 @@ public class XmlThemeBuilder extends DefaultHandler {
private final CircleBuilder<?> mCircleBuilder = CircleStyle.builder(); private final CircleBuilder<?> mCircleBuilder = CircleStyle.builder();
private final ExtrusionBuilder<?> mExtrusionBuilder = ExtrusionStyle.builder(); private final ExtrusionBuilder<?> mExtrusionBuilder = ExtrusionStyle.builder();
private final LineBuilder<?> mLineBuilder = LineStyle.builder(); private final LineBuilder<?> mLineBuilder = LineStyle.builder();
final SymbolBuilder<?> mSymbolBuilder = SymbolStyle.builder(); private final SymbolBuilder<?> mSymbolBuilder = SymbolStyle.builder();
private final TextBuilder<?> mTextBuilder = TextStyle.builder(); private final TextBuilder<?> mTextBuilder = TextStyle.builder();
private RuleBuilder mCurrentRule; private RuleBuilder mCurrentRule;
TextureAtlas mTextureAtlas; private TextureAtlas mTextureAtlas;
int mLevels = 0; int mLevels = 0;
int mMapBackground = 0xffffffff; int mMapBackground = 0xffffffff;
@ -151,8 +151,7 @@ public class XmlThemeBuilder extends DefaultHandler {
private final ThemeCallback mThemeCallback; private final ThemeCallback mThemeCallback;
RenderTheme mRenderTheme; RenderTheme mRenderTheme;
final float mScale; private final float mScale, mScale2;
private final float mScale2;
private Set<String> mCategories; private Set<String> mCategories;
private XmlRenderThemeStyleLayer mCurrentLayer; private XmlRenderThemeStyleLayer mCurrentLayer;
@ -171,12 +170,11 @@ public class XmlThemeBuilder extends DefaultHandler {
@Override @Override
public void endDocument() { public void endDocument() {
Rule[] rules = new Rule[mRulesList.size()]; Rule[] rules = new Rule[mRulesList.size()];
for (int i = 0, n = rules.length; i < n; i++) for (int i = 0, n = rules.length; i < n; i++)
rules[i] = mRulesList.get(i).onComplete(null); rules[i] = mRulesList.get(i).onComplete(null);
mRenderTheme = new RenderTheme(mMapBackground, mTextScale, rules, mLevels); mRenderTheme = createTheme(rules);
mRulesList.clear(); mRulesList.clear();
mStyles.clear(); mStyles.clear();
@ -186,6 +184,10 @@ public class XmlThemeBuilder extends DefaultHandler {
mTextureAtlas = null; mTextureAtlas = null;
} }
RenderTheme createTheme(Rule[] rules) {
return new RenderTheme(mMapBackground, mTextScale, rules, mLevels);
}
@Override @Override
public void endElement(String uri, String localName, String qName) { public void endElement(String uri, String localName, String qName) {
mElementStack.pop(); mElementStack.pop();
@ -425,7 +427,7 @@ public class XmlThemeBuilder extends DefaultHandler {
return b; return b;
} }
TextureRegion getAtlasRegion(String src) { private TextureRegion getAtlasRegion(String src) {
if (mTextureAtlas == null) if (mTextureAtlas == null)
return null; return null;
@ -1008,7 +1010,7 @@ public class XmlThemeBuilder extends DefaultHandler {
/** /**
* @return a new Symbol with the given rendering attributes. * @return a new Symbol with the given rendering attributes.
*/ */
SymbolStyle createSymbol(String elementName, Attributes attributes) { private SymbolStyle createSymbol(String elementName, Attributes attributes) {
SymbolBuilder<?> b = mSymbolBuilder.reset(); SymbolBuilder<?> b = mSymbolBuilder.reset();
String src = null; String src = null;
@ -1042,7 +1044,7 @@ public class XmlThemeBuilder extends DefaultHandler {
try { try {
Bitmap bitmap = CanvasAdapter.getBitmapAsset(mTheme.getRelativePathPrefix(), src, b.symbolWidth, b.symbolHeight, b.symbolPercent); Bitmap bitmap = CanvasAdapter.getBitmapAsset(mTheme.getRelativePathPrefix(), src, b.symbolWidth, b.symbolHeight, b.symbolPercent);
if (bitmap != null) if (bitmap != null)
return b.bitmap(bitmap).build(); return buildSymbol(b, src, bitmap);
} catch (Exception e) { } catch (Exception e) {
log.debug(e.getMessage()); log.debug(e.getMessage());
} }
@ -1051,6 +1053,10 @@ public class XmlThemeBuilder extends DefaultHandler {
return b.texture(getAtlasRegion(src)).build(); return b.texture(getAtlasRegion(src)).build();
} }
SymbolStyle buildSymbol(SymbolBuilder<?> b, String src, Bitmap bitmap) {
return b.bitmap(bitmap).build();
}
private ExtrusionStyle createExtrusion(String elementName, Attributes attributes, int level) { private ExtrusionStyle createExtrusion(String elementName, Attributes attributes, int level) {
ExtrusionBuilder<?> b = mExtrusionBuilder.reset(); ExtrusionBuilder<?> b = mExtrusionBuilder.reset();
b.level(level); b.level(level);
@ -1113,7 +1119,7 @@ public class XmlThemeBuilder extends DefaultHandler {
+ value); + value);
} }
static void validateExists(String name, Object obj, String elementName) { private static void validateExists(String name, Object obj, String elementName) {
if (obj == null) if (obj == null)
throw new ThemeException("missing attribute " + name throw new ThemeException("missing attribute " + name
+ " for element: " + elementName); + " for element: " + elementName);

View File

@ -1,7 +1,7 @@
/* /*
* Copyright 2010, 2011, 2012 mapsforge.org * Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2013 Hannes Janetzek * Copyright 2013 Hannes Janetzek
* Copyright 2016 devemux86 * Copyright 2016-2017 devemux86
* Copyright 2017 Longri * Copyright 2017 Longri
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
@ -27,38 +27,30 @@ import org.oscim.renderer.atlas.TextureRegion;
*/ */
public final class SymbolStyle extends RenderStyle<SymbolStyle> { public final class SymbolStyle extends RenderStyle<SymbolStyle> {
public final String sourceName;
public final Bitmap bitmap; public final Bitmap bitmap;
public final TextureRegion texture; public final TextureRegion texture;
public final int hash;
public final int symbolWidth; public final int symbolWidth;
public final int symbolHeight; public final int symbolHeight;
public final int symbolPercent; public final int symbolPercent;
public SymbolStyle(Bitmap bitmap) { public SymbolStyle(Bitmap bitmap) {
this.sourceName = null; this(bitmap, null, 0);
this.bitmap = bitmap;
this.texture = null;
this.symbolWidth = 0;
this.symbolHeight = 0;
this.symbolPercent = 100;
} }
public SymbolStyle(TextureRegion texture) { public SymbolStyle(TextureRegion texture) {
this.sourceName = null; this(null, texture, 0);
this.bitmap = null;
this.texture = texture;
this.symbolWidth = 0;
this.symbolHeight = 0;
this.symbolPercent = 100;
} }
public SymbolStyle(String sourceName) { public SymbolStyle(int hash) {
this.sourceName = sourceName; this(null, null, hash);
this.bitmap = null; }
this.texture = null;
private SymbolStyle(Bitmap bitmap, TextureRegion texture, int hash) {
this.bitmap = bitmap;
this.texture = texture;
this.hash = hash;
this.symbolWidth = 0; this.symbolWidth = 0;
this.symbolHeight = 0; this.symbolHeight = 0;
@ -66,9 +58,9 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
} }
public SymbolStyle(SymbolBuilder<?> b) { public SymbolStyle(SymbolBuilder<?> b) {
this.sourceName = b.sourceName;
this.bitmap = b.bitmap; this.bitmap = b.bitmap;
this.texture = b.texture; this.texture = b.texture;
this.hash = b.hash;
this.symbolWidth = b.symbolWidth; this.symbolWidth = b.symbolWidth;
this.symbolHeight = b.symbolHeight; this.symbolHeight = b.symbolHeight;
@ -98,9 +90,9 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
public static class SymbolBuilder<T extends SymbolBuilder<T>> extends StyleBuilder<T> { public static class SymbolBuilder<T extends SymbolBuilder<T>> extends StyleBuilder<T> {
public String sourceName;
public Bitmap bitmap; public Bitmap bitmap;
public TextureRegion texture; public TextureRegion texture;
public int hash;
public int symbolWidth; public int symbolWidth;
public int symbolHeight; public int symbolHeight;
@ -115,6 +107,7 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
this.bitmap = symbol.bitmap; this.bitmap = symbol.bitmap;
this.texture = symbol.texture; this.texture = symbol.texture;
this.hash = symbol.hash;
this.symbolWidth = symbol.symbolWidth; this.symbolWidth = symbol.symbolWidth;
this.symbolHeight = symbol.symbolHeight; this.symbolHeight = symbol.symbolHeight;
@ -133,8 +126,8 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
return self(); return self();
} }
public T sourceName(String sourceName) { public T hash(int hash) {
this.sourceName = sourceName; this.hash = hash;
return self(); return self();
} }
@ -156,7 +149,7 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
public T reset() { public T reset() {
bitmap = null; bitmap = null;
texture = null; texture = null;
sourceName = null; hash = 0;
symbolWidth = 0; symbolWidth = 0;
symbolHeight = 0; symbolHeight = 0;