Merge branch 'renderingAxes'
This commit is contained in:
commit
db0966450f
17 changed files with 3077 additions and 1504 deletions
|
@ -36,7 +36,6 @@ public class MapRenderingTypes {
|
|||
|
||||
private static final Log log = LogUtil.getLog(MapRenderingTypes.class);
|
||||
|
||||
// TODO Internet access bits for point, polygon
|
||||
/** standard schema :
|
||||
polygon : ll aaaaa ttttt 11 : 14 bits
|
||||
multi : ll aaaaa ttttt 00 : 14 bits
|
||||
|
@ -47,6 +46,7 @@ public class MapRenderingTypes {
|
|||
t - object type, s - subtype
|
||||
*/
|
||||
|
||||
// keep sync ! not change values
|
||||
public final static int MULTY_POLYGON_TYPE = 0;
|
||||
public final static int POLYGON_TYPE = 3;
|
||||
public final static int POLYLINE_TYPE = 2;
|
||||
|
|
|
@ -1,561 +0,0 @@
|
|||
package net.osmand.render;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import net.osmand.osm.MapRenderingTypes;
|
||||
import net.osmand.LogUtil;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
public class OsmandRenderingRulesParser {
|
||||
|
||||
|
||||
private final static Log log = LogUtil.getLog(OsmandRenderingRulesParser.class);
|
||||
|
||||
public static class EffectAttributes {
|
||||
public int color = 0;
|
||||
public float strokeWidth = 0;
|
||||
public String pathEffect = null;
|
||||
public int shadowColor = 0;
|
||||
public float shadowRadius = 0;
|
||||
public String cap = null;
|
||||
|
||||
}
|
||||
|
||||
public static class TextAttributes {
|
||||
public int textColor = 0;
|
||||
public int textOrder = 0;
|
||||
public float textSize = 0;
|
||||
public boolean textBold = false;
|
||||
public String textShield = null;
|
||||
public int textMinDistance = 0;
|
||||
public boolean textOnPath = false;
|
||||
public int textWrapWidth = 0;
|
||||
public float textHaloRadius = 0;
|
||||
public int textDy = 0;
|
||||
public String ref = null;
|
||||
}
|
||||
|
||||
protected static class SwitchState {
|
||||
List<FilterState> filters = new ArrayList<FilterState>();
|
||||
}
|
||||
|
||||
public static class FilterState {
|
||||
public int minzoom = -1;
|
||||
public int maxzoom = -1;
|
||||
public String tag = null;
|
||||
public String val = null;
|
||||
public int layer = 0;
|
||||
public int textLength = 0;
|
||||
public float order = 0;
|
||||
public int orderType = -1;
|
||||
public Boolean nightMode = null;
|
||||
|
||||
public String shader = null;
|
||||
|
||||
// point
|
||||
public String icon = null;
|
||||
|
||||
public EffectAttributes main = new EffectAttributes();
|
||||
public TextAttributes text = null;
|
||||
public List<EffectAttributes> effectAttributes = new ArrayList<EffectAttributes>(3);
|
||||
|
||||
protected EffectAttributes getEffectAttributes(int i) {
|
||||
i -= 2;
|
||||
while (i >= effectAttributes.size()) {
|
||||
effectAttributes.add(new EffectAttributes());
|
||||
}
|
||||
return effectAttributes.get(i);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public interface RenderingRuleVisitor {
|
||||
|
||||
/**
|
||||
* @param state - one of the point, polygon, line, text state
|
||||
* @param filter
|
||||
*/
|
||||
public void visitRule(int state, FilterState filter);
|
||||
|
||||
public void rendering(String name, String depends, int defaultColor, int defaultNightColor);
|
||||
}
|
||||
|
||||
|
||||
public final static int POINT_STATE = MapRenderingTypes.POINT_TYPE;
|
||||
public final static int LINE_STATE = MapRenderingTypes.POLYLINE_TYPE;
|
||||
public final static int POLYGON_STATE = MapRenderingTypes.POLYGON_TYPE;
|
||||
public final static int TEXT_STATE = 4;
|
||||
public final static int ORDER_STATE = 5;
|
||||
|
||||
public void parseRenderingRules(InputStream is, RenderingRuleVisitor visitor) throws IOException, SAXException {
|
||||
try {
|
||||
final SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
|
||||
saxParser.parse(is, new RenderingRulesHandler(saxParser, visitor));
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private class RenderingRulesHandler extends DefaultHandler {
|
||||
private final SAXParser parser;
|
||||
private final RenderingRuleVisitor visitor;
|
||||
private int state;
|
||||
|
||||
Stack<Object> stack = new Stack<Object>();
|
||||
|
||||
|
||||
public RenderingRulesHandler(SAXParser parser, RenderingRuleVisitor visitor){
|
||||
this.parser = parser;
|
||||
this.visitor = visitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
|
||||
name = parser.isNamespaceAware() ? localName : name;
|
||||
if("filter".equals(name)){ //$NON-NLS-1$
|
||||
FilterState st = parseFilterAttributes(attributes);
|
||||
stack.push(st);
|
||||
} else if("order".equals(name)){ //$NON-NLS-1$
|
||||
state = ORDER_STATE;
|
||||
} else if("text".equals(name)){ //$NON-NLS-1$
|
||||
state = TEXT_STATE;
|
||||
} else if("point".equals(name)){ //$NON-NLS-1$
|
||||
state = POINT_STATE;
|
||||
} else if("line".equals(name)){ //$NON-NLS-1$
|
||||
state = LINE_STATE;
|
||||
} else if("polygon".equals(name)){ //$NON-NLS-1$
|
||||
state = POLYGON_STATE;
|
||||
} else if("switch".equals(name)){ //$NON-NLS-1$
|
||||
SwitchState st = new SwitchState();
|
||||
stack.push(st);
|
||||
} else if("case".equals(name)){ //$NON-NLS-1$
|
||||
FilterState st = parseFilterAttributes(attributes);
|
||||
((SwitchState)stack.peek()).filters.add(st);
|
||||
} else if("renderer".equals(name)){ //$NON-NLS-1$
|
||||
String dc = attributes.getValue("defaultColor");
|
||||
int defaultColor = 0;
|
||||
if(dc != null && dc.length() > 0){
|
||||
defaultColor = parseColor(dc);
|
||||
}
|
||||
String dnc = attributes.getValue("defaultNightColor");
|
||||
int defautNightColor = defaultColor;
|
||||
if(dnc != null && dnc.length() > 0){
|
||||
defautNightColor = parseColor(dnc);
|
||||
}
|
||||
visitor.rendering(attributes.getValue("name"), attributes.getValue("depends"), defaultColor, defautNightColor); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
log.warn("Unknown tag" + name); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String name) throws SAXException {
|
||||
name = parser.isNamespaceAware() ? localName : name;
|
||||
if ("filter".equals(name)) { //$NON-NLS-1$
|
||||
List<FilterState> list = popAndAggregateState();
|
||||
for (FilterState pop : list) {
|
||||
if (pop.tag != null && (pop.minzoom != -1 || state == ORDER_STATE)) {
|
||||
visitor.visitRule(state, pop);
|
||||
}
|
||||
}
|
||||
} else if("switch".equals(name)){ //$NON-NLS-1$
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<FilterState> popAndAggregateState() {
|
||||
FilterState pop = (FilterState) stack.pop();
|
||||
List<FilterState> res = null;
|
||||
for (int i = stack.size() - 1; i >= 0; i--) {
|
||||
Object o = stack.get(i);
|
||||
if(o instanceof FilterState){
|
||||
if(res == null){
|
||||
mergeStateInto((FilterState) o, pop);
|
||||
} else {
|
||||
for(FilterState f : res){
|
||||
mergeStateInto((FilterState) o, f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<FilterState> filters = ((SwitchState)o).filters;
|
||||
if (res == null) {
|
||||
res = new ArrayList<FilterState>();
|
||||
res.add(pop);
|
||||
}
|
||||
int l = res.size();
|
||||
for (int t = 0; t < filters.size() - 1; t++) {
|
||||
for (int j = 0; j < l; j++) {
|
||||
FilterState n = new FilterState();
|
||||
mergeStateInto(res.get(j), n);
|
||||
res.add(n);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < res.size(); j++) {
|
||||
mergeStateInto(filters.get(j / l), res.get(j));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(res == null){
|
||||
return Collections.singletonList(pop);
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeStateInto(FilterState toMerge, FilterState mergeInto){
|
||||
if(toMerge.maxzoom != -1 && mergeInto.maxzoom == -1){
|
||||
mergeInto.maxzoom = toMerge.maxzoom;
|
||||
}
|
||||
|
||||
if(toMerge.minzoom != -1 && mergeInto.minzoom == -1){
|
||||
mergeInto.minzoom = toMerge.minzoom;
|
||||
}
|
||||
if(toMerge.nightMode != null && mergeInto.nightMode == null){
|
||||
mergeInto.nightMode = toMerge.nightMode;
|
||||
}
|
||||
if(toMerge.icon != null && mergeInto.icon == null){
|
||||
mergeInto.icon = toMerge.icon;
|
||||
}
|
||||
if(toMerge.tag != null && mergeInto.tag == null){
|
||||
mergeInto.tag = toMerge.tag;
|
||||
}
|
||||
if(toMerge.orderType != -1 && mergeInto.orderType == -1){
|
||||
mergeInto.orderType = toMerge.orderType;
|
||||
}
|
||||
if(toMerge.layer != 0 && mergeInto.layer == 0){
|
||||
mergeInto.layer = toMerge.layer;
|
||||
}
|
||||
if(toMerge.order != 0 && mergeInto.order == 0){
|
||||
mergeInto.order = toMerge.order;
|
||||
}
|
||||
if(toMerge.textLength != 0 && mergeInto.textLength == 0){
|
||||
mergeInto.textLength = toMerge.textLength;
|
||||
}
|
||||
if(toMerge.val != null && mergeInto.val == null){
|
||||
mergeInto.val = toMerge.val;
|
||||
}
|
||||
if(toMerge.text != null){
|
||||
if(mergeInto.text == null){
|
||||
mergeInto.text = new TextAttributes();
|
||||
}
|
||||
if(toMerge.text.textColor != 0 && mergeInto.text.textColor == 0){
|
||||
mergeInto.text.textColor = toMerge.text.textColor;
|
||||
}
|
||||
if(toMerge.text.textSize != 0 && mergeInto.text.textSize == 0){
|
||||
mergeInto.text.textSize = toMerge.text.textSize;
|
||||
}
|
||||
if(toMerge.text.textOrder != 0 && mergeInto.text.textOrder == 0){
|
||||
mergeInto.text.textOrder = toMerge.text.textOrder;
|
||||
}
|
||||
if(toMerge.text.textBold && !mergeInto.text.textBold){
|
||||
mergeInto.text.textBold = toMerge.text.textBold;
|
||||
}
|
||||
if(toMerge.text.textShield != null && mergeInto.text.textShield == null){
|
||||
mergeInto.text.textShield = toMerge.text.textShield;
|
||||
}
|
||||
|
||||
if(toMerge.text.ref != null && mergeInto.text.ref == null){
|
||||
mergeInto.text.ref = toMerge.text.ref;
|
||||
}
|
||||
|
||||
if(toMerge.text.textMinDistance != 0 && mergeInto.text.textMinDistance == 0){
|
||||
mergeInto.text.textMinDistance = toMerge.text.textMinDistance;
|
||||
}
|
||||
if(toMerge.text.textDy != 0 && mergeInto.text.textDy == 0){
|
||||
mergeInto.text.textDy = toMerge.text.textDy;
|
||||
}
|
||||
if(toMerge.text.textHaloRadius != 0 && mergeInto.text.textHaloRadius == 0){
|
||||
mergeInto.text.textHaloRadius = toMerge.text.textHaloRadius;
|
||||
}
|
||||
if(toMerge.text.textWrapWidth != 0 && mergeInto.text.textWrapWidth == 0){
|
||||
mergeInto.text.textWrapWidth = toMerge.text.textWrapWidth;
|
||||
}
|
||||
if(toMerge.text.textOnPath && !mergeInto.text.textOnPath){
|
||||
mergeInto.text.textOnPath = toMerge.text.textOnPath;
|
||||
}
|
||||
}
|
||||
|
||||
mergeStateInto(toMerge.main, mergeInto.main);
|
||||
while(mergeInto.effectAttributes.size() < toMerge.effectAttributes.size()){
|
||||
mergeInto.effectAttributes.add(new EffectAttributes());
|
||||
}
|
||||
for(int i=0; i<toMerge.effectAttributes.size(); i++){
|
||||
mergeStateInto(toMerge.effectAttributes.get(i), mergeInto.effectAttributes.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeStateInto(EffectAttributes toMerge, EffectAttributes mergeInto){
|
||||
if(toMerge.color != 0 && mergeInto.color == 0){
|
||||
mergeInto.color = toMerge.color;
|
||||
}
|
||||
|
||||
if(toMerge.strokeWidth != 0 && mergeInto.strokeWidth == 0){
|
||||
mergeInto.strokeWidth = toMerge.strokeWidth;
|
||||
}
|
||||
|
||||
if(toMerge.pathEffect != null && mergeInto.pathEffect == null){
|
||||
mergeInto.pathEffect = toMerge.pathEffect;
|
||||
}
|
||||
if(toMerge.shadowRadius != 0 && mergeInto.shadowRadius == 0){
|
||||
mergeInto.shadowRadius = toMerge.shadowRadius;
|
||||
}
|
||||
|
||||
if(toMerge.shadowColor != 0 && mergeInto.shadowColor == 0){
|
||||
mergeInto.shadowColor = toMerge.shadowColor;
|
||||
}
|
||||
if(toMerge.cap != null && mergeInto.cap == null){
|
||||
mergeInto.cap = toMerge.cap;
|
||||
}
|
||||
}
|
||||
|
||||
public FilterState parseFilterAttributes(Attributes attributes){
|
||||
FilterState state = new FilterState();
|
||||
if(this.state == TEXT_STATE){
|
||||
state.text = new TextAttributes();
|
||||
}
|
||||
for(int i=0; i<attributes.getLength(); i++){
|
||||
String name = attributes.getLocalName(i);
|
||||
String val = attributes.getValue(i);
|
||||
if(name.equals("tag")){ //$NON-NLS-1$
|
||||
state.tag = val;
|
||||
} else if(name.equals("value")){ //$NON-NLS-1$
|
||||
state.val = val;
|
||||
} else if(name.equals("minzoom")){ //$NON-NLS-1$
|
||||
state.minzoom = Integer.parseInt(val);
|
||||
} else if(name.equals("maxzoom")){ //$NON-NLS-1$
|
||||
state.maxzoom = Integer.parseInt(val);
|
||||
} else if(name.equals("maxzoom")){ //$NON-NLS-1$
|
||||
state.maxzoom = Integer.parseInt(val);
|
||||
} else if(name.equals("layer")){ //$NON-NLS-1$
|
||||
state.layer = Integer.parseInt(val);
|
||||
} else if(name.equals("orderType")){ //$NON-NLS-1$
|
||||
int i1 = val.equals("polygon") ? 3 : (val.equals("line") ? 2 : 1); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
state.orderType = i1;
|
||||
} else if(name.equals("order")){ //$NON-NLS-1$
|
||||
state.order = Float.parseFloat(val);
|
||||
} else if(name.equals("nightMode")){ //$NON-NLS-1$
|
||||
state.nightMode = Boolean.parseBoolean(val);
|
||||
} else if(name.equals("icon")){ //$NON-NLS-1$
|
||||
state.icon = val;
|
||||
} else if(name.equals("color")){ //$NON-NLS-1$
|
||||
state.main.color = parseColor(val);
|
||||
} else if(name.startsWith("color_")){ //$NON-NLS-1$
|
||||
EffectAttributes ef = state.getEffectAttributes(Integer.parseInt(name.substring(6)));
|
||||
ef.color = parseColor(val);
|
||||
} else if(name.equals("shader")){ //$NON-NLS-1$
|
||||
state.shader = val;
|
||||
} else if(name.equals("strokeWidth")){ //$NON-NLS-1$
|
||||
state.main.strokeWidth = Float.parseFloat(val);
|
||||
} else if(name.startsWith("strokeWidth_")){ //$NON-NLS-1$
|
||||
EffectAttributes ef = state.getEffectAttributes(Integer.parseInt(name.substring(12)));
|
||||
ef.strokeWidth = Float.parseFloat(val);
|
||||
} else if(name.equals("pathEffect")){ //$NON-NLS-1$
|
||||
state.main.pathEffect = val;
|
||||
} else if(name.startsWith("pathEffect_")){ //$NON-NLS-1$
|
||||
EffectAttributes ef = state.getEffectAttributes(Integer.parseInt(name.substring(11)));
|
||||
ef.pathEffect = val;
|
||||
} else if(name.equals("shadowRadius")){ //$NON-NLS-1$
|
||||
state.main.shadowRadius = Float.parseFloat(val);
|
||||
} else if(name.startsWith("shadowRadius_")){ //$NON-NLS-1$
|
||||
EffectAttributes ef = state.getEffectAttributes(Integer.parseInt(name.substring(14)));
|
||||
ef.shadowRadius = Float.parseFloat(val);
|
||||
} else if(name.equals("shadowColor")){ //$NON-NLS-1$
|
||||
state.main.shadowColor = parseColor(val);
|
||||
} else if(name.startsWith("shadowColor_")){ //$NON-NLS-1$
|
||||
EffectAttributes ef = state.getEffectAttributes(Integer.parseInt(name.substring(12)));
|
||||
ef.shadowColor = parseColor(val);
|
||||
} else if(name.equals("cap")){ //$NON-NLS-1$
|
||||
state.main.cap = val;
|
||||
} else if(name.startsWith("cap_")){ //$NON-NLS-1$
|
||||
EffectAttributes ef = state.getEffectAttributes(Integer.parseInt(name.substring(4)));
|
||||
ef.cap = val;
|
||||
} else if(name.equals("ref")){ //$NON-NLS-1$
|
||||
state.text.ref = val;
|
||||
} else if(name.equals("textSize")){ //$NON-NLS-1$
|
||||
state.text.textSize = Float.parseFloat(val);
|
||||
} else if(name.equals("textOrder")){ //$NON-NLS-1$
|
||||
state.text.textOrder = Integer.parseInt(val);
|
||||
} else if(name.equals("textBold")){ //$NON-NLS-1$
|
||||
state.text.textBold = Boolean.parseBoolean(val);
|
||||
} else if(name.equals("textColor")){ //$NON-NLS-1$
|
||||
state.text.textColor = parseColor(val);
|
||||
} else if(name.equals("textLength")){ //$NON-NLS-1$
|
||||
state.textLength = Integer.parseInt(val);
|
||||
} else if(name.equals("textShield")){ //$NON-NLS-1$
|
||||
state.text.textShield = val;
|
||||
} else if(name.equals("textMinDistance")){ //$NON-NLS-1$
|
||||
state.text.textMinDistance = Integer.parseInt(val);
|
||||
} else if(name.equals("textOnPath")){ //$NON-NLS-1$
|
||||
state.text.textOnPath = Boolean.parseBoolean(val);
|
||||
} else if(name.equals("textWrapWidth")){ //$NON-NLS-1$
|
||||
state.text.textWrapWidth = Integer.parseInt(val);
|
||||
} else if(name.equals("textDy")){ //$NON-NLS-1$
|
||||
state.text.textDy = Integer.parseInt(val);
|
||||
} else if(name.equals("textHaloRadius")){ //$NON-NLS-1$
|
||||
state.text.textHaloRadius = Float.parseFloat(val);
|
||||
} else {
|
||||
log.warn("Unknown attribute " + name); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the color string, and return the corresponding color-int.
|
||||
* If the string cannot be parsed, throws an IllegalArgumentException
|
||||
* exception. Supported formats are:
|
||||
* #RRGGBB
|
||||
* #AARRGGBB
|
||||
* 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta',
|
||||
* 'yellow', 'lightgray', 'darkgray'
|
||||
*/
|
||||
public static int parseColor(String colorString) {
|
||||
if (colorString.charAt(0) == '#') {
|
||||
// Use a long to avoid rollovers on #ffXXXXXX
|
||||
long color = Long.parseLong(colorString.substring(1), 16);
|
||||
if (colorString.length() == 7) {
|
||||
// Set the alpha value
|
||||
color |= 0x00000000ff000000;
|
||||
} else if (colorString.length() != 9) {
|
||||
throw new IllegalArgumentException("Unknown color" + colorString); //$NON-NLS-1$
|
||||
}
|
||||
return (int)color;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown color" + colorString); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
|
||||
// TEST purpose
|
||||
public static void main(String[] args) throws IOException, SAXException {
|
||||
OsmandRenderingRulesParser parser = new OsmandRenderingRulesParser();
|
||||
parser.parseRenderingRules(OsmandRenderingRulesParser.class.getResourceAsStream("hm.render.xml"), //$NON-NLS-1$
|
||||
new RenderingRuleVisitor() {
|
||||
|
||||
@Override
|
||||
public void rendering(String name, String depends, int defColor, int defaultNightColor) {
|
||||
System.out.println("Renderer " + name); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRule(int state, FilterState filter) {
|
||||
if(filter.nightMode != null){
|
||||
System.out.println(filter.minzoom +" " +filter.tag + " " + filter.val);
|
||||
}
|
||||
String gen = generateAttributes(state, filter);
|
||||
if (gen != null) {
|
||||
String res = ""; //$NON-NLS-1$
|
||||
if (filter.maxzoom != -1) {
|
||||
res += " zoom : " +filter.minzoom + "-" + filter.maxzoom; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
res += " zoom : " +filter.minzoom; //$NON-NLS-1$
|
||||
}
|
||||
res += " tag="+filter.tag; //$NON-NLS-1$
|
||||
res += " val="+filter.val; //$NON-NLS-1$
|
||||
if(filter.layer != 0){
|
||||
res += " layer="+filter.layer; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
res += gen;
|
||||
System.out.println(res);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public static String colorToString(int color) {
|
||||
if ((0xFF000000 & color) == 0xFF000000) {
|
||||
return "#" + Integer.toHexString(color & 0x00FFFFFF); //$NON-NLS-1$
|
||||
} else {
|
||||
return "#" + Integer.toHexString(color); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
private static String generateAttributes(int state, FilterState s){
|
||||
String res = ""; //$NON-NLS-1$
|
||||
if(s.shader != null){
|
||||
res+=" shader=" + s.shader; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if(s.icon != null){
|
||||
res+= " icon="+s.icon; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if(s.order != 0){
|
||||
res+= " order="+s.order; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if(s.orderType != 0){
|
||||
res+= " orderType="+s.orderType; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
res = generateAttributes(s.main, res, ""); //$NON-NLS-1$
|
||||
int p = 2;
|
||||
for(EffectAttributes ef : s.effectAttributes){
|
||||
res = generateAttributes(ef, res, "_"+(p++)); //$NON-NLS-1$
|
||||
}
|
||||
if(s.text != null){
|
||||
if(s.text.textSize != 0){
|
||||
res+= " textSize="+s.text.textSize; //$NON-NLS-1$
|
||||
}
|
||||
if(s.text.textOrder != 0){
|
||||
res+= " textOrder="+s.text.textOrder; //$NON-NLS-1$
|
||||
}
|
||||
if(s.text.ref != null){
|
||||
res+= " ref="+s.text.ref; //$NON-NLS-1$
|
||||
}
|
||||
if(s.text.textColor != 0){
|
||||
res+= " textColor="+colorToString(s.text.textColor); //$NON-NLS-1$
|
||||
}
|
||||
if(s.text.textShield != null){
|
||||
res+= " textShield="+s.text.textShield; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if(state == POLYGON_STATE){
|
||||
// return res;
|
||||
} else if(state == LINE_STATE){
|
||||
// return res;
|
||||
} else if(state == POINT_STATE){
|
||||
// return res;
|
||||
} else if(state == TEXT_STATE){
|
||||
// return res;
|
||||
} else if(state == ORDER_STATE){
|
||||
return res;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static String generateAttributes(EffectAttributes s, String res, String prefix) {
|
||||
if(s.color != 0){
|
||||
res +=" color"+prefix+"="+colorToString(s.color); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
if(s.strokeWidth != 0){
|
||||
res+= " strokeWidth"+prefix+"="+s.strokeWidth; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
if(s.pathEffect != null){
|
||||
res+= " pathEffect"+prefix+"="+s.pathEffect; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
132
DataExtractionOSM/src/net/osmand/render/RenderingRule.java
Normal file
132
DataExtractionOSM/src/net/osmand/render/RenderingRule.java
Normal file
|
@ -0,0 +1,132 @@
|
|||
package net.osmand.render;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class RenderingRule {
|
||||
|
||||
private RenderingRuleProperty[] properties;
|
||||
private int[] intProperties;
|
||||
private float[] floatProperties;
|
||||
private List<RenderingRule> ifElseChildren;
|
||||
private List<RenderingRule> ifChildren;
|
||||
|
||||
private final RenderingRulesStorage storage;
|
||||
|
||||
public RenderingRule(Map<String, String> attributes, RenderingRulesStorage storage){
|
||||
this.storage = storage;
|
||||
process(attributes);
|
||||
}
|
||||
|
||||
private void process(Map<String, String> attributes) {
|
||||
ArrayList<RenderingRuleProperty> props = new ArrayList<RenderingRuleProperty>(attributes.size());
|
||||
intProperties = new int[attributes.size()];
|
||||
int i = 0;
|
||||
Iterator<Entry<String, String>> it = attributes.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<String, String> e = it.next();
|
||||
RenderingRuleProperty property = storage.PROPS.get(e.getKey());
|
||||
if (property != null) {
|
||||
props.add(property);
|
||||
|
||||
if (property.isString()) {
|
||||
intProperties[i] = storage.getDictionaryValue(e.getValue());
|
||||
} else if (property.isFloat()) {
|
||||
if (floatProperties == null) {
|
||||
// lazy creates
|
||||
floatProperties = new float[attributes.size()];
|
||||
}
|
||||
floatProperties[i] = property.parseFloatValue(e.getValue());
|
||||
} else {
|
||||
intProperties[i] = property.parseIntValue(e.getValue());
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
properties = props.toArray(new RenderingRuleProperty[props.size()]);
|
||||
}
|
||||
|
||||
private int getPropertyIndex(String property){
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
RenderingRuleProperty prop = properties[i];
|
||||
if (prop.getAttrName().equals(property)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String getStringPropertyValue(String property) {
|
||||
int i = getPropertyIndex(property);
|
||||
if(i >= 0){
|
||||
return storage.getStringValue(intProperties[i]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public float getFloatPropertyValue(String property) {
|
||||
int i = getPropertyIndex(property);
|
||||
if(i >= 0){
|
||||
return floatProperties[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getColorPropertyValue(String property) {
|
||||
int i = getPropertyIndex(property);
|
||||
if(i >= 0){
|
||||
return RenderingRuleProperty.colorToString(intProperties[i]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getIntPropertyValue(String property) {
|
||||
int i = getPropertyIndex(property);
|
||||
if(i >= 0){
|
||||
return intProperties[i];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected int getIntProp(int ind){
|
||||
return intProperties[ind];
|
||||
}
|
||||
|
||||
protected float getFloatProp(int ind){
|
||||
return floatProperties[ind];
|
||||
}
|
||||
|
||||
public RenderingRuleProperty[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<RenderingRule> getIfChildren() {
|
||||
return ifChildren != null ? ifChildren : Collections.EMPTY_LIST ;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<RenderingRule> getIfElseChildren() {
|
||||
return ifElseChildren != null ? ifElseChildren : Collections.EMPTY_LIST ;
|
||||
}
|
||||
|
||||
public void addIfChildren(RenderingRule rr){
|
||||
if(ifChildren == null){
|
||||
ifChildren = new ArrayList<RenderingRule>();
|
||||
}
|
||||
ifChildren.add(rr);
|
||||
}
|
||||
|
||||
public void addIfElseChildren(RenderingRule rr){
|
||||
if(ifElseChildren == null){
|
||||
ifElseChildren = new ArrayList<RenderingRule>();
|
||||
}
|
||||
ifElseChildren.add(rr);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
package net.osmand.render;
|
||||
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
|
||||
public class RenderingRuleProperty {
|
||||
private final static Log log = LogUtil.getLog(RenderingRuleProperty.class);
|
||||
|
||||
private final static int INT_TYPE = 1;
|
||||
private final static int FLOAT_TYPE = 2;
|
||||
private final static int STRING_TYPE = 3;
|
||||
private final static int COLOR_TYPE = 4;
|
||||
private final static int BOOLEAN_TYPE = 5;
|
||||
|
||||
public static final int TRUE_VALUE = 1;
|
||||
public static final int FALSE_VALUE = 0;
|
||||
|
||||
protected final int type;
|
||||
protected final boolean input;
|
||||
protected final String attrName;
|
||||
|
||||
protected int id = -1;
|
||||
|
||||
// use for custom rendering rule properties
|
||||
protected String name;
|
||||
protected String description;
|
||||
protected String[] possibleValues;
|
||||
|
||||
private RenderingRuleProperty(String attrName, int type, boolean input){
|
||||
this.attrName = attrName;
|
||||
this.type = type;
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public boolean isInputProperty() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public boolean isOutputProperty() {
|
||||
return !input;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
if (this.id != -1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getAttrName() {
|
||||
return attrName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
protected void setPossibleValues(String[] possibleValues) {
|
||||
this.possibleValues = possibleValues;
|
||||
}
|
||||
|
||||
public String[] getPossibleValues() {
|
||||
if (isBoolean()) {
|
||||
return new String[] { "true", "false" };
|
||||
}
|
||||
return possibleValues;
|
||||
}
|
||||
|
||||
public boolean isBoolean() {
|
||||
return type == BOOLEAN_TYPE;
|
||||
}
|
||||
|
||||
public boolean isFloat() {
|
||||
return type == FLOAT_TYPE;
|
||||
}
|
||||
|
||||
public boolean isInt() {
|
||||
return type == INT_TYPE;
|
||||
}
|
||||
|
||||
public boolean isColor() {
|
||||
return type == COLOR_TYPE;
|
||||
}
|
||||
|
||||
public boolean isString() {
|
||||
return type == STRING_TYPE;
|
||||
}
|
||||
|
||||
public boolean isIntParse(){
|
||||
return type == INT_TYPE || type == STRING_TYPE || type == COLOR_TYPE || type == BOOLEAN_TYPE;
|
||||
}
|
||||
|
||||
public boolean accept(int ruleValue, int renderingProperty){
|
||||
if(!isIntParse() || !input){
|
||||
return false;
|
||||
}
|
||||
return ruleValue == renderingProperty;
|
||||
}
|
||||
|
||||
public boolean accept(float ruleValue, float renderingProperty){
|
||||
if(type != FLOAT_TYPE || !input){
|
||||
return false;
|
||||
}
|
||||
return ruleValue == renderingProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "#RenderingRuleProperty " + getAttrName();
|
||||
}
|
||||
|
||||
|
||||
public int parseIntValue(String value){
|
||||
if(type == INT_TYPE){
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
log.error("Rendering parse " + value);
|
||||
}
|
||||
return -1;
|
||||
} else if(type == BOOLEAN_TYPE){
|
||||
return Boolean.parseBoolean(value) ? TRUE_VALUE : FALSE_VALUE;
|
||||
} else if(type == STRING_TYPE){
|
||||
// requires dictionary to parse
|
||||
return -1;
|
||||
} else if(type == COLOR_TYPE){
|
||||
try {
|
||||
return parseColor(value);
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Rendering parse " + e.getMessage());
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public float parseFloatValue(String value){
|
||||
if(type == FLOAT_TYPE){
|
||||
try {
|
||||
return Float.parseFloat(value);
|
||||
} catch (NumberFormatException e) {
|
||||
log.error("Rendering parse " + value);
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static RenderingRuleProperty createOutputIntProperty(String name){
|
||||
return new RenderingRuleProperty(name, INT_TYPE, false);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createOutputBooleanProperty(String name){
|
||||
return new RenderingRuleProperty(name, BOOLEAN_TYPE, false);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createInputBooleanProperty(String name){
|
||||
return new RenderingRuleProperty(name, BOOLEAN_TYPE, true);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createOutputFloatProperty(String name){
|
||||
return new RenderingRuleProperty(name, FLOAT_TYPE, false);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createOutputStringProperty(String name){
|
||||
return new RenderingRuleProperty(name, STRING_TYPE, false);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createInputIntProperty(String name){
|
||||
return new RenderingRuleProperty(name, INT_TYPE, true);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createInputColorProperty(String name){
|
||||
return new RenderingRuleProperty(name, COLOR_TYPE, true);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createOutputColorProperty(String name){
|
||||
return new RenderingRuleProperty(name, COLOR_TYPE, false);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createInputStringProperty(String name){
|
||||
return new RenderingRuleProperty(name, STRING_TYPE, true);
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createInputLessIntProperty(String name){
|
||||
return new RenderingRuleProperty(name, INT_TYPE, true) {
|
||||
@Override
|
||||
public boolean accept(int ruleValue, int renderingProperty) {
|
||||
if(!isIntParse() || !input){
|
||||
return false;
|
||||
}
|
||||
return ruleValue >= renderingProperty;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static RenderingRuleProperty createInputGreaterIntProperty(String name){
|
||||
return new RenderingRuleProperty(name, INT_TYPE, true) {
|
||||
@Override
|
||||
public boolean accept(int ruleValue, int renderingProperty) {
|
||||
if(!isIntParse() || !input){
|
||||
return false;
|
||||
}
|
||||
return ruleValue <= renderingProperty;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the color string, and return the corresponding color-int.
|
||||
* If the string cannot be parsed, throws an IllegalArgumentException
|
||||
* exception. Supported formats are:
|
||||
* #RRGGBB
|
||||
* #AARRGGBB
|
||||
* 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta',
|
||||
* 'yellow', 'lightgray', 'darkgray'
|
||||
*/
|
||||
public static int parseColor(String colorString) {
|
||||
if (colorString.charAt(0) == '#') {
|
||||
// Use a long to avoid rollovers on #ffXXXXXX
|
||||
long color = Long.parseLong(colorString.substring(1), 16);
|
||||
if (colorString.length() == 7) {
|
||||
// Set the alpha value
|
||||
color |= 0x00000000ff000000;
|
||||
} else if (colorString.length() != 9) {
|
||||
throw new IllegalArgumentException("Unknown color" + colorString); //$NON-NLS-1$
|
||||
}
|
||||
return (int)color;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown color" + colorString); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public static String colorToString(int color) {
|
||||
if ((0xFF000000 & color) == 0xFF000000) {
|
||||
return "#" + Integer.toHexString(color & 0x00FFFFFF); //$NON-NLS-1$
|
||||
} else {
|
||||
return "#" + Integer.toHexString(color); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
package net.osmand.render;
|
||||
|
||||
|
||||
public class RenderingRuleSearchRequest {
|
||||
|
||||
private final RenderingRulesStorage storage;
|
||||
private final RenderingRuleSearchRequest dependsRequest;
|
||||
RenderingRuleProperty[] props;
|
||||
int[] values;
|
||||
float[] fvalues;
|
||||
|
||||
int[] savedValues;
|
||||
float[] savedFvalues;
|
||||
|
||||
boolean searchResult = false;
|
||||
|
||||
|
||||
public final RenderingRuleStorageProperties ALL;
|
||||
|
||||
public RenderingRuleSearchRequest(RenderingRulesStorage storage) {
|
||||
this.storage = storage;
|
||||
this.ALL = storage.PROPS;
|
||||
if(storage.getDependsStorage() != null){
|
||||
dependsRequest = new RenderingRuleSearchRequest(storage.getDependsStorage());
|
||||
} else {
|
||||
dependsRequest = null;
|
||||
}
|
||||
props = storage.PROPS.getPoperties();
|
||||
values = new int[props.length];
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (!props[i].isColor()) {
|
||||
values[i] = -1;
|
||||
}
|
||||
}
|
||||
fvalues = new float[props.length];
|
||||
saveState();
|
||||
}
|
||||
|
||||
public void setStringFilter(RenderingRuleProperty p, String filter) {
|
||||
assert p.isInputProperty();
|
||||
values[p.getId()] = storage.getDictionaryValue(filter);
|
||||
}
|
||||
|
||||
public void setIntFilter(RenderingRuleProperty p, int filter) {
|
||||
assert p.isInputProperty();
|
||||
values[p.getId()] = filter;
|
||||
}
|
||||
|
||||
public void setBooleanFilter(RenderingRuleProperty p, boolean filter) {
|
||||
assert p.isInputProperty();
|
||||
values[p.getId()] = filter ? RenderingRuleProperty.TRUE_VALUE : RenderingRuleProperty.FALSE_VALUE;
|
||||
}
|
||||
|
||||
public void saveState() {
|
||||
savedValues = new int[values.length];
|
||||
savedFvalues = new float[fvalues.length];
|
||||
System.arraycopy(values, 0, savedValues, 0, values.length);
|
||||
System.arraycopy(fvalues, 0, savedFvalues, 0, fvalues.length);
|
||||
}
|
||||
|
||||
public void clearState() {
|
||||
System.arraycopy(savedValues, 0, values, 0, values.length);
|
||||
System.arraycopy(savedFvalues, 0, fvalues, 0, fvalues.length);
|
||||
}
|
||||
|
||||
public void setInitialTagValueZoom(String tag, String val, int zoom){
|
||||
clearState();
|
||||
setIntFilter(ALL.R_MINZOOM, zoom);
|
||||
setIntFilter(ALL.R_MAXZOOM, zoom);
|
||||
setStringFilter(ALL.R_TAG, tag);
|
||||
setStringFilter(ALL.R_VALUE, val);
|
||||
}
|
||||
|
||||
public boolean isFound() {
|
||||
return searchResult;
|
||||
}
|
||||
|
||||
public boolean search(int state) {
|
||||
return search(state, true);
|
||||
}
|
||||
|
||||
public boolean search(int state, boolean loadOutput) {
|
||||
searchResult = false;
|
||||
int tagKey = values[storage.PROPS.R_TAG.getId()];
|
||||
int valueKey = values[storage.PROPS.R_VALUE.getId()];
|
||||
boolean result = searchInternal(state, tagKey, valueKey, loadOutput);
|
||||
if (result) {
|
||||
searchResult = true;
|
||||
return true;
|
||||
}
|
||||
result = searchInternal(state, tagKey, 0, loadOutput);
|
||||
if (result) {
|
||||
searchResult = true;
|
||||
return true;
|
||||
}
|
||||
result = searchInternal(state, 0, 0, loadOutput);
|
||||
if (result) {
|
||||
searchResult = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(dependsRequest != null){
|
||||
// TODO search depends ?
|
||||
// and copy results to local array
|
||||
dependsRequest.search(state);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean searchInternal(int state, int tagKey, int valueKey, boolean loadOutput) {
|
||||
values[storage.PROPS.R_TAG.getId()] = tagKey;
|
||||
values[storage.PROPS.R_VALUE.getId()] = valueKey;
|
||||
RenderingRule accept = storage.getRule(state, tagKey, valueKey);
|
||||
if (accept == null) {
|
||||
return false;
|
||||
}
|
||||
boolean match = visitRule(accept, loadOutput);
|
||||
return match;
|
||||
}
|
||||
|
||||
private boolean visitRule(RenderingRule rule, boolean loadOutput) {
|
||||
RenderingRuleProperty[] properties = rule.getProperties();
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
RenderingRuleProperty rp = properties[i];
|
||||
if (rp.isInputProperty()) {
|
||||
boolean match;
|
||||
if (rp.isFloat()) {
|
||||
match = rp.accept(rule.getFloatProp(i), fvalues[rp.getId()]);
|
||||
} else {
|
||||
match = rp.accept(rule.getIntProp(i), values[rp.getId()]);
|
||||
}
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!loadOutput) {
|
||||
return true;
|
||||
}
|
||||
// accept it
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
RenderingRuleProperty rp = properties[i];
|
||||
if (rp.isOutputProperty()) {
|
||||
searchResult = true;
|
||||
if (rp.isFloat()) {
|
||||
fvalues[rp.getId()] = rule.getFloatProp(i);
|
||||
} else {
|
||||
values[rp.getId()] = rule.getIntProp(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (RenderingRule rr : rule.getIfElseChildren()) {
|
||||
boolean match = visitRule(rr, loadOutput);
|
||||
if (match) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(RenderingRule rr : rule.getIfChildren()){
|
||||
visitRule(rr, loadOutput);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public boolean isSpecified(RenderingRuleProperty property){
|
||||
if(property.isFloat()){
|
||||
return fvalues[property.getId()] != 0;
|
||||
} else {
|
||||
int val = values[property.getId()];
|
||||
if(property.isColor()){
|
||||
return val != 0;
|
||||
} else {
|
||||
return val != -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RenderingRuleProperty[] getProperties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
public String getStringPropertyValue(RenderingRuleProperty property) {
|
||||
int val = values[property.getId()];
|
||||
if(val < 0){
|
||||
return null;
|
||||
}
|
||||
return storage.getStringValue(val);
|
||||
}
|
||||
|
||||
public float getFloatPropertyValue(RenderingRuleProperty property) {
|
||||
return fvalues[property.getId()];
|
||||
}
|
||||
|
||||
public String getColorStringPropertyValue(RenderingRuleProperty property) {
|
||||
return RenderingRuleProperty.colorToString(values[property.getId()]);
|
||||
}
|
||||
|
||||
public int getIntPropertyValue(RenderingRuleProperty property) {
|
||||
return values[property.getId()];
|
||||
}
|
||||
|
||||
public int getIntPropertyValue(RenderingRuleProperty property, int defValue) {
|
||||
int val = values[property.getId()];
|
||||
return val == -1 ? defValue : val;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
package net.osmand.render;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RenderingRuleStorageProperties {
|
||||
|
||||
public static final String TEXT_LENGTH = "textLength";
|
||||
public static final String REF = "ref";
|
||||
public static final String TEXT_SHIELD = "textShield";
|
||||
public static final String SHADOW_RADIUS = "shadowRadius";
|
||||
public static final String SHADOW_COLOR = "shadowColor";
|
||||
public static final String SHADER = "shader";
|
||||
public static final String CAP_3 = "cap_3";
|
||||
public static final String CAP_2 = "cap_2";
|
||||
public static final String CAP = "cap";
|
||||
public static final String PATH_EFFECT_3 = "pathEffect_3";
|
||||
public static final String PATH_EFFECT_2 = "pathEffect_2";
|
||||
public static final String PATH_EFFECT = "pathEffect";
|
||||
public static final String STROKE_WIDTH_3 = "strokeWidth_3";
|
||||
public static final String STROKE_WIDTH_2 = "strokeWidth_2";
|
||||
public static final String STROKE_WIDTH = "strokeWidth";
|
||||
public static final String COLOR_3 = "color_3";
|
||||
public static final String COLOR = "color";
|
||||
public static final String COLOR_2 = "color_2";
|
||||
public static final String TEXT_BOLD = "textBold";
|
||||
public static final String TEXT_ORDER = "textOrder";
|
||||
public static final String TEXT_MIN_DISTANCE = "textMinDistance";
|
||||
public static final String TEXT_ON_PATH = "textOnPath";
|
||||
public static final String ICON = "icon";
|
||||
public static final String LAYER = "layer";
|
||||
public static final String ORDER = "order";
|
||||
public static final String ORDER_TYPE = "orderType";
|
||||
public static final String TAG = "tag";
|
||||
public static final String VALUE = "value";
|
||||
public static final String MINZOOM = "minzoom";
|
||||
public static final String MAXZOOM = "maxzoom";
|
||||
public static final String NIGHT_MODE = "nightMode";
|
||||
public static final String TEXT_DY = "textDy";
|
||||
public static final String TEXT_SIZE = "textSize";
|
||||
public static final String TEXT_COLOR = "textColor";
|
||||
public static final String TEXT_HALO_RADIUS = "textHaloRadius";
|
||||
public static final String TEXT_WRAP_WIDTH = "textWrapWidth";
|
||||
|
||||
public RenderingRuleProperty R_TEXT_LENGTH;
|
||||
public RenderingRuleProperty R_REF;
|
||||
public RenderingRuleProperty R_TEXT_SHIELD;
|
||||
public RenderingRuleProperty R_SHADOW_RADIUS;
|
||||
public RenderingRuleProperty R_SHADOW_COLOR;
|
||||
public RenderingRuleProperty R_SHADER;
|
||||
public RenderingRuleProperty R_CAP_3;
|
||||
public RenderingRuleProperty R_CAP_2;
|
||||
public RenderingRuleProperty R_CAP;
|
||||
public RenderingRuleProperty R_PATH_EFFECT_3;
|
||||
public RenderingRuleProperty R_PATH_EFFECT_2;
|
||||
public RenderingRuleProperty R_PATH_EFFECT;
|
||||
public RenderingRuleProperty R_STROKE_WIDTH_3;
|
||||
public RenderingRuleProperty R_STROKE_WIDTH_2;
|
||||
public RenderingRuleProperty R_STROKE_WIDTH;
|
||||
public RenderingRuleProperty R_COLOR_3;
|
||||
public RenderingRuleProperty R_COLOR;
|
||||
public RenderingRuleProperty R_COLOR_2;
|
||||
public RenderingRuleProperty R_TEXT_BOLD;
|
||||
public RenderingRuleProperty R_TEXT_ORDER;
|
||||
public RenderingRuleProperty R_TEXT_MIN_DISTANCE;
|
||||
public RenderingRuleProperty R_TEXT_ON_PATH;
|
||||
public RenderingRuleProperty R_ICON;
|
||||
public RenderingRuleProperty R_LAYER;
|
||||
public RenderingRuleProperty R_ORDER;
|
||||
public RenderingRuleProperty R_ORDER_TYPE;
|
||||
public RenderingRuleProperty R_TAG;
|
||||
public RenderingRuleProperty R_VALUE;
|
||||
public RenderingRuleProperty R_MINZOOM;
|
||||
public RenderingRuleProperty R_MAXZOOM;
|
||||
public RenderingRuleProperty R_NIGHT_MODE;
|
||||
public RenderingRuleProperty R_TEXT_DY;
|
||||
public RenderingRuleProperty R_TEXT_SIZE;
|
||||
public RenderingRuleProperty R_TEXT_COLOR;
|
||||
public RenderingRuleProperty R_TEXT_HALO_RADIUS;
|
||||
public RenderingRuleProperty R_TEXT_WRAP_WIDTH;
|
||||
|
||||
final Map<String, RenderingRuleProperty> properties = new LinkedHashMap<String, RenderingRuleProperty>();
|
||||
final List<RenderingRuleProperty> rules = new ArrayList<RenderingRuleProperty>();
|
||||
final List<RenderingRuleProperty> customRules = new ArrayList<RenderingRuleProperty>();
|
||||
|
||||
public RenderingRuleStorageProperties() {
|
||||
createDefaultRenderingRuleProperties();
|
||||
}
|
||||
|
||||
public void createDefaultRenderingRuleProperties() {
|
||||
R_TAG = registerRuleInternal(RenderingRuleProperty.createInputStringProperty(TAG));
|
||||
R_VALUE = registerRuleInternal(RenderingRuleProperty.createInputStringProperty(VALUE));
|
||||
R_MINZOOM = registerRuleInternal(RenderingRuleProperty.createInputGreaterIntProperty(MINZOOM));
|
||||
R_MAXZOOM = registerRuleInternal(RenderingRuleProperty.createInputLessIntProperty(MAXZOOM));
|
||||
R_NIGHT_MODE = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(NIGHT_MODE));
|
||||
R_LAYER = registerRuleInternal(RenderingRuleProperty.createInputIntProperty(LAYER));
|
||||
R_ORDER_TYPE = registerRuleInternal(RenderingRuleProperty.createInputIntProperty(ORDER_TYPE));
|
||||
R_TEXT_LENGTH = registerRuleInternal(RenderingRuleProperty.createInputIntProperty(TEXT_LENGTH));
|
||||
R_REF = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(REF));
|
||||
|
||||
// order - no sense to make it float
|
||||
R_ORDER = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(ORDER));
|
||||
|
||||
// text properties
|
||||
R_TEXT_WRAP_WIDTH = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_WRAP_WIDTH));
|
||||
R_TEXT_DY = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_DY));
|
||||
R_TEXT_HALO_RADIUS = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_HALO_RADIUS));
|
||||
R_TEXT_SIZE = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_SIZE));
|
||||
R_TEXT_ORDER = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_ORDER));
|
||||
R_TEXT_MIN_DISTANCE = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_MIN_DISTANCE));
|
||||
R_TEXT_SHIELD = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(TEXT_SHIELD));
|
||||
|
||||
|
||||
R_TEXT_COLOR = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(TEXT_COLOR));
|
||||
|
||||
R_TEXT_BOLD = registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(TEXT_BOLD));
|
||||
R_TEXT_ON_PATH = registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(TEXT_ON_PATH));
|
||||
|
||||
// point
|
||||
R_ICON = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(ICON));
|
||||
|
||||
// polygon/way
|
||||
R_COLOR = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR));
|
||||
R_COLOR_2 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR_2));
|
||||
R_COLOR_3 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR_3));
|
||||
R_STROKE_WIDTH = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH));
|
||||
R_STROKE_WIDTH_2 = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH_2));
|
||||
R_STROKE_WIDTH_3 = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH_3));
|
||||
|
||||
R_PATH_EFFECT = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT));
|
||||
R_PATH_EFFECT_2 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT_2));
|
||||
R_PATH_EFFECT_3 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT_3));
|
||||
R_CAP = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP));
|
||||
R_CAP_2 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP_2));
|
||||
R_CAP_3 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP_3));
|
||||
R_SHADER = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(SHADER));
|
||||
|
||||
R_SHADOW_COLOR = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(SHADOW_COLOR));
|
||||
R_SHADOW_RADIUS = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(SHADOW_RADIUS));
|
||||
}
|
||||
|
||||
public RenderingRuleProperty get(String name) {
|
||||
return properties.get(name);
|
||||
}
|
||||
|
||||
public RenderingRuleProperty[] getPoperties() {
|
||||
return rules.toArray(new RenderingRuleProperty[rules.size()]);
|
||||
}
|
||||
|
||||
public List<RenderingRuleProperty> getCustomRules() {
|
||||
return customRules;
|
||||
}
|
||||
|
||||
private RenderingRuleProperty registerRuleInternal(RenderingRuleProperty p) {
|
||||
properties.put(p.getAttrName(), p);
|
||||
p.setId(rules.size());
|
||||
rules.add(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
public RenderingRuleProperty registerRule(RenderingRuleProperty p) {
|
||||
registerRuleInternal(p);
|
||||
customRules.add(p);
|
||||
return p;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,417 @@
|
|||
package net.osmand.render;
|
||||
|
||||
import gnu.trove.map.hash.TIntObjectHashMap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.osm.MapRenderingTypes;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
public class RenderingRulesStorage {
|
||||
|
||||
private final static Log log = LogUtil.getLog(RenderingRulesStorage.class);
|
||||
|
||||
// keep sync !
|
||||
public final static int POINT_RULES = MapRenderingTypes.POINT_TYPE;
|
||||
public final static int LINE_RULES = MapRenderingTypes.POLYLINE_TYPE;
|
||||
public final static int POLYGON_RULES = MapRenderingTypes.POLYGON_TYPE;
|
||||
public final static int TEXT_RULES = 4;
|
||||
public final static int ORDER_RULES = 5;
|
||||
private final static int LENGTH_RULES = 6;
|
||||
|
||||
private final static int SHIFT_TAG_VAL = 16;
|
||||
|
||||
List<String> dictionary = new ArrayList<String>();
|
||||
Map<String, Integer> dictionaryMap = new LinkedHashMap<String, Integer>();
|
||||
|
||||
public final RenderingRuleStorageProperties PROPS = new RenderingRuleStorageProperties();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected TIntObjectHashMap<RenderingRule>[] tagValueGlobalRules = new TIntObjectHashMap[LENGTH_RULES];
|
||||
|
||||
private int bgColor = 0;
|
||||
private int bgNightColor = 0;
|
||||
private String renderingName;
|
||||
private String depends;
|
||||
private RenderingRulesStorage dependsStorage;
|
||||
|
||||
|
||||
public RenderingRulesStorage(){
|
||||
// register empty string as 0
|
||||
getDictionaryValue("");
|
||||
}
|
||||
|
||||
public int getDictionaryValue(String val) {
|
||||
if(dictionaryMap.containsKey(val)){
|
||||
return dictionaryMap.get(val);
|
||||
}
|
||||
int nextInd = dictionaryMap.size();
|
||||
dictionaryMap.put(val, nextInd);
|
||||
dictionary.add(val);
|
||||
return nextInd;
|
||||
|
||||
}
|
||||
|
||||
public String getStringValue(int i){
|
||||
return dictionary.get(i);
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return renderingName;
|
||||
}
|
||||
|
||||
public int getBgColor() {
|
||||
return bgColor;
|
||||
}
|
||||
|
||||
public int getBgNightColor() {
|
||||
return bgNightColor;
|
||||
}
|
||||
|
||||
public int getBgColor(boolean nightMode){
|
||||
return nightMode ? bgNightColor : bgColor;
|
||||
}
|
||||
|
||||
public String getDepends() {
|
||||
return depends;
|
||||
}
|
||||
|
||||
public RenderingRulesStorage getDependsStorage() {
|
||||
return dependsStorage;
|
||||
}
|
||||
|
||||
public void setDependsStorage(RenderingRulesStorage dependsStorage) {
|
||||
this.dependsStorage = dependsStorage;
|
||||
}
|
||||
|
||||
|
||||
public void parseRulesFromXmlInputStream(InputStream is) throws SAXException, IOException {
|
||||
try {
|
||||
final SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
|
||||
saxParser.parse(is, new RenderingRulesHandler(saxParser));
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String colorToString(int color) {
|
||||
if ((0xFF000000 & color) == 0xFF000000) {
|
||||
return "#" + Integer.toHexString(color & 0x00FFFFFF); //$NON-NLS-1$
|
||||
} else {
|
||||
return "#" + Integer.toHexString(color); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerGlobalRule(RenderingRule rr, int state, Map<String, String> attrsMap) throws SAXException {
|
||||
int tag = rr.getIntPropertyValue(RenderingRuleStorageProperties.TAG);
|
||||
if(tag == -1){
|
||||
throw new SAXException("Attribute tag should be specified for root filter " + attrsMap.toString());
|
||||
}
|
||||
int value = rr.getIntPropertyValue(RenderingRuleStorageProperties.VALUE);
|
||||
if(value == -1){
|
||||
throw new SAXException("Attribute tag should be specified for root filter " + attrsMap.toString());
|
||||
}
|
||||
int key = (tag << SHIFT_TAG_VAL) + value;
|
||||
RenderingRule toInsert = rr;
|
||||
RenderingRule previous = tagValueGlobalRules[state].get(key);
|
||||
if(previous != null){
|
||||
if(previous.getProperties().length != 0){
|
||||
toInsert = new RenderingRule(Collections.EMPTY_MAP, RenderingRulesStorage.this);
|
||||
toInsert.addIfElseChildren(previous);
|
||||
} else {
|
||||
toInsert = previous;
|
||||
}
|
||||
toInsert.addIfElseChildren(rr);
|
||||
}
|
||||
tagValueGlobalRules[state].put(key, toInsert);
|
||||
}
|
||||
|
||||
private class GroupRules {
|
||||
Map<String, String> groupAttributes = new LinkedHashMap<String, String>();
|
||||
List<RenderingRule> children = new ArrayList<RenderingRule>();
|
||||
List<GroupRules> childrenGroups = new ArrayList<GroupRules>();
|
||||
|
||||
private void addGroupFilter(RenderingRule rr) {
|
||||
for (RenderingRule ch : children) {
|
||||
ch.addIfChildren(rr);
|
||||
}
|
||||
for(GroupRules gch : childrenGroups){
|
||||
gch.addGroupFilter(rr);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerGlobalRules(int state) throws SAXException {
|
||||
for (RenderingRule ch : children) {
|
||||
registerGlobalRule(ch, state, groupAttributes);
|
||||
}
|
||||
for(GroupRules gch : childrenGroups){
|
||||
gch.registerGlobalRules(state);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class RenderingRulesHandler extends DefaultHandler {
|
||||
private final SAXParser parser;
|
||||
private int state;
|
||||
|
||||
Stack<Object> stack = new Stack<Object>();
|
||||
|
||||
Map<String, String> attrsMap = new LinkedHashMap<String, String>();
|
||||
|
||||
|
||||
public RenderingRulesHandler(SAXParser parser){
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
|
||||
name = parser.isNamespaceAware() ? localName : name;
|
||||
boolean stateChanged = false;
|
||||
if("filter".equals(name)){ //$NON-NLS-1$
|
||||
attrsMap.clear();
|
||||
if (stack.size() > 0 && stack.peek() instanceof GroupRules) {
|
||||
GroupRules parent = ((GroupRules) stack.peek());
|
||||
attrsMap.putAll(parent.groupAttributes);
|
||||
}
|
||||
parseAttributes(attributes, attrsMap);
|
||||
RenderingRule renderingRule = new RenderingRule(attrsMap, RenderingRulesStorage.this);
|
||||
|
||||
if (stack.size() > 0 && stack.peek() instanceof GroupRules) {
|
||||
GroupRules parent = ((GroupRules) stack.peek());
|
||||
parent.children.add(renderingRule);
|
||||
} else if (stack.size() > 0 && stack.peek() instanceof RenderingRule) {
|
||||
RenderingRule parent = ((RenderingRule) stack.peek());
|
||||
parent.addIfElseChildren(renderingRule);
|
||||
} else {
|
||||
registerGlobalRule(renderingRule, state, attrsMap);
|
||||
}
|
||||
stack.push(renderingRule);
|
||||
} else if("groupFilter".equals(name)){ //$NON-NLS-1$
|
||||
attrsMap.clear();
|
||||
parseAttributes(attributes, attrsMap);
|
||||
RenderingRule renderingRule = new RenderingRule(attrsMap, RenderingRulesStorage.this);
|
||||
if (stack.size() > 0 && stack.peek() instanceof GroupRules) {
|
||||
GroupRules parent = ((GroupRules) stack.peek());
|
||||
parent.addGroupFilter(renderingRule);
|
||||
} else if (stack.size() > 0 && stack.peek() instanceof RenderingRule) {
|
||||
((RenderingRule) stack.peek()).addIfChildren(renderingRule);
|
||||
} else {
|
||||
throw new SAXException("Group filter without parent");
|
||||
}
|
||||
stack.push(renderingRule);
|
||||
} else if("group".equals(name)){ //$NON-NLS-1$
|
||||
GroupRules groupRules = new GroupRules();
|
||||
if (stack.size() > 0 && stack.peek() instanceof GroupRules) {
|
||||
GroupRules parent = ((GroupRules) stack.peek());
|
||||
groupRules.groupAttributes.putAll(parent.groupAttributes);
|
||||
parent.childrenGroups.add(groupRules);
|
||||
}
|
||||
parseAttributes(attributes, groupRules.groupAttributes);
|
||||
stack.push(groupRules);
|
||||
} else if("order".equals(name)){ //$NON-NLS-1$
|
||||
state = ORDER_RULES;
|
||||
stateChanged = true;
|
||||
} else if("text".equals(name)){ //$NON-NLS-1$
|
||||
state = TEXT_RULES;
|
||||
stateChanged = true;
|
||||
} else if("point".equals(name)){ //$NON-NLS-1$
|
||||
state = POINT_RULES;
|
||||
stateChanged = true;
|
||||
} else if("line".equals(name)){ //$NON-NLS-1$
|
||||
state = LINE_RULES;
|
||||
stateChanged = true;
|
||||
} else if("polygon".equals(name)){ //$NON-NLS-1$
|
||||
state = POLYGON_RULES;
|
||||
stateChanged = true;
|
||||
} else if("renderingProperty".equals(name)){ //$NON-NLS-1$
|
||||
String attr = attributes.getValue("attr");
|
||||
RenderingRuleProperty prop;
|
||||
String type = attributes.getValue("type");
|
||||
if("boolean".equalsIgnoreCase(type)){
|
||||
prop = RenderingRuleProperty.createInputBooleanProperty(attr);
|
||||
} else if("string".equalsIgnoreCase(type)){
|
||||
prop = RenderingRuleProperty.createInputStringProperty(attr);
|
||||
} else {
|
||||
prop = RenderingRuleProperty.createInputIntProperty(attr);
|
||||
}
|
||||
prop.setDescription(attributes.getValue("description"));
|
||||
prop.setName(attributes.getValue("name"));
|
||||
if(attributes.getValue("possibleValues") != null){
|
||||
prop.setPossibleValues(attributes.getValue("possibleValues").split(","));
|
||||
}
|
||||
PROPS.registerRule(prop);
|
||||
} else if("renderingStyle".equals(name)){ //$NON-NLS-1$
|
||||
String dc = attributes.getValue("defaultColor");
|
||||
int defaultColor = 0;
|
||||
if(dc != null && dc.length() > 0){
|
||||
bgColor = RenderingRuleProperty.parseColor(dc);
|
||||
}
|
||||
String dnc = attributes.getValue("defaultNightColor");
|
||||
bgNightColor = defaultColor;
|
||||
if(dnc != null && dnc.length() > 0){
|
||||
bgNightColor = RenderingRuleProperty.parseColor(dnc);
|
||||
}
|
||||
renderingName = attributes.getValue("name");
|
||||
depends = attributes.getValue("depends");
|
||||
} else if("renderer".equals(name)){ //$NON-NLS-1$
|
||||
throw new SAXException("Rendering style is deprecated and no longer supported.");
|
||||
} else {
|
||||
log.warn("Unknown tag : " + name); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if(stateChanged){
|
||||
tagValueGlobalRules[state] = new TIntObjectHashMap<RenderingRule>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Map<String, String> parseAttributes(Attributes attributes, Map<String, String> m) {
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
String name = parser.isNamespaceAware() ? attributes.getLocalName(i) : attributes.getQName(i);
|
||||
m.put(name, attributes.getValue(i));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String name) throws SAXException {
|
||||
name = parser.isNamespaceAware() ? localName : name;
|
||||
if ("filter".equals(name)) { //$NON-NLS-1$
|
||||
stack.pop();
|
||||
} else if("group".equals(name)){ //$NON-NLS-1$
|
||||
GroupRules group = (GroupRules) stack.pop();
|
||||
if (stack.size() == 0) {
|
||||
group.registerGlobalRules(state);
|
||||
}
|
||||
} else if("groupFilter".equals(name)){ //$NON-NLS-1$
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getTagValueKey(String tag, String value){
|
||||
int itag = getDictionaryValue(tag);
|
||||
int ivalue = getDictionaryValue(value);
|
||||
return (itag << SHIFT_TAG_VAL) | ivalue;
|
||||
}
|
||||
|
||||
public String getValueString(int tagValueKey){
|
||||
return getStringValue(tagValueKey & ((1 << SHIFT_TAG_VAL) - 1));
|
||||
}
|
||||
|
||||
public String getTagString(int tagValueKey){
|
||||
return getStringValue(tagValueKey >> SHIFT_TAG_VAL);
|
||||
}
|
||||
|
||||
protected RenderingRule getRule(int state, int itag, int ivalue){
|
||||
if(tagValueGlobalRules[state] != null){
|
||||
return tagValueGlobalRules[state].get((itag << SHIFT_TAG_VAL) | ivalue);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void printDebug(int state, PrintStream out){
|
||||
for(int key : tagValueGlobalRules[state].keys()) {
|
||||
RenderingRule rr = tagValueGlobalRules[state].get(key);
|
||||
out.print("\n\n"+getTagString(key) + " : " + getValueString(key));
|
||||
printRenderingRule("", rr, out);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printRenderingRule(String indent, RenderingRule rr, PrintStream out){
|
||||
indent += " ";
|
||||
out.print("\n"+indent);
|
||||
for(RenderingRuleProperty p : rr.getProperties()){
|
||||
out.print(" " + p.getAttrName() + "= ");
|
||||
if(p.isString()){
|
||||
out.print("\"" + rr.getStringPropertyValue(p.getAttrName()) + "\"");
|
||||
} else if(p.isFloat()){
|
||||
out.print(rr.getFloatPropertyValue(p.getAttrName()));
|
||||
} else if(p.isColor()){
|
||||
out.print(rr.getColorPropertyValue(p.getAttrName()));
|
||||
} else if(p.isIntParse()){
|
||||
out.print(rr.getIntPropertyValue(p.getAttrName()));
|
||||
}
|
||||
}
|
||||
for(RenderingRule rc : rr.getIfElseChildren()){
|
||||
printRenderingRule(indent, rc, out);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws SAXException, IOException {
|
||||
RenderingRulesStorage storage = new RenderingRulesStorage();
|
||||
storage.parseRulesFromXmlInputStream(RenderingRulesStorage.class.getResourceAsStream("new_default.render.xml"));
|
||||
// storage.printDebug(LINE_RULES, System.out);
|
||||
long tm = System.nanoTime();
|
||||
int count = 100000;
|
||||
for (int i = 0; i < count; i++) {
|
||||
RenderingRuleSearchRequest searchRequest = new RenderingRuleSearchRequest(storage);
|
||||
searchRequest.setStringFilter(storage.PROPS.R_TAG, "highway");
|
||||
searchRequest.setStringFilter(storage.PROPS.R_VALUE, "motorway");
|
||||
// searchRequest.setIntFilter(storage.PROPS.R_LAYER, 1);
|
||||
searchRequest.setIntFilter(storage.PROPS.R_MINZOOM, 14);
|
||||
searchRequest.setIntFilter(storage.PROPS.R_MAXZOOM, 14);
|
||||
// searchRequest.setStringFilter(storage.PROPS.R_ORDER_TYPE, "line");
|
||||
// searchRequest.setBooleanFilter(storage.PROPS.R_NIGHT_MODE, true);
|
||||
// searchRequest.setBooleanFilter(storage.PROPS.get("hmRendered"), true);
|
||||
|
||||
searchRequest.search(ORDER_RULES);
|
||||
printResult(searchRequest, new PrintStream(new OutputStream() {
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
|
||||
}
|
||||
}));
|
||||
}
|
||||
System.out.println((System.nanoTime()- tm)/ (1e6f * count) );
|
||||
}
|
||||
|
||||
private static void printResult(RenderingRuleSearchRequest searchRequest, PrintStream out) {
|
||||
if(searchRequest.isFound()){
|
||||
out.print(" Found : ");
|
||||
for (RenderingRuleProperty rp : searchRequest.getProperties()) {
|
||||
if(rp.isOutputProperty() && searchRequest.isSpecified(rp)){
|
||||
out.print(" " + rp.getAttrName() + "= ");
|
||||
if(rp.isString()){
|
||||
out.print("\"" + searchRequest.getStringPropertyValue(rp) + "\"");
|
||||
} else if(rp.isFloat()){
|
||||
out.print(searchRequest.getFloatPropertyValue(rp));
|
||||
} else if(rp.isColor()){
|
||||
out.print(searchRequest.getColorStringPropertyValue(rp));
|
||||
} else if(rp.isIntParse()){
|
||||
out.print(searchRequest.getIntPropertyValue(rp));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.println("Not found");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
1362
DataExtractionOSM/src/net/osmand/render/new_default.render.xml
Normal file
1362
DataExtractionOSM/src/net/osmand/render/new_default.render.xml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<resources>
|
||||
<string name="pref_vector_rendering">Vector rendering</string>
|
||||
<string name="pref_overlay">Overlay/underlay</string>
|
||||
<string name="pref_raster_map">Raster map</string>
|
||||
<string name="pref_vector_map">Vector map</string>
|
||||
<string name="delete_confirmation_title">About to delete</string>
|
||||
<string name="delete_confirmation_msg">Are you sure about deleting %1$s?</string>
|
||||
<string name="city_type_suburb">Suburb</string>
|
||||
|
|
|
@ -5,27 +5,31 @@
|
|||
|
||||
|
||||
<PreferenceScreen android:key="map_settings" android:title="@string/rendering_settings" android:summary="@string/rendering_settings_descr">
|
||||
<PreferenceCategory android:title="@string/pref_raster_map">
|
||||
<ListPreference android:title="@string/map_tile_source" android:summary="@string/map_tile_source_descr" android:key="map_tile_sources"></ListPreference>
|
||||
<CheckBoxPreference android:key="use_internet_to_download_tiles" android:title="@string/use_internet" android:summary="@string/use_internet_to_download_tile"></CheckBoxPreference>
|
||||
<ListPreference android:title="@string/max_level_download_tile" android:summary="@string/max_level_download_tile_descr"
|
||||
android:key="max_level_download_tile"></ListPreference>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/pref_vector_map">
|
||||
<CheckBoxPreference android:summary="@string/map_vector_data_descr" android:title="@string/map_vector_data"
|
||||
android:key="map_vector_data"></CheckBoxPreference>
|
||||
<ListPreference android:title="@string/map_tile_source" android:summary="@string/map_tile_source_descr" android:key="map_tile_sources"></ListPreference>
|
||||
<CheckBoxPreference android:summary="@string/use_english_names_descr" android:title="@string/use_english_names"
|
||||
android:key="use_english_names"></CheckBoxPreference>
|
||||
<CheckBoxPreference android:key="show_more_map_detail" android:title="@string/show_more_map_detail"
|
||||
android:summary="@string/show_more_map_detail_descr"></CheckBoxPreference>
|
||||
<ListPreference android:key="renderer" android:title="@string/renderers" android:summary="@string/renderers_descr"></ListPreference>
|
||||
<ListPreference android:key="daynight_mode" android:title="@string/daynight" android:summary="@string/daynight_descr"></ListPreference>
|
||||
<ListPreference android:title="@string/level_to_switch_vector_raster" android:summary="@string/level_to_switch_vector_raster_descr"
|
||||
android:key="level_to_switch_vector_raster"></ListPreference>
|
||||
<ListPreference android:key="map_text_size" android:title="@string/map_text_size" android:summary="@string/map_text_size_descr"/>
|
||||
</PreferenceCategory>
|
||||
<CheckBoxPreference android:key="use_high_res_maps" android:title="@string/use_high_res_maps" android:summary="@string/use_high_res_maps_descr"></CheckBoxPreference>
|
||||
<PreferenceCategory android:title="@string/pref_overlay">
|
||||
<ListPreference android:title="@string/map_overlay" android:summary="@string/map_overlay_descr" android:key="map_overlay"></ListPreference>
|
||||
<net.osmand.plus.views.SeekBarPreference android:key="overlay_transparency" android:defaultValue="0" android:max="255"
|
||||
android:dialogMessage="@string/modify_transparency" android:title="@string/overlay_transparency" android:summary="@string/overlay_transparency_descr"/>
|
||||
<ListPreference android:title="@string/map_underlay" android:summary="@string/map_underlay_descr" android:key="map_underlay"></ListPreference>
|
||||
<net.osmand.plus.views.SeekBarPreference android:key="map_transparency" android:defaultValue="0" android:max="255"
|
||||
android:dialogMessage="@string/modify_transparency" android:title="@string/map_transparency" android:summary="@string/map_transparency_descr"/>
|
||||
<CheckBoxPreference android:summary="@string/continuous_rendering_descr" android:title="@string/continuous_rendering"
|
||||
android:key="use_step_by_step_rendering" />
|
||||
<ListPreference android:key="map_text_size" android:title="@string/map_text_size" android:summary="@string/map_text_size_descr"/>
|
||||
<CheckBoxPreference android:key="use_high_res_maps" android:title="@string/use_high_res_maps" android:summary="@string/use_high_res_maps_descr"></CheckBoxPreference>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/pref_vector_rendering" android:key="custom_vector_rendering">
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
|
@ -69,17 +73,17 @@
|
|||
|
||||
|
||||
<PreferenceScreen android:key="general_settings" android:title="@string/general_settings" android:summary="@string/general_settings_descr">
|
||||
<CheckBoxPreference android:key="use_internet_to_download_tiles" android:title="@string/use_internet" android:summary="@string/use_internet_to_download_tile"></CheckBoxPreference>
|
||||
<ListPreference android:title="@string/max_level_download_tile" android:summary="@string/max_level_download_tile_descr"
|
||||
android:key="max_level_download_tile"></ListPreference>
|
||||
<CheckBoxPreference android:summary="@string/use_english_names_descr" android:title="@string/use_english_names"
|
||||
android:key="use_english_names"></CheckBoxPreference>
|
||||
<ListPreference android:key="map_screen_orientation" android:title="@string/map_screen_orientation" android:summary="@string/map_screen_orientation_descr"></ListPreference>
|
||||
<ListPreference android:key="daynight_mode" android:title="@string/daynight" android:summary="@string/daynight_descr"></ListPreference>
|
||||
<CheckBoxPreference android:title="@string/auto_zoom_map" android:summary="@string/auto_zoom_map_descr" android:key="auto_zoom_map"></CheckBoxPreference>
|
||||
<CheckBoxPreference android:key="show_view_angle" android:title="@string/show_view_angle" android:summary="@string/show_view_angle_descr"></CheckBoxPreference>
|
||||
<ListPreference android:key="rotate_map" android:title="@string/rotate_map_to_bearing" android:summary="@string/rotate_map_to_bearing_descr"></ListPreference>
|
||||
<ListPreference android:key="map_screen_orientation" android:title="@string/map_screen_orientation" android:summary="@string/map_screen_orientation_descr"></ListPreference>
|
||||
<ListPreference android:key="preferred_locale" android:title="@string/preferred_locale" android:summary="@string/preferred_locale_descr"></ListPreference>
|
||||
<ListPreference android:key="default_metric_system" android:title="@string/unit_of_length" android:summary="@string/unit_of_length_descr"></ListPreference>
|
||||
<ListPreference android:key="position_on_map" android:title="@string/position_on_map" android:summary="@string/position_on_map_descr"></ListPreference>
|
||||
<CheckBoxPreference android:key="use_trackball_for_movements" android:title="@string/use_trackball" android:summary="@string/use_trackball_descr"></CheckBoxPreference>
|
||||
<ListPreference android:key="preferred_locale" android:title="@string/preferred_locale" android:summary="@string/preferred_locale_descr"></ListPreference>
|
||||
<EditTextPreference android:title="@string/application_dir" android:key="external_storage_dir"></EditTextPreference>
|
||||
</PreferenceScreen>
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ import net.osmand.osm.LatLon;
|
|||
import net.osmand.plus.activities.ApplicationMode;
|
||||
import net.osmand.plus.activities.OsmandApplication;
|
||||
import net.osmand.plus.activities.search.SearchHistoryHelper;
|
||||
import net.osmand.plus.render.BaseOsmandRender;
|
||||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.routing.RouteProvider.RouteService;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
|
@ -143,7 +143,7 @@ public class OsmandSettings {
|
|||
}
|
||||
// update vector renderer
|
||||
RendererRegistry registry = ctx.getRendererRegistry();
|
||||
BaseOsmandRender newRenderer = registry.getRenderer(RENDERER.get());
|
||||
RenderingRulesStorage newRenderer = registry.getRenderer(RENDERER.get());
|
||||
if (newRenderer == null) {
|
||||
newRenderer = registry.defaultRender();
|
||||
}
|
||||
|
@ -564,18 +564,6 @@ public class OsmandSettings {
|
|||
return USE_ENGLISH_NAMES.get();
|
||||
}
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final OsmandPreference<Boolean> SHOW_MORE_MAP_DETAIL = new BooleanPreference("show_more_map_detail", false, true);
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final CommonPreference<Boolean> USE_STEP_BY_STEP_RENDERING = new BooleanPreference("use_step_by_step_rendering",
|
||||
true, false);
|
||||
{
|
||||
USE_STEP_BY_STEP_RENDERING.setModeDefaultValue(ApplicationMode.CAR, true);
|
||||
USE_STEP_BY_STEP_RENDERING.setModeDefaultValue(ApplicationMode.BICYCLE, true);
|
||||
USE_STEP_BY_STEP_RENDERING.setModeDefaultValue(ApplicationMode.PEDESTRIAN, true);
|
||||
}
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final CommonPreference<Boolean> MAP_VECTOR_DATA = new BooleanPreference("map_vector_data",
|
||||
false, true);
|
||||
|
@ -1001,7 +989,7 @@ public class OsmandSettings {
|
|||
if(val == null){
|
||||
val = RendererRegistry.DEFAULT_RENDER;
|
||||
}
|
||||
BaseOsmandRender loaded = ctx.getRendererRegistry().getRenderer(val);
|
||||
RenderingRulesStorage loaded = ctx.getRendererRegistry().getRenderer(val);
|
||||
if (loaded != null) {
|
||||
ctx.getRendererRegistry().setCurrentSelectedRender(loaded);
|
||||
super.setValue(prefs, val);
|
||||
|
@ -1011,12 +999,20 @@ public class OsmandSettings {
|
|||
return false;
|
||||
};
|
||||
};
|
||||
{
|
||||
RENDERER.setModeDefaultValue(ApplicationMode.CAR, RendererRegistry.CAR_RENDER);
|
||||
RENDERER.setModeDefaultValue(ApplicationMode.PEDESTRIAN, RendererRegistry.PEDESTRIAN_RENDER);
|
||||
RENDERER.setModeDefaultValue(ApplicationMode.BICYCLE, RendererRegistry.BICYCLE_RENDER);
|
||||
}
|
||||
|
||||
Map<String, CommonPreference<String>> customRendersProps = new LinkedHashMap<String, OsmandSettings.CommonPreference<String>>();
|
||||
public CommonPreference<String> getCustomRenderProperty(String attrName){
|
||||
if(!customRendersProps.containsKey(attrName)){
|
||||
customRendersProps.put(attrName, new StringPreference("renderer_"+attrName, "", false));
|
||||
}
|
||||
return customRendersProps.get(attrName);
|
||||
}
|
||||
{
|
||||
CommonPreference<String> pref = getCustomRenderProperty("appMode");
|
||||
pref.setModeDefaultValue(ApplicationMode.CAR, "car");
|
||||
pref.setModeDefaultValue(ApplicationMode.PEDESTRIAN, "pedestrian");
|
||||
pref.setModeDefaultValue(ApplicationMode.BICYCLE, "bicycle");
|
||||
}
|
||||
|
||||
public final OsmandPreference<Boolean> VOICE_MUTE = new BooleanPreference("voice_mute", false, true);
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ import net.osmand.plus.AsyncLoadingThread.MapLoadRequest;
|
|||
import net.osmand.plus.AsyncLoadingThread.TileLoadDownloadRequest;
|
||||
import net.osmand.plus.AsyncLoadingThread.TransportLoadRequest;
|
||||
import net.osmand.plus.activities.OsmandApplication;
|
||||
import net.osmand.plus.render.BaseOsmandRender;
|
||||
import net.osmand.plus.render.MapRenderRepositories;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
@ -435,7 +435,7 @@ public class ResourceManager {
|
|||
context.getRendererRegistry().setExternalRenderers(externalRenderers);
|
||||
String r = context.getSettings().RENDERER.get();
|
||||
if(r != null){
|
||||
BaseOsmandRender obj = context.getRendererRegistry().getRenderer(r);
|
||||
RenderingRulesStorage obj = context.getRendererRegistry().getRenderer(r);
|
||||
if(obj != null){
|
||||
context.getRendererRegistry().setCurrentSelectedRender(obj);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import net.osmand.map.TileSourceManager;
|
|||
import net.osmand.map.TileSourceManager.TileSourceTemplate;
|
||||
import net.osmand.plus.NavigationService;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.OsmandSettings.CommonPreference;
|
||||
import net.osmand.plus.OsmandSettings.DayNightMode;
|
||||
import net.osmand.plus.OsmandSettings.MetricsConstants;
|
||||
import net.osmand.plus.OsmandSettings.OsmandPreference;
|
||||
|
@ -22,8 +23,11 @@ import net.osmand.plus.ProgressDialogImplementation;
|
|||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.render.MapRenderRepositories;
|
||||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.routing.RouteProvider.RouteService;
|
||||
import net.osmand.plus.views.SeekBarPreference;
|
||||
import net.osmand.render.RenderingRuleProperty;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
|
@ -43,6 +47,7 @@ import android.preference.CheckBoxPreference;
|
|||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
@ -160,12 +165,10 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
registerBooleanPreference(osmandSettings.USE_TRACKBALL_FOR_MOVEMENTS,screen);
|
||||
registerBooleanPreference(osmandSettings.USE_HIGH_RES_MAPS,screen);
|
||||
registerBooleanPreference(osmandSettings.USE_ENGLISH_NAMES,screen);
|
||||
registerBooleanPreference(osmandSettings.SHOW_MORE_MAP_DETAIL,screen);
|
||||
registerBooleanPreference(osmandSettings.AUTO_ZOOM_MAP,screen);
|
||||
registerBooleanPreference(osmandSettings.AUTO_FOLLOW_ROUTE_NAV,screen);
|
||||
registerBooleanPreference(osmandSettings.SAVE_TRACK_TO_GPX,screen);
|
||||
registerBooleanPreference(osmandSettings.DEBUG_RENDERING_INFO,screen);
|
||||
registerBooleanPreference(osmandSettings.USE_STEP_BY_STEP_RENDERING,screen);
|
||||
registerBooleanPreference(osmandSettings.FAST_ROUTE_MODE,screen);
|
||||
registerBooleanPreference(osmandSettings.USE_OSMAND_ROUTING_SERVICE_ALWAYS,screen);
|
||||
registerBooleanPreference(osmandSettings.USE_INTERNET_TO_DOWNLOAD_TILES,screen);
|
||||
|
@ -284,6 +287,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
entries = (String[]) rendererNames.toArray(new String[rendererNames.size()]);
|
||||
registerListPreference(osmandSettings.RENDERER, screen, entries, entries);
|
||||
|
||||
createCustomRenderingProperties();
|
||||
|
||||
tileSourcePreference = (ListPreference) screen.findPreference(osmandSettings.MAP_TILE_SOURCES.getId());
|
||||
tileSourcePreference.setOnPreferenceChangeListener(this);
|
||||
overlayPreference = (ListPreference) screen.findPreference(osmandSettings.MAP_OVERLAY.getId());
|
||||
|
@ -304,6 +309,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
applicationDir.setOnPreferenceChangeListener(this);
|
||||
|
||||
|
||||
|
||||
broadcastReceiver = new BroadcastReceiver(){
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
@ -334,6 +340,35 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
}
|
||||
}
|
||||
|
||||
private void createCustomRenderingProperties() {
|
||||
RenderingRulesStorage renderer = getMyApplication().getRendererRegistry().getCurrentSelectedRenderer();
|
||||
PreferenceCategory cat = (PreferenceCategory) findPreference("custom_vector_rendering");
|
||||
cat.removeAll();
|
||||
if(renderer != null){
|
||||
for(RenderingRuleProperty p : renderer.PROPS.getCustomRules()){
|
||||
CommonPreference<String> custom = getMyApplication().getSettings().getCustomRenderProperty(p.getAttrName());
|
||||
ListPreference lp = new ListPreference(this);
|
||||
lp.setOnPreferenceChangeListener(this);
|
||||
lp.setKey(custom.getId());
|
||||
lp.setTitle(p.getName());
|
||||
lp.setSummary(p.getDescription());
|
||||
cat.addPreference(lp);
|
||||
|
||||
|
||||
LinkedHashMap<String, Object> vals = new LinkedHashMap<String, Object>();
|
||||
screenPreferences.put(custom.getId(), lp);
|
||||
listPreferences.put(custom.getId(), custom);
|
||||
listPrefValues.put(custom.getId(), vals);
|
||||
String[] names = p.getPossibleValues();
|
||||
for(int i=0; i<names.length; i++){
|
||||
vals.put(names[i], names[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void reloadVoiceListPreference(PreferenceScreen screen) {
|
||||
String[] entries;
|
||||
String[] entrieValues;
|
||||
|
@ -516,6 +551,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
} else {
|
||||
Toast.makeText(this, R.string.renderer_load_exception, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
createCustomRenderingProperties();
|
||||
}
|
||||
} else if(preference == applicationDir){
|
||||
warnAboutChangingStorage((String) newValue);
|
||||
|
|
|
@ -1,414 +0,0 @@
|
|||
package net.osmand.plus.render;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.plus.render.OsmandRenderer.RenderingContext;
|
||||
import net.osmand.plus.render.OsmandRenderer.RenderingPaintProperties;
|
||||
import net.osmand.render.OsmandRenderingRulesParser;
|
||||
import net.osmand.render.OsmandRenderingRulesParser.EffectAttributes;
|
||||
import net.osmand.render.OsmandRenderingRulesParser.FilterState;
|
||||
import net.osmand.render.OsmandRenderingRulesParser.RenderingRuleVisitor;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint.Cap;
|
||||
|
||||
|
||||
public class BaseOsmandRender implements RenderingRuleVisitor {
|
||||
|
||||
public String name = "default"; //$NON-NLS-1$
|
||||
public List<String> depends = new ArrayList<String>();
|
||||
public List<BaseOsmandRender> dependRenderers = new ArrayList<BaseOsmandRender>();
|
||||
private static final Log log = LogUtil.getLog(BaseOsmandRender.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Map<String, List<FilterState>>>[] rules = new LinkedHashMap[6];
|
||||
|
||||
|
||||
private int defaultColor;
|
||||
private int defaultNightColor;
|
||||
|
||||
|
||||
public void init(InputStream is) throws IOException, SAXException{
|
||||
long time = System.currentTimeMillis();
|
||||
OsmandRenderingRulesParser parser = new OsmandRenderingRulesParser();
|
||||
parser.parseRenderingRules(is, this);
|
||||
log.info("Init render " + name + " for " + (System.currentTimeMillis() - time) + " ms"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
|
||||
}
|
||||
|
||||
public BaseOsmandRender() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rendering(String name, String depends, int defaultColor, int defaultNightColor) {
|
||||
this.name = name;
|
||||
this.defaultColor = defaultColor;
|
||||
this.defaultNightColor = defaultNightColor;
|
||||
if(depends != null && depends.length() > 0){
|
||||
for(String s : depends.split(",")) { //$NON-NLS-1$
|
||||
if(s.trim().length() > 0){
|
||||
this.depends.add(s.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getDefaultColor(boolean nightMode) {
|
||||
int r = nightMode ? defaultNightColor : defaultColor ;
|
||||
if (r == 0) {
|
||||
for (BaseOsmandRender d : dependRenderers) {
|
||||
r = d.getDefaultColor(nightMode);
|
||||
if (r != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRule(int state, FilterState filter) {
|
||||
boolean accept = filter.minzoom != -1 || state == OsmandRenderingRulesParser.ORDER_STATE;
|
||||
if(state == OsmandRenderingRulesParser.POINT_STATE){
|
||||
accept &= RenderingIcons.getIcons().containsKey(filter.icon);
|
||||
}
|
||||
if(state == OsmandRenderingRulesParser.ORDER_STATE){
|
||||
accept &= filter.order != 0 && filter.orderType != 0;
|
||||
}
|
||||
if (accept) {
|
||||
if (rules[state] == null) {
|
||||
rules[state] = new LinkedHashMap<String, Map<String, List<FilterState>>>();
|
||||
}
|
||||
if (rules[state].get(filter.tag) == null) {
|
||||
rules[state].put(filter.tag, new LinkedHashMap<String, List<FilterState>>());
|
||||
}
|
||||
if (rules[state].get(filter.tag).get(filter.val) == null) {
|
||||
rules[state].get(filter.tag).put(filter.val, new ArrayList<FilterState>(3));
|
||||
}
|
||||
rules[state].get(filter.tag).get(filter.val).add(filter);
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getPointIcon(String tag, String val, int zoom, boolean nightMode) {
|
||||
Integer i = getPointIconImpl(tag, val, zoom, nightMode);
|
||||
if (i == null) {
|
||||
i = getPointIconImpl(tag, null, zoom, nightMode);
|
||||
}
|
||||
if (i == null) {
|
||||
for (BaseOsmandRender d : dependRenderers) {
|
||||
i = d.getPointIcon(tag, val, zoom, nightMode);
|
||||
if (i != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// type
|
||||
public float getObjectOrder(String tag, String val, int type, int layer) {
|
||||
if(type == 0){
|
||||
// replace multipolygon with polygon
|
||||
type = 3;
|
||||
}
|
||||
float f = getObjectOrderImpl(tag, val, type, layer);
|
||||
if (f == 0) {
|
||||
f = getObjectOrderImpl(tag, null, type, layer);
|
||||
}
|
||||
if (f == 0) {
|
||||
f = getObjectOrderImpl("", null, type, layer); //$NON-NLS-1$
|
||||
}
|
||||
if(f == 0){
|
||||
for(BaseOsmandRender d : dependRenderers){
|
||||
f = d.getObjectOrder(tag, val, type, layer);
|
||||
if (f != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (f == 0) {
|
||||
if (type == 0 || type == 3) {
|
||||
return 1f;
|
||||
} else if (type == 1) {
|
||||
return 128f;
|
||||
} else {
|
||||
return 35f;
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean renderPolyline(String tag, String val, int zoom, RenderingContext rc, OsmandRenderer o, int layer, boolean nightMode){
|
||||
boolean r = renderPolylineImpl(tag, val, zoom, rc, o, layer, nightMode);
|
||||
if(!r){
|
||||
r = renderPolylineImpl(tag, null, zoom, rc, o, layer, nightMode);
|
||||
}
|
||||
if(!r){
|
||||
for(BaseOsmandRender d : dependRenderers){
|
||||
r = d.renderPolyline(tag, val, zoom, rc, o, layer, nightMode);
|
||||
if (r) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
public boolean renderPolygon(String tag, String val, int zoom, RenderingContext rc, OsmandRenderer o, boolean nightMode){
|
||||
boolean r = renderPolygonImpl(tag,val, zoom, rc, o, nightMode);
|
||||
if(!r){
|
||||
r = renderPolygonImpl(tag, null, zoom, rc, o, nightMode);
|
||||
}
|
||||
if(!r){
|
||||
for(BaseOsmandRender d : dependRenderers){
|
||||
r = d.renderPolygon(tag, val, zoom, rc, o, nightMode);
|
||||
if (r) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public String renderObjectText(String name, String tag, String val, RenderingContext rc, boolean ref, boolean nightMode) {
|
||||
if(name == null || name.length() == 0){
|
||||
return null;
|
||||
}
|
||||
String ret = renderObjectTextImpl(name, tag, val, rc, ref, nightMode);
|
||||
if(ret == null){
|
||||
ret = renderObjectTextImpl(name, tag, null, rc, ref, nightMode);
|
||||
}
|
||||
if(ret == null){
|
||||
for(BaseOsmandRender d : dependRenderers){
|
||||
ret = d.renderObjectText(name, tag, val, rc, ref, nightMode);
|
||||
if (ret != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean isObjectVisible(String tag, String val, int zoom, int type, boolean nightMode) {
|
||||
if (type == 0) {
|
||||
// replace multipolygon with polygon
|
||||
type = 3;
|
||||
}
|
||||
if (isObjectVisibleImpl(tag, val, zoom, type, nightMode)) {
|
||||
return true;
|
||||
}
|
||||
if (isObjectVisibleImpl(tag, null, zoom, type, nightMode)) {
|
||||
return true;
|
||||
}
|
||||
for (BaseOsmandRender d : dependRenderers) {
|
||||
if (d.isObjectVisible(tag, val, zoom, type, nightMode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean isObjectVisibleImpl(String tag, String val, int zoom, int type, boolean nightMode) {
|
||||
FilterState fs = findBestFilterState(tag, val, zoom, nightMode, 0, null, 0, rules[type]);
|
||||
return fs != null;
|
||||
}
|
||||
|
||||
private float getObjectOrderImpl(String tag, String val, int type, int layer) {
|
||||
if (rules[OsmandRenderingRulesParser.ORDER_STATE] != null) {
|
||||
Map<String, List<FilterState>> map = rules[OsmandRenderingRulesParser.ORDER_STATE].get(tag);
|
||||
if (map != null) {
|
||||
List<FilterState> list = map.get(val);
|
||||
if (list != null) {
|
||||
int sz = list.size();
|
||||
for (int i = 0; i < sz; i++) {
|
||||
FilterState f = list.get(i);
|
||||
if (f.orderType == type && f.layer == layer) {
|
||||
return f.order;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private Integer getPointIconImpl(String tag, String val, int zoom, boolean nightMode) {
|
||||
FilterState fs = findBestFilterState(tag, val, zoom, nightMode, 0, null, 0, rules[OsmandRenderingRulesParser.POINT_STATE]);
|
||||
if (fs != null) {
|
||||
Integer i = RenderingIcons.getIcons().get(fs.icon);
|
||||
return i == null ? 0 : i;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private FilterState findBestFilterState(String tag, String val, int zoom, boolean nightMode, int layer, Boolean ref,
|
||||
int nameLength, Map<String, Map<String, List<FilterState>>> mapTag) {
|
||||
if (mapTag != null) {
|
||||
Map<String, List<FilterState>> map = mapTag.get(tag);
|
||||
if (map != null) {
|
||||
List<FilterState> list = map.get(val);
|
||||
if (list != null) {
|
||||
FilterState bestResult = null;
|
||||
boolean prevDayNightMatches = false;
|
||||
boolean prevLayerMatches = false;
|
||||
int sz = list.size();
|
||||
for (int i = 0; i < sz; i++) {
|
||||
FilterState f = list.get(i);
|
||||
if (f.minzoom <= zoom && (zoom <= f.maxzoom || f.maxzoom == -1)) {
|
||||
if(ref != null && !checkRefTextRule(f, ref.booleanValue())){
|
||||
continue;
|
||||
}
|
||||
if(f.textLength != nameLength){
|
||||
continue;
|
||||
}
|
||||
boolean dayNightMatches = (f.nightMode != null && f.nightMode.booleanValue() == nightMode) ||
|
||||
(!nightMode && f.nightMode == null);
|
||||
boolean layerMatches = f.layer == layer;
|
||||
boolean defLayerMatches = f.layer == 0;
|
||||
if (dayNightMatches || !prevDayNightMatches){
|
||||
if(dayNightMatches && !prevDayNightMatches){
|
||||
if(layerMatches || defLayerMatches){
|
||||
prevDayNightMatches = true;
|
||||
prevLayerMatches = false;
|
||||
}
|
||||
}
|
||||
if(layerMatches){
|
||||
prevLayerMatches = true;
|
||||
bestResult = f;
|
||||
} else if(defLayerMatches && !prevLayerMatches){
|
||||
bestResult = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean renderPolylineImpl(String tag, String val, int zoom, RenderingContext rc, OsmandRenderer o, int layer, boolean nightMode) {
|
||||
FilterState found = findBestFilterState(tag, val, zoom, nightMode, layer, null, 0, rules[OsmandRenderingRulesParser.LINE_STATE]);
|
||||
if (found != null) {
|
||||
// to not make transparent
|
||||
rc.main.color = Color.BLACK;
|
||||
if (found.shader != null) {
|
||||
Integer i = RenderingIcons.getIcons().get(found.shader);
|
||||
if (i != null) {
|
||||
rc.main.shader = o.getShader(i);
|
||||
}
|
||||
}
|
||||
rc.main.fillArea = false;
|
||||
applyEffectAttributes(found.main, rc.main, o);
|
||||
if (found.effectAttributes.size() > 0) {
|
||||
applyEffectAttributes(found.effectAttributes.get(0), rc.second, o);
|
||||
if (found.effectAttributes.size() > 1) {
|
||||
applyEffectAttributes(found.effectAttributes.get(1), rc.third, o);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private boolean renderPolygonImpl(String tag, String val, int zoom, RenderingContext rc, OsmandRenderer o, boolean nightMode) {
|
||||
FilterState f = findBestFilterState(tag, val, zoom, nightMode, 0, null, 0, rules[OsmandRenderingRulesParser.POLYGON_STATE]);
|
||||
if (f != null) {
|
||||
if (f.shader != null) {
|
||||
Integer i = RenderingIcons.getIcons().get(f.shader);
|
||||
if (i != null) {
|
||||
// to not make transparent
|
||||
rc.main.color = Color.BLACK;
|
||||
rc.main.shader = o.getShader(i);
|
||||
}
|
||||
}
|
||||
rc.main.fillArea = true;
|
||||
applyEffectAttributes(f.main, rc.main, o);
|
||||
if (f.effectAttributes.size() > 0) {
|
||||
applyEffectAttributes(f.effectAttributes.get(0), rc.second, o);
|
||||
if (f.effectAttributes.size() > 1) {
|
||||
applyEffectAttributes(f.effectAttributes.get(1), rc.third, o);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void applyEffectAttributes(EffectAttributes ef, RenderingPaintProperties props, OsmandRenderer o){
|
||||
if(ef.cap != null){
|
||||
props.cap = Cap.valueOf(ef.cap.toUpperCase());
|
||||
}
|
||||
if(ef.color != 0){
|
||||
// do not set transparent color
|
||||
props.color = ef.color;
|
||||
}
|
||||
if(ef.pathEffect != null){
|
||||
props.pathEffect = o.getDashEffect(ef.pathEffect);
|
||||
}
|
||||
if(ef.strokeWidth > 0){
|
||||
props.strokeWidth = ef.strokeWidth;
|
||||
}
|
||||
if(ef.shadowColor != 0 && ef.shadowRadius > 0){
|
||||
props.shadowColor = ef.shadowColor;
|
||||
props.shadowLayer = (int) ef.shadowRadius;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean checkRefTextRule(FilterState f, boolean ref){
|
||||
if(ref){
|
||||
return f.text != null && f.text.ref != null;
|
||||
} else {
|
||||
return f.text == null || f.text.ref == null || "true".equals(f.text.ref); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
private String renderObjectTextImpl(String name, String tag, String val, RenderingContext rc, boolean ref, boolean nightMode) {
|
||||
FilterState fs = findBestFilterState(tag, val, rc.zoom, nightMode, 0, ref, name.length(), rules[OsmandRenderingRulesParser.TEXT_STATE]);
|
||||
if(fs == null){
|
||||
fs = findBestFilterState(tag, val, rc.zoom, nightMode, 0, ref, 0, rules[OsmandRenderingRulesParser.TEXT_STATE]);
|
||||
}
|
||||
if(fs != null){
|
||||
fillTextProperties(fs, rc);
|
||||
return name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void fillTextProperties(FilterState f, RenderingContext rc) {
|
||||
rc.textSize = f.text.textSize;
|
||||
rc.textColor = f.text.textColor == 0 ? Color.BLACK : f.text.textColor;
|
||||
rc.textOrder = f.text.textOrder;
|
||||
rc.textMinDistance = f.text.textMinDistance;
|
||||
rc.showTextOnPath = f.text.textOnPath;
|
||||
Integer i = RenderingIcons.getIcons().get(f.text.textShield);
|
||||
rc.textShield = i== null ? 0 : i.intValue();
|
||||
rc.textWrapWidth = f.text.textWrapWidth;
|
||||
rc.textHaloRadius = f.text.textHaloRadius;
|
||||
rc.textBold = f.text.textBold;
|
||||
rc.textDy = f.text.textDy;
|
||||
}
|
||||
|
||||
public List<String> getDepends() {
|
||||
return depends;
|
||||
}
|
||||
|
||||
public void setDependRenderers(List<BaseOsmandRender> dependRenderers) {
|
||||
this.dependRenderers = dependRenderers;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.IProgress;
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.binary.BinaryMapDataObject;
|
||||
|
@ -31,11 +32,14 @@ import net.osmand.osm.MapRenderingTypes;
|
|||
import net.osmand.osm.MapUtils;
|
||||
import net.osmand.osm.MultyPolygon;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.OsmandSettings.CommonPreference;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.RotatedTileBox;
|
||||
import net.osmand.plus.activities.OsmandApplication;
|
||||
import net.osmand.plus.render.OsmandRenderer.RenderingContext;
|
||||
import net.osmand.render.OsmandRenderingRulesParser;
|
||||
import net.osmand.render.RenderingRuleProperty;
|
||||
import net.osmand.render.RenderingRuleSearchRequest;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
|
@ -57,7 +61,6 @@ public class MapRenderRepositories {
|
|||
|
||||
private static String BASEMAP_NAME = "basemap";
|
||||
|
||||
|
||||
// lat/lon box of requested vector data
|
||||
private RectF cObjectsBox = new RectF();
|
||||
// cached objects in order to render rotation without reloading data from db
|
||||
|
@ -81,7 +84,8 @@ public class MapRenderRepositories {
|
|||
private RenderingContext currentRenderingContext;
|
||||
private SearchRequest<BinaryMapDataObject> searchRequest;
|
||||
private OsmandSettings prefs;
|
||||
public MapRenderRepositories(Context context){
|
||||
|
||||
public MapRenderRepositories(Context context) {
|
||||
this.context = context;
|
||||
this.renderer = new OsmandRenderer(context);
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
|
@ -92,10 +96,9 @@ public class MapRenderRepositories {
|
|||
return context;
|
||||
}
|
||||
|
||||
|
||||
public BinaryMapIndexReader initializeNewResource(final IProgress progress, File file) {
|
||||
long start = System.currentTimeMillis();
|
||||
if(files.containsKey(file.getAbsolutePath())){
|
||||
if (files.containsKey(file.getAbsolutePath())) {
|
||||
closeConnection(files.get(file.getAbsolutePath()), file.getAbsolutePath());
|
||||
}
|
||||
RandomAccessFile raf = null;
|
||||
|
@ -103,14 +106,14 @@ public class MapRenderRepositories {
|
|||
try {
|
||||
raf = new RandomAccessFile(file, "r"); //$NON-NLS-1$
|
||||
reader = new BinaryMapIndexReader(raf);
|
||||
if(reader.getVersion() != IndexConstants.BINARY_MAP_VERSION){
|
||||
if (reader.getVersion() != IndexConstants.BINARY_MAP_VERSION) {
|
||||
return null;
|
||||
}
|
||||
files.put(file.getAbsolutePath(), reader);
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("No connection or unsupported version", e); //$NON-NLS-1$
|
||||
if(raf != null){
|
||||
if (raf != null) {
|
||||
try {
|
||||
raf.close();
|
||||
} catch (IOException e1) {
|
||||
|
@ -118,7 +121,7 @@ public class MapRenderRepositories {
|
|||
}
|
||||
return null;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if(raf != null){
|
||||
if (raf != null) {
|
||||
try {
|
||||
raf.close();
|
||||
} catch (IOException e1) {
|
||||
|
@ -140,7 +143,7 @@ public class MapRenderRepositories {
|
|||
return prevBmpLocation;
|
||||
}
|
||||
|
||||
protected void closeConnection(BinaryMapIndexReader c, String file){
|
||||
protected void closeConnection(BinaryMapIndexReader c, String file) {
|
||||
files.remove(file);
|
||||
try {
|
||||
c.close();
|
||||
|
@ -160,60 +163,59 @@ public class MapRenderRepositories {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void clearAllResources(){
|
||||
public void clearAllResources() {
|
||||
clearCache();
|
||||
for(String f : new ArrayList<String>(files.keySet())){
|
||||
for (String f : new ArrayList<String>(files.keySet())) {
|
||||
closeConnection(files.get(f), f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean updateMapIsNeeded(RotatedTileBox box){
|
||||
public boolean updateMapIsNeeded(RotatedTileBox box) {
|
||||
if (files.isEmpty() || box == null) {
|
||||
return false;
|
||||
}
|
||||
if(requestedBox == null){
|
||||
if (requestedBox == null) {
|
||||
return true;
|
||||
}
|
||||
if(requestedBox.getZoom() != box.getZoom()){
|
||||
if (requestedBox.getZoom() != box.getZoom()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
float deltaRotate = requestedBox.getRotate() - box.getRotate();
|
||||
if(deltaRotate > 180){
|
||||
if (deltaRotate > 180) {
|
||||
deltaRotate -= 360;
|
||||
} else if(deltaRotate < -180){
|
||||
} else if (deltaRotate < -180) {
|
||||
deltaRotate += 360;
|
||||
}
|
||||
if(Math.abs(deltaRotate) > 25){
|
||||
if (Math.abs(deltaRotate) > 25) {
|
||||
return true;
|
||||
}
|
||||
return !requestedBox.containsTileBox(box);
|
||||
}
|
||||
|
||||
public boolean isEmpty(){
|
||||
public boolean isEmpty() {
|
||||
return files.isEmpty();
|
||||
}
|
||||
|
||||
public void interruptLoadingMap(){
|
||||
public void interruptLoadingMap() {
|
||||
interrupted = true;
|
||||
if(currentRenderingContext != null){
|
||||
if (currentRenderingContext != null) {
|
||||
currentRenderingContext.interrupted = true;
|
||||
}
|
||||
if(searchRequest != null){
|
||||
if (searchRequest != null) {
|
||||
searchRequest.setInterrupted(true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkWhetherInterrupted(){
|
||||
if(interrupted || (currentRenderingContext != null && currentRenderingContext.interrupted)){
|
||||
private boolean checkWhetherInterrupted() {
|
||||
if (interrupted || (currentRenderingContext != null && currentRenderingContext.interrupted)) {
|
||||
requestedBox = bmpLocation;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean basemapExists(){
|
||||
public boolean basemapExists() {
|
||||
for (String f : files.keySet()) {
|
||||
if (f.toLowerCase().contains(BASEMAP_NAME)) {
|
||||
return true;
|
||||
|
@ -222,7 +224,7 @@ public class MapRenderRepositories {
|
|||
return false;
|
||||
}
|
||||
|
||||
private boolean loadVectorData(RectF dataBox, final int zoom, final BaseOsmandRender renderingType, final boolean nightMode){
|
||||
private boolean loadVectorData(RectF dataBox, final int zoom, final RenderingRuleSearchRequest renderingReq, final boolean nightMode) {
|
||||
double cBottomLatitude = dataBox.bottom;
|
||||
double cTopLatitude = dataBox.top;
|
||||
double cLeftLongitude = dataBox.left;
|
||||
|
@ -256,13 +258,22 @@ public class MapRenderRepositories {
|
|||
int type = types.get(j);
|
||||
int mask = type & 3;
|
||||
TagValuePair pair = root.decodeType(type);
|
||||
if (pair != null && renderingType.isObjectVisible(pair.tag, pair.value, zoom, mask, nightMode)) {
|
||||
if (pair != null) {
|
||||
if(mask == MapRenderingTypes.MULTY_POLYGON_TYPE){
|
||||
mask = RenderingRulesStorage.POLYGON_RULES;
|
||||
}
|
||||
renderingReq.setInitialTagValueZoom(pair.tag, pair.value, zoom);
|
||||
if (renderingReq.search(mask, false)) {
|
||||
return true;
|
||||
}
|
||||
if(pair != null && mask == OsmandRenderingRulesParser.POINT_STATE &&
|
||||
renderingType.isObjectVisible(pair.tag, pair.value, zoom, OsmandRenderingRulesParser.TEXT_STATE, nightMode)){
|
||||
if (mask == RenderingRulesStorage.POINT_RULES) {
|
||||
renderingReq.setInitialTagValueZoom(pair.tag, pair.value, zoom);
|
||||
if (renderingReq.search(RenderingRulesStorage.TEXT_RULES, false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -283,7 +294,7 @@ public class MapRenderRepositories {
|
|||
}
|
||||
|
||||
for (String mapName : files.keySet()) {
|
||||
if(basemapSearch && !mapName.toLowerCase().contains(BASEMAP_NAME)){
|
||||
if (basemapSearch && !mapName.toLowerCase().contains(BASEMAP_NAME)) {
|
||||
continue;
|
||||
}
|
||||
BinaryMapIndexReader c = files.get(mapName);
|
||||
|
@ -299,12 +310,12 @@ public class MapRenderRepositories {
|
|||
}
|
||||
count++;
|
||||
|
||||
for(int i=0; i < r.getTypes().length; i++){
|
||||
for (int i = 0; i < r.getTypes().length; i++) {
|
||||
if ((r.getTypes()[i] & 0x3) == MapRenderingTypes.MULTY_POLYGON_TYPE) {
|
||||
// multy polygon r.getId() >> 3
|
||||
TagValuePair pair = r.getMapIndex().decodeType(MapRenderingTypes.getMainObjectType(r.getTypes()[i]),
|
||||
MapRenderingTypes.getObjectSubType(r.getTypes()[i]));
|
||||
if(pair != null){
|
||||
if (pair != null) {
|
||||
pair = new TagValuePair(pair.tag, pair.value, r.getTypes()[i]);
|
||||
if (!multiPolygons.containsKey(pair)) {
|
||||
multiPolygons.put(pair, new ArrayList<BinaryMapDataObject>());
|
||||
|
@ -334,34 +345,53 @@ public class MapRenderRepositories {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void validateLatLonBox(RectF box){
|
||||
if(box.top > 90){
|
||||
private void validateLatLonBox(RectF box) {
|
||||
if (box.top > 90) {
|
||||
box.top = 85.5f;
|
||||
}
|
||||
if(box.bottom < -90){
|
||||
if (box.bottom < -90) {
|
||||
box.bottom = -85.5f;
|
||||
}
|
||||
if(box.left <= -180){
|
||||
if (box.left <= -180) {
|
||||
box.left = -179.5f;
|
||||
}
|
||||
if(box.right > 180){
|
||||
if (box.right > 180) {
|
||||
box.right = 180.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void loadMap(RotatedTileBox tileRect, List<IMapDownloaderCallback> notifyList) {
|
||||
interrupted = false;
|
||||
if(currentRenderingContext != null){
|
||||
if (currentRenderingContext != null) {
|
||||
currentRenderingContext = null;
|
||||
}
|
||||
try {
|
||||
// find selected rendering type
|
||||
OsmandApplication app = ((OsmandApplication)context.getApplicationContext());
|
||||
OsmandApplication app = ((OsmandApplication) context.getApplicationContext());
|
||||
Boolean renderDay = app.getDaynightHelper().getDayNightRenderer();
|
||||
boolean nightMode = renderDay != null && !renderDay.booleanValue();
|
||||
// boolean moreDetail = prefs.SHOW_MORE_MAP_DETAIL.get();
|
||||
BaseOsmandRender renderingType = app.getRendererRegistry().getCurrentSelectedRenderer();
|
||||
RenderingRulesStorage storage = app.getRendererRegistry().getCurrentSelectedRenderer();
|
||||
RenderingRuleSearchRequest renderingReq = new RenderingRuleSearchRequest(storage);
|
||||
renderingReq.setBooleanFilter(renderingReq.ALL.R_NIGHT_MODE, nightMode);
|
||||
for (RenderingRuleProperty customProp : storage.PROPS.getCustomRules()) {
|
||||
CommonPreference<String> settings = app.getSettings().getCustomRenderProperty(customProp.getAttrName());
|
||||
String res = settings.get();
|
||||
if (!Algoritms.isEmpty(res)) {
|
||||
if (customProp.isString()) {
|
||||
renderingReq.setStringFilter(customProp, res);
|
||||
} else if (customProp.isBoolean()) {
|
||||
renderingReq.setBooleanFilter(customProp, "true".equalsIgnoreCase(res));
|
||||
} else {
|
||||
try {
|
||||
renderingReq.setIntFilter(customProp, Integer.parseInt(res));
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
renderingReq.saveState();
|
||||
|
||||
// prevent editing
|
||||
requestedBox = new RotatedTileBox(tileRect);
|
||||
|
@ -383,7 +413,7 @@ public class MapRenderRepositories {
|
|||
dataBox.bottom -= hi;
|
||||
}
|
||||
validateLatLonBox(dataBox);
|
||||
boolean loaded = loadVectorData(dataBox, requestedBox.getZoom(), renderingType, nightMode);
|
||||
boolean loaded = loadVectorData(dataBox, requestedBox.getZoom(), renderingReq, nightMode);
|
||||
if (!loaded || checkWhetherInterrupted()) {
|
||||
return;
|
||||
}
|
||||
|
@ -406,22 +436,16 @@ public class MapRenderRepositories {
|
|||
|
||||
now = System.currentTimeMillis();
|
||||
|
||||
|
||||
Bitmap bmp = Bitmap.createBitmap(currentRenderingContext.width, currentRenderingContext.height, Config.RGB_565);
|
||||
|
||||
boolean stepByStep = prefs.USE_STEP_BY_STEP_RENDERING.get();
|
||||
// 1. generate image step by step
|
||||
if (stepByStep) {
|
||||
this.prevBmp = this.bmp;
|
||||
this.prevBmpLocation = this.bmpLocation;
|
||||
this.bmp = bmp;
|
||||
this.bmpLocation = tileRect;
|
||||
}
|
||||
|
||||
|
||||
|
||||
renderer.generateNewBitmap(currentRenderingContext, cObjects, bmp,
|
||||
prefs.USE_ENGLISH_NAMES.get(), renderingType, stepByStep ? notifyList : null);
|
||||
renderer.generateNewBitmap(currentRenderingContext, cObjects, bmp, prefs.USE_ENGLISH_NAMES.get(), renderingReq,
|
||||
notifyList, storage.getBgColor(nightMode));
|
||||
String renderingDebugInfo = currentRenderingContext.renderingDebugInfo;
|
||||
if (checkWhetherInterrupted()) {
|
||||
currentRenderingContext = null;
|
||||
|
@ -430,20 +454,15 @@ public class MapRenderRepositories {
|
|||
currentRenderingContext = null;
|
||||
|
||||
// 2. replace whole image
|
||||
if (!stepByStep) {
|
||||
this.bmp = bmp;
|
||||
this.bmpLocation = tileRect;
|
||||
} else {
|
||||
this.prevBmp = null;
|
||||
this.prevBmpLocation = null;
|
||||
}
|
||||
if(prefs.DEBUG_RENDERING_INFO.get()){
|
||||
String timeInfo = "Search done in "+ searchTime+" ms"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
|
||||
if(renderingDebugInfo != null){
|
||||
timeInfo += "\n"+renderingDebugInfo;
|
||||
if (prefs.DEBUG_RENDERING_INFO.get()) {
|
||||
String timeInfo = "Search done in " + searchTime + " ms"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
|
||||
if (renderingDebugInfo != null) {
|
||||
timeInfo += "\n" + renderingDebugInfo;
|
||||
}
|
||||
final String msg = timeInfo;
|
||||
handler.post(new Runnable(){
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
|
||||
|
@ -452,7 +471,7 @@ public class MapRenderRepositories {
|
|||
}
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Runtime memory exception", e); //$NON-NLS-1$
|
||||
handler.post(new Runnable(){
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(context, R.string.rendering_exception, Toast.LENGTH_SHORT).show();
|
||||
|
@ -462,7 +481,7 @@ public class MapRenderRepositories {
|
|||
log.error("Out of memory error", e); //$NON-NLS-1$
|
||||
cObjects = new ArrayList<BinaryMapDataObject>();
|
||||
cObjectsBox = new RectF();
|
||||
handler.post(new Runnable(){
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(context, R.string.rendering_out_of_memory, Toast.LENGTH_SHORT).show();
|
||||
|
@ -481,7 +500,6 @@ public class MapRenderRepositories {
|
|||
return prevBmp;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void clearCache() {
|
||||
cObjects = new ArrayList<BinaryMapDataObject>();
|
||||
cObjectsBox = new RectF();
|
||||
|
@ -489,10 +507,10 @@ public class MapRenderRepositories {
|
|||
requestedBox = prevBmpLocation = bmpLocation = null;
|
||||
}
|
||||
|
||||
// / Manipulating with multipolygons
|
||||
|
||||
/// Manipulating with multipolygons
|
||||
|
||||
public List<MultyPolygon> proccessMultiPolygons(Map<TagValuePair, List<BinaryMapDataObject>> multyPolygons, int leftX, int rightX, int bottomY, int topY, int zoom){
|
||||
public List<MultyPolygon> proccessMultiPolygons(Map<TagValuePair, List<BinaryMapDataObject>> multyPolygons, int leftX, int rightX,
|
||||
int bottomY, int topY, int zoom) {
|
||||
List<MultyPolygon> listPolygons = new ArrayList<MultyPolygon>(multyPolygons.size());
|
||||
List<TLongList> completedRings = new ArrayList<TLongList>();
|
||||
List<TLongList> incompletedRings = new ArrayList<TLongList>();
|
||||
|
@ -501,7 +519,7 @@ public class MapRenderRepositories {
|
|||
for (TagValuePair type : multyPolygons.keySet()) {
|
||||
List<BinaryMapDataObject> directList;
|
||||
List<BinaryMapDataObject> inverselist;
|
||||
if(((type.additionalAttribute >> 15) & 1) == 1){
|
||||
if (((type.additionalAttribute >> 15) & 1) == 1) {
|
||||
TagValuePair directType = new TagValuePair(type.tag, type.value, type.additionalAttribute & ((1 << 15) - 1));
|
||||
if (!multyPolygons.containsKey(directType)) {
|
||||
inverselist = multyPolygons.get(type);
|
||||
|
@ -523,10 +541,10 @@ public class MapRenderRepositories {
|
|||
completedRingNames.clear();
|
||||
incompletedRingNames.clear();
|
||||
log.debug("Process multypolygon " + type.tag + " " + type.value + //$NON-NLS-1$ //$NON-NLS-2$
|
||||
" direct list : " +directList + " rev : " + inverselist); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
" direct list : " + directList + " rev : " + inverselist); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
MultyPolygon pl = processMultiPolygon(leftX, rightX, bottomY, topY, listPolygons, completedRings, incompletedRings,
|
||||
completedRingNames, incompletedRingNames, type, directList, inverselist, zoom);
|
||||
if(pl != null){
|
||||
if (pl != null) {
|
||||
listPolygons.add(pl);
|
||||
}
|
||||
}
|
||||
|
@ -534,8 +552,9 @@ public class MapRenderRepositories {
|
|||
}
|
||||
|
||||
private MultyPolygon processMultiPolygon(int leftX, int rightX, int bottomY, int topY, List<MultyPolygon> listPolygons,
|
||||
List<TLongList> completedRings, List<TLongList> incompletedRings, List<String> completedRingNames, List<String> incompletedRingNames,
|
||||
TagValuePair type, List<BinaryMapDataObject> directList, List<BinaryMapDataObject> inverselist, int zoom) {
|
||||
List<TLongList> completedRings, List<TLongList> incompletedRings, List<String> completedRingNames,
|
||||
List<String> incompletedRingNames, TagValuePair type, List<BinaryMapDataObject> directList,
|
||||
List<BinaryMapDataObject> inverselist, int zoom) {
|
||||
MultyPolygon pl = new MultyPolygon();
|
||||
// delete direction last bit (to not show point)
|
||||
pl.setTag(type.tag);
|
||||
|
@ -564,9 +583,9 @@ public class MapRenderRepositories {
|
|||
y = o.getPoint31YTile(km == 0 ? i : len - i - 1);
|
||||
boolean inside = leftX <= x && x <= rightX && y >= topY && y <= bottomY;
|
||||
boolean lineEnded = calculateLineCoordinates(inside, x, y, pinside, px, py, leftX, rightX, bottomY, topY, coordinates);
|
||||
if(lineEnded){
|
||||
processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames,
|
||||
coordinates, o.getName());
|
||||
if (lineEnded) {
|
||||
processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames, coordinates,
|
||||
o.getName());
|
||||
// create new line if it goes outside
|
||||
coordinates = new TLongArrayList();
|
||||
}
|
||||
|
@ -574,19 +593,19 @@ public class MapRenderRepositories {
|
|||
py = y;
|
||||
pinside = inside;
|
||||
}
|
||||
processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames,
|
||||
coordinates, o.getName());
|
||||
processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames, coordinates,
|
||||
o.getName());
|
||||
}
|
||||
}
|
||||
if(completedRings.size() == 0 && incompletedRings.size() == 0){
|
||||
if (completedRings.size() == 0 && incompletedRings.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (incompletedRings.size() > 0) {
|
||||
unifyIncompletedRings(incompletedRings, completedRings, completedRingNames, incompletedRingNames, leftX, rightX, bottomY, topY, dbId, zoom);
|
||||
unifyIncompletedRings(incompletedRings, completedRings, completedRingNames, incompletedRingNames, leftX, rightX, bottomY, topY,
|
||||
dbId, zoom);
|
||||
} else {
|
||||
// due to self intersection small objects (for low zooms check only coastline)
|
||||
if (zoom >= 13
|
||||
|| ("natural".equals(type.tag) && "coastline".equals(type.value))) { //$NON-NLS-1$//$NON-NLS-2$
|
||||
if (zoom >= 13 || ("natural".equals(type.tag) && "coastline".equals(type.value))) { //$NON-NLS-1$//$NON-NLS-2$
|
||||
boolean clockwiseFound = false;
|
||||
for (TLongList c : completedRings) {
|
||||
if (isClockwiseWay(c)) {
|
||||
|
@ -622,15 +641,15 @@ public class MapRenderRepositories {
|
|||
}
|
||||
|
||||
// Copied from MapAlgorithms
|
||||
private boolean isClockwiseWay(TLongList c){
|
||||
if(c.size() == 0){
|
||||
private boolean isClockwiseWay(TLongList c) {
|
||||
if (c.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// calculate middle Y
|
||||
int mask = 0xffffffff;
|
||||
long middleY = 0;
|
||||
for(int i=0; i< c.size(); i++) {
|
||||
for (int i = 0; i < c.size(); i++) {
|
||||
middleY += (c.get(i) & mask);
|
||||
}
|
||||
middleY /= (long) c.size();
|
||||
|
@ -671,9 +690,9 @@ public class MapRenderRepositories {
|
|||
}
|
||||
}
|
||||
|
||||
if(firstX != -360){
|
||||
if (firstX != -360) {
|
||||
boolean clockwise = (!firstDirectionUp) == (previousX < firstX);
|
||||
if(clockwise){
|
||||
if (clockwise) {
|
||||
clockwiseSum += Math.abs(previousX - firstX);
|
||||
} else {
|
||||
clockwiseSum -= Math.abs(previousX - firstX);
|
||||
|
@ -687,7 +706,7 @@ public class MapRenderRepositories {
|
|||
private int ray_intersect_x(int prevX, int prevY, int x, int y, int middleY) {
|
||||
// prev node above line
|
||||
// x,y node below line
|
||||
if(prevY > y){
|
||||
if (prevY > y) {
|
||||
int tx = prevX;
|
||||
int ty = prevY;
|
||||
x = prevX;
|
||||
|
@ -712,7 +731,7 @@ public class MapRenderRepositories {
|
|||
}
|
||||
|
||||
// NOT WORKING GOOD !
|
||||
private boolean isClockwiseWayOld(TLongList c){
|
||||
private boolean isClockwiseWayOld(TLongList c) {
|
||||
double angle = 0;
|
||||
double prevAng = 0;
|
||||
int px = 0;
|
||||
|
@ -743,7 +762,6 @@ public class MapRenderRepositories {
|
|||
return angle < 0;
|
||||
}
|
||||
|
||||
|
||||
private void processMultipolygonLine(List<TLongList> completedRings, List<TLongList> incompletedRings,
|
||||
List<String> completedRingsNames, List<String> incompletedRingsNames, TLongList coordinates, String name) {
|
||||
if (coordinates.size() > 0) {
|
||||
|
@ -772,7 +790,7 @@ public class MapRenderRepositories {
|
|||
}
|
||||
if (coordinates.get(0) == coordinates.get(coordinates.size() - 1)) {
|
||||
completedRings.add(coordinates);
|
||||
if(oldName != null){
|
||||
if (oldName != null) {
|
||||
completedRingsNames.add(oldName);
|
||||
} else {
|
||||
completedRingsNames.add(name);
|
||||
|
@ -789,12 +807,11 @@ public class MapRenderRepositories {
|
|||
}
|
||||
}
|
||||
|
||||
private void unifyIncompletedRings(List<TLongList> incompletedRings, List<TLongList> completedRings,
|
||||
List<String> completedRingNames, List<String> incompletedRingNames,
|
||||
int leftX, int rightX, int bottomY, int topY, long dbId, int zoom) {
|
||||
private void unifyIncompletedRings(List<TLongList> incompletedRings, List<TLongList> completedRings, List<String> completedRingNames,
|
||||
List<String> incompletedRingNames, int leftX, int rightX, int bottomY, int topY, long dbId, int zoom) {
|
||||
int mask = 0xffffffff;
|
||||
Set<Integer> nonvisitedRings = new LinkedHashSet<Integer>();
|
||||
for(int j = 0; j< incompletedRings.size(); j++){
|
||||
for (int j = 0; j < incompletedRings.size(); j++) {
|
||||
TLongList i = incompletedRings.get(j);
|
||||
int x = (int) (i.get(i.size() - 1) >> 32);
|
||||
int y = (int) (i.get(i.size() - 1) & mask);
|
||||
|
@ -812,26 +829,24 @@ public class MapRenderRepositories {
|
|||
float dy = (float) MapUtils.get31LatitudeY(y);
|
||||
float dsy = (float) MapUtils.get31LatitudeY(sy);
|
||||
String str;
|
||||
if(!end){
|
||||
if (!end) {
|
||||
str = " Start point (to close) not found : end_x = {0}, end_y = {1}, start_x = {2}, start_y = {3} : bounds {4} {5} - {6} {7}"; //$NON-NLS-1$
|
||||
System.err.println(
|
||||
MessageFormat.format(dbId + str,
|
||||
dx, dy, dsx, dsy, leftX+"", topY+"", rightX+"", bottomY+"")); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
System.err
|
||||
.println(MessageFormat.format(dbId + str, dx, dy, dsx, dsy, leftX + "", topY + "", rightX + "", bottomY + "")); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
}
|
||||
if(!st){
|
||||
if (!st) {
|
||||
str = " End not found : end_x = {0}, end_y = {1}, start_x = {2}, start_y = {3} : bounds {4} {5} - {6} {7}"; //$NON-NLS-1$
|
||||
System.err.println(
|
||||
MessageFormat.format(dbId + str,
|
||||
dx, dy, dsx, dsy, leftX+"", topY+"", rightX+"", bottomY+"")); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
System.err
|
||||
.println(MessageFormat.format(dbId + str, dx, dy, dsx, dsy, leftX + "", topY + "", rightX + "", bottomY + "")); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
}
|
||||
} else {
|
||||
nonvisitedRings.add(j);
|
||||
}
|
||||
}
|
||||
for(int j = 0; j< incompletedRings.size(); j++){
|
||||
for (int j = 0; j < incompletedRings.size(); j++) {
|
||||
TLongList i = incompletedRings.get(j);
|
||||
String name = incompletedRingNames.get(j);
|
||||
if(!nonvisitedRings.contains(j)){
|
||||
if (!nonvisitedRings.contains(j)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -863,7 +878,7 @@ public class MapRenderRepositories {
|
|||
int csy = (int) (cni.get(0) & mask);
|
||||
if (h % 4 == 0) {
|
||||
// top
|
||||
if (csy == topY && csx >= safelyAddDelta(x, - EVAL_DELTA)) {
|
||||
if (csy == topY && csx >= safelyAddDelta(x, -EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (csx - x) <= mindiff) {
|
||||
mindiff = (csx - x);
|
||||
nextRingIndex = ni;
|
||||
|
@ -871,7 +886,7 @@ public class MapRenderRepositories {
|
|||
}
|
||||
} else if (h % 4 == 1) {
|
||||
// right
|
||||
if (csx == rightX && csy >= safelyAddDelta(y, - EVAL_DELTA)) {
|
||||
if (csx == rightX && csy >= safelyAddDelta(y, -EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (csy - y) <= mindiff) {
|
||||
mindiff = (csy - y);
|
||||
nextRingIndex = ni;
|
||||
|
@ -935,17 +950,16 @@ public class MapRenderRepositories {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
completedRings.add(i);
|
||||
completedRingNames.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
private int safelyAddDelta(int number, int delta){
|
||||
private int safelyAddDelta(int number, int delta) {
|
||||
int res = number + delta;
|
||||
if(delta > 0 && res < number){
|
||||
if (delta > 0 && res < number) {
|
||||
return Integer.MAX_VALUE;
|
||||
} else if(delta < 0 && res > number){
|
||||
} else if (delta < 0 && res > number) {
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
return res;
|
||||
|
@ -954,8 +968,7 @@ public class MapRenderRepositories {
|
|||
/**
|
||||
* @return -1 if there is no instersection or x<<32 | y
|
||||
*/
|
||||
private long calculateIntersection(int x, int y, int px, int py, int leftX, int rightX,
|
||||
int bottomY, int topY){
|
||||
private long calculateIntersection(int x, int y, int px, int py, int leftX, int rightX, int bottomY, int topY) {
|
||||
int by = -1;
|
||||
int bx = -1;
|
||||
// firstly try to search if the line goes in
|
||||
|
@ -1030,7 +1043,7 @@ public class MapRenderRepositories {
|
|||
|
||||
}
|
||||
|
||||
if(px == rightX || px == leftX || py == topY || py == bottomY){
|
||||
if (px == rightX || px == leftX || py == topY || py == bottomY) {
|
||||
bx = px;
|
||||
by = py;
|
||||
}
|
||||
|
@ -1054,11 +1067,11 @@ public class MapRenderRepositories {
|
|||
}
|
||||
} else {
|
||||
long is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY);
|
||||
if(inside){
|
||||
if (inside) {
|
||||
// assert is != -1;
|
||||
coordinates.add(is);
|
||||
coordinates.add((((long) x) << 32) | ((long) y));
|
||||
} else if(is != -1){
|
||||
} else if (is != -1) {
|
||||
int bx = (int) (is >> 32);
|
||||
int by = (int) (is & 0xffffffff);
|
||||
coordinates.add(is);
|
||||
|
@ -1071,7 +1084,6 @@ public class MapRenderRepositories {
|
|||
return lineEnded;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, BinaryMapIndexReader> getMetaInfoFiles() {
|
||||
return files;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package net.osmand.plus.render;
|
||||
|
||||
import gnu.trove.list.array.TIntArrayList;
|
||||
import gnu.trove.map.hash.TFloatObjectHashMap;
|
||||
import gnu.trove.map.hash.TIntObjectHashMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -11,12 +11,16 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.binary.BinaryMapDataObject;
|
||||
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
|
||||
import net.osmand.data.MapTileDownloader.IMapDownloaderCallback;
|
||||
import net.osmand.osm.MapRenderingTypes;
|
||||
import net.osmand.osm.MultyPolygon;
|
||||
import net.osmand.render.RenderingRuleProperty;
|
||||
import net.osmand.render.RenderingRuleSearchRequest;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
import net.sf.junidecode.Junidecode;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -86,19 +90,22 @@ public class OsmandRenderer {
|
|||
int shieldRes = 0;
|
||||
int textOrder = 20;
|
||||
|
||||
public void fillProperties(RenderingContext rc, float centerX, float centerY){
|
||||
this.centerX = centerX + rc.textDx;
|
||||
this.centerY = centerY + rc.textDy;
|
||||
textColor = rc.textColor;
|
||||
textSize = rc.textSize;
|
||||
textShadow = (int) rc.textHaloRadius;
|
||||
textWrap = rc.textWrapWidth;
|
||||
bold = rc.textBold;
|
||||
minDistance = rc.textMinDistance;
|
||||
shieldRes = rc.textShield;
|
||||
if(rc.textOrder >= 0){
|
||||
textOrder = rc.textOrder;
|
||||
public void fillProperties(RenderingRuleSearchRequest render, float centerX, float centerY){
|
||||
this.centerX = centerX;
|
||||
this.centerY = centerY + render.getIntPropertyValue(render.ALL.R_TEXT_DY, 0);
|
||||
textColor = render.getIntPropertyValue(render.ALL.R_TEXT_COLOR);
|
||||
if(textColor == 0){
|
||||
textColor = Color.BLACK;
|
||||
}
|
||||
textSize = render.getIntPropertyValue(render.ALL.R_TEXT_SIZE);
|
||||
textShadow = render.getIntPropertyValue(render.ALL.R_TEXT_HALO_RADIUS, 0);
|
||||
textWrap = render.getIntPropertyValue(render.ALL.R_TEXT_WRAP_WIDTH, 0);
|
||||
bold = render.getIntPropertyValue(render.ALL.R_TEXT_BOLD, 0) > 0;
|
||||
minDistance = render.getIntPropertyValue(render.ALL.R_TEXT_MIN_DISTANCE,0);
|
||||
if(render.isSpecified(render.ALL.R_TEXT_SHIELD)) {
|
||||
shieldRes = RenderingIcons.getIcons().get(render.getStringPropertyValue(render.ALL.R_TEXT_SHIELD));
|
||||
}
|
||||
textOrder = render.getIntPropertyValue(render.ALL.R_TEXT_ORDER, 20);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,94 +144,8 @@ public class OsmandRenderer {
|
|||
float cosRotateTileSize;
|
||||
float sinRotateTileSize;
|
||||
|
||||
// These properties are used for rendering one object
|
||||
// polyline props
|
||||
boolean showTextOnPath = false;
|
||||
String showAnotherText = null;
|
||||
float textSize = 0;
|
||||
int textColor = 0;
|
||||
int textMinDistance = 0;
|
||||
int textWrapWidth = 0;
|
||||
float textDx = 0;
|
||||
float textDy = 0;
|
||||
float textHaloRadius = 0;
|
||||
boolean textBold;
|
||||
int textShield = 0;
|
||||
int textOrder = -1;
|
||||
|
||||
String renderingDebugInfo;
|
||||
|
||||
RenderingPaintProperties main = new RenderingPaintProperties();
|
||||
RenderingPaintProperties second = new RenderingPaintProperties();
|
||||
RenderingPaintProperties third = new RenderingPaintProperties();
|
||||
RenderingPaintProperties[] adds = null;
|
||||
|
||||
|
||||
|
||||
public void clearText() {
|
||||
showAnotherText = null;
|
||||
showTextOnPath = false;
|
||||
textSize = 0;
|
||||
textColor = 0;
|
||||
textOrder = -1;
|
||||
textMinDistance = 0;
|
||||
textWrapWidth = 0;
|
||||
textDx = 0;
|
||||
textDy = 0;
|
||||
textHaloRadius = 0;
|
||||
textBold = false;
|
||||
textShield = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* package*/ static class RenderingPaintProperties {
|
||||
int color;
|
||||
float strokeWidth;
|
||||
int shadowLayer;
|
||||
int shadowColor;
|
||||
boolean fillArea;
|
||||
PathEffect pathEffect;
|
||||
Shader shader;
|
||||
Cap cap;
|
||||
|
||||
public void emptyLine(){
|
||||
color = 0;
|
||||
strokeWidth = 0;
|
||||
cap = Cap.BUTT;
|
||||
pathEffect = null;
|
||||
fillArea = false;
|
||||
shader = null;
|
||||
shadowColor = 0;
|
||||
shadowLayer = 0;
|
||||
}
|
||||
|
||||
public void updatePaint(Paint p){
|
||||
p.setStyle(fillArea ? Style.FILL_AND_STROKE : Style.STROKE);
|
||||
p.setColor(color);
|
||||
p.setShader(shader);
|
||||
if(shadowColor == 0){
|
||||
shadowLayer = 0;
|
||||
}
|
||||
p.setShadowLayer(shadowLayer, 0, 0, shadowColor);
|
||||
p.setStrokeWidth(strokeWidth);
|
||||
p.setStrokeCap(cap);
|
||||
if (!fillArea) {
|
||||
p.setPathEffect(pathEffect);
|
||||
}
|
||||
}
|
||||
|
||||
public void emptyArea(){
|
||||
color = 0;
|
||||
strokeWidth = 0;
|
||||
cap = Cap.BUTT;
|
||||
fillArea = false;
|
||||
shader = null;
|
||||
pathEffect = null;
|
||||
shadowColor = 0;
|
||||
shadowLayer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public OsmandRenderer(Context context) {
|
||||
|
@ -273,7 +194,7 @@ public class OsmandRenderer {
|
|||
return shaders.get(resId);
|
||||
}
|
||||
|
||||
private void put(TFloatObjectHashMap<TIntArrayList> map, Float k, int v, int init){
|
||||
private void put(TIntObjectHashMap<TIntArrayList> map, int k, int v, int init){
|
||||
if(!map.containsKey(k)){
|
||||
map.put(k, new TIntArrayList());
|
||||
}
|
||||
|
@ -282,33 +203,33 @@ public class OsmandRenderer {
|
|||
|
||||
|
||||
public Bitmap generateNewBitmap(RenderingContext rc, List<BinaryMapDataObject> objects, Bitmap bmp, boolean useEnglishNames,
|
||||
BaseOsmandRender renderer, List<IMapDownloaderCallback> notifyList) {
|
||||
RenderingRuleSearchRequest render, List<IMapDownloaderCallback> notifyList, int defaultColor) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
// fill area
|
||||
Canvas cv = new Canvas(bmp);
|
||||
if(renderer != null){
|
||||
int dc = renderer.getDefaultColor(rc.nightMode);
|
||||
if(dc != 0){
|
||||
paintFillEmpty.setColor(dc);
|
||||
}
|
||||
if(defaultColor != 0){
|
||||
paintFillEmpty.setColor(defaultColor);
|
||||
}
|
||||
cv.drawRect(0, 0, bmp.getWidth(), bmp.getHeight(), paintFillEmpty);
|
||||
|
||||
// put in order map
|
||||
int sz = objects.size();
|
||||
int init = sz / 4;
|
||||
TFloatObjectHashMap<TIntArrayList> orderMap = new TFloatObjectHashMap<TIntArrayList>();
|
||||
if (renderer != null) {
|
||||
TIntObjectHashMap<TIntArrayList> orderMap = new TIntObjectHashMap<TIntArrayList>();
|
||||
if (render != null) {
|
||||
for (int i = 0; i < sz; i++) {
|
||||
BinaryMapDataObject o = objects.get(i);
|
||||
int sh = i << 8;
|
||||
|
||||
if (o instanceof MultyPolygon) {
|
||||
int mask = MapRenderingTypes.MULTY_POLYGON_TYPE;
|
||||
int layer = ((MultyPolygon) o).getLayer();
|
||||
put(orderMap, renderer.getObjectOrder(((MultyPolygon) o).getTag(), ((MultyPolygon) o).getValue(),
|
||||
mask, layer), sh, init);
|
||||
render.setInitialTagValueZoom(((MultyPolygon) o).getTag(), ((MultyPolygon) o).getValue(), rc.zoom);
|
||||
render.setIntFilter(render.ALL.R_LAYER, layer);
|
||||
render.setIntFilter(render.ALL.R_ORDER_TYPE, MapRenderingTypes.POLYGON_TYPE);
|
||||
if(render.search(RenderingRulesStorage.ORDER_RULES)) {
|
||||
put(orderMap, render.getIntPropertyValue(render.ALL.R_ORDER), sh, init);
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < o.getTypes().length; j++) {
|
||||
// put(orderMap, BinaryMapDataObject.getOrder(o.getTypes()[j]), sh + j, init);
|
||||
|
@ -322,7 +243,12 @@ public class OsmandRenderer {
|
|||
TagValuePair pair = o.getMapIndex().decodeType(MapRenderingTypes.getMainObjectType(wholeType),
|
||||
MapRenderingTypes.getObjectSubType(wholeType));
|
||||
if (pair != null) {
|
||||
put(orderMap, renderer.getObjectOrder(pair.tag, pair.value, mask, layer), sh + j, init);
|
||||
render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
|
||||
render.setIntFilter(render.ALL.R_LAYER, layer);
|
||||
render.setIntFilter(render.ALL.R_ORDER_TYPE, mask);
|
||||
if(render.search(RenderingRulesStorage.ORDER_RULES)) {
|
||||
put(orderMap, render.getIntPropertyValue(render.ALL.R_ORDER), sh + j, init);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -341,7 +267,7 @@ public class OsmandRenderer {
|
|||
rc.sinRotateTileSize = FloatMath.sin((float) Math.toRadians(rc.rotate)) * TILE_SIZE;
|
||||
|
||||
|
||||
float[] keys = orderMap.keys();
|
||||
int[] keys = orderMap.keys();
|
||||
Arrays.sort(keys);
|
||||
int objCount = 0;
|
||||
for (int k = 0; k < keys.length; k++) {
|
||||
|
@ -353,7 +279,7 @@ public class OsmandRenderer {
|
|||
BinaryMapDataObject obj = objects.get(ind);
|
||||
|
||||
// show text only for main type
|
||||
drawObj(obj, renderer, cv, rc, l, l == 0);
|
||||
drawObj(obj, render, cv, rc, l, l == 0);
|
||||
|
||||
objCount++;
|
||||
}
|
||||
|
@ -647,10 +573,10 @@ public class OsmandRenderer {
|
|||
}
|
||||
|
||||
|
||||
protected void drawObj(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, int l, boolean renderText) {
|
||||
protected void drawObj(BinaryMapDataObject obj, RenderingRuleSearchRequest render, Canvas canvas, RenderingContext rc, int l, boolean renderText) {
|
||||
rc.allObjects++;
|
||||
if (obj instanceof MultyPolygon) {
|
||||
drawMultiPolygon(obj, render,canvas, rc);
|
||||
drawMultiPolygon(obj, render, canvas, rc);
|
||||
} else {
|
||||
int mainType = obj.getTypes()[l];
|
||||
int t = mainType & 3;
|
||||
|
@ -707,28 +633,20 @@ public class OsmandRenderer {
|
|||
return rc.tempPoint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void clearCachedResources(){
|
||||
cachedIcons.clear();
|
||||
shaders.clear();
|
||||
}
|
||||
|
||||
private void drawMultiPolygon(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc) {
|
||||
private void drawMultiPolygon(BinaryMapDataObject obj, RenderingRuleSearchRequest render, Canvas canvas, RenderingContext rc) {
|
||||
String tag = ((MultyPolygon)obj).getTag();
|
||||
String value = ((MultyPolygon)obj).getValue();
|
||||
if(render == null || tag == null){
|
||||
return;
|
||||
}
|
||||
rc.main.emptyArea();
|
||||
rc.second.emptyLine();
|
||||
rc.main.color = Color.rgb(245, 245, 245);
|
||||
|
||||
boolean rendered = render.renderPolygon(tag, value, rc.zoom, rc, this, rc.nightMode);
|
||||
if(!rendered){
|
||||
render.setInitialTagValueZoom(tag, value, rc.zoom);
|
||||
boolean rendered = render.search(RenderingRulesStorage.POLYGON_RULES);
|
||||
if(!rendered || !updatePaint(render, paint, 0, true)){
|
||||
return;
|
||||
}
|
||||
rc.visible++;
|
||||
|
@ -754,21 +672,16 @@ public class OsmandRenderer {
|
|||
}
|
||||
}
|
||||
}
|
||||
rc.main.updatePaint(paint);
|
||||
canvas.drawPath(path, paint);
|
||||
// for test purpose
|
||||
// rc.second.strokeWidth = 1.5f;
|
||||
// rc.second.color = Color.BLACK;
|
||||
|
||||
if (rc.second.strokeWidth != 0) {
|
||||
rc.second.updatePaint(paint);
|
||||
// render.strokeWidth = 1.5f;
|
||||
// render.color = Color.BLACK;
|
||||
if (updatePaint(render, paint, 1, false)) {
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void drawPolygon(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, TagValuePair pair) {
|
||||
|
||||
private void drawPolygon(BinaryMapDataObject obj, RenderingRuleSearchRequest render, Canvas canvas, RenderingContext rc, TagValuePair pair) {
|
||||
if(render == null || pair == null){
|
||||
return;
|
||||
}
|
||||
|
@ -776,12 +689,11 @@ public class OsmandRenderer {
|
|||
float yText = 0;
|
||||
int zoom = rc.zoom;
|
||||
Path path = null;
|
||||
rc.main.emptyArea();
|
||||
rc.second.emptyLine();
|
||||
// rc.main.color = Color.rgb(245, 245, 245);
|
||||
|
||||
boolean rendered = render.renderPolygon(pair.tag, pair.value, zoom, rc, this, rc.nightMode);
|
||||
if(!rendered){
|
||||
// rc.main.color = Color.rgb(245, 245, 245);
|
||||
render.setInitialTagValueZoom(pair.tag, pair.value, zoom);
|
||||
boolean rendered = render.search(RenderingRulesStorage.POLYGON_RULES);
|
||||
if(!rendered || !updatePaint(render, paint, 0, true)){
|
||||
return;
|
||||
}
|
||||
rc.visible++;
|
||||
|
@ -800,11 +712,8 @@ public class OsmandRenderer {
|
|||
}
|
||||
|
||||
if (path != null && len > 0) {
|
||||
|
||||
rc.main.updatePaint(paint);
|
||||
canvas.drawPath(path, paint);
|
||||
if (rc.second.strokeWidth != 0) {
|
||||
rc.second.updatePaint(paint);
|
||||
if (updatePaint(render, paint, 1, false)) {
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
String name = obj.getName();
|
||||
|
@ -812,11 +721,81 @@ public class OsmandRenderer {
|
|||
drawPointText(render, rc, pair, xText / len, yText / len, name);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private void drawPointText(BaseOsmandRender render, RenderingContext rc, TagValuePair pair, float xText, float yText, String name) {
|
||||
rc.clearText();
|
||||
private boolean updatePaint(RenderingRuleSearchRequest req, Paint p, int ind, boolean area){
|
||||
RenderingRuleProperty rColor;
|
||||
RenderingRuleProperty rStrokeW;
|
||||
RenderingRuleProperty rCap;
|
||||
RenderingRuleProperty rPathEff;
|
||||
if(ind == 0){
|
||||
rColor = req.ALL.R_COLOR;
|
||||
rStrokeW = req.ALL.R_STROKE_WIDTH;
|
||||
rCap = req.ALL.R_CAP;
|
||||
rPathEff = req.ALL.R_PATH_EFFECT;
|
||||
} else if(ind == 1){
|
||||
rColor = req.ALL.R_COLOR_2;
|
||||
rStrokeW = req.ALL.R_STROKE_WIDTH_2;
|
||||
rCap = req.ALL.R_CAP_2;
|
||||
rPathEff = req.ALL.R_PATH_EFFECT_2;
|
||||
} else {
|
||||
rColor = req.ALL.R_COLOR_3;
|
||||
rStrokeW = req.ALL.R_STROKE_WIDTH_3;
|
||||
rCap = req.ALL.R_CAP_3;
|
||||
rPathEff = req.ALL.R_PATH_EFFECT_3;
|
||||
}
|
||||
if(area){
|
||||
if(!req.isSpecified(rColor) && !req.isSpecified(req.ALL.R_SHADER)){
|
||||
return false;
|
||||
}
|
||||
p.setStyle(Style.FILL_AND_STROKE);
|
||||
p.setStrokeWidth(0);
|
||||
} else {
|
||||
if(!req.isSpecified(rStrokeW)){
|
||||
return false;
|
||||
}
|
||||
p.setStyle(Style.STROKE);
|
||||
p.setStrokeWidth(req.getFloatPropertyValue(rStrokeW));
|
||||
String cap = req.getStringPropertyValue(rCap);
|
||||
if(!Algoritms.isEmpty(cap)){
|
||||
p.setStrokeCap(Cap.valueOf(cap.toUpperCase()));
|
||||
} else {
|
||||
p.setStrokeCap(Cap.BUTT);
|
||||
}
|
||||
String pathEffect = req.getStringPropertyValue(rPathEff);
|
||||
if (!Algoritms.isEmpty(pathEffect)) {
|
||||
p.setPathEffect(getDashEffect(pathEffect));
|
||||
} else {
|
||||
p.setPathEffect(null);
|
||||
}
|
||||
}
|
||||
p.setColor(req.getIntPropertyValue(rColor));
|
||||
|
||||
if(ind == 0){
|
||||
Integer resId = RenderingIcons.getIcons().get(req.getStringPropertyValue(req.ALL.R_SHADER));
|
||||
if(resId != null){
|
||||
p.setColor(Color.BLACK);
|
||||
p.setShader(getShader(resId));
|
||||
} else {
|
||||
p.setShader(null);
|
||||
}
|
||||
|
||||
int shadowColor = req.getIntPropertyValue(req.ALL.R_SHADOW_COLOR);
|
||||
int shadowLayer = req.getIntPropertyValue(req.ALL.R_SHADOW_RADIUS);
|
||||
if(shadowColor == 0){
|
||||
shadowLayer = 0;
|
||||
}
|
||||
p.setShadowLayer(shadowLayer, 0, 0, shadowColor);
|
||||
} else {
|
||||
p.setShader(null);
|
||||
p.setShadowLayer(0, 0, 0, 0);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void drawPointText(RenderingRuleSearchRequest render, RenderingContext rc, TagValuePair pair, float xText, float yText, String name) {
|
||||
String ref = null;
|
||||
if (name.charAt(0) == MapRenderingTypes.REF_CHAR) {
|
||||
ref = name.substring(1);
|
||||
|
@ -833,28 +812,39 @@ public class OsmandRenderer {
|
|||
}
|
||||
|
||||
if (ref != null && ref.trim().length() > 0) {
|
||||
rc.clearText();
|
||||
ref = render.renderObjectText(ref, pair.tag, pair.value, rc, true, rc.nightMode);
|
||||
render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
|
||||
render.setIntFilter(render.ALL.R_TEXT_LENGTH, ref.length());
|
||||
render.setBooleanFilter(render.ALL.R_REF, true);
|
||||
if(render.search(RenderingRulesStorage.TEXT_RULES)){
|
||||
if(render.getIntPropertyValue(render.ALL.R_TEXT_SIZE) > 0){
|
||||
TextDrawInfo text = new TextDrawInfo(ref);
|
||||
text.fillProperties(rc, xText, yText);
|
||||
text.fillProperties(render, xText, yText);
|
||||
rc.textToDraw.add(text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
name = render.renderObjectText(name, pair.tag, pair.value, rc, false, rc.nightMode);
|
||||
if (rc.textSize > 0 && name != null) {
|
||||
render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
|
||||
render.setIntFilter(render.ALL.R_TEXT_LENGTH, name.length());
|
||||
render.setBooleanFilter(render.ALL.R_REF, false);
|
||||
if(render.search(RenderingRulesStorage.TEXT_RULES) ){
|
||||
if(render.getIntPropertyValue(render.ALL.R_TEXT_SIZE) > 0){
|
||||
TextDrawInfo info = new TextDrawInfo(name);
|
||||
info.fillProperties(rc, xText, yText);
|
||||
info.fillProperties(render, xText, yText);
|
||||
rc.textToDraw.add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void drawPoint(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, TagValuePair pair, boolean renderText) {
|
||||
private void drawPoint(BinaryMapDataObject obj, RenderingRuleSearchRequest render, Canvas canvas, RenderingContext rc, TagValuePair pair, boolean renderText) {
|
||||
if(render == null || pair == null){
|
||||
return;
|
||||
}
|
||||
render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
|
||||
render.search(RenderingRulesStorage.POINT_RULES);
|
||||
|
||||
Integer resId = render.getPointIcon(pair.tag, pair.value, rc.zoom, rc.nightMode);
|
||||
Integer resId = RenderingIcons.getIcons().get(render.getStringPropertyValue(render.ALL.R_ICON));
|
||||
String name = null;
|
||||
if (renderText) {
|
||||
name = obj.getName();
|
||||
|
@ -890,7 +880,7 @@ public class OsmandRenderer {
|
|||
|
||||
|
||||
|
||||
private void drawPolyline(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, TagValuePair pair, int layer) {
|
||||
private void drawPolyline(BinaryMapDataObject obj, RenderingRuleSearchRequest render, Canvas canvas, RenderingContext rc, TagValuePair pair, int layer) {
|
||||
if(render == null || pair == null){
|
||||
return;
|
||||
}
|
||||
|
@ -898,16 +888,15 @@ public class OsmandRenderer {
|
|||
if(length < 2){
|
||||
return;
|
||||
}
|
||||
rc.main.emptyLine();
|
||||
rc.second.emptyLine();
|
||||
rc.third.emptyLine();
|
||||
rc.adds = null;
|
||||
boolean res = render.renderPolyline(pair.tag, pair.value, rc.zoom, rc, this, layer, rc.nightMode);
|
||||
if(rc.main.strokeWidth == 0 || !res){
|
||||
render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
|
||||
render.setIntFilter(render.ALL.R_LAYER, layer);
|
||||
boolean rendered = render.search(RenderingRulesStorage.LINE_RULES);
|
||||
if(!rendered || !updatePaint(render, paint, 0, false)){
|
||||
return;
|
||||
}
|
||||
boolean oneway = false;
|
||||
if(rc.zoom >= 16 && "highway".equals(pair.tag) && MapRenderingTypes.isOneWayWay(obj.getHighwayAttributes())){ //$NON-NLS-1$
|
||||
rc.adds = getOneWayProperties();
|
||||
oneway = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -953,20 +942,17 @@ public class OsmandRenderer {
|
|||
yPrev = p.y;
|
||||
}
|
||||
if (path != null) {
|
||||
rc.main.updatePaint(paint);
|
||||
canvas.drawPath(path, paint);
|
||||
if (rc.second.strokeWidth != 0) {
|
||||
rc.second.updatePaint(paint);
|
||||
if (updatePaint(render, paint, 1, false)) {
|
||||
canvas.drawPath(path, paint);
|
||||
if (rc.third.strokeWidth != 0) {
|
||||
rc.third.updatePaint(paint);
|
||||
if (updatePaint(render, paint, 2, false)) {
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
}
|
||||
if (rc.adds != null) {
|
||||
for (int i = 0; i < rc.adds.length; i++) {
|
||||
rc.adds[i].updatePaint(paint);
|
||||
canvas.drawPath(path, paint);
|
||||
if(oneway){
|
||||
Paint[] paints = getOneWayPaints();
|
||||
for (int i = 0; i < paints.length; i++) {
|
||||
canvas.drawPath(path, paints[i]);
|
||||
}
|
||||
}
|
||||
if (obj.getName() != null && obj.getName().length() > 0) {
|
||||
|
@ -986,22 +972,28 @@ public class OsmandRenderer {
|
|||
}
|
||||
}
|
||||
if(ref != null && ref.trim().length() > 0){
|
||||
rc.clearText();
|
||||
ref = render.renderObjectText(ref, pair.tag, pair.value, rc, true, rc.nightMode);
|
||||
render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
|
||||
render.setIntFilter(render.ALL.R_TEXT_LENGTH, ref.length());
|
||||
render.setBooleanFilter(render.ALL.R_REF, true);
|
||||
if(render.search(RenderingRulesStorage.TEXT_RULES)){
|
||||
if(render.getIntPropertyValue(render.ALL.R_TEXT_SIZE) > 0){
|
||||
TextDrawInfo text = new TextDrawInfo(ref);
|
||||
text.fillProperties(rc, middlePoint.x, middlePoint.y);
|
||||
text.fillProperties(render, middlePoint.x, middlePoint.y);
|
||||
text.pathRotate = pathRotate;
|
||||
rc.textToDraw.add(text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(name != null && name.trim().length() > 0){
|
||||
rc.clearText();
|
||||
name = render.renderObjectText(name, pair.tag, pair.value, rc, false, rc.nightMode);
|
||||
if (rc.textSize > 0) {
|
||||
render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
|
||||
render.setIntFilter(render.ALL.R_TEXT_LENGTH, name.length());
|
||||
render.setBooleanFilter(render.ALL.R_REF, false);
|
||||
if (render.search(RenderingRulesStorage.TEXT_RULES) && render.getIntPropertyValue(render.ALL.R_TEXT_SIZE) > 0) {
|
||||
TextDrawInfo text = new TextDrawInfo(name);
|
||||
if (!rc.showTextOnPath) {
|
||||
text.fillProperties(rc, middlePoint.x, middlePoint.y);
|
||||
if (render.getIntPropertyValue(render.ALL.R_TEXT_ON_PATH, 0) == 0) {
|
||||
text.fillProperties(render, middlePoint.x, middlePoint.y);
|
||||
rc.textToDraw.add(text);
|
||||
} else {
|
||||
paintText.setTextSize(text.textSize);
|
||||
|
@ -1019,10 +1011,11 @@ public class OsmandRenderer {
|
|||
}
|
||||
}
|
||||
}
|
||||
text.fillProperties(rc, xMid / 2, yMid / 2);
|
||||
text.fillProperties(render, xMid / 2, yMid / 2);
|
||||
text.pathRotate = pathRotate;
|
||||
text.drawOnPath = path;
|
||||
text.vOffset = rc.main.strokeWidth / 2 - 1;
|
||||
float strokeWidth = render.getFloatPropertyValue(render.ALL.R_STROKE_WIDTH);
|
||||
text.vOffset = strokeWidth / 2 - 1;
|
||||
rc.textToDraw.add(text);
|
||||
}
|
||||
}
|
||||
|
@ -1032,37 +1025,36 @@ public class OsmandRenderer {
|
|||
}
|
||||
}
|
||||
}
|
||||
private static RenderingPaintProperties[] oneWay = null;
|
||||
public static RenderingPaintProperties[] getOneWayProperties(){
|
||||
private static Paint[] oneWay = null;
|
||||
private static Paint oneWayPaint(){
|
||||
Paint oneWay = new Paint();
|
||||
oneWay.setStyle(Style.STROKE);
|
||||
oneWay.setColor(0xff6c70d5);
|
||||
oneWay.setAntiAlias(true);
|
||||
return oneWay;
|
||||
}
|
||||
public static Paint[] getOneWayPaints(){
|
||||
if(oneWay == null){
|
||||
PathEffect arrowDashEffect1 = new DashPathEffect(new float[] { 0, 12, 10, 152 }, 0);
|
||||
PathEffect arrowDashEffect2 = new DashPathEffect(new float[] { 0, 12, 9, 153 }, 1);
|
||||
PathEffect arrowDashEffect3 = new DashPathEffect(new float[] { 0, 18, 2, 154 }, 1);
|
||||
PathEffect arrowDashEffect4 = new DashPathEffect(new float[] { 0, 18, 1, 155 }, 1);
|
||||
oneWay = new RenderingPaintProperties[4];
|
||||
oneWay[0] = new RenderingPaintProperties();
|
||||
oneWay[0].emptyLine();
|
||||
oneWay[0].color = 0xff6c70d5;
|
||||
oneWay[0].strokeWidth = 1;
|
||||
oneWay[0].pathEffect = arrowDashEffect1;
|
||||
oneWay = new Paint[4];
|
||||
oneWay[0] = oneWayPaint();
|
||||
oneWay[0].setStrokeWidth(1);
|
||||
oneWay[0].setPathEffect(arrowDashEffect1);
|
||||
|
||||
oneWay[1] = new RenderingPaintProperties();
|
||||
oneWay[1].emptyLine();
|
||||
oneWay[1].color = 0xff6c70d5;
|
||||
oneWay[1].strokeWidth = 2;
|
||||
oneWay[1].pathEffect = arrowDashEffect2;
|
||||
oneWay[1] = oneWayPaint();
|
||||
oneWay[1].setStrokeWidth(2);
|
||||
oneWay[1].setPathEffect(arrowDashEffect2);
|
||||
|
||||
oneWay[2] = new RenderingPaintProperties();
|
||||
oneWay[2].emptyLine();
|
||||
oneWay[2].color = 0xff6c70d5;
|
||||
oneWay[2].strokeWidth = 3;
|
||||
oneWay[2].pathEffect = arrowDashEffect3;
|
||||
oneWay[2] = oneWayPaint();
|
||||
oneWay[2].setStrokeWidth(3);
|
||||
oneWay[2].setPathEffect(arrowDashEffect3);
|
||||
|
||||
oneWay[3] = new RenderingPaintProperties();
|
||||
oneWay[3].emptyLine();
|
||||
oneWay[3].color = 0xff6c70d5;
|
||||
oneWay[3].strokeWidth = 4;
|
||||
oneWay[3].pathEffect = arrowDashEffect4;
|
||||
oneWay[3] = oneWayPaint();
|
||||
oneWay[3].setStrokeWidth(4);
|
||||
oneWay[3].setPathEffect(arrowDashEffect4);
|
||||
|
||||
}
|
||||
return oneWay;
|
||||
|
|
|
@ -4,16 +4,15 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.render.OsmandRenderingRulesParser;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.xml.sax.SAXException;
|
||||
|
@ -24,72 +23,27 @@ public class RendererRegistry {
|
|||
private final static Log log = LogUtil.getLog(RendererRegistry.class);
|
||||
|
||||
public final static String DEFAULT_RENDER = "default"; //$NON-NLS-1$
|
||||
public final static String CAR_RENDER = "car"; //$NON-NLS-1$
|
||||
public final static String BICYCLE_RENDER = "bicycle"; //$NON-NLS-1$
|
||||
public final static String PEDESTRIAN_RENDER = "pedestrian"; //$NON-NLS-1$
|
||||
|
||||
|
||||
|
||||
public RendererRegistry(){
|
||||
internalRenderers.put(DEFAULT_RENDER, "default.render.xml"); //$NON-NLS-1$
|
||||
internalRenderers.put(CAR_RENDER, "car.render.xml"); //$NON-NLS-1$
|
||||
internalRenderers.put(BICYCLE_RENDER, "bicycle.render.xml"); //$NON-NLS-1$
|
||||
internalRenderers.put(PEDESTRIAN_RENDER, "pedestrian.render.xml"); //$NON-NLS-1$
|
||||
internalRenderers.put("all-purpose (more detail)", "all-purpose.render.xml"); //$NON-NLS-1$
|
||||
internalRenderers.put("bicycle (more detail)", "bicycle-all.render.xml"); //$NON-NLS-1$
|
||||
internalRenderers.put("pedestrian (more detail)", "pedestrian-all.render.xml"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private BaseOsmandRender defaultRender = null;
|
||||
private BaseOsmandRender currentSelectedRender = null;
|
||||
private RenderingRulesStorage defaultRender = null;
|
||||
private RenderingRulesStorage currentSelectedRender = null;
|
||||
|
||||
private Map<String, File> externalRenderers = new LinkedHashMap<String, File>();
|
||||
private Map<String, String> internalRenderers = new LinkedHashMap<String, String>();
|
||||
|
||||
private Map<String, BaseOsmandRender> renderers = new LinkedHashMap<String, BaseOsmandRender>();
|
||||
private Map<String, RenderingRulesStorage> renderers = new LinkedHashMap<String, RenderingRulesStorage>();
|
||||
|
||||
public BaseOsmandRender defaultRender() {
|
||||
public RendererRegistry(){
|
||||
internalRenderers.put(DEFAULT_RENDER, "new_default.render.xml");
|
||||
}
|
||||
|
||||
public RenderingRulesStorage defaultRender() {
|
||||
if(defaultRender == null){
|
||||
defaultRender = getRenderer(DEFAULT_RENDER);
|
||||
if (defaultRender == null) {
|
||||
try {
|
||||
defaultRender = new BaseOsmandRender();
|
||||
defaultRender.init(OsmandRenderingRulesParser.class.getResourceAsStream("default.render.xml")); //$NON-NLS-1$
|
||||
} catch (IOException e) {
|
||||
log.error("Exception initialize renderer", e); //$NON-NLS-1$
|
||||
} catch (SAXException e) {
|
||||
log.error("Exception initialize renderer", e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultRender;
|
||||
}
|
||||
|
||||
public BaseOsmandRender carRender() {
|
||||
BaseOsmandRender renderer = getRenderer(CAR_RENDER);
|
||||
if(renderer == null){
|
||||
return defaultRender();
|
||||
}
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public BaseOsmandRender bicycleRender() {
|
||||
BaseOsmandRender renderer = getRenderer(BICYCLE_RENDER);
|
||||
if(renderer == null){
|
||||
return defaultRender();
|
||||
}
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public BaseOsmandRender pedestrianRender() {
|
||||
BaseOsmandRender renderer = getRenderer(PEDESTRIAN_RENDER);
|
||||
if(renderer == null){
|
||||
return defaultRender();
|
||||
}
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public BaseOsmandRender getRenderer(String name){
|
||||
public RenderingRulesStorage getRenderer(String name){
|
||||
if(renderers.containsKey(name)){
|
||||
return renderers.get(name);
|
||||
}
|
||||
|
@ -103,7 +57,7 @@ public class RendererRegistry {
|
|||
return externalRenderers.containsKey(name) || internalRenderers.containsKey(name);
|
||||
}
|
||||
|
||||
private BaseOsmandRender getRenderer(String name, Set<String> loadedRenderers) {
|
||||
private RenderingRulesStorage getRenderer(String name, Set<String> loadedRenderers) {
|
||||
try {
|
||||
return loadRenderer(name);
|
||||
} catch (IOException e) {
|
||||
|
@ -114,38 +68,35 @@ public class RendererRegistry {
|
|||
return null;
|
||||
}
|
||||
|
||||
public BaseOsmandRender loadRenderer(String name) throws IOException, SAXException {
|
||||
public RenderingRulesStorage loadRenderer(String name) throws IOException, SAXException {
|
||||
return loadRenderer(name, new LinkedHashSet<String>());
|
||||
}
|
||||
|
||||
private BaseOsmandRender loadRenderer(String name, Set<String> loadedRenderers) throws IOException, SAXException {
|
||||
private RenderingRulesStorage loadRenderer(String name, Set<String> loadedRenderers) throws IOException, SAXException {
|
||||
InputStream is = null;
|
||||
if(externalRenderers.containsKey(name)){
|
||||
is = new FileInputStream(externalRenderers.get(name));
|
||||
} else if(internalRenderers.containsKey(name)){
|
||||
is = OsmandRenderingRulesParser.class.getResourceAsStream(internalRenderers.get(name));
|
||||
is = RenderingRulesStorage.class.getResourceAsStream(internalRenderers.get(name));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not found " + name); //$NON-NLS-1$
|
||||
}
|
||||
BaseOsmandRender b = new BaseOsmandRender();
|
||||
b.init(is);
|
||||
RenderingRulesStorage main = new RenderingRulesStorage();
|
||||
main.parseRulesFromXmlInputStream(is);
|
||||
loadedRenderers.add(name);
|
||||
List<BaseOsmandRender> dependencies = new ArrayList<BaseOsmandRender>();
|
||||
for (String s : b.getDepends()) {
|
||||
if (loadedRenderers.contains(s)) {
|
||||
if(!Algoritms.isEmpty(main.getDepends())){
|
||||
if (loadedRenderers.contains(main.getDepends())) {
|
||||
log.warn("Circular dependencies found " + name); //$NON-NLS-1$
|
||||
} else {
|
||||
BaseOsmandRender dep = getRenderer(s, loadedRenderers);
|
||||
RenderingRulesStorage dep = getRenderer(main.getDepends(), loadedRenderers);
|
||||
if (dep == null) {
|
||||
log.warn("Dependent renderer not found : " + name); //$NON-NLS-1$
|
||||
} else{
|
||||
dependencies.add(dep);
|
||||
}
|
||||
main.setDependsStorage(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
b.setDependRenderers(dependencies);
|
||||
renderers.put(name, b);
|
||||
return b;
|
||||
renderers.put(name, main);
|
||||
return main;
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,14 +112,14 @@ public class RendererRegistry {
|
|||
return names;
|
||||
}
|
||||
|
||||
public BaseOsmandRender getCurrentSelectedRenderer() {
|
||||
public RenderingRulesStorage getCurrentSelectedRenderer() {
|
||||
if(currentSelectedRender == null){
|
||||
return defaultRender();
|
||||
}
|
||||
return currentSelectedRender;
|
||||
}
|
||||
|
||||
public void setCurrentSelectedRender(BaseOsmandRender currentSelectedRender) {
|
||||
public void setCurrentSelectedRender(RenderingRulesStorage currentSelectedRender) {
|
||||
this.currentSelectedRender = currentSelectedRender;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue