Render themes: tag transform (#587)
This commit is contained in:
parent
7c2d2d3759
commit
61318bff8a
@ -301,11 +301,24 @@
|
||||
<xs:attribute name="id" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<!-- tag-transform element -->
|
||||
<xs:complexType name="tag-transform">
|
||||
<xs:attribute name="k" type="xs:string" use="required" />
|
||||
<xs:attribute name="v" type="xs:string" use="optional" />
|
||||
<xs:attribute name="k-match" type="xs:string" use="required" />
|
||||
<xs:attribute name="v-match" type="xs:string" use="optional" />
|
||||
</xs:complexType>
|
||||
|
||||
<!-- rendertheme element -->
|
||||
<xs:complexType name="rendertheme">
|
||||
<xs:sequence maxOccurs="1" minOccurs="0">
|
||||
<xs:element name="stylemenu" maxOccurs="1" minOccurs="0" type="tns:stylemenu" />
|
||||
|
||||
<!-- tag definitions -->
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:element name="tag-transform" type="tns:tag-transform" />
|
||||
</xs:choice>
|
||||
|
||||
<!-- style definitions -->
|
||||
<xs:sequence maxOccurs="256" minOccurs="0">
|
||||
<xs:choice maxOccurs="unbounded" minOccurs="0">
|
||||
|
@ -251,6 +251,20 @@ public class RenderTheme implements IRenderTheme {
|
||||
public void scaleTextSize(float scaleFactor) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transformKey(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag transformTag(Tag tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStyles() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
RenderTheme t = new RenderTheme();
|
||||
|
||||
@ -261,11 +275,4 @@ public class RenderTheme implements IRenderTheme {
|
||||
t.matchElement(GeometryType.POLY, e.tags, 16);
|
||||
t.matchElement(GeometryType.POLY, e.tags, 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStyles() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package org.oscim.test;
|
||||
|
||||
import org.oscim.backend.canvas.Color;
|
||||
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||
import org.oscim.core.Tag;
|
||||
import org.oscim.core.TagSet;
|
||||
import org.oscim.theme.IRenderTheme;
|
||||
import org.oscim.theme.styles.AreaStyle;
|
||||
@ -46,6 +47,16 @@ public class DebugTheme implements IRenderTheme {
|
||||
public void scaleTextSize(float scaleFactor) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transformKey(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag transformTag(Tag tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStyles() {
|
||||
}
|
||||
|
@ -3,6 +3,17 @@
|
||||
version="1" xmlns="http://opensciencemap.org/rendertheme"
|
||||
xsi:schemaLocation="http://opensciencemap.org/rendertheme https://raw.githubusercontent.com/mapsforge/vtm/master/resources/rendertheme.xsd">
|
||||
|
||||
<!--<tag-transform k="kind" v="building" k-match="building" v-match="yes" />-->
|
||||
<!--<tag-transform k="kind" v="building_part" k-match="building:part" v-match="yes" />-->
|
||||
<tag-transform k="root_id" k-match="ref" />
|
||||
|
||||
<tag-transform k="roof_color" k-match="roof:colour" />
|
||||
<tag-transform k="roof_direction" k-match="roof:direction" />
|
||||
<tag-transform k="roof_height" k-match="roof:height" />
|
||||
<tag-transform k="roof_material" k-match="roof:material" />
|
||||
<tag-transform k="roof_orientation" k-match="roof:orientation" />
|
||||
<tag-transform k="roof_shape" k-match="roof:shape" />
|
||||
|
||||
<!-- base style for fixed width lines -->
|
||||
<style-line cap="butt" fix="true" id="fix" width="1.0" />
|
||||
|
||||
|
@ -3,6 +3,11 @@
|
||||
version="1" xmlns="http://opensciencemap.org/rendertheme"
|
||||
xsi:schemaLocation="http://opensciencemap.org/rendertheme https://raw.githubusercontent.com/mapsforge/vtm/master/resources/rendertheme.xsd">
|
||||
|
||||
<tag-transform k="render_height" k-match="height" />
|
||||
<tag-transform k="render_min_height" k-match="min_height" />
|
||||
<!--<tag-transform k="layer" v="building" k-match="building" v-match="yes" />-->
|
||||
<!--<tag-transform k="layer" v="building:part" k-match="building:part" v-match="yes" />-->
|
||||
|
||||
<!--###### TEXT styles ######-->
|
||||
|
||||
<!--default label-->
|
||||
|
@ -19,6 +19,8 @@
|
||||
*/
|
||||
package org.oscim.core;
|
||||
|
||||
import org.oscim.theme.IRenderTheme;
|
||||
|
||||
/**
|
||||
* The MapElement class is a reusable container for a geometry
|
||||
* with tags.
|
||||
@ -63,10 +65,9 @@ public class MapElement extends GeometryBuffer {
|
||||
/**
|
||||
* @return height in meters, if present
|
||||
*/
|
||||
public Float getHeight() {
|
||||
String v = tags.getValue(Tag.KEY_HEIGHT);
|
||||
if (v == null)
|
||||
v = tags.getValue("render_height"); // OpenMapTiles
|
||||
public Float getHeight(IRenderTheme theme) {
|
||||
String res = theme.transformKey(Tag.KEY_HEIGHT);
|
||||
String v = tags.getValue(res != null ? res : Tag.KEY_HEIGHT);
|
||||
if (v != null)
|
||||
return Float.parseFloat(v);
|
||||
return null;
|
||||
@ -75,22 +76,21 @@ public class MapElement extends GeometryBuffer {
|
||||
/**
|
||||
* @return minimum height in meters, if present
|
||||
*/
|
||||
public Float getMinHeight() {
|
||||
String v = tags.getValue(Tag.KEY_MIN_HEIGHT);
|
||||
if (v == null)
|
||||
v = tags.getValue("render_min_height"); // OpenMapTiles
|
||||
public Float getMinHeight(IRenderTheme theme) {
|
||||
String res = theme.transformKey(Tag.KEY_MIN_HEIGHT);
|
||||
String v = tags.getValue(res != null ? res : Tag.KEY_MIN_HEIGHT);
|
||||
if (v != null)
|
||||
return Float.parseFloat(v);
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isBuilding() {
|
||||
public boolean isBuilding() { // TODO from themes (with overzoom ref)
|
||||
return tags.containsKey(Tag.KEY_BUILDING)
|
||||
|| "building".equals(tags.getValue("kind")) // Mapzen
|
||||
|| "building".equals(tags.getValue("layer")); // OpenMapTiles
|
||||
}
|
||||
|
||||
public boolean isBuildingPart() {
|
||||
public boolean isBuildingPart() { // TODO from themes (with overzoom ref)
|
||||
return tags.containsKey(Tag.KEY_BUILDING_PART)
|
||||
|| "building_part".equals(tags.getValue("kind")) // Mapzen
|
||||
|| "building:part".equals(tags.getValue("layer")); // OpenMapTiles
|
||||
|
@ -65,9 +65,9 @@ public class Tag {
|
||||
public static final String KEY_BUILDING_MATERIAL = "building:material";
|
||||
public static final String KEY_BUILDING_MIN_LEVEL = "building:min_level";
|
||||
public static final String KEY_BUILDING_PART = "building:part";
|
||||
public static final String KEY_COLOR = "colour";
|
||||
//public static final String KEY_COLOR = "colour";
|
||||
public static final String KEY_HEIGHT = "height";
|
||||
public static final String KEY_MATERIAL = "material";
|
||||
//public static final String KEY_MATERIAL = "material";
|
||||
public static final String KEY_MIN_HEIGHT = "min_height";
|
||||
public static final String KEY_ROOF = "roof";
|
||||
public static final String KEY_ROOF_ANGLE = "roof:angle";
|
||||
|
@ -31,6 +31,7 @@ import org.oscim.renderer.OffscreenRenderer;
|
||||
import org.oscim.renderer.OffscreenRenderer.Mode;
|
||||
import org.oscim.renderer.bucket.ExtrusionBuckets;
|
||||
import org.oscim.renderer.bucket.RenderBuckets;
|
||||
import org.oscim.theme.IRenderTheme;
|
||||
import org.oscim.theme.styles.ExtrusionStyle;
|
||||
import org.oscim.theme.styles.RenderStyle;
|
||||
|
||||
@ -66,6 +67,8 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
||||
|
||||
private final ZoomLimiter mZoomLimiter;
|
||||
|
||||
protected final IRenderTheme mRenderTheme;
|
||||
|
||||
class BuildingElement {
|
||||
MapElement element;
|
||||
ExtrusionStyle style;
|
||||
@ -103,6 +106,8 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
||||
mRenderer = new BuildingRenderer(tileLayer.tileRenderer(), mZoomLimiter, mesh, TRANSLUCENT);
|
||||
if (POST_AA)
|
||||
mRenderer = new OffscreenRenderer(Mode.SSAO_FXAA, mRenderer);
|
||||
|
||||
mRenderTheme = tileLayer.getTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -160,22 +165,22 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
||||
int height = 0; // cm
|
||||
int minHeight = 0; // cm
|
||||
|
||||
Float f = element.getHeight();
|
||||
Float f = element.getHeight(mRenderTheme);
|
||||
if (f != null)
|
||||
height = (int) (f * 100);
|
||||
else {
|
||||
// #TagFromTheme: generalize level/height tags
|
||||
String v = element.tags.getValue(Tag.KEY_BUILDING_LEVELS);
|
||||
String v = getValue(element, Tag.KEY_BUILDING_LEVELS);
|
||||
if (v != null)
|
||||
height = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||
}
|
||||
|
||||
f = element.getMinHeight();
|
||||
f = element.getMinHeight(mRenderTheme);
|
||||
if (f != null)
|
||||
minHeight = (int) (f * 100);
|
||||
else {
|
||||
// #TagFromTheme: level/height tags
|
||||
String v = element.tags.getValue(Tag.KEY_BUILDING_MIN_LEVEL);
|
||||
String v = getValue(element, Tag.KEY_BUILDING_MIN_LEVEL);
|
||||
if (v != null)
|
||||
minHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||
}
|
||||
@ -202,15 +207,14 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
||||
if (!partBuilding.element.isBuildingPart())
|
||||
continue;
|
||||
|
||||
String refId = partBuilding.element.tags.getValue(Tag.KEY_REF); // #TagFromTheme
|
||||
refId = refId == null ? partBuilding.element.tags.getValue("root_id") : refId; // Mapzen
|
||||
String refId = getValue(partBuilding.element, Tag.KEY_REF);
|
||||
if (refId == null)
|
||||
continue;
|
||||
|
||||
// Search buildings which inherit parts
|
||||
for (BuildingElement rootBuilding : tileBuildings) {
|
||||
if (rootBuilding.element.isBuildingPart()
|
||||
|| !(refId.equals(rootBuilding.element.tags.getValue(Tag.KEY_ID))))
|
||||
|| !(refId.equals(getValue(rootBuilding.element, Tag.KEY_ID))))
|
||||
continue;
|
||||
|
||||
rootBuildings.add(rootBuilding);
|
||||
@ -239,6 +243,15 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
||||
return ebs;
|
||||
}
|
||||
|
||||
protected String getKeyOrDefault(String key) {
|
||||
String res = mRenderTheme.transformKey(key);
|
||||
return res != null ? res : key;
|
||||
}
|
||||
|
||||
protected String getValue(MapElement element, String key) {
|
||||
return element.tags.getValue(getKeyOrDefault(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(MapTile tile, boolean success) {
|
||||
if (success) {
|
||||
|
@ -101,12 +101,12 @@ public class S3DBLayer extends BuildingLayer {
|
||||
int roofHeight = 0;
|
||||
|
||||
// Get roof height
|
||||
String v = element.tags.getValue(Tag.KEY_ROOF_HEIGHT);
|
||||
String v = getValue(element, Tag.KEY_ROOF_HEIGHT);
|
||||
if (v != null) {
|
||||
roofHeight = (int) (Float.parseFloat(v) * 100);
|
||||
} else if ((v = element.tags.getValue(Tag.KEY_ROOF_LEVELS)) != null) {
|
||||
} else if ((v = getValue(element, Tag.KEY_ROOF_LEVELS)) != null) {
|
||||
roofHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||
} else if ((v = element.tags.getValue(Tag.KEY_ROOF_ANGLE)) != null) {
|
||||
} else if ((v = getValue(element, Tag.KEY_ROOF_ANGLE)) != null) {
|
||||
Box bb = null;
|
||||
for (int k = 0; k < element.index[0]; k += 2) {
|
||||
float p1 = element.points[k];
|
||||
@ -122,17 +122,17 @@ public class S3DBLayer extends BuildingLayer {
|
||||
// Angle is simplified, 40 is an estimated constant
|
||||
roofHeight = (int) ((Float.parseFloat(v) / 45.f) * (minSize * 40));
|
||||
}
|
||||
} else if ((v = element.tags.getValue(Tag.KEY_ROOF_SHAPE)) != null && !v.equals(Tag.VALUE_FLAT)) {
|
||||
} else if ((v = getValue(element, Tag.KEY_ROOF_SHAPE)) != null && !v.equals(Tag.VALUE_FLAT)) {
|
||||
roofHeight = (2 * BUILDING_LEVEL_HEIGHT);
|
||||
}
|
||||
|
||||
// Get building height
|
||||
v = element.tags.getValue(Tag.KEY_HEIGHT);
|
||||
v = getValue(element, Tag.KEY_HEIGHT);
|
||||
if (v != null) {
|
||||
maxHeight = (int) (Float.parseFloat(v) * 100);
|
||||
} else {
|
||||
// #TagFromTheme: generalize level/height tags
|
||||
if ((v = element.tags.getValue(Tag.KEY_BUILDING_LEVELS)) != null) {
|
||||
if ((v = getValue(element, Tag.KEY_BUILDING_LEVELS)) != null) {
|
||||
maxHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||
maxHeight += roofHeight;
|
||||
}
|
||||
@ -140,22 +140,22 @@ public class S3DBLayer extends BuildingLayer {
|
||||
if (maxHeight == 0)
|
||||
maxHeight = extrusion.defaultHeight * 100;
|
||||
|
||||
v = element.tags.getValue(Tag.KEY_MIN_HEIGHT);
|
||||
v = getValue(element, Tag.KEY_MIN_HEIGHT);
|
||||
if (v != null)
|
||||
minHeight = (int) (Float.parseFloat(v) * 100);
|
||||
else {
|
||||
// #TagFromTheme: level/height tags
|
||||
if ((v = element.tags.getValue(Tag.KEY_BUILDING_MIN_LEVEL)) != null)
|
||||
if ((v = getValue(element, Tag.KEY_BUILDING_MIN_LEVEL)) != null)
|
||||
minHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||
}
|
||||
|
||||
// Get building color
|
||||
Integer bColor = null;
|
||||
if (mColored) {
|
||||
if (element.tags.containsKey(Tag.KEY_BUILDING_COLOR)) {
|
||||
bColor = S3DBUtils.getColor(element.tags.getValue(Tag.KEY_BUILDING_COLOR), false, false);
|
||||
} else if (element.tags.containsKey(Tag.KEY_BUILDING_MATERIAL)) {
|
||||
bColor = S3DBUtils.getMaterialColor(element.tags.getValue(Tag.KEY_BUILDING_MATERIAL), false);
|
||||
if ((v = getValue(element, Tag.KEY_BUILDING_COLOR)) != null) {
|
||||
bColor = S3DBUtils.getColor(v, false, false);
|
||||
} else if ((v = getValue(element, Tag.KEY_BUILDING_MATERIAL)) != null) {
|
||||
bColor = S3DBUtils.getMaterialColor(v, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,25 +190,32 @@ public class S3DBLayer extends BuildingLayer {
|
||||
if (!partBuilding.element.isBuildingPart())
|
||||
continue;
|
||||
|
||||
TagSet partTags = partBuilding.element.tags;
|
||||
String refId = partTags.getValue(Tag.KEY_REF); // #TagFromTheme
|
||||
refId = refId == null ? partTags.getValue("root_id") : refId; // Mapzen
|
||||
String refId = getValue(partBuilding.element, Tag.KEY_REF);
|
||||
if (refId == null)
|
||||
continue;
|
||||
|
||||
TagSet partTags = partBuilding.element.tags;
|
||||
|
||||
// Search buildings which inherit parts
|
||||
for (BuildingElement rootBuilding : tileBuildings) {
|
||||
if (rootBuilding.element.isBuildingPart()
|
||||
|| !(refId.equals(rootBuilding.element.tags.getValue(Tag.KEY_ID))))
|
||||
continue;
|
||||
|
||||
if ((getValue(rootBuilding.element, Tag.KEY_ROOF_SHAPE) != null)
|
||||
&& (getValue(partBuilding.element, Tag.KEY_ROOF_SHAPE) == null)) {
|
||||
partBuilding.element.tags.add(rootBuilding.element.tags.get(getKeyOrDefault(Tag.KEY_ROOF_SHAPE)));
|
||||
}
|
||||
|
||||
if (mColored) {
|
||||
TagSet rootTags = rootBuilding.element.tags;
|
||||
|
||||
for (int i = 0; i < rootTags.size(); i++) {
|
||||
Tag rTag = rootTags.get(i);
|
||||
if ((rTag.key.equals(Tag.KEY_COLOR) && !partTags.containsKey(Tag.KEY_MATERIAL)
|
||||
|| rTag.key.equals(Tag.KEY_ROOF_COLOR) && !partTags.containsKey(Tag.KEY_ROOF_MATERIAL)
|
||||
|| rTag.key.equals(Tag.KEY_ROOF_SHAPE))
|
||||
if ((rTag.key.equals(getKeyOrDefault(Tag.KEY_BUILDING_COLOR))
|
||||
&& !partTags.containsKey(getKeyOrDefault(Tag.KEY_BUILDING_MATERIAL))
|
||||
|| rTag.key.equals(getKeyOrDefault(Tag.KEY_ROOF_COLOR))
|
||||
&& !partTags.containsKey(getKeyOrDefault(Tag.KEY_ROOF_MATERIAL)))
|
||||
&& !partTags.containsKey(rTag.key)) {
|
||||
partTags.add(rTag);
|
||||
}
|
||||
@ -243,22 +250,22 @@ public class S3DBLayer extends BuildingLayer {
|
||||
String v;
|
||||
|
||||
if (mColored) {
|
||||
v = element.tags.getValue(Tag.KEY_ROOF_COLOR);
|
||||
v = getValue(element, Tag.KEY_ROOF_COLOR);
|
||||
if (v != null)
|
||||
roofColor = S3DBUtils.getColor(v, true, false);
|
||||
else if ((v = element.tags.getValue(Tag.KEY_ROOF_MATERIAL)) != null)
|
||||
else if ((v = getValue(element, Tag.KEY_ROOF_MATERIAL)) != null)
|
||||
roofColor = S3DBUtils.getMaterialColor(v, true);
|
||||
}
|
||||
|
||||
boolean roofOrientationAcross = false;
|
||||
if ((v = element.tags.getValue(Tag.KEY_ROOF_ORIENTATION)) != null) {
|
||||
if ((v = getValue(element, Tag.KEY_ROOF_ORIENTATION)) != null) {
|
||||
if (v.equals(Tag.VALUE_ACROSS)) {
|
||||
roofOrientationAcross = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Calc roof shape
|
||||
v = element.tags.getValue(Tag.KEY_ROOF_SHAPE);
|
||||
v = getValue(element, Tag.KEY_ROOF_SHAPE);
|
||||
if (v == null) {
|
||||
v = Tag.VALUE_FLAT;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
* Copyright 2013 Hannes Janetzek
|
||||
* Copyright 2017 devemux86
|
||||
* Copyright 2018 Gustl22
|
||||
*
|
||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||
*
|
||||
@ -19,6 +20,7 @@
|
||||
package org.oscim.theme;
|
||||
|
||||
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||
import org.oscim.core.Tag;
|
||||
import org.oscim.core.TagSet;
|
||||
import org.oscim.theme.styles.RenderStyle;
|
||||
|
||||
@ -63,6 +65,16 @@ public interface IRenderTheme {
|
||||
*/
|
||||
void scaleTextSize(float scaleFactor);
|
||||
|
||||
/**
|
||||
* @return the transformed tag key of this RenderTheme.
|
||||
*/
|
||||
String transformKey(String key);
|
||||
|
||||
/**
|
||||
* @return the transformed tag of this RenderTheme.
|
||||
*/
|
||||
Tag transformTag(Tag tag);
|
||||
|
||||
class ThemeException extends IllegalArgumentException {
|
||||
public ThemeException(String string) {
|
||||
super(string);
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright 2014 Hannes Janetzek
|
||||
* Copyright 2017 Longri
|
||||
* Copyright 2017 devemux86
|
||||
* Copyright 2018 Gustl22
|
||||
*
|
||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||
*
|
||||
@ -19,6 +20,7 @@
|
||||
package org.oscim.theme;
|
||||
|
||||
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||
import org.oscim.core.Tag;
|
||||
import org.oscim.core.TagSet;
|
||||
import org.oscim.theme.rule.Rule;
|
||||
import org.oscim.theme.rule.Rule.Element;
|
||||
@ -31,6 +33,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RenderTheme implements IRenderTheme {
|
||||
static final Logger log = LoggerFactory.getLogger(RenderTheme.class);
|
||||
@ -44,6 +47,9 @@ public class RenderTheme implements IRenderTheme {
|
||||
private final Rule[] mRules;
|
||||
private final boolean mMapsforgeTheme;
|
||||
|
||||
private final Map<String, String> mTransformKeyMap;
|
||||
private final Map<Tag, Tag> mTransformTagMap;
|
||||
|
||||
class RenderStyleCache {
|
||||
final int matchType;
|
||||
final LRUCache<MatchingCacheKey, RenderStyleItem> cache;
|
||||
@ -79,7 +85,17 @@ public class RenderTheme implements IRenderTheme {
|
||||
this(mapBackground, baseTextSize, rules, levels, false);
|
||||
}
|
||||
|
||||
public RenderTheme(int mapBackground, float baseTextSize, Rule[] rules, int levels,
|
||||
Map<String, String> transformKeyMap, Map<Tag, Tag> transformTagMap) {
|
||||
this(mapBackground, baseTextSize, rules, levels, transformKeyMap, transformTagMap, false);
|
||||
}
|
||||
|
||||
public RenderTheme(int mapBackground, float baseTextSize, Rule[] rules, int levels, boolean mapsforgeTheme) {
|
||||
this(mapBackground, baseTextSize, rules, levels, null, null, mapsforgeTheme);
|
||||
}
|
||||
|
||||
public RenderTheme(int mapBackground, float baseTextSize, Rule[] rules, int levels,
|
||||
Map<String, String> transformKeyMap, Map<Tag, Tag> transformTagMap, boolean mapsforgeTheme) {
|
||||
if (rules == null)
|
||||
throw new IllegalArgumentException("rules missing");
|
||||
|
||||
@ -89,6 +105,9 @@ public class RenderTheme implements IRenderTheme {
|
||||
mRules = rules;
|
||||
mMapsforgeTheme = mapsforgeTheme;
|
||||
|
||||
mTransformKeyMap = transformKeyMap;
|
||||
mTransformTagMap = transformTagMap;
|
||||
|
||||
mStyleCache = new RenderStyleCache[3];
|
||||
mStyleCache[0] = new RenderStyleCache(Element.NODE);
|
||||
mStyleCache[1] = new RenderStyleCache(Element.LINE);
|
||||
@ -272,6 +291,20 @@ public class RenderTheme implements IRenderTheme {
|
||||
rule.scaleTextSize(scaleFactor * mBaseTextSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transformKey(String key) {
|
||||
if (mTransformKeyMap != null)
|
||||
return mTransformKeyMap.get(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag transformTag(Tag tag) {
|
||||
if (mTransformTagMap != null)
|
||||
return mTransformTagMap.get(tag);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStyles() {
|
||||
for (Rule rule : mRules)
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright 2016-2018 devemux86
|
||||
* Copyright 2016-2017 Longri
|
||||
* Copyright 2016 Andrey Novikov
|
||||
* Copyright 2018 Gustl22
|
||||
*
|
||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||
*
|
||||
@ -64,6 +65,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
@ -168,6 +170,9 @@ public class XmlThemeBuilder extends DefaultHandler {
|
||||
private XmlRenderThemeStyleLayer mCurrentLayer;
|
||||
private XmlRenderThemeStyleMenu mRenderThemeStyleMenu;
|
||||
|
||||
private Map<String, String> mTransformKeyMap = new HashMap<>();
|
||||
private Map<Tag, Tag> mTransformTagMap = new HashMap<>();
|
||||
|
||||
public XmlThemeBuilder(ThemeFile theme) {
|
||||
this(theme, null);
|
||||
}
|
||||
@ -202,7 +207,7 @@ public class XmlThemeBuilder extends DefaultHandler {
|
||||
}
|
||||
|
||||
RenderTheme createTheme(Rule[] rules) {
|
||||
return new RenderTheme(mMapBackground, mTextScale, rules, mLevels, mMapsforgeTheme);
|
||||
return new RenderTheme(mMapBackground, mTextScale, rules, mLevels, mTransformKeyMap, mTransformTagMap, mMapsforgeTheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -369,6 +374,10 @@ public class XmlThemeBuilder extends DefaultHandler {
|
||||
mRenderThemeStyleMenu = new XmlRenderThemeStyleMenu(getStringAttribute(attributes, "id"),
|
||||
getStringAttribute(attributes, "defaultlang"), getStringAttribute(attributes, "defaultvalue"));
|
||||
|
||||
} else if ("tag-transform".equals(localName)) {
|
||||
checkState(qName, Element.RENDERING_STYLE);
|
||||
tagTransform(localName, attributes);
|
||||
|
||||
} else {
|
||||
log.error("unknown element: {}", localName);
|
||||
throw new SAXException("unknown element: " + localName);
|
||||
@ -1239,6 +1248,44 @@ public class XmlThemeBuilder extends DefaultHandler {
|
||||
return dashIntervals;
|
||||
}
|
||||
|
||||
private void tagTransform(String localName, Attributes attributes) {
|
||||
String k, v, matchKey, matchValue;
|
||||
k = v = matchKey = matchValue = null;
|
||||
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
String name = attributes.getLocalName(i);
|
||||
String value = attributes.getValue(i);
|
||||
|
||||
switch (name) {
|
||||
case "k":
|
||||
k = value;
|
||||
break;
|
||||
case "v":
|
||||
v = value;
|
||||
break;
|
||||
case "k-match":
|
||||
matchKey = value;
|
||||
break;
|
||||
case "v-match":
|
||||
matchValue = value;
|
||||
break;
|
||||
default:
|
||||
logUnknownAttribute(localName, name, value, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (k == null || k.isEmpty() || matchKey == null || matchKey.isEmpty()) {
|
||||
log.debug("empty key in element " + localName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v == null && matchValue == null) {
|
||||
mTransformKeyMap.put(matchKey, k);
|
||||
} else {
|
||||
mTransformTagMap.put(new Tag(matchKey, matchValue), new Tag(k, v));
|
||||
}
|
||||
}
|
||||
|
||||
private static void validateNonNegative(String name, float value) {
|
||||
if (value < 0)
|
||||
throw new ThemeException(name + " must not be negative: "
|
||||
|
Loading…
x
Reference in New Issue
Block a user